├── .autod.conf.js ├── .editorconfig ├── .eslintrc ├── .gitignore ├── .travis.yml ├── HISTORY.md ├── README.md ├── appveyor.yml ├── index.js ├── lib ├── parse.js ├── stringify.js └── util.js ├── package.json └── test ├── index.test.js ├── parse.test.js └── stringify.test.js /.autod.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | write: true, 5 | prefix: '^', 6 | devprefix: '^', 7 | exclude: [ 8 | 'test/fixtures', 9 | ], 10 | devdep: [ 11 | 'autod', 12 | 'egg-bin', 13 | 'egg-ci', 14 | ], 15 | keep: [ 16 | ], 17 | semver: [ 18 | ], 19 | }; 20 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | 15 | [Makefile] 16 | indent_style = tab 17 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "egg", 3 | "rules": { 4 | "no-var": "off" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - '4' 5 | - '6' 6 | - '7' 7 | install: 8 | - npm i npminstall && npminstall 9 | script: 10 | - npm run ci 11 | after_script: 12 | - npminstall codecov && codecov 13 | -------------------------------------------------------------------------------- /HISTORY.md: -------------------------------------------------------------------------------- 1 | 2 | 1.0.4 / 2016-12-27 3 | ================== 4 | 5 | * style: use eslint 6 | * deps upgrade debug 7 | * chore: use egg-bin for test 8 | 9 | ## 1.0.3 / 2015-02-15 10 | 11 | - fix: return self if transformer is empty 12 | 13 | ## 1.0.2 / 2015-02-15 14 | 15 | - fix: should clone transformer object 16 | 17 | ## 1.0.1 / 2015-02-13 18 | 19 | - fix: should use transformed object after function call 20 | 21 | ## 1.0.0 22 | 23 | Big change! 24 | 25 | - new API `rename(filepath, transformer)` 26 | - split parse and stringify methods 27 | - support template in transform object 28 | 29 | ## 0.2.3 30 | 31 | fix `../` path 32 | 33 | ## 0.2.2 34 | 35 | fix relative path when dirname is empty 36 | 37 | ## 0.2.1 38 | 39 | - empty string will not throw 40 | - support relative path 41 | 42 | ## 0.2.0 43 | 44 | First commit 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rename 2 | 3 | Rename files using some transformers. 4 | 5 | --- 6 | 7 | [![NPM version](https://img.shields.io/npm/v/rename.svg?style=flat)](https://npmjs.org/package/rename) 8 | [![Build Status](https://img.shields.io/travis/popomore/rename.svg?style=flat)](https://travis-ci.org/popomore/rename) 9 | [![Build Status](https://img.shields.io/coveralls/popomore/rename.svg?style=flat)](https://coveralls.io/r/popomore/rename) 10 | [![NPM downloads](http://img.shields.io/npm/dm/rename.svg?style=flat)](https://npmjs.org/package/rename) 11 | 12 | **NOTE: Rename < 0.2.0 is not the same lib, you can see [renamer](https://www.npmjs.org/package/renamer). 1.0.0 have a big change.** 13 | 14 | ## Install 15 | 16 | ``` 17 | $ npm install rename -g 18 | ``` 19 | 20 | ## Usage 21 | 22 | Rename file using another filepath. 23 | 24 | ```js 25 | rename('a.js', 'b.js'); 26 | // => b.js 27 | ``` 28 | 29 | Rename file using a _transform object_ that contain some property. 30 | 31 | ``` 32 | { 33 | dirname: "replace dirname", 34 | prefix: "add prefix before basename", 35 | basename: "replace dirname", 36 | suffix: "add prefix after basename", 37 | extname: "replace extname" 38 | } 39 | ``` 40 | 41 | Add `-debug` suffix 42 | 43 | ```js 44 | rename('a.js', {suffix: '-debug'}); 45 | // => a-debug.js 46 | ``` 47 | 48 | Also can use a _transform function_ that could return a _transform object_. 49 | 50 | ```js 51 | rename('a.js', function() { 52 | return {suffix: '-debug'}; 53 | }); 54 | // => a-debug.js 55 | ``` 56 | 57 | ## API 58 | 59 | ### rename(filepath, transformer) 60 | 61 | #### filepath 62 | 63 | Filepath can be a string or object. Parse the filepath to _file object_ if it's a string. 64 | 65 | _File object_ should contain property dirname, basename and extname. 66 | 67 | ```js 68 | rename({ 69 | basename: 'a', 70 | extname: '.js' 71 | }, 'b.js'); 72 | // => b.js 73 | ``` 74 | 75 | #### transformer 76 | 77 | Transformer can be a function, string or object. 78 | 79 | Simple example about _transform function_ using custom property. 80 | 81 | ```js 82 | function transformer(fileObj) { 83 | return { 84 | suffix: fileObj.hash || '-debug' 85 | }; 86 | } 87 | 88 | rename({ 89 | basename: 'a', 90 | extname: '.js' 91 | }, transformer); 92 | // => a-debug.js 93 | 94 | rename({ 95 | basename: 'a', 96 | extname: '.js', 97 | hash: '-123' 98 | }, transformer); 99 | // => a-123.js 100 | ``` 101 | 102 | The value of _transform object_ can be template that parsed from _file object_. 103 | 104 | ``` 105 | rename({ 106 | basename: 'c', 107 | extname: '.js', 108 | hash: '111' 109 | }, { 110 | suffix: '-${hash}', 111 | }).should.eql('c-111.js'); 112 | ``` 113 | 114 | ### rename.parse 115 | 116 | Generate a _file object_ from a string or object. 117 | 118 | ### rename.stringify 119 | 120 | Generate a filepath from _file object_. 121 | 122 | ## LISENCE 123 | 124 | Copyright (c) 2017 popomore. Licensed under the MIT license. 125 | 126 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | matrix: 3 | - nodejs_version: '4' 4 | - nodejs_version: '6' 5 | - nodejs_version: '7' 6 | 7 | install: 8 | - ps: Install-Product node $env:nodejs_version 9 | - npm i npminstall && node_modules\.bin\npminstall 10 | 11 | test_script: 12 | - node --version 13 | - npm --version 14 | - npm run ci 15 | 16 | build: off 17 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var debug = require('debug')('rename'); 4 | var parse = require('./lib/parse'); 5 | var stringify = require('./lib/stringify'); 6 | var util = require('./lib/util'); 7 | 8 | module.exports = rename; 9 | module.exports.parse = parse; 10 | module.exports.stringify = stringify; 11 | 12 | /* 13 | Rename filepath using transformer 14 | */ 15 | function rename(filepath, transformer) { 16 | var result; 17 | /* 18 | Return a file object 19 | 20 | { 21 | dirname 22 | basename 23 | extname 24 | origin 25 | } 26 | */ 27 | var fileObj = parse(filepath); 28 | 29 | if (!transformer) { 30 | result = stringify(fileObj); 31 | debug('transform to %s with no transformer', result); 32 | return result; 33 | } 34 | 35 | /* 36 | transformed object 37 | 38 | { 39 | dirname 40 | prefix 41 | basename 42 | suffix 43 | extname 44 | } 45 | */ 46 | var transformed = util.isFunction(transformer) ? transformer(fileObj) : transformer; 47 | 48 | // rename it when transformer is string as a filepath 49 | if (util.isString(transformed)) { 50 | result = transformed || stringify(fileObj); 51 | debug('transform from %j to `%s` with %j', fileObj, result, transformed); 52 | return result; 53 | } 54 | 55 | if (!util.isObject(transformed)) { 56 | throw new Error('transformer should be string, function or object.'); 57 | } 58 | 59 | result = transform(fileObj, transformed); 60 | debug('transform from %j to `%s` with %j', fileObj, result, transformed); 61 | return result; 62 | } 63 | 64 | function transform(fileObj, transformed) { 65 | transformed = parseTemplate(transformed, fileObj); 66 | var result = {}; 67 | result.dirname = choose('dirname', transformed, fileObj); 68 | result.extname = choose('extname', transformed, fileObj); 69 | result.basename = [ 70 | transformed.prefix || '', 71 | choose('basename', transformed, fileObj), 72 | transformed.suffix || '', 73 | ].join(''); 74 | return stringify(result); 75 | } 76 | 77 | function choose(name, changed, origin) { 78 | return name in changed ? (changed[name] || '') : origin[name]; 79 | } 80 | 81 | // parse template like ${xxx} in transformed using file object 82 | var RE_REPLACE = /\$\{?([a-zA-Z0-9-_]*)\}?/g; 83 | function parseTemplate(transformed, fileObj) { 84 | var result = {}; 85 | Object.keys(transformed).forEach(function(key) { 86 | result[key] = !transformed[key] ? 87 | transformed[key] : 88 | transformed[key].replace(RE_REPLACE, function(_, matched) { 89 | return fileObj[matched] || ''; 90 | }); 91 | }); 92 | return result; 93 | } 94 | -------------------------------------------------------------------------------- /lib/parse.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var assert = require('assert'); 4 | var debug = require('debug')('rename:parse'); 5 | var extname = require('path').extname; 6 | var dirname = require('path').dirname; 7 | var basename = require('path').basename; 8 | var util = require('./util'); 9 | 10 | module.exports = function parse(path) { 11 | assert(util.isString(path) || util.isObject(path), 12 | 'Argument should be string or object.'); 13 | 14 | var orig = path; 15 | 16 | if (util.isString(path)) { 17 | path = toObject(path); 18 | } else { 19 | path.dirname = path.dirname || ''; 20 | path.extname = path.extname || ''; 21 | path.basename = path.basename || ''; 22 | path.origin = path.origin || ''; 23 | } 24 | 25 | debug('parse from %j to %j', orig, path); 26 | return path; 27 | }; 28 | 29 | function toObject(path) { 30 | var ext = extname(path); 31 | return { 32 | dirname: dirname(path), 33 | basename: basename(path, ext), 34 | extname: ext, 35 | origin: path, 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /lib/stringify.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var assert = require('assert'); 4 | var debug = require('debug')('stringify'); 5 | var join = require('path').join; 6 | var isObject = require('./util').isObject; 7 | 8 | module.exports = function stringify(obj) { 9 | assert(isObject(obj), 'Argument should be object.'); 10 | 11 | obj.dirname = obj.dirname || '.'; 12 | obj.extname = obj.extname || ''; 13 | obj.basename = obj.basename || ''; 14 | 15 | 16 | var path = join(obj.dirname, obj.basename + obj.extname); 17 | if (path === '.') { 18 | path = ''; 19 | } 20 | debug('stringify to %s', path); 21 | return path; 22 | }; 23 | -------------------------------------------------------------------------------- /lib/util.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var toString = Object.prototype.toString; 4 | 5 | exports.isString = function isString(arg) { 6 | return toString.call(arg) === '[object String]'; 7 | }; 8 | 9 | exports.isObject = function isObject(arg) { 10 | return toString.call(arg) === '[object Object]'; 11 | }; 12 | 13 | exports.isFunction = function isFunction(arg) { 14 | return toString.call(arg) === '[object Function]'; 15 | }; 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rename", 3 | "version": "1.0.4", 4 | "description": "Rename files using some transformers.", 5 | "main": "index", 6 | "dependencies": { 7 | "debug": "^2.5.2" 8 | }, 9 | "devDependencies": { 10 | "autod": "^2.7.1", 11 | "egg-bin": "^1.9.1", 12 | "egg-ci": "^1.1.0", 13 | "eslint": "^3.12.2", 14 | "eslint-config-egg": "^3.2.0", 15 | "should": "^11.1.2" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/popomore/rename" 20 | }, 21 | "homepage": "https://github.com/popomore/rename", 22 | "author": "popomore ", 23 | "license": "MIT", 24 | "keywards": [ 25 | "rename", 26 | "file", 27 | "path", 28 | "transform" 29 | ], 30 | "scripts": { 31 | "lint": "eslint index.js lib test", 32 | "test": "npm run lint && egg-bin test", 33 | "ci": "npm run lint && egg-bin cov", 34 | "cov": "egg-bin cov", 35 | "autod": "autod" 36 | }, 37 | "ci": { 38 | "version": "4, 6, 7" 39 | }, 40 | "files": [ 41 | "index.js", 42 | "lib" 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /test/index.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('should'); 4 | var rename = require('..'); 5 | 6 | describe('rename', function() { 7 | 8 | it('string', function() { 9 | rename('a.js', 'b.js').should.eql('b.js'); 10 | rename('a.js', '').should.eql('a.js'); 11 | rename('a.js').should.eql('a.js'); 12 | rename('a.js', null).should.eql('a.js'); 13 | rename('a.js', undefined).should.eql('a.js'); 14 | rename({ 15 | basename: 'a', 16 | extname: '.js', 17 | }, '').should.eql('a.js'); 18 | }); 19 | 20 | it('function', function() { 21 | function transformer(fileObj) { 22 | var result = { 23 | extname: '.css', 24 | }; 25 | if (fileObj.basename === 'd') { 26 | result.dirname = fileObj.dirname + '/d'; 27 | } 28 | result.suffix = fileObj.hash || '-debug'; 29 | return result; 30 | } 31 | 32 | rename('a/b/c.js', transformer).should.eql('a/b/c-debug.css'); 33 | rename('./a/b/d.js', transformer).should.eql('a/b/d/d-debug.css'); 34 | rename({ 35 | dirname: 'a/b', 36 | basename: 'c', 37 | extname: '.js', 38 | hash: '-abc', 39 | }, transformer).should.eql('a/b/c-abc.css'); 40 | 41 | rename('a.js', function() { 42 | return 'b.js'; 43 | }).should.eql('b.js'); 44 | }); 45 | 46 | it('object', function() { 47 | rename('a/b/c.js', { 48 | dirname: 'd/e', 49 | prefix: 'pre-', 50 | suffix: '-debug', 51 | extname: '.css', 52 | basename: 'f', 53 | }).should.eql('d/e/pre-f-debug.css'); 54 | 55 | rename('./a/b/c.js', { 56 | prefix: 'pre-', 57 | suffix: '-debug', 58 | extname: '.css', 59 | basename: 'f', 60 | }).should.eql('a/b/pre-f-debug.css'); 61 | 62 | rename('../a/b/c.js', { 63 | prefix: 'pre-', 64 | suffix: '-debug', 65 | extname: '.css', 66 | basename: 'f', 67 | }).should.eql('../a/b/pre-f-debug.css'); 68 | 69 | rename('./c.js', { 70 | prefix: 'pre-', 71 | suffix: '-debug', 72 | extname: '.css', 73 | basename: 'f', 74 | }).should.eql('pre-f-debug.css'); 75 | 76 | rename('../c.js', { 77 | prefix: 'pre-', 78 | suffix: '-debug', 79 | extname: '.css', 80 | basename: 'f', 81 | }).should.eql('../pre-f-debug.css'); 82 | 83 | rename('c.js', { 84 | prefix: 'pre-', 85 | suffix: '-debug', 86 | extname: '.css', 87 | basename: 'f', 88 | }).should.eql('pre-f-debug.css'); 89 | 90 | rename('a/b/c.js', { 91 | dirname: null, 92 | extname: null, 93 | basename: null, 94 | }).should.eql(''); 95 | 96 | rename('a/b/c.js', {}).should.eql('a/b/c.js'); 97 | }); 98 | 99 | it('object more than once', function() { 100 | var transform = { 101 | suffix: '-${hash}', 102 | }; 103 | rename({ hash: '123', basename: 'c' }, transform).should.eql('c-123'); 104 | rename({ hash: '456', basename: 'c' }, transform).should.eql('c-456'); 105 | }); 106 | 107 | it('template', function() { 108 | rename({ 109 | basename: 'c', 110 | extname: '.js', 111 | hash: '111', 112 | }, { 113 | suffix: '-${hash}', 114 | }).should.eql('c-111.js'); 115 | 116 | rename({ 117 | basename: 'c', 118 | extname: '.js', 119 | hash: '111', 120 | }, function() { 121 | return { 122 | suffix: '-${hash}', 123 | }; 124 | }).should.eql('c-111.js'); 125 | 126 | rename({ 127 | basename: 'c', 128 | extname: '.js', 129 | hash: '111', 130 | }, function() { 131 | return { 132 | suffix: '-${noexist}', 133 | }; 134 | }).should.eql('c-.js'); 135 | }); 136 | 137 | it('error', function() { 138 | shouldThrow([]); 139 | shouldThrow(true); 140 | }); 141 | }); 142 | 143 | function shouldThrow(opt) { 144 | (function() { 145 | rename('a.js', opt); 146 | }).should.throw('transformer should be string, function or object.'); 147 | } 148 | -------------------------------------------------------------------------------- /test/parse.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('should'); 4 | var parse = require('../lib/parse'); 5 | 6 | describe('rename.parse', function() { 7 | 8 | it('should parse string or object', function() { 9 | parse(''); 10 | parse({}); 11 | 12 | shouldThrow(); 13 | shouldThrow(null); 14 | shouldThrow(undefined); 15 | shouldThrow([]); 16 | shouldThrow(/reg/); 17 | 18 | function shouldThrow(obj) { 19 | (function() { 20 | parse(obj); 21 | }).should.throw('Argument should be string or object.'); 22 | } 23 | }); 24 | 25 | describe('string', function() { 26 | 27 | it('should parse normal filepath', function() { 28 | parse('/home/admin/file.js').should.eql({ 29 | dirname: '/home/admin', 30 | basename: 'file', 31 | extname: '.js', 32 | origin: '/home/admin/file.js', 33 | }); 34 | }); 35 | 36 | it('should parse filepath without extname', function() { 37 | parse('/home/admin/file').should.eql({ 38 | dirname: '/home/admin', 39 | basename: 'file', 40 | extname: '', 41 | origin: '/home/admin/file', 42 | }); 43 | }); 44 | 45 | it('should parse relative filepath', function() { 46 | parse('./file').should.eql({ 47 | dirname: '.', 48 | basename: 'file', 49 | extname: '', 50 | origin: './file', 51 | }); 52 | parse('../file').should.eql({ 53 | dirname: '..', 54 | basename: 'file', 55 | extname: '', 56 | origin: '../file', 57 | }); 58 | parse('../dir/file').should.eql({ 59 | dirname: '../dir', 60 | basename: 'file', 61 | extname: '', 62 | origin: '../dir/file', 63 | }); 64 | parse('file').should.eql({ 65 | dirname: '.', 66 | basename: 'file', 67 | extname: '', 68 | origin: 'file', 69 | }); 70 | }); 71 | }); 72 | 73 | describe('object', function() { 74 | 75 | it('should parse empty', function() { 76 | parse({}).should.eql({ 77 | dirname: '', 78 | basename: '', 79 | extname: '', 80 | origin: '', 81 | }); 82 | }); 83 | 84 | it('should return the origin object', function() { 85 | var orig = { 86 | dirname: '/home/admin', 87 | basename: 'file', 88 | extname: '.js', 89 | origin: '/home/admin/file.js', 90 | }; 91 | parse(orig).should.equal(orig); 92 | }); 93 | 94 | it('should pass custom property', function() { 95 | parse({ hash: '123456' }).should.eql({ 96 | dirname: '', 97 | basename: '', 98 | extname: '', 99 | origin: '', 100 | hash: '123456', 101 | }); 102 | }); 103 | }); 104 | }); 105 | -------------------------------------------------------------------------------- /test/stringify.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('should'); 4 | var stringify = require('../lib/stringify'); 5 | 6 | describe('rename.stringify', function() { 7 | 8 | it('should stringify object', function() { 9 | stringify({}); 10 | 11 | shouldThrow(); 12 | shouldThrow(''); 13 | shouldThrow(null); 14 | shouldThrow(undefined); 15 | shouldThrow([]); 16 | shouldThrow(/reg/); 17 | 18 | function shouldThrow(obj) { 19 | (function() { 20 | stringify(obj); 21 | }).should.throw('Argument should be object.'); 22 | } 23 | }); 24 | 25 | it('should stringify normal filepath', function() { 26 | stringify({ 27 | dirname: '/home/admin', 28 | basename: 'file', 29 | extname: '.js', 30 | }).should.eql('/home/admin/file.js'); 31 | }); 32 | 33 | it('should stringify filepath without extname', function() { 34 | stringify({ 35 | dirname: '/home/admin', 36 | basename: 'file', 37 | extname: '', 38 | }).should.eql('/home/admin/file'); 39 | }); 40 | 41 | it('should stringify relative filepath', function() { 42 | stringify({ 43 | dirname: '.', 44 | basename: 'file', 45 | extname: '', 46 | }).should.eql('file'); 47 | stringify({ 48 | dirname: '..', 49 | basename: 'file', 50 | extname: '', 51 | }).should.eql('../file'); 52 | }); 53 | 54 | it('should stringify without dirname', function() { 55 | stringify({ 56 | basename: 'file', 57 | extname: '.js', 58 | }).should.eql('file.js'); 59 | }); 60 | 61 | it('should stringify without extname', function() { 62 | stringify({ 63 | dirname: '/home/admin', 64 | basename: 'file', 65 | }).should.eql('/home/admin/file'); 66 | }); 67 | }); 68 | --------------------------------------------------------------------------------