Skip to content

Commit

Permalink
use split-string, simplify
Browse files Browse the repository at this point in the history
  • Loading branch information
jonschlinkert committed Jun 21, 2017
1 parent 84adad4 commit 30466a3
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 40 deletions.
58 changes: 23 additions & 35 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,57 +7,45 @@

'use strict';

var toPath = require('to-object-path');
var split = require('split-string');
var extend = require('extend-shallow');
var isPlainObject = require('is-plain-object');
var isObject = require('is-extendable');

module.exports = function(obj, path, val) {
module.exports = function(obj, prop, val) {
if (!isObject(obj)) {
return obj;
}

if (Array.isArray(path)) {
path = toPath(path);
if (Array.isArray(prop)) {
prop = [].concat.apply([], prop).join('.');
}

if (typeof path !== 'string') {
if (typeof prop !== 'string') {
return obj;
}

var segs = path.split('.');
var len = segs.length, i = -1;
var res = obj;
var last;

while (++i < len) {
var key = segs[i];

while (key[key.length - 1] === '\\') {
key = key.slice(0, -1) + '.' + segs[++i];
}

if (i === len - 1) {
last = key;
break;
}

if (!isObject(obj[key])) {
obj[key] = {};
var keys = split(prop, {sep: '.', brackets: true});
var len = keys.length;
var idx = -1;
var current = obj;

while (++idx < len) {
var key = keys[idx];
if (idx !== len - 1) {
if (!isObject(current[key])) {
current[key] = {};
}
current = current[key];
continue;
}
obj = obj[key];
}

if (obj.hasOwnProperty(last) && isObject(obj[last])) {
if (isPlainObject(val)) {
extend(obj[last], val);
if (isPlainObject(current[key]) && isPlainObject(val)) {
current[key] = extend({}, current[key], val);
} else {
obj[last] = val;
current[key] = val;
}

} else {
obj[last] = val;
}
return res;
};

return obj;
};
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@
"dependencies": {
"extend-shallow": "^2.0.1",
"is-extendable": "^0.1.1",
"is-plain-object": "^2.0.1",
"to-object-path": "^0.3.0"
"is-plain-object": "^2.0.3",
"split-string": "^3.0.1"
},
"devDependencies": {
"gulp-format-md": "^0.1.12",
"mocha": "^3.4.1"
"mocha": "^3.4.2"
},
"keywords": [
"get",
Expand Down
45 changes: 43 additions & 2 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ describe('set', function() {
assert.deepEqual(actual, {a: 'a', b: {c: {d: 'eee'}}});
});

it('should work with nested arrays in keys', function() {
var actual = set({a: 'a', b: {c: 'd'}}, [['b'], ['c', 'd']], 'eee');
assert.deepEqual(actual, {a: 'a', b: {c: {d: 'eee'}}});
});

it('should set a deeply nested value.', function() {
var actual = set({a: 'a', b: {c: 'd'}}, 'b.c.d', 'eee');
assert.deepEqual(actual, {a: 'a', b: {c: {d: 'eee'}}});
Expand Down Expand Up @@ -141,13 +146,49 @@ describe('set', function() {
});

describe('escaping', function() {
it('should recognize escaped dots:', function() {
it('should not split inside double quotes:', function() {
var o = {};
set(o, 'a."b.c.d".e', 'c');
assert.equal(o.a['b.c.d'].e, 'c');
});

it('should not split inside single quotes:', function() {
var o = {};
set(o, "a.'b.c.d'.e", 'c');
assert.equal(o.a['b.c.d'].e, 'c');
});

it('should not split inside square brackets:', function() {
var o = {};
set(o, "a.[b.c.d].e", 'c');
assert.equal(o.a['[b.c.d]'].e, 'c');
});

it('should not split inside parens:', function() {
var o = {};
set(o, "a.(b.c.d).e", 'c');
assert.equal(o.a['(b.c.d)'].e, 'c');
});

it('should not split inside angle brackets:', function() {
var o = {};
set(o, "a.<b.c.d>.e", 'c');
assert.equal(o.a['<b.c.d>'].e, 'c');
});

it('should not split inside curly braces:', function() {
var o = {};
set(o, "a.{b.c.d}.e", 'c');
assert.equal(o.a['{b.c.d}'].e, 'c');
});

it('should not split escaped dots:', function() {
var o = {};
set(o, 'a\\.b.c.d.e', 'c');
assert.equal(o['a.b'].c.d.e, 'c');
});

it('should work with multple escaped dots:', function() {
it('should work with multiple escaped dots:', function() {
var obj1 = {};
set(obj1, 'e\\.f\\.g', 1);
assert.equal(obj1['e.f.g'], 1);
Expand Down

0 comments on commit 30466a3

Please sign in to comment.