├── .editorconfig ├── .eslintrc.json ├── .gitattributes ├── .gitignore ├── .travis.yml ├── .verb.md ├── LICENSE ├── README.md ├── gulpfile.js ├── index.js ├── package.json └── test.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | end_of_line = lf 7 | charset = utf-8 8 | indent_size = 2 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | insert_final_newline = false 15 | 16 | [test/**] 17 | trim_trailing_whitespace = false 18 | insert_final_newline = false 19 | 20 | [templates/**] 21 | trim_trailing_whitespace = false 22 | insert_final_newline = false 23 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "ecmaFeatures": { 3 | "modules": true, 4 | "experimentalObjectRestSpread": true 5 | }, 6 | "env": { 7 | "browser": false, 8 | "es6": true, 9 | "node": true, 10 | "mocha": true 11 | }, 12 | "globals": { 13 | "document": false, 14 | "navigator": false, 15 | "window": false 16 | }, 17 | "rules": { 18 | "accessor-pairs": 2, 19 | "arrow-spacing": [ 20 | 2, 21 | { 22 | "before": true, 23 | "after": true 24 | } 25 | ], 26 | "block-spacing": [ 27 | 2, 28 | "always" 29 | ], 30 | "brace-style": [ 31 | 2, 32 | "1tbs", 33 | { 34 | "allowSingleLine": true 35 | } 36 | ], 37 | "comma-dangle": [ 38 | 2, 39 | "never" 40 | ], 41 | "comma-spacing": [ 42 | 2, 43 | { 44 | "before": false, 45 | "after": true 46 | } 47 | ], 48 | "comma-style": [ 49 | 2, 50 | "last" 51 | ], 52 | "constructor-super": 2, 53 | "curly": [ 54 | 2, 55 | "multi-line" 56 | ], 57 | "dot-location": [ 58 | 2, 59 | "property" 60 | ], 61 | "eol-last": 2, 62 | "eqeqeq": [ 63 | 2, 64 | "allow-null" 65 | ], 66 | "generator-star-spacing": [ 67 | 2, 68 | { 69 | "before": true, 70 | "after": true 71 | } 72 | ], 73 | "handle-callback-err": [ 74 | 2, 75 | "^(err|error)$" 76 | ], 77 | "indent": [ 78 | 2, 79 | 2, 80 | { 81 | "SwitchCase": 1 82 | } 83 | ], 84 | "key-spacing": [ 85 | 2, 86 | { 87 | "beforeColon": false, 88 | "afterColon": true 89 | } 90 | ], 91 | "new-cap": [ 92 | 2, 93 | { 94 | "newIsCap": true, 95 | "capIsNew": false 96 | } 97 | ], 98 | "new-parens": 2, 99 | "no-array-constructor": 2, 100 | "no-caller": 2, 101 | "no-class-assign": 2, 102 | "no-cond-assign": 2, 103 | "no-const-assign": 2, 104 | "no-control-regex": 2, 105 | "no-debugger": 2, 106 | "no-delete-var": 2, 107 | "no-dupe-args": 2, 108 | "no-dupe-class-members": 2, 109 | "no-dupe-keys": 2, 110 | "no-duplicate-case": 2, 111 | "no-empty-character-class": 2, 112 | "no-empty-label": 2, 113 | "no-eval": 2, 114 | "no-ex-assign": 2, 115 | "no-extend-native": 2, 116 | "no-extra-bind": 2, 117 | "no-extra-boolean-cast": 2, 118 | "no-extra-parens": [ 119 | 2, 120 | "functions" 121 | ], 122 | "no-fallthrough": 2, 123 | "no-floating-decimal": 2, 124 | "no-func-assign": 2, 125 | "no-implied-eval": 2, 126 | "no-inner-declarations": [ 127 | 2, 128 | "functions" 129 | ], 130 | "no-invalid-regexp": 2, 131 | "no-irregular-whitespace": 2, 132 | "no-iterator": 2, 133 | "no-label-var": 2, 134 | "no-labels": 2, 135 | "no-lone-blocks": 2, 136 | "no-mixed-spaces-and-tabs": 2, 137 | "no-multi-spaces": 2, 138 | "no-multi-str": 2, 139 | "no-multiple-empty-lines": [ 140 | 2, 141 | { 142 | "max": 1 143 | } 144 | ], 145 | "no-native-reassign": 2, 146 | "no-negated-in-lhs": 2, 147 | "no-new": 2, 148 | "no-new-func": 2, 149 | "no-new-object": 2, 150 | "no-new-require": 2, 151 | "no-new-wrappers": 2, 152 | "no-obj-calls": 2, 153 | "no-octal": 2, 154 | "no-octal-escape": 2, 155 | "no-proto": 0, 156 | "no-redeclare": 2, 157 | "no-regex-spaces": 2, 158 | "no-return-assign": 2, 159 | "no-self-compare": 2, 160 | "no-sequences": 2, 161 | "no-shadow-restricted-names": 2, 162 | "no-spaced-func": 2, 163 | "no-sparse-arrays": 2, 164 | "no-this-before-super": 2, 165 | "no-throw-literal": 2, 166 | "no-trailing-spaces": 0, 167 | "no-undef": 2, 168 | "no-undef-init": 2, 169 | "no-unexpected-multiline": 2, 170 | "no-unneeded-ternary": [ 171 | 2, 172 | { 173 | "defaultAssignment": false 174 | } 175 | ], 176 | "no-unreachable": 2, 177 | "no-unused-vars": [ 178 | 2, 179 | { 180 | "vars": "all", 181 | "args": "none" 182 | } 183 | ], 184 | "no-useless-call": 0, 185 | "no-with": 2, 186 | "one-var": [ 187 | 0, 188 | { 189 | "initialized": "never" 190 | } 191 | ], 192 | "operator-linebreak": [ 193 | 0, 194 | "after", 195 | { 196 | "overrides": { 197 | "?": "before", 198 | ":": "before" 199 | } 200 | } 201 | ], 202 | "padded-blocks": [ 203 | 0, 204 | "never" 205 | ], 206 | "quotes": [ 207 | 2, 208 | "single", 209 | "avoid-escape" 210 | ], 211 | "radix": 2, 212 | "semi": [ 213 | 2, 214 | "always" 215 | ], 216 | "semi-spacing": [ 217 | 2, 218 | { 219 | "before": false, 220 | "after": true 221 | } 222 | ], 223 | "space-after-keywords": [ 224 | 2, 225 | "always" 226 | ], 227 | "space-before-blocks": [ 228 | 2, 229 | "always" 230 | ], 231 | "space-before-function-paren": [ 232 | 2, 233 | "never" 234 | ], 235 | "space-before-keywords": [ 236 | 2, 237 | "always" 238 | ], 239 | "space-in-parens": [ 240 | 2, 241 | "never" 242 | ], 243 | "space-infix-ops": 2, 244 | "space-return-throw-case": 2, 245 | "space-unary-ops": [ 246 | 2, 247 | { 248 | "words": true, 249 | "nonwords": false 250 | } 251 | ], 252 | "spaced-comment": [ 253 | 0, 254 | "always", 255 | { 256 | "markers": [ 257 | "global", 258 | "globals", 259 | "eslint", 260 | "eslint-disable", 261 | "*package", 262 | "!", 263 | "," 264 | ] 265 | } 266 | ], 267 | "use-isnan": 2, 268 | "valid-typeof": 2, 269 | "wrap-iife": [ 270 | 2, 271 | "any" 272 | ], 273 | "yoda": [ 274 | 2, 275 | "never" 276 | ] 277 | } 278 | } 279 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Enforce Unix newlines 2 | *.* text eol=lf 3 | *.css text eol=lf 4 | *.html text eol=lf 5 | *.js text eol=lf 6 | *.json text eol=lf 7 | *.less text eol=lf 8 | *.md text eol=lf 9 | *.yml text eol=lf 10 | 11 | *.jpg binary 12 | *.gif binary 13 | *.png binary 14 | *.jpeg binary -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Numerous always-ignore extensions 2 | *.csv 3 | *.dat 4 | *.diff 5 | *.err 6 | *.gz 7 | *.log 8 | *.orig 9 | *.out 10 | *.pid 11 | *.rar 12 | *.rej 13 | *.seed 14 | *.swo 15 | *.swp 16 | *.vi 17 | *.yo-rc.json 18 | *.zip 19 | *~ 20 | .ruby-version 21 | lib-cov 22 | npm-debug.log 23 | 24 | # Always-ignore dirs 25 | /bower_components/ 26 | /coverage/ 27 | /node_modules/ 28 | /temp/ 29 | /tmp/ 30 | /vendor/ 31 | _gh_pages 32 | 33 | # OS or Editor folders 34 | *.esproj 35 | *.komodoproject 36 | .komodotools 37 | *.sublime-* 38 | ._* 39 | .cache 40 | .DS_Store 41 | .idea 42 | .project 43 | .settings 44 | .tmproj 45 | nbproject 46 | Thumbs.db 47 | 48 | # grunt-html-validation 49 | validation-status.json 50 | validation-report.json 51 | 52 | # misc 53 | TODO.md 54 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - "12" 5 | - "10" 6 | - "8" 7 | matrix: 8 | fast_finish: true 9 | -------------------------------------------------------------------------------- /.verb.md: -------------------------------------------------------------------------------- 1 | # {%= name %} {%= badge("fury") %} {%= badge("travis") %} 2 | 3 | > {%= description %} 4 | 5 | ## Install 6 | 7 | {%= include("install-npm", {save: true}) %} 8 | 9 | ## Usage 10 | 11 | ```js 12 | var sortObj = require('{%= name %}'); 13 | ``` 14 | 15 | By default, the keys on an object will be sorted in ascending order: 16 | 17 | ```js 18 | sortObj({a: 1, c: 2, b: 3}); 19 | //=> {a: 1, b: 3, c: 2} 20 | ``` 21 | 22 | The second param can be an object of `options` OR an array of `keys`: 23 | 24 | **object** 25 | 26 | ```js 27 | sortObj({a: 1, c: 2, b: 3}, {keys: ['a', 'b']}); 28 | //=> {a: 1, b: 3} 29 | ``` 30 | 31 | **array** 32 | 33 | ```js 34 | sortObj({a: 1, c: 2, b: 3}, ['a', 'c']); 35 | //=> {a: 1, c: 2} 36 | ``` 37 | 38 | ## Options 39 | 40 | * `keys` {Array} The returned object will contain only the specified keys, in the same order. 41 | * `sort` {Function} Sort function to sort the keys using JavaScript's `.sort()` method. 42 | * `sortOrder` {String} Valid values are `desc` or `asc`, case insensitive. 43 | * `sortBy` {String} Sort function that is passed the entire object, rather than just the keys - as with the `.sort()` method. 44 | 45 | ### options.keys 46 | 47 | Create a new object with only the given keys. 48 | 49 | ```js 50 | var o = {a: 1, c: 2, e: 5, d: 4, b: 3}; 51 | sortObj(o, {keys: ['a', 'b']}); 52 | 53 | //=> {a: 1, b: 3} 54 | ``` 55 | 56 | ### options.sort 57 | 58 | Function to be passed to javascript's `.sort()` method: 59 | 60 | ```js 61 | var o = {a: 1, c: 2, e: 5, d: 4, b: 3}; 62 | var obj = sortObj(o, { 63 | sort: function (a, b) { 64 | return a < b ? -1 : 1; 65 | } 66 | }); 67 | obj; 68 | //=> {a: 1, b: 3, c: 2, d: 4, e: 5} 69 | ``` 70 | 71 | ### options.sortOrder 72 | 73 | Valid values are `desc` or `asc`, case insensitive: 74 | 75 | ```js 76 | var o = {a: 1, c: 2, e: 5, d: 4, b: 3}; 77 | sortObj(o, {sortOrder: 'ASC'}); 78 | //=> {e: 5, d: 4, c: 3, b: 2, a: 1} 79 | ``` 80 | 81 | ### options.sortBy 82 | 83 | Function that returns an array of keys to sort by: 84 | 85 | ```js 86 | var old = {one: 'aa', two: 'bc', three: 'ab'}; 87 | var o = sortObj(old, { 88 | sortBy: function (obj) { 89 | var arr = []; 90 | Object.keys(obj).filter(function(key) { 91 | if (/^a/.test(obj[key])) arr.push(key); 92 | }); 93 | return arr.reverse(); 94 | } 95 | }); 96 | //=> {three: 'ab', one: 'aa'} 97 | ``` 98 | 99 | ## Author 100 | {%= include("author") %} 101 | 102 | ## License 103 | {%= copyright({year: 2014}) %} 104 | {%= license %} 105 | 106 | *** 107 | 108 | {%= include("footer") %} 109 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2016, Brian Woodward. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sort-object [![NPM version](https://img.shields.io/npm/v/sort-object.svg)](https://www.npmjs.com/package/sort-object) [![Build Status](https://img.shields.io/travis/doowb/sort-object.svg)](https://travis-ci.org/doowb/sort-object) 2 | 3 | > Sort the keys in an object. 4 | 5 | ## Install 6 | 7 | Install with [npm](https://www.npmjs.com/): 8 | 9 | ```sh 10 | $ npm i sort-object --save 11 | ``` 12 | 13 | ## Usage 14 | 15 | ```js 16 | var sortObj = require('sort-object'); 17 | ``` 18 | 19 | By default, the keys on an object will be sorted in ascending order: 20 | 21 | ```js 22 | sortObj({a: 1, c: 2, b: 3}); 23 | //=> {a: 1, b: 3, c: 2} 24 | ``` 25 | 26 | The second param can be an object of `options` OR an array of `keys`: 27 | 28 | **object** 29 | 30 | ```js 31 | sortObj({a: 1, c: 2, b: 3}, {keys: ['a', 'b']}); 32 | //=> {a: 1, b: 3} 33 | ``` 34 | 35 | **array** 36 | 37 | ```js 38 | sortObj({a: 1, c: 2, b: 3}, ['a', 'c']); 39 | //=> {a: 1, c: 2} 40 | ``` 41 | 42 | ## Options 43 | 44 | * `keys` {Array} The returned object will contain only the specified keys, in the same order. 45 | * `sort` {Function} Sort function to sort the keys using JavaScript's `.sort()` method. 46 | * `sortOrder` {String} Valid values are `desc` or `asc`, case insensitive. 47 | * `sortBy` {String} Sort function that is passed the entire object, rather than just the keys - as with the `.sort()` method. 48 | 49 | ### options.keys 50 | 51 | Create a new object with only the given keys. 52 | 53 | ```js 54 | var o = {a: 1, c: 2, e: 5, d: 4, b: 3}; 55 | sortObj(o, {keys: ['a', 'b']}); 56 | 57 | //=> {a: 1, b: 3} 58 | ``` 59 | 60 | ### options.sort 61 | 62 | Function to be passed to javascript's `.sort()` method: 63 | 64 | ```js 65 | var o = {a: 1, c: 2, e: 5, d: 4, b: 3}; 66 | var obj = sortObj(o, { 67 | sort: function (a, b) { 68 | return a < b ? -1 : 1; 69 | } 70 | }); 71 | obj; 72 | //=> {a: 1, b: 3, c: 2, d: 4, e: 5} 73 | ``` 74 | 75 | ### options.sortOrder 76 | 77 | Valid values are `desc` or `asc`, case insensitive: 78 | 79 | ```js 80 | var o = {a: 1, c: 2, e: 5, d: 4, b: 3}; 81 | sortObj(o, {sortOrder: 'ASC'}); 82 | //=> {e: 5, d: 4, c: 3, b: 2, a: 1} 83 | ``` 84 | 85 | ### options.sortBy 86 | 87 | Function that returns an array of keys to sort by: 88 | 89 | ```js 90 | var old = {one: 'aa', two: 'bc', three: 'ab'}; 91 | var o = sortObj(old, { 92 | sortBy: function (obj) { 93 | var arr = []; 94 | Object.keys(obj).filter(function(key) { 95 | if (/^a/.test(obj[key])) arr.push(key); 96 | }); 97 | return arr.reverse(); 98 | } 99 | }); 100 | //=> {three: 'ab', one: 'aa'} 101 | ``` 102 | 103 | ## Author 104 | **Brian Woodward** 105 | 106 | + [github/doowb](https://github.com/doowb) 107 | + [twitter/doowb](http://twitter.com/doowb) 108 | 109 | ## License 110 | Copyright © 2014-2016 [Brian Woodward](https://github.com/doowb) 111 | Released under the MIT license. 112 | 113 | *** 114 | 115 | _This file was generated by [verb](https://github.com/verbose/verb) on February 03, 2016._ 116 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'); 4 | var mocha = require('gulp-mocha'); 5 | var istanbul = require('gulp-istanbul'); 6 | var eslint = require('gulp-eslint'); 7 | 8 | gulp.task('coverage', function() { 9 | return gulp.src(['index.js']) 10 | .pipe(istanbul({includeUntested: true})) 11 | .pipe(istanbul.hookRequire()); 12 | }); 13 | 14 | gulp.task('mocha', ['coverage'], function() { 15 | return gulp.src('test.js') 16 | .pipe(mocha()) 17 | .pipe(istanbul.writeReports()); 18 | }); 19 | 20 | gulp.task('eslint', function() { 21 | return gulp.src(['*.js']) 22 | .pipe(eslint()) 23 | .pipe(eslint.format()); 24 | }); 25 | 26 | gulp.task('default', ['mocha', 'eslint']); 27 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * sort-object 3 | * 4 | * Copyright (c) 2014-2015, Brian Woodward. 5 | * Licensed under the MIT License 6 | */ 7 | 8 | 'use strict'; 9 | 10 | var isObject = require('is-extendable'); 11 | var sortDesc = require('sort-desc'); 12 | var bytewise = require('bytewise'); 13 | var union = require('union-value'); 14 | var sortAsc = require('sort-asc'); 15 | var get = require('get-value'); 16 | 17 | var sortFns = {desc: sortDesc, asc: sortAsc}; 18 | 19 | /** 20 | * Expose `sort` 21 | */ 22 | 23 | module.exports = sort; 24 | 25 | function sort(obj, options) { 26 | if (Array.isArray(options)) { 27 | options = { keys: options }; 28 | } 29 | 30 | var opts = options || {}; 31 | var prop = opts.prop; 32 | var getFn = opts.get || function(val) { 33 | if (prop) return get(val, prop); 34 | }; 35 | var fn = opts.sort || sortAsc; 36 | 37 | if (Boolean(opts.sortOrder)) { 38 | fn = sortFns[opts.sortOrder.toLowerCase()]; 39 | } 40 | 41 | var keys = opts.keys || []; 42 | 43 | if (Boolean(opts.sortBy)) { 44 | keys = opts.sortBy(obj); 45 | fn = null; 46 | } 47 | 48 | if (Boolean(opts.keys)) { 49 | if (!opts.sort && !opts.sortOrder && !opts.sortBy) { 50 | fn = null; 51 | } 52 | } 53 | 54 | var tmp = {}; 55 | var sortBy = {}; 56 | 57 | var build = keys.length === 0 ? fromObj : fromKeys; 58 | build(obj, keys, tmp, sortBy, function(val) { 59 | return getFn(val, prop); 60 | }); 61 | 62 | if (fn) { 63 | keys.sort(fn); 64 | } 65 | 66 | var len = keys.length, i = 0, j = 0; 67 | var res = {}, prev; 68 | while (len--) { 69 | var key = keys[i++]; 70 | if (prev !== key) j = 0; 71 | var k = get(sortBy, key)[j++]; 72 | res[k] = tmp[k]; 73 | prev = key; 74 | } 75 | return res; 76 | } 77 | 78 | // build up the sorting information from the `obj` 79 | function fromObj(obj, keys, tmp, sortBy, fn) { 80 | for (var key in obj) { 81 | var val = obj[key]; 82 | var item = isObject(val) ? (fn(val) || key) : key; 83 | item = isObject(item) ? bytewise.encode(JSON.stringify(item)).toString() : item; 84 | union(sortBy, item, [key]); 85 | keys.push(item); 86 | tmp[key] = val; 87 | } 88 | } 89 | 90 | // build up the sorting information from the supplied keys 91 | function fromKeys(obj, keys, tmp, sortBy) { 92 | var len = keys.length, i = 0; 93 | while (len--) { 94 | var key = keys[i++]; 95 | var val = obj[key]; 96 | union(sortBy, key, [key]); 97 | tmp[key] = val; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sort-object", 3 | "description": "Sort the keys in an object.", 4 | "version": "3.0.3", 5 | "homepage": "https://github.com/doowb/sort-object", 6 | "author": "Brian Woodward (https://github.com/doowb)", 7 | "maintainers": [ 8 | "Jon Schlinkert (https://github.com/jonschlinkert)" 9 | ], 10 | "repository": "doowb/sort-object", 11 | "bugs": { 12 | "url": "https://github.com/doowb/sort-object/issues" 13 | }, 14 | "license": "MIT", 15 | "files": [ 16 | "index.js" 17 | ], 18 | "main": "index.js", 19 | "engines": { 20 | "node": ">=8.0.0" 21 | }, 22 | "scripts": { 23 | "test": "mocha" 24 | }, 25 | "dependencies": { 26 | "bytewise": "^1.1.0", 27 | "get-value": "^2.0.2", 28 | "is-extendable": "^0.1.1", 29 | "sort-asc": "^0.2.0", 30 | "sort-desc": "^0.2.0", 31 | "union-value": "^2.0.1" 32 | }, 33 | "devDependencies": { 34 | "gulp": "^3.9.0", 35 | "gulp-eslint": "^1.1.1", 36 | "gulp-istanbul": "^0.10.3", 37 | "gulp-mocha": "^2.2.0", 38 | "mocha": "^3.5.3", 39 | "should": "^13.1.3" 40 | }, 41 | "keywords": [ 42 | "arr", 43 | "array", 44 | "function", 45 | "js", 46 | "key", 47 | "keys", 48 | "obj", 49 | "object", 50 | "order", 51 | "re", 52 | "re-order", 53 | "sort", 54 | "util", 55 | "utils" 56 | ], 57 | "verb": { 58 | "related": { 59 | "list": [] 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * sort-object 3 | * 4 | * Copyright (c) 2014-2015, Brian Woodward. 5 | * Licensed under the MIT License 6 | */ 7 | 8 | 'use strict'; 9 | 10 | require('should'); 11 | var sortAsc = require('sort-asc'); 12 | var sortDesc = require('sort-desc'); 13 | var sortObj = require('./'); 14 | 15 | var makeCollection = function(postFix) { 16 | postFix = postFix || ''; 17 | var collection = {}; 18 | collection['one' + postFix] = { data: { date: '2015-JUN-30' } }; 19 | collection['two' + postFix] = { data: { date: '2015-JUN-30' } }; 20 | collection['three' + postFix] = { data: { date: '2015-JUN-30' } }; 21 | collection['four' + postFix] = { data: { date: '2015-JUN-21' } }; 22 | collection['five' + postFix] = { data: { date: '2015-JUN-21' } }; 23 | collection['six' + postFix] = { data: { date: '2015-JUN-21' } }; 24 | collection['seven' + postFix] = { data: { date: '2015-JUN-29' } }; 25 | collection['eight' + postFix] = { data: { date: '2015-JUN-29' } }; 26 | collection['nine' + postFix] = { data: { date: '2015-JUN-29' } }; 27 | collection['ten' + postFix] = { data: { date: '2015-JUN-29' } }; 28 | return collection; 29 | }; 30 | 31 | describe('sort object', function() { 32 | it('should create a new object with only the given keys.', function() { 33 | var o = {a: 1, c: 2, b: 3}; 34 | var actual = sortObj(o, {keys: ['a', 'b']}); 35 | 36 | Object.keys(actual)[0].should.equal('a'); 37 | Object.keys(actual)[1].should.equal('b'); 38 | actual.should.not.have.property('c'); 39 | }); 40 | 41 | it('should sort the keys on an object with alphabetical keys', function() { 42 | var o = {a: 1, c: 2, b: 3}; 43 | var actual = sortObj(o); 44 | 45 | Object.keys(actual)[0].should.equal('a'); 46 | Object.keys(actual)[1].should.equal('b'); 47 | Object.keys(actual)[2].should.equal('c'); 48 | }); 49 | 50 | it('should sort the keys on an object with numerical keys', function() { 51 | var o = {1: 1, 3: 3, 2: 2}; 52 | var actual = sortObj(o); 53 | 54 | Object.keys(actual)[0].should.equal('1'); 55 | Object.keys(actual)[1].should.equal('2'); 56 | Object.keys(actual)[2].should.equal('3'); 57 | }); 58 | 59 | it('should sort the keys on an object in descending order.', function() { 60 | var o = {a: 1, c: 2, b: 3}; 61 | var actual = sortObj(o, {sortOrder: 'desc'}); 62 | 63 | Object.keys(actual)[0].should.equal('c'); 64 | Object.keys(actual)[1].should.equal('b'); 65 | Object.keys(actual)[2].should.equal('a'); 66 | }); 67 | 68 | it('should sort the keys on an object in ascending order.', function() { 69 | var o = {a: 1, c: 2, b: 3}; 70 | var actual = sortObj(o, {sortOrder: 'asc'}); 71 | 72 | Object.keys(actual)[0].should.equal('a'); 73 | Object.keys(actual)[1].should.equal('b'); 74 | Object.keys(actual)[2].should.equal('c'); 75 | }); 76 | 77 | it('should sort the keys using a custom function.', function() { 78 | var o = {a: 1, c: 2, e: 5, d: 4, b: 3}; 79 | var actual = sortObj(o, { 80 | sort: function(a, b) { 81 | return a < b ? -1 : 1; 82 | } 83 | }); 84 | actual.should.eql({a: 1, b: 3, c: 2, d: 4, e: 5}); 85 | 86 | Object.keys(actual)[0].should.equal('a'); 87 | Object.keys(actual)[1].should.equal('b'); 88 | Object.keys(actual)[2].should.equal('c'); 89 | }); 90 | 91 | it('should sort keys to the order in the given array.', function() { 92 | var o = sortObj({a: 'a', b: 'b', c: 'c'}, ['c', 'a', 'b']); 93 | 94 | Object.keys(o)[0].should.equal('c'); 95 | Object.keys(o)[1].should.equal('a'); 96 | Object.keys(o)[2].should.equal('b'); 97 | }); 98 | 99 | it('should use a function to sort keys in the given array.', function() { 100 | var o = sortObj({a: 'a', b: 'b', c: 'c'}, { 101 | keys: ['c', 'a'], 102 | sort: sortDesc 103 | }); 104 | 105 | Object.keys(o)[0].should.equal('c'); 106 | Object.keys(o)[1].should.equal('a'); 107 | o.should.not.have.property('b'); 108 | }); 109 | 110 | it('should use a function to sort keys in the given array.', function() { 111 | var o = sortObj({a: 'a', b: 'b', c: 'c'}, { 112 | keys: ['b', 'a'], 113 | sort: sortAsc 114 | }); 115 | 116 | Object.keys(o)[0].should.equal('a'); 117 | Object.keys(o)[1].should.equal('b'); 118 | o.should.not.have.property('c'); 119 | }); 120 | 121 | it('should use a `sortBy` function to return an array of keys to sort by.', function() { 122 | var old = {one: 'aa', two: 'bc', three: 'ab'}; 123 | var o = sortObj(old, { 124 | sortBy: function(obj) { 125 | var arr = []; 126 | Object.keys(obj).filter(function(key) { 127 | if (/^a/.test(obj[key])) { 128 | arr.push(key); 129 | } 130 | }); 131 | return arr.reverse(); 132 | } 133 | }); 134 | 135 | Object.keys(o).length.should.equal(2); 136 | Object.keys(o)[0].should.equal('three'); 137 | Object.keys(o)[1].should.equal('one'); 138 | }); 139 | 140 | it('should sort the keys of a complex obj', function() { 141 | var collection = makeCollection(); 142 | var actual = sortObj(collection); 143 | Object.keys(actual)[0].should.equal('eight'); 144 | Object.keys(actual)[1].should.equal('five'); 145 | Object.keys(actual)[2].should.equal('four'); 146 | Object.keys(actual)[3].should.equal('nine'); 147 | Object.keys(actual)[4].should.equal('one'); 148 | Object.keys(actual)[5].should.equal('seven'); 149 | Object.keys(actual)[6].should.equal('six'); 150 | Object.keys(actual)[7].should.equal('ten'); 151 | Object.keys(actual)[8].should.equal('three'); 152 | Object.keys(actual)[9].should.equal('two'); 153 | }); 154 | 155 | it('should sort the keys of a complex obj with keys containing `.`', function() { 156 | var collection = makeCollection('.md'); 157 | var actual = sortObj(collection); 158 | Object.keys(actual)[0].should.equal('eight.md'); 159 | Object.keys(actual)[1].should.equal('five.md'); 160 | Object.keys(actual)[2].should.equal('four.md'); 161 | Object.keys(actual)[3].should.equal('nine.md'); 162 | Object.keys(actual)[4].should.equal('one.md'); 163 | Object.keys(actual)[5].should.equal('seven.md'); 164 | Object.keys(actual)[6].should.equal('six.md'); 165 | Object.keys(actual)[7].should.equal('ten.md'); 166 | Object.keys(actual)[8].should.equal('three.md'); 167 | Object.keys(actual)[9].should.equal('two.md'); 168 | }); 169 | 170 | it('should use a `prop` string to sort on value properties.', function() { 171 | var collection = makeCollection(); 172 | var actual = sortObj(collection, { prop: 'data.date' }); 173 | Object.keys(actual)[0].should.equal('four'); 174 | Object.keys(actual)[1].should.equal('five'); 175 | Object.keys(actual)[2].should.equal('six'); 176 | Object.keys(actual)[3].should.equal('seven'); 177 | Object.keys(actual)[4].should.equal('eight'); 178 | Object.keys(actual)[5].should.equal('nine'); 179 | Object.keys(actual)[6].should.equal('ten'); 180 | Object.keys(actual)[7].should.equal('one'); 181 | Object.keys(actual)[8].should.equal('two'); 182 | Object.keys(actual)[9].should.equal('three'); 183 | }); 184 | 185 | it('should use a `prop` string to sort on value properties with keys containing `.`', function() { 186 | var collection = makeCollection('.md'); 187 | var actual = sortObj(collection, { prop: 'data.date' }); 188 | Object.keys(actual)[0].should.equal('four.md'); 189 | Object.keys(actual)[1].should.equal('five.md'); 190 | Object.keys(actual)[2].should.equal('six.md'); 191 | Object.keys(actual)[3].should.equal('seven.md'); 192 | Object.keys(actual)[4].should.equal('eight.md'); 193 | Object.keys(actual)[5].should.equal('nine.md'); 194 | Object.keys(actual)[6].should.equal('ten.md'); 195 | Object.keys(actual)[7].should.equal('one.md'); 196 | Object.keys(actual)[8].should.equal('two.md'); 197 | Object.keys(actual)[9].should.equal('three.md'); 198 | }); 199 | 200 | it('should use a `prop` string to sort on value properties in descending order.', function() { 201 | var collection = makeCollection(); 202 | var actual = sortObj(collection, { prop: 'data.date', sortOrder: 'desc' }); 203 | Object.keys(actual)[0].should.equal('one'); 204 | Object.keys(actual)[1].should.equal('two'); 205 | Object.keys(actual)[2].should.equal('three'); 206 | Object.keys(actual)[3].should.equal('seven'); 207 | Object.keys(actual)[4].should.equal('eight'); 208 | Object.keys(actual)[5].should.equal('nine'); 209 | Object.keys(actual)[6].should.equal('ten'); 210 | Object.keys(actual)[7].should.equal('four'); 211 | Object.keys(actual)[8].should.equal('five'); 212 | Object.keys(actual)[9].should.equal('six'); 213 | }); 214 | 215 | it('should use a `prop` string to sort on value properties in ascending order.', function() { 216 | var collection = makeCollection(); 217 | var actual = sortObj(collection, { prop: 'data.date', sortOrder: 'asc' }); 218 | Object.keys(actual)[0].should.equal('four'); 219 | Object.keys(actual)[1].should.equal('five'); 220 | Object.keys(actual)[2].should.equal('six'); 221 | Object.keys(actual)[3].should.equal('seven'); 222 | Object.keys(actual)[4].should.equal('eight'); 223 | Object.keys(actual)[5].should.equal('nine'); 224 | Object.keys(actual)[6].should.equal('ten'); 225 | Object.keys(actual)[7].should.equal('one'); 226 | Object.keys(actual)[8].should.equal('two'); 227 | Object.keys(actual)[9].should.equal('three'); 228 | }); 229 | 230 | it('should use a `prop` string to sort on object values by index.', function() { 231 | var collection = makeCollection(); 232 | Object.keys(collection).forEach(function(key, i) { 233 | collection[key].data.complex = { 234 | index: i, 235 | key: key 236 | }; 237 | }); 238 | var actual = sortObj(collection, { prop: 'data.complex' }); 239 | Object.keys(actual)[0].should.equal('one'); 240 | Object.keys(actual)[1].should.equal('two'); 241 | Object.keys(actual)[2].should.equal('three'); 242 | Object.keys(actual)[3].should.equal('four'); 243 | Object.keys(actual)[4].should.equal('five'); 244 | Object.keys(actual)[5].should.equal('six'); 245 | Object.keys(actual)[6].should.equal('seven'); 246 | Object.keys(actual)[7].should.equal('eight'); 247 | Object.keys(actual)[8].should.equal('nine'); 248 | Object.keys(actual)[9].should.equal('ten'); 249 | }); 250 | 251 | it('should use a `prop` string to sort on object values by index in descending order.', function() { 252 | var collection = makeCollection(); 253 | Object.keys(collection).forEach(function(key, i) { 254 | collection[key].data.complex = { 255 | index: i, 256 | key: key 257 | }; 258 | }); 259 | var actual = sortObj(collection, { prop: 'data.complex', sortOrder: 'desc' }); 260 | Object.keys(actual)[0].should.equal('ten'); 261 | Object.keys(actual)[1].should.equal('nine'); 262 | Object.keys(actual)[2].should.equal('eight'); 263 | Object.keys(actual)[3].should.equal('seven'); 264 | Object.keys(actual)[4].should.equal('six'); 265 | Object.keys(actual)[5].should.equal('five'); 266 | Object.keys(actual)[6].should.equal('four'); 267 | Object.keys(actual)[7].should.equal('three'); 268 | Object.keys(actual)[8].should.equal('two'); 269 | Object.keys(actual)[9].should.equal('one'); 270 | }); 271 | 272 | it('should use a `prop` string to sort on object values by key.', function() { 273 | var collection = makeCollection(); 274 | Object.keys(collection).forEach(function(key, i) { 275 | collection[key].data.complex = { 276 | key: key, 277 | index: i 278 | }; 279 | }); 280 | var actual = sortObj(collection, { prop: 'data.complex' }); 281 | Object.keys(actual)[0].should.equal('eight'); 282 | Object.keys(actual)[1].should.equal('five'); 283 | Object.keys(actual)[2].should.equal('four'); 284 | Object.keys(actual)[3].should.equal('nine'); 285 | Object.keys(actual)[4].should.equal('one'); 286 | Object.keys(actual)[5].should.equal('seven'); 287 | Object.keys(actual)[6].should.equal('six'); 288 | Object.keys(actual)[7].should.equal('ten'); 289 | Object.keys(actual)[8].should.equal('three'); 290 | Object.keys(actual)[9].should.equal('two'); 291 | }); 292 | 293 | it('should use a `prop` string to sort on object values by key in descending order.', function() { 294 | var collection = makeCollection(); 295 | Object.keys(collection).forEach(function(key, i) { 296 | collection[key].data.complex = { 297 | key: key, 298 | index: i 299 | }; 300 | }); 301 | var actual = sortObj(collection, { prop: 'data.complex', sortOrder: 'desc'}); 302 | Object.keys(actual)[0].should.equal('two'); 303 | Object.keys(actual)[1].should.equal('three'); 304 | Object.keys(actual)[2].should.equal('ten'); 305 | Object.keys(actual)[3].should.equal('six'); 306 | Object.keys(actual)[4].should.equal('seven'); 307 | Object.keys(actual)[5].should.equal('one'); 308 | Object.keys(actual)[6].should.equal('nine'); 309 | Object.keys(actual)[7].should.equal('four'); 310 | Object.keys(actual)[8].should.equal('five'); 311 | Object.keys(actual)[9].should.equal('eight'); 312 | }); 313 | }); 314 | --------------------------------------------------------------------------------