Skip to content

Commit

Permalink
✨ List wild card notation (#170)
Browse files Browse the repository at this point in the history
* 🚧 Parse list wild card

* ✨ Apply list wildcard notation
  • Loading branch information
nlepage committed Dec 15, 2017
1 parent c1caf7c commit 84ea1dd
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 14 deletions.
17 changes: 10 additions & 7 deletions packages/immutadot/src/path/apply.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import {
getSliceBounds,
pathAlreadyApplied,
} from './utils'

import {
allProps,
index,
list,
prop,
slice,
} from './consts'

import {
getSliceBounds,
pathAlreadyApplied,
} from './utils'

import {
isNil,
length,
Expand Down Expand Up @@ -110,11 +111,13 @@ const apply = operation => {
return [false, newArr]
}

if (propType === list) {
if (propType === list || propType === allProps) {
const newObj = copy(curObj, false)
let noop = true

for (const listProp of propValue) {
const listProps = allProps ? Object.keys(newObj) : propValue

for (const listProp of listProps) {
const [iNoop] = walkPath(newObj, curPath, [[prop, listProp], ...pathRest], true)
noop = noop && iNoop
}
Expand Down
31 changes: 31 additions & 0 deletions packages/immutadot/src/path/apply.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,37 @@ describe('path.apply', () => {
)
})

it('should inc in all props', () => {
immutaTest(
input => {
const output = inc(input, 'nested.{*}.val')
expect(output).toEqual({
nested: {
'prop1': { val: 1 },
'prop2': { val: 6 },
'prop{3}': { val: 6 },
'"prop4"': { val: 4 },
},
other: {},
})
return output
},
{
nested: {
'prop1': { val: 0 },
'prop2': { val: 5 },
'prop{3}': { val: 5 },
'"prop4"': { val: 3 },
},
other: {},
},
'nested.prop1.val',
'nested.prop2.val',
'nested.prop{3}.val',
'nested."prop4".val',
)
})

it('should throw an explicit error when en empty path is given as parameter', () => {
expect(() => inc({}, '')).toThrowError('path should not be empty')
})
Expand Down
1 change: 1 addition & 0 deletions packages/immutadot/src/path/consts.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export const allProps = Symbol('allProps')
export const index = Symbol('index')
export const list = Symbol('list')
export const prop = Symbol('prop')
Expand Down
21 changes: 14 additions & 7 deletions packages/immutadot/src/path/toPath.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import {
filter,
map,
race,
regexp,
} from './parser.utils'

import {
allProps,
index,
list,
prop,
slice,
} from './consts'

import {
filter,
map,
race,
regexp,
} from './parser.utils'

import {
isIndex,
isSliceIndex,
Expand Down Expand Up @@ -109,6 +110,11 @@ const sliceNotationParser = map(
([sliceStart, sliceEnd, rest]) => [[slice, [toSliceIndex(sliceStart, 0), toSliceIndex(sliceEnd)]], ...stringToPath(rest)],
)

const listWildCardParser = map(
regexp(/^{\*}\.?(.*)$/),
([rest]) => [[allProps], ...stringToPath(rest)],
)

const listPropRegexp = /^,?((?!["'])([^,]*)|(["'])(.*?[^\\])\3)(.*)/
function* extractListProps(rawProps) {
if (rawProps.startsWith(',')) yield ''
Expand Down Expand Up @@ -145,6 +151,7 @@ const applyParsers = race([
sliceNotationParser,
bareBracketNotationParser,
incompleteBareBracketNotationParser,
listWildCardParser,
listNotationParser,
incompleteListNotationParser,
pathSegmentEndedByNewSegment,
Expand Down
5 changes: 5 additions & 0 deletions packages/immutadot/src/path/toPath.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-env jest */
import {
allProps,
index,
list,
prop,
Expand Down Expand Up @@ -54,6 +55,10 @@ describe('path.toPath', () => {
expect(toPath('{abc,"defg[0]}.foo.{\'bar')).toEqual([[prop, '{abc,"defg'], [index, 0], [prop, '}'], [prop, 'foo'], [prop, '{\'bar']])
})

it('should convert list wildcard notation path', () => {
expect(toPath('{*}')).toEqual([[allProps]])
})

it('should convert mixed path', () => {
expect(toPath('a[0]["b.c"].666[1:].{1a,2b,3c}')).toEqual([[prop, 'a'], [index, 0], [prop, 'b.c'], [prop, '666'], [slice, [1, undefined]], [list, ['1a', '2b', '3c']]])
expect(toPath('a.[0].["b.c"]666[1:2:3]{1a}{"2b",\'3c\'}')).toEqual([[prop, 'a'], [index, 0], [prop, 'b.c'], [prop, '666'], [prop, '1:2:3'], [prop, '1a'], [list, ['2b', '3c']]])
Expand Down

0 comments on commit 84ea1dd

Please sign in to comment.