From 6cfceb5226c931ee86f7ec799ba96ec08c38f821 Mon Sep 17 00:00:00 2001 From: Alejandro Hernandez Date: Wed, 7 Feb 2024 15:47:22 -0500 Subject: [PATCH] Do not remove zeroes from tree paths --- .changeset/big-plums-wave.md | 5 +++++ src/array.js | 22 +++++++++++++++++++++- src/collection.js | 1 + src/string.js | 2 ++ src/tree.js | 6 +++--- test/tree.spec.js | 6 ++++++ 6 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 .changeset/big-plums-wave.md diff --git a/.changeset/big-plums-wave.md b/.changeset/big-plums-wave.md new file mode 100644 index 00000000..573e3a41 --- /dev/null +++ b/.changeset/big-plums-wave.md @@ -0,0 +1,5 @@ +--- +'futil': patch +--- + +Do not remove zeroes from tree paths diff --git a/src/array.js b/src/array.js index e85e264b..7bea470d 100644 --- a/src/array.js +++ b/src/array.js @@ -18,7 +18,9 @@ let last = _.takeRight(1) * @signature joinString -> [string1, string2, ...stringN] -> string1 + joinString + string2 + joinString ... + stringN * @typescript {(join: string, x: any[]) => string} */ -export let compactJoin = _.curry((join, x) => _.compact(x).join(join)) +export let compactJoin = + // TODO: (major) Do not use `_.compact` as removes the number 0. + _.curry((join, x) => _.compact(x).join(join)) /** * Compacts and joins an array with `.` @@ -171,6 +173,24 @@ export let dotEncoder = encoder('.') */ export let slashEncoder = encoder('/') +// The name "pack" is tentative. It's intended to behave as `_.compact` without +// removing the number 0. +let pack = _.remove( + (x) => x === undefined || x === null || x === false || x === '' +) + +// Internal use until we release next major +let __internalEncoder = (separator) => ({ + encode: _.flow(pack, _.join(separator)), + decode: _.split(separator), +}) + +// Internal use until we release next major +export let __internalDotEncoder = __internalEncoder('.') + +// Internal use until we release next major +export let __internalSlashEncoder = __internalEncoder('/') + /** * Takes a predicate function and an array, and returns an array of arrays where each element has one or more elements of the original array. Similar to Haskell's [groupBy](http://zvon.org/other/haskell/Outputlist/groupBy_f.html). diff --git a/src/collection.js b/src/collection.js index 5ffb5962..ac6329c3 100644 --- a/src/collection.js +++ b/src/collection.js @@ -59,6 +59,7 @@ export let insertAtIndex = _.curry((index, val, collection) => * @signature (fn, collection) -> collection */ export let compactMap = _.curry((fn, collection) => + // TODO: (major) Do not use `_.compact` as removes the number 0. _.flow(_.map(fn), _.compact)(collection) ) diff --git a/src/string.js b/src/string.js index ad4c02da..50991d4c 100644 --- a/src/string.js +++ b/src/string.js @@ -27,6 +27,8 @@ export const quote = wrap('"', '"') * @signature 'asdf' -> '(asdf)' */ export const parens = wrap('(', ')') + +// TODO: (major) Do not use `_.compact` as removes the number 0. export const concatStrings = _.flow(_.compact, _.map(_.trim), _.join(' ')) /** diff --git a/src/tree.js b/src/tree.js index c1b27295..2498118d 100644 --- a/src/tree.js +++ b/src/tree.js @@ -7,7 +7,7 @@ import _ from 'lodash/fp' import { findIndexed } from './conversion' -import { pushOn, dotEncoder, slashEncoder } from './array' +import { pushOn, __internalDotEncoder, __internalSlashEncoder } from './array' /** * A default check if something can be traversed - currently it is arrays and plain objects. @@ -239,7 +239,7 @@ export let treeValues = (x, i, xs) => [x, ...xs] * @signature (build, encoder) -> treePathBuilderFunction */ export let treePath = - (build = treeKeys, encoder = dotEncoder) => + (build = treeKeys, encoder = __internalDotEncoder) => (...args) => (encoder.encode || encoder)(build(...args).reverse()) @@ -249,7 +249,7 @@ export let treePath = * @signature prop -> treePathBuilderFunction */ export let propTreePath = (prop) => - treePath(_.flow(treeValues, _.map(prop)), slashEncoder) + treePath(_.flow(treeValues, _.map(prop)), __internalSlashEncoder) /** * Creates a flat object with a property for each node, using `buildPath` to determine the keys. `buildPath` takes the same arguments as a tree walking iteratee. It will default to a dot tree path. diff --git a/test/tree.spec.js b/test/tree.spec.js index 8f3660c9..74b60ae8 100644 --- a/test/tree.spec.js +++ b/test/tree.spec.js @@ -22,6 +22,12 @@ describe('Tree Functions', () => { } expect(F.traverse(x)).to.deep.equal(x) }) + describe('treePath', () => { + it('should not remove zeroes', () => { + let path = F.treePath()(null, 'first', [], ['second', 0, 'third']) + expect(path).to.equal('third.0.second.first') + }) + }) describe('walk', () => { let x = { a: 1,