Skip to content

Instantly share code, notes, and snippets.

@DaBs
Created September 18, 2018 14:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DaBs/8b13e5a34c8aea1c15b38ea93125cbb4 to your computer and use it in GitHub Desktop.
Save DaBs/8b13e5a34c8aea1c15b38ea93125cbb4 to your computer and use it in GitHub Desktop.
/* eslint-disable */
const path = require('path');
const fs = require('fs-extra');
const md5File = require('md5-file');
class Postprocessor {
constructor(options) {
this.pattern = options.pattern;
this.root = path.resolve(options.root);
this.outputDirectory = path.resolve(options.outputDirectory);
}
getMD5FilePath(filepath) {
let md5hash;
try {
md5hash = md5File.sync(filepath);
} catch (e) {
console.error(e);
}
const filename = path.basename(filepath)
const filenameParts = filename.split('.');
const extension = filenameParts.pop();
const newFileName = [ ...filenameParts, md5hash, extension ].join('.');
return filepath.replace(filename, newFileName);
}
process(css) {
const matches = css.match(this.pattern) || [];
const trimmedMatches = matches.map(match => {
let trimmed = match.slice(4, -1); // Get rid of url()
const firstCharacter = trimmed.slice(0, 1); // Figure out if we have quotes around the asset and trim it too
if (firstCharacter === "'" || firstCharacter === '"') {
trimmed = trimmed.slice(1, -1);
}
// Finally remove any query parameters
trimmed = trimmed.split('?')[0].split('#')[0];
return trimmed;
});
for (let match of trimmedMatches) {
const absolutePath = path.join(this.root, match);
if (fs.existsSync(absolutePath) && fs.lstatSync(absolutePath).isFile()) {
const md5Path = this.getMD5FilePath(absolutePath);
const md5Relative = md5Path.slice(this.root.length);
const outputRelativePath = path.join(this.outputDirectory.slice(this.root.length), md5Relative);
const outputAbsolutePath = path.join(this.root, outputRelativePath);
try {
fs.copySync(absolutePath, outputAbsolutePath, { overwrite: false });
} catch (e) {
throw new Error(`Error: ${e} in path: ${absolutePath}`);
}
css = css.replace(match, outputRelativePath.replace(/\\/g, '/'));
}
}
return css;
}
}
const defaults = {
root: __dirname,
outputDirectory: path.join(__dirname, './fingerprinted'),
pattern: /url\((?!data)([\w\d\.\-/'"?#]+)\)/gi,
excludes: [/node_modules/gi]
};
class FingerprintLess {
constructor(options) {
const mergedOptions = { ...defaults, ...options };
this.options = mergedOptions;
}
install(less, pluginManager) {
pluginManager.addPostProcessor(new Postprocessor(this.options), 9999)
}
}
module.exports = FingerprintLess;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment