Skip to content

Commit

Permalink
Add escapePath()
Browse files Browse the repository at this point in the history
Fixes sindresorhus#83

Signed-off-by: Richie Bendall <richiebendall@gmail.com>
  • Loading branch information
Richienb committed Jan 22, 2022
1 parent aa1be1e commit 052d273
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 2 deletions.
23 changes: 23 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,26 @@ console.log(object);
```
*/
export function deleteProperty(object: Record<string, any>, path: string): boolean;

/**
Escape special characters in a path. Useful for sanitizing user input.
@param path The path to sanitize.
@example
```
import {getProperty, escapePath} from 'dot-prop';
const object = {
foo: {
bar: ['👸🏻 You found me Mario!'],
},
'foo.bar[0]' : '🍄 The princess is in another castle!',
};
const escapedPath = escapePath('foo.bar[0]');
console.log(getProperty(object, escapedPath));
//=> '🍄 The princess is in another castle!'
```
*/
export function escapePath(path: string): string;
8 changes: 8 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -281,3 +281,11 @@ export function hasProperty(object, path) {

return true;
}

export function escapePath(path) {
if (typeof path !== 'string') {
throw new TypeError('Expected a string');
}

return path.replace(/[\\.[]/g, '\\$&');
}
17 changes: 16 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ npm install dot-prop
## Usage

```js
import {getProperty, setProperty, hasProperty, deleteProperty} from 'dot-prop';
import {getProperty, setProperty, hasProperty, deleteProperty, escapePath} from 'dot-prop';

// Getter
getProperty({foo: {bar: 'unicorn'}}, 'foo.bar');
Expand Down Expand Up @@ -61,6 +61,17 @@ object.foo.bar = {x: 'y', y: 'x'};
deleteProperty(object, 'foo.bar.x');
console.log(object);
//=> {foo: {bar: {y: 'x'}}}

const object = {
foo: {
bar: ['👸🏻 You found me Mario!'],
},
'foo.bar[0]' : '🍄 The princess is in another castle!',
};
const escapedPath = escapePath('foo.bar[0]');

console.log(getProperty(object, escapedPath));
//=> '🍄 The princess is in another castle!'
```

## API
Expand Down Expand Up @@ -89,6 +100,10 @@ Delete the property at the given path.

Returns a boolean of whether the property existed before being deleted.

### escapePath(path)

Escape special characters in a path. Useful for sanitizing user input.

#### object

Type: `object | array`
Expand Down
16 changes: 15 additions & 1 deletion test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import test from 'ava';
import {getProperty, setProperty, hasProperty, deleteProperty} from './index.js';
import {getProperty, setProperty, hasProperty, deleteProperty, escapePath} from './index.js';

test('getProperty', t => {
const fixture1 = {foo: {bar: 1}};
Expand Down Expand Up @@ -383,6 +383,20 @@ test('hasProperty', t => {
}, 'foo[0].bar.1'));
});

test('escapePath', t => {
t.is(escapePath('foo.bar[0]'), 'foo\\.bar\\[0]');
t.is(escapePath('foo\\.bar[0]'), 'foo\\\\\\.bar\\[0]');
t.is(escapePath('foo\\\\.bar\\\\[0]'), 'foo\\\\\\\\\\.bar\\\\\\\\\\[0]');
t.is(escapePath('foo[0].bar'), 'foo\\[0]\\.bar');
t.is(escapePath('foo.bar[0].baz'), 'foo\\.bar\\[0]\\.baz');
t.is(escapePath('[0].foo'), '\\[0]\\.foo');
t.is(escapePath(''), '');
t.throws(() => escapePath(0), {
instanceOf: TypeError,
message: 'Expected a string',
});
});

test('prevent setting/getting `__proto__`', t => {
setProperty({}, '__proto__.unicorn', '🦄');
t.not({}.unicorn, '🦄'); // eslint-disable-line no-use-extend-native/no-use-extend-native
Expand Down

0 comments on commit 052d273

Please sign in to comment.