Nutmeg Pumpkin Macchiato

    postcss-copy

    7.1.0 • Public • Published

    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

    Install

    npm i postcss-copy

    DownloadsWeekly Downloads

    1,540

    Version

    7.1.0

    License

    MIT

    Last publish

    Collaborators

    • geutuser
    • tinchoz49