npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

postcss-copy

v7.1.0

Published

A postcss plugin to copy all assets referenced in CSS to a custom destination folder and updating the URLs.

Downloads

24,699

Readme

postcss-copy

Build Status Build status Coverage Status Dependency Status devDependency Status

An async postcss plugin to copy all assets referenced in CSS files to a custom destination folder and updating the URLs.

Sections | --- | Install | Quick Start | Options | Custom Hash Function | Transform | Using postcss-import | About lifecyle and the fileMeta object | Roadmap | Credits |

Install

With npm do:

$ npm install postcss-copy

Quick Start

Using postcss-cli

// postcss.config.js
module.exports = {
    plugins: [
        require('postcss-copy')({
            dest: 'dist'
        })
    ]
};
$ postcss src/index.css

Using Gulp

var gulp = require('gulp');
var postcss = require('gulp-postcss');
var postcssCopy = require('postcss-copy');

gulp.task('buildCss', function () {
    var processors = [
        postcssCopy({
            basePath: ['src', 'otherSrc']
            dest: 'dist'
        })
    ];

    return gulp
        .src(['src/**/*.css', 'otherSrc/**/*.css'])
        .pipe(postcss(processors))
        .pipe(gulp.dest('dist'));
});

Options

basePath ({string|array} default = process.cwd())

Define one/many base path for your CSS files.

dest ({string} required)

Define the dest path of your CSS files and assets.

template ({string | function} default = '[hash].[ext][query]')

Define a template name for your final url assets.

  • string template
    • [hash]: Let you use a hash name based on the contents of the file.
    • [name]: Real name of your asset.
    • [path]: Original relative path of your asset.
    • [ext]: Extension of the asset.
    • [query]: Query string.
    • [qparams]: Query string params without the ?.
    • [qhash]: Query string hash without the #.
  • function template
var copyOpts = {
    ...,
    template(fileMeta) {
        return 'assets/custom-name-' + fileMeta.name + '.' + fileMeta.ext;
    }
}

preservePath ({boolean} default = false)

Flag option to notify to postcss-copy that your CSS files destination are going to preserve the directory structure. It's helpful if you are using postcss-cli with the --base option or gulp-postcss with multiple files (e.g: gulp.src('src/**/*.css'))

ignore ({string | string[] | function} default = [])

Option to ignore assets in your CSS file.

Using the ! key in your CSS:
.btn {
    background-image: url('!images/button.jpg');
}
.background {
    background-image: url('!images/background.jpg');
}
Using a string or array with micromatch support to ignore files:
// ignore with string
var copyOpts = {
    ...,
    ignore: 'images/*.jpg'
}
// ignore with array
var copyOpts = {
    ...,
    ignore: ['images/button.+(jpg|png)', 'images/background.jpg']
}
Using a custom function:
// ignore function
var copyOpts = {
    ...,
    ignore(fileMeta, opts) {
        return (fileMeta.filename.indexOf('images/button.jpg') ||
                fileMeta.filename.indexOf('images/background.jpg'));
    }
}

hashFunction

Define a custom function to create the hash name.

var copyOpts = {
    ...,
    hashFunction(contents) {
        // borschik
        return crypto.createHash('sha1')
            .update(contents)
            .digest('base64')
            .replace(/\+/g, '-')
            .replace(/\//g, '_')
            .replace(/=/g, '')
            .replace(/^[+-]+/g, '');
    }
};

transform

Extend the copy method to apply a transform in the contents (e.g: optimize images).

IMPORTANT: The function must return the fileMeta (modified) or a promise using resolve(fileMeta).

var Imagemin = require('imagemin');
var imageminJpegtran = require('imagemin-jpegtran');
var imageminPngquant = require('imagemin-pngquant');

var copyOpts = {
    ...,
    transform(fileMeta) {
        if (['jpg', 'png'].indexOf(fileMeta.ext) === -1) {
            return fileMeta;
        }
        return Imagemin.buffer(fileMeta.contents, {
            plugins: [
                imageminPngquant(),
                imageminJpegtran({
                    progressive: true
                })
            ]
        })
        .then(result => {
            fileMeta.contents = result;
            return fileMeta; // <- important
        });
    }
};

Using copy with postcss-import

postcss-import is a great plugin that allow us work our css files in a modular way with the same behavior of CommonJS.

One thing more... postcss-import has the ability of load files from node_modules. If you are using a custom basePath and you want to track your assets from node_modules you need to add the node_modules folder in the basePath option:

myProject/
|-- node_modules/
|-- dest/
|-- src/

Full example

var gulp = require('gulp');
var postcss = require('gulp-postcss');
var postcssCopy = require('postcss-copy');
var postcssImport = require('postcss-import');
var path = require('path');

gulp.task('buildCss', function () {
    var processors = [
        postcssImport(),
        postcssCopy({
            basePath: ['src', 'node_modules'],
            preservePath: true,
            dest: 'dist'
        })
    ];

    return gulp
        .src('src/**/*.css')
        .pipe(postcss(processors, {to: 'dist/css/index.css'}))
        .pipe(gulp.dest('dist/css'));
});

About lifecyle and the fileMeta object

The fileMeta is a literal object with meta information about the copy process. Its information grows with the progress of the copy process.

The lifecyle of the copy process is:

  1. Detect the url in the CSS files

  2. Validate url

  3. Initialize the fileMeta:

    {
        sourceInputFile, // path to the origin CSS file
        sourceValue, // origin asset value taked from the CSS file
        filename, // filename normalized without query string
        absolutePath, // absolute path of the asset file
        fullName, // name of the asset file
        path, // relative path of the asset file
        name, // name without extension
        ext, // extension name
        query, // full query string
        qparams, // query string params without the char '?'
        qhash, // query string hash without the char '#'
        basePath // basePath found
    }
  4. Check ignore function

  5. Read the asset file (using a cache buffer if exists)

  6. Add content property in the fileMeta object

  7. Execute custom transform

  8. Create hash name based on the custom transform

  9. Add hash property in the fileMeta object

  10. Define template for the new asset

  11. Add resultAbsolutePath and extra properties in the fileMeta object

  12. Write in destination

  13. Write the new URL in the PostCSS node value.

On roadmap

nothing for now :)

Credits

  • Thanks to @conradz and his rework plugin rework-assets my inspiration in this plugin.
  • Thanks to @MoOx for let me create the copy function in his postcss-url plugin.
  • Thanks to @webpack, i take the idea of define templates from his awesome file-loader
  • Huge thanks to @TrySound for his work in this project.

License

MIT