Permalink
Browse files

first version

  • Loading branch information...
1 parent a748911 commit bb8cd0601d9e9798f306192d75f8430e2975fb3b @navyxie committed Jul 23, 2016
View
@@ -0,0 +1,2 @@
+service_name: travis-pro
+repo_token: 8ijKDgHIO7DtTSrWY0ph3HYA8uAK21WQu
View
@@ -1,3 +1,5 @@
node_modules
coverage
-npm-debug.log
+npm-debug.log
+.DS_Store
+.test_dist_img
View
@@ -1,3 +1,5 @@
node_modules
coverage
-npm-debug.log
+npm-debug.log
+.DS_Store
+.test_dist_img
View
@@ -0,0 +1,14 @@
+language: node_js
+
+repo_token: 8ijKDgHIO7DtTSrWY0ph3HYA8uAK21WQu
+
+node_js:
+
+ - 0.10.35
+
+script: npm test
+
+after_script: npm run cov
+
+after_success:
+ "curl -L -l https://coveralls.io/repos/github/navyxie/gulp-custom-css-urls/badge.svg?branch=master"
View
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 navyxie <navyxie2010@mgail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
@@ -1 +1,50 @@
# gulp-custom-css-urls
+
+[![Build Status via Travis CI](https://travis-ci.org/navyxie/gulp-custom-css-urls.svg?branch=master)](https://travis-ci.org/navyxie/gulp-custom-css-urls) [![Coverage Status](https://coveralls.io/repos/github/navyxie/gulp-custom-css-urls/badge.svg?branch=master)](https://coveralls.io/github/navyxie/gulp-custom-css-urls?branch=master)
+
+a plugin for gulp to custom you image url inline css file, and support output image file, then you can upload image file to Cloud CDN.
+
+## usage
+
+```js
+var customCssUrls = require('gulp-custom-css-urls');
+var gulp = require('gulp');
+var path = require('path');
+gulp.task('demo',function(){
+ return gulp.src('assets/**/*.css')
+ .pipe(customCssUrls({
+ /**
+ * static filepath relative absolute filepath's physical position.
+ * eg:
+ * image path inline css is '/images/demo.png',
+ * image absoulte filepath is '/Users/Navy/Desktop/code/demo/assets/images/demo.png',
+ * the process(process.cwd()) path is '/Users/Navy/Desktop/code/demo',
+ * so the image path relative website root path is 'assets/'
+ */
+ staticfile_relative_website_rootpath: 'assets/',
+ outputImage: true, // output images file , default to false
+ outputImage_path: './.gulp_dist_output_images', // default to './.gulp_dist_output_images'
+ modify: function (imageRelativePath, cssFilePath, imageRelativeWebsiteRootPath, imgInfo) {
+ // modify image url before prepend or append
+ // the imgInfo param is object, {hash: 3503865059, width: 1782, height: 530, orgin_filename: 'custom.png'}
+ return path.join(imageRelativeWebsiteRootPath, path.basename(imageRelativePath)); //let the relative path become an absolute path
+ },
+ prepend: '', // prepend string before image url
+ append: '', // append string after image url
+ processPath: process.cwd() // custom process path , default to process.cwd()
+ }))
+ .pipe(gulp.dest('tmp/'));
+})
+gulp.task('default',['demo']);
+```
+
+//css file content, input:
+> div{background-image: url('/images/example.png');}
+// output filename formats: (filename + '_' + imgWidth + '_' + imgHeight + '.' + crc32 + ext)
+> div{background-image: url('/images/example_width_height.hash.png');}
+
+
+## test
+
+- npm test
+- npm run cov
View
@@ -1,3 +1,133 @@
-module.export = function () {
+var through2 = require('through2');
+var _ = require('lodash');
+var rework = require('rework');
+var reworkUrl = require('rework-plugin-url');
+var bufferCrc32 = require('buffer-crc32');
+var imageSize = require('image-size');
+var fs = require('fs');
+var path = require('path');
+var vfs = require('vinyl-fs');
+var rename = require('gulp-rename');
+
+
+// Maximum buffer size, with a default of 128 kilobytes.
+// TO-DO: make this adaptive based on the initial signature of the image
+var MaxBufferSize = 128*1024;
+function syncFileToBuffer (filepath) {
+ // read from the file, synchronously
+ var descriptor = fs.openSync(filepath, 'r');
+ var size = fs.fstatSync(descriptor).size;
+ var bufferSize = Math.min(size, MaxBufferSize);
+ var buffer = new Buffer(bufferSize);
+ fs.readSync(descriptor, buffer, 0, bufferSize, 0);
+ fs.closeSync(descriptor);
+ return buffer;
+}
+
+
+function customUrls (file, options, cb) {
+
+ // css
+ var filePath = file.path;
+ var fileContents = file.contents.toString();
+ var cssDirname = path.dirname(filePath);
+
+ // options
+ var modify = options.modify; // function you can modify return url before prepend or append
+ var prepend = options.prepend;
+ var append = options.append;
+ var outputImage = options.outputImage; // output images
+ var outputImage_path = options.outputImage_path || './.gulp_dist_output_images'; // output images filepath
+ var relative_root = options.staticfile_relative_website_rootpath || ''; //static filepath relative absolute filepath's physical position. (eg: /images/demo.png, absoulte filepath is /Users/Navy/Desktop/code/demo/assets/images/demo.png, process.cwd() is /Users/Navy/Desktop/code/demo, so the relative_root is assets)
+ var processPath = options.processPath || process.cwd();
+
+ // format images url inline css
+ var formattedContents = rework(fileContents).use(reworkUrl(function(url){
+ var formattedUrl = url; // image origin filepath
+ var imgAbsolutePath = formattedUrl; // image absolute filepath
+
+ //if images url is data:base64 , continue
+ if (formattedUrl.indexOf('data:') === 0) {
+ return formattedUrl;
+ }
+ // if images url is netword file , continue
+ if (/^(http|https|ftp|\/\/)/gi.test(formattedUrl)) {
+ return formattedUrl;
+ }
+
+ // image filepath is relative to website root
+ if (/^(\/)/gi.test(formattedUrl)) {
+ imgAbsolutePath = path.join(processPath, relative_root, formattedUrl);
+ } else {
+ // image filepath is a relative path
+ imgAbsolutePath = path.resolve(cssDirname, formattedUrl);
+ }
+
+ // images filename info
+ var imgExt = path.extname(formattedUrl);
+ var imgFileFullName = path.basename(formattedUrl);
+ var imgFileName = path.basename(formattedUrl, imgExt);
+ // image filepath relative website root path.
+ var img_relative_website_root_path = path.dirname(path.relative(relative_root, path.relative(processPath, imgAbsolutePath)));
+ // calculate image file crc32 value
+ var crc32 = bufferCrc32.unsigned(syncFileToBuffer(imgAbsolutePath));
+
+ // get image size info
+ var imgWH = imageSize(imgAbsolutePath);
+
+ //rename image, the format is ('imgFileName' + '_' + 'imageWidth' + '_' + 'imageHeight' + 'imageCrc32Value' + 'imageExt');
+ formattedUrl = imgFileName + '_' + imgWH.width + '_' + imgWH.height + '.' + crc32 + imgExt;
+
+ // if need to output match's images, do it.
+ if (outputImage) {
+ var outputBasename = path.basename(formattedUrl);
+ var outputDirname = path.join(outputImage_path, img_relative_website_root_path);
+ var outputFilepath = path.join(processPath, outputDirname, outputBasename);
+ console.info('output image file from: ', imgAbsolutePath, ' to: ', outputFilepath);
+ // copy image form imgAbsolutePath to outputFilepath
+ vfs.src(imgAbsolutePath).pipe(rename({basename:path.basename(outputFilepath, imgExt)})).pipe(vfs.dest(path.dirname(outputFilepath)));
+ }
+
+ // mofify url
+ if (_.isFunction(modify)) {
+ formattedUrl = modify(formattedUrl, filePath, '/' + img_relative_website_root_path, {hash: crc32, width: imgWH.width, height: imgWH.height, orgin_filename: imgFileFullName});
+ }
+
+ // prepend string
+ if (typeof prepend === 'string') {
+ formattedUrl = prepend + formattedUrl;
+ }
+
+ // append string
+ if (typeof append === 'string') {
+ formattedUrl += append;
+ }
+
+ return formattedUrl;
+
+ })).toString();
+
+ cb(null, formattedContents);
+};
+
+module.exports = function (options) {
+ if (!_.isObject(options)) {
+ options = {};
+ }
+ return through2.obj(function(file, enc, cb) {
+ var that = this;
+ if (file.isNull()) {
+ return cb(null, file);
+ }
+ var customedContents = customUrls(file, options, function (err, customedContents) {
+ if (err) {
+ return cb(err);
+ } else {
+ file.contents = new Buffer(customedContents);
+ that.push(file);
+ return cb(null, file);
+ }
+ });
+ });
}
View
@@ -1,24 +1,42 @@
{
"name": "gulp-custom-css-urls",
- "version": "0.0.0",
- "description": "a gulp plugin custom url inline in css",
+ "version": "0.0.1",
+ "description": "a gulp plugin custom image url inline in css",
"main": "index.js",
- "scripts": {},
+ "scripts": {
+ "test": "npm install && mocha --recursive test/",
+ "cov": "npm install && ./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage"
+ },
"repository": {
"type": "git",
"url": "https://github.com/navyxie/gulp-custom-css-urls.git"
},
"keywords": [
"gulp",
"css",
- "image"
+ "image",
+ "publish",
+ "web",
+ "frontend"
],
"dependencies": {
"buffer-crc32": "^0.2.5",
+ "gulp-rename": "^1.2.2",
"image-size": "^0.5.0",
- "reword": "^0.2.0",
- "rework-plugin-url": "^1.1.0",
- "through2": "^2.0.1"
+ "lodash": "^4.13.1",
+ "rework": "^1.0.1",
+ "rework-plugin-url": "^1.0.1",
+ "through2": "2.0.1",
+ "vinyl-fs": "^2.4.3"
+ },
+ "devDependencies": {
+ "coveralls": "2.11.9",
+ "exec-sync": "^0.1.6",
+ "istanbul": "^0.4.3",
+ "mocha": "^2.2.5",
+ "should": "^7.0.2",
+ "through2": "2.0.1",
+ "vinyl-fs": "^2.4.3"
},
"author": {
"name": "navyxie"
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -0,0 +1 @@
+div{background-image: url('/images/example.png');}
@@ -0,0 +1 @@
+div{background-image: url('../images/example.png');}
@@ -0,0 +1 @@
+div{background-image: url("data:image/jpeg;base64,JC")}
View
@@ -0,0 +1,63 @@
+var should = require('should');
+var vfs = require("vinyl-fs");
+var customCssUrls = require('../index');
+var through2 = require("through2");
+var path = require('path');
+var execSync = require('exec-sync');
+var testBase64Data = [
+ 'div {\n',
+ ' background-image: url("data:image/jpeg;base64,JC");\n',
+ '}'
+].join('');
+function dataBase64() {
+ return through2.obj(function(file, encoding, cb) {
+ var fileContents = file.contents.toString();
+ fileContents.should.equal(testBase64Data);
+ file.contents = new Buffer(fileContents);
+ this.push(file);
+ cb();
+ });
+}
+describe('gulp-custom-css-urls', function() {
+ this.timeout(5000);
+ var staticfile_relative_website_rootpath = 'test/assets/';
+ it('should not change anything in fileContents if image url is data:base64', function () {
+ vfs.src('test/assets/styles/example3.css')
+ .pipe(customCssUrls())
+ .pipe(dataBase64())
+ });
+ it('should be ok if image url is relative to website root path', function (done) {
+ vfs.src('test/assets/styles/example1.css')
+ .pipe(customCssUrls({
+ staticfile_relative_website_rootpath: staticfile_relative_website_rootpath,
+ modify: function (imageRelativePath, cssFilePath, imageRelativeWebsiteRootPath, imgInfo) {
+ imageRelativePath.should.equal('example_1968_920.1373564769.png');
+ imageRelativeWebsiteRootPath.should.equal('/images');
+ imgInfo.should.have.properties({hash: 1373564769, width: 1968, height: 920, orgin_filename: 'example.png' });
+ done();
+ return imageRelativePath;
+ }
+ }))
+ });
+ it('should be ok if image url is relative to css file path', function (done) {
+ vfs.src('test/assets/styles/example2.css')
+ .pipe(customCssUrls({
+ staticfile_relative_website_rootpath: staticfile_relative_website_rootpath,
+ modify: function (imageRelativePath, cssFilePath, imageRelativeWebsiteRootPath, imgInfo) {
+ imageRelativePath.should.equal('example_1968_920.1373564769.png');
+ imageRelativeWebsiteRootPath.should.equal('/images');
+ imgInfo.should.have.properties({hash: 1373564769, width: 1968, height: 920, orgin_filename: 'example.png' });
+ setTimeout(function () {done()}, 2000);
+ return imageRelativePath;
+ },
+ outputImage: true,
+ outputImage_path: './.test_dist_img'
+ }))
+ });
+ after(function(done){
+ setTimeout(function () {
+ execSync("rm -r " + path.join(process.cwd(), './.test_dist_img'));
+ done();
+ },3000);
+ })
+});

0 comments on commit bb8cd06

Please sign in to comment.