{"id":19066499,"url":"https://github.com/geut/postcss-copy","last_synced_at":"2025-04-28T12:29:16.790Z","repository":{"id":57327905,"uuid":"41365982","full_name":"geut/postcss-copy","owner":"geut","description":"An async postcss plugin to copy all assets referenced in CSS files to a custom destination folder and updating the URLs.","archived":false,"fork":false,"pushed_at":"2017-06-30T03:10:11.000Z","size":2133,"stargazers_count":38,"open_issues_count":3,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-13T19:47:20.366Z","etag":null,"topics":["assets","copy","css","postcss-plugin","postcss-plugins"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/geut.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-08-25T13:50:26.000Z","updated_at":"2022-07-18T10:49:16.000Z","dependencies_parsed_at":"2022-09-17T11:20:19.418Z","dependency_job_id":null,"html_url":"https://github.com/geut/postcss-copy","commit_stats":null,"previous_names":[],"tags_count":51,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geut%2Fpostcss-copy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geut%2Fpostcss-copy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geut%2Fpostcss-copy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geut%2Fpostcss-copy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/geut","download_url":"https://codeload.github.com/geut/postcss-copy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251313179,"owners_count":21569371,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["assets","copy","css","postcss-plugin","postcss-plugins"],"created_at":"2024-11-09T00:57:05.061Z","updated_at":"2025-04-28T12:29:16.741Z","avatar_url":"https://github.com/geut.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# postcss-copy\n[![Build Status](https://travis-ci.org/geut/postcss-copy.svg?branch=master)](https://travis-ci.org/geut/postcss-copy)\n[![Build status](https://ci.appveyor.com/api/projects/status/hx0tmjv1qi0au9oy?svg=true)](https://ci.appveyor.com/project/tinchoz49/postcss-copy)\n[![Coverage Status](https://coveralls.io/repos/github/geut/postcss-copy/badge.svg?branch=master)](https://coveralls.io/github/geut/postcss-copy?branch=master)\n[![Dependency Status](https://david-dm.org/geut/postcss-copy.svg)](https://david-dm.org/geut/postcss-copy)\n[![devDependency Status](https://david-dm.org/geut/postcss-copy/dev-status.svg)](https://david-dm.org/geut/postcss-copy#info=devDependencies)\n\u003e An **async** postcss plugin to copy all assets referenced in CSS files to a custom destination folder and updating the URLs.\n\nSections |\n--- |\n[Install](#install) |\n[Quick Start](#quick-start) |\n[Options](#options) |\n[Custom Hash Function](#custom-hash-function) |\n[Transform](#using-transform) |\n[Using postcss-import](#using-postcss-import) |\n[About lifecyle and the fileMeta object](#lifecyle) |\n[Roadmap](#roadmap) |\n[Credits](#credits) |\n\n\n## \u003ca name=\"install\"\u003e\u003c/a\u003e Install\n\nWith [npm](https://npmjs.com/package/postcss-copy) do:\n\n```\n$ npm install postcss-copy\n```\n\n## \u003ca name=\"quick-start\"\u003e\u003c/a\u003e Quick Start\n\n### Using [postcss-cli](https://github.com/postcss/postcss-cli)\n```js\n// postcss.config.js\nmodule.exports = {\n    plugins: [\n        require('postcss-copy')({\n            dest: 'dist'\n        })\n    ]\n};\n```\n```bash\n$ postcss src/index.css\n```\n\n### Using [Gulp](https://github.com/postcss/gulp-postcss)\n\n```js\nvar gulp = require('gulp');\nvar postcss = require('gulp-postcss');\nvar postcssCopy = require('postcss-copy');\n\ngulp.task('buildCss', function () {\n    var processors = [\n        postcssCopy({\n            basePath: ['src', 'otherSrc']\n            dest: 'dist'\n        })\n    ];\n\n    return gulp\n        .src(['src/**/*.css', 'otherSrc/**/*.css'])\n        .pipe(postcss(processors))\n        .pipe(gulp.dest('dist'));\n});\n```\n\n## \u003ca name=\"options\"\u003e\u003c/a\u003e Options\n\n#### basePath ({string|array} default = process.cwd())\nDefine one/many base path for your CSS files.\n\n#### dest ({string} required)\nDefine the dest path of your CSS files and assets.\n\n#### template ({string | function} default = '[hash].[ext][query]')\nDefine a template name for your final url assets.\n* string template\n    * **[hash]**: Let you use a hash name based on the contents of the file.\n    * **[name]**: Real name of your asset.\n    * **[path]**: Original relative path of your asset.\n    * **[ext]**: Extension of the asset.\n    * **[query]**: Query string.\n    * **[qparams]**: Query string params without the ```?```.\n    * **[qhash]**: Query string hash without the ```#```.\n* function template\n```js\nvar copyOpts = {\n    ...,\n    template(fileMeta) {\n        return 'assets/custom-name-' + fileMeta.name + '.' + fileMeta.ext;\n    }\n}\n```\n\n#### preservePath ({boolean} default = false)\nFlag option to notify to postcss-copy that your CSS files destination are going to preserve the directory structure.\nIt's helpful if you are using `postcss-cli` with the --base option or `gulp-postcss` with multiple files (e.g: `gulp.src('src/**/*.css')`)\n\n#### ignore ({string | string[] | function} default = [])\nOption to ignore assets in your CSS file.\n\n##### Using the ```!``` key in your CSS:\n```css\n.btn {\n    background-image: url('!images/button.jpg');\n}\n.background {\n    background-image: url('!images/background.jpg');\n}\n```\n\n##### Using a string or array with [micromatch](https://github.com/jonschlinkert/micromatch) support to ignore files:\n```js\n// ignore with string\nvar copyOpts = {\n    ...,\n    ignore: 'images/*.jpg'\n}\n// ignore with array\nvar copyOpts = {\n    ...,\n    ignore: ['images/button.+(jpg|png)', 'images/background.jpg']\n}\n```\n##### Using a custom function:\n```js\n// ignore function\nvar copyOpts = {\n    ...,\n    ignore(fileMeta, opts) {\n        return (fileMeta.filename.indexOf('images/button.jpg') ||\n                fileMeta.filename.indexOf('images/background.jpg'));\n    }\n}\n```\n\n#### \u003ca name=\"custom-hash-function\"\u003e\u003c/a\u003e hashFunction\nDefine a custom function to create the hash name.\n```js\nvar copyOpts = {\n    ...,\n    hashFunction(contents) {\n        // borschik\n        return crypto.createHash('sha1')\n            .update(contents)\n            .digest('base64')\n            .replace(/\\+/g, '-')\n            .replace(/\\//g, '_')\n            .replace(/=/g, '')\n            .replace(/^[+-]+/g, '');\n    }\n};\n```\n\n#### \u003ca name=\"using-transform\"\u003e\u003c/a\u003e transform\nExtend the copy method to apply a transform in the contents (e.g: optimize images).\n\n**IMPORTANT:** The function must return the fileMeta (modified) or a promise using ```resolve(fileMeta)```.\n```js\nvar Imagemin = require('imagemin');\nvar imageminJpegtran = require('imagemin-jpegtran');\nvar imageminPngquant = require('imagemin-pngquant');\n\nvar copyOpts = {\n    ...,\n    transform(fileMeta) {\n        if (['jpg', 'png'].indexOf(fileMeta.ext) === -1) {\n            return fileMeta;\n        }\n        return Imagemin.buffer(fileMeta.contents, {\n            plugins: [\n                imageminPngquant(),\n                imageminJpegtran({\n                    progressive: true\n                })\n            ]\n        })\n        .then(result =\u003e {\n            fileMeta.contents = result;\n            return fileMeta; // \u003c- important\n        });\n    }\n};\n```\n\n#### \u003ca name=\"using-postcss-import\"\u003e\u003c/a\u003e Using copy with postcss-import\n[postcss-import](https://github.com/postcss/postcss-import) is a great plugin that allow us work our css files in a modular way with the same behavior of CommonJS.\n\n***One thing more...***\npostcss-import has the ability of load files from node_modules. If you are using a custom `basePath` and you want to\ntrack your assets from `node_modules` you need to add the `node_modules` folder in the `basePath` option:\n\n```\nmyProject/\n|-- node_modules/\n|-- dest/\n|-- src/\n```\n\n### Full example\n```js\nvar gulp = require('gulp');\nvar postcss = require('gulp-postcss');\nvar postcssCopy = require('postcss-copy');\nvar postcssImport = require('postcss-import');\nvar path = require('path');\n\ngulp.task('buildCss', function () {\n    var processors = [\n        postcssImport(),\n        postcssCopy({\n            basePath: ['src', 'node_modules'],\n            preservePath: true,\n            dest: 'dist'\n        })\n    ];\n\n    return gulp\n        .src('src/**/*.css')\n        .pipe(postcss(processors, {to: 'dist/css/index.css'}))\n        .pipe(gulp.dest('dist/css'));\n});\n```\n\n#### \u003ca name=\"lifecyle\"\u003e\u003c/a\u003e About lifecyle and the fileMeta object\nThe fileMeta is a literal object with meta information about the copy process. Its information grows with the progress of the copy process.\n\nThe lifecyle of the copy process is:\n\n1. Detect the url in the CSS files\n2. Validate url\n3. Initialize the fileMeta:\n\n    ```js\n    {\n        sourceInputFile, // path to the origin CSS file\n        sourceValue, // origin asset value taked from the CSS file\n        filename, // filename normalized without query string\n        absolutePath, // absolute path of the asset file\n        fullName, // name of the asset file\n        path, // relative path of the asset file\n        name, // name without extension\n        ext, // extension name\n        query, // full query string\n        qparams, // query string params without the char '?'\n        qhash, // query string hash without the char '#'\n        basePath // basePath found\n    }\n    ```\n4. Check ignore function\n5. Read the asset file (using a cache buffer if exists)\n6. Add ```content``` property in the fileMeta object\n7. Execute custom transform\n8. Create hash name based on the custom transform\n9. Add ```hash``` property in the fileMeta object\n10. Define template for the new asset\n11. Add ```resultAbsolutePath``` and ```extra``` properties in the fileMeta object\n12. Write in destination\n13. Write the new URL in the PostCSS node value.\n\n## \u003ca name=\"roadmap\"\u003e\u003c/a\u003e On roadmap\n\nnothing for now :)\n\n## \u003ca name=\"credits\"\u003e\u003c/a\u003e Credits\n\n* Thanks to @conradz and his rework plugin [rework-assets](https://github.com/conradz/rework-assets) my inspiration in this plugin.\n* Thanks to @MoOx for let me create the copy function in his [postcss-url](https://github.com/postcss/postcss-url) plugin.\n* Thanks to @webpack, i take the idea of define templates from his awesome [file-loader](https://github.com/webpack/file-loader)\n* Huge thanks to @TrySound for his work in this project.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeut%2Fpostcss-copy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgeut%2Fpostcss-copy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeut%2Fpostcss-copy/lists"}