diff --git a/.babelrc b/.babelrc
index f91ebace..7a8bc5a7 100644
--- a/.babelrc
+++ b/.babelrc
@@ -1,8 +1,4 @@
{
- "presets": [
- "env"
- ],
- "plugins": [
- "transform-object-rest-spread"
- ]
+ "presets": ["env"],
+ "plugins": ["transform-object-rest-spread"]
}
diff --git a/.codeclimate.yml b/.codeclimate.yml
index 556c1559..9ac19cfd 100644
--- a/.codeclimate.yml
+++ b/.codeclimate.yml
@@ -11,15 +11,15 @@ engines:
enabled: true
ratings:
paths:
- - "**.inc"
- - "**.js"
- - "**.jsx"
- - "**.module"
- - "**.php"
- - "**.py"
- - "**.rb"
+ - "**.inc"
+ - "**.js"
+ - "**.jsx"
+ - "**.module"
+ - "**.php"
+ - "**.py"
+ - "**.rb"
exclude_paths:
-- "lib/"
-- "tests/"
-- "spec/"
-- "**/vendor/"
+ - "lib/"
+ - "tests/"
+ - "spec/"
+ - "**/vendor/"
diff --git a/.eslintrc.js b/.eslintrc.js
index b8590f9c..145cc3c3 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,7 +1,7 @@
module.exports = {
- extends: 'smartprocure',
- parser: 'babel-eslint',
+ extends: "smartprocure",
+ parser: "babel-eslint",
parserOptions: {
- sourceType: 'module'
- }
+ sourceType: "module",
+ },
}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 654ce3e7..1574c142 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,166 +1,212 @@
# 1.71.3
+
- Library issue resolution, two libraries where auto-updating minor versions and no longer compatible in those versions.
- Added ignore for yarn as NPM is being used currently
- Added versioning of package-lock files to resolve dependency issue.
# 1.71.2
-- Tests:
+
+- Tests:
- Replaced all `eql` with `deep.equal`
- Replaced all unnecessary `deep.equal` assertions with `.equal`
- Replaced `to.equal(true)` and `to.equal(false)` with `to.be.true` and `to.be.false`
# 1.71.1
+
- Organized and added to regexp tests
# 1.71.0
+
- New docs site! The new docs site is packed with awesome features. We've got dark mode, super fast search, embedded runkits, and the ability to search futil, lodash, and ramda based on input/output expectations.
# 1.70.0
+
- Add state to deprecated methods so they can be inspected
# 1.69.9
+
- Removed basic function tests from the misc.spec file. A separate PR moves them into the function.spec file.
# 1.69.8
+
- Organized string tests
# 1.69.7
+
- Organized and added to functions tests
# 1.69.6
+
- Organized and added to logic tests
# 1.69.5
+
- Organized and added lang tests
# 1.69.4
+
- Organized and added to conversions tests
# 1.69.3
+
- Moves tests from algebra file to collections file to mirror functions file system
# 1.69.2
+
- Adds and revised the array tests
# 1.69.1
+
- Fixed f and F discrepancy. Changed all f. to F. in all tests for consistency.
# 1.69.0
+
- Add `isPromise` utility
# 1.68.0
+
- Add `mapTree`, `mapTreeLeaves`, `leavesBy`
- Improve `leaves` performance (by not adding branches at all instead of rejecting them later)
- Passes all props to `treeToArrayBy` iteratees - previously only `node` was passed
# 1.67.3
+
- Fixed `import` syntax in docs
# 1.67.2
+
- change fixed issue, Logic functions behave unpredictably with `undefined` as predicate
-- add test cases to logic.spec for when.
+- add test cases to logic.spec for when.
- drop IE 10 support
# 1.67.1
+
- Fix `isBlank` docs
# 1.67.0
+
- Improvements to `unwind`: use `_.castArray` to avoid unwinding strings and other array-likes
- Add `unwindArray`
# 1.66.3
+
- Use deep comparison on F.{simple,}diff
# 1.66.2
+
- Allow `walkAsync` to handle non-async traversals
# 1.66.1
+
- Kill promises in `findIndexedAsync` to fix regeneratorRuntime shenanigans
# 1.66.0
+
- Add `walkAsync`
- Add `findIndexedAsync` (used internally and not documented, but exported for testing)
- Add `mapArgs`
- Add `commonKeys` and `firstCommonKey`
# 1.65.0
+
- Add support for regular expression arguments to `highlight`
- Clarify `highlight` description in README
- Add description for `postingsForWords` to README
# 1.64.4
+
- Change `domLens.hover` to use `onMouseEnter`/`onMouseLeave` instead of `onMouseOver`/`onMouseOut`
# 1.64.3
+
- Fix typo in README
# 1.64.2
+
- Handle `[]`, `undefined`, and `null` arguments in `chunkBy`
# 1.64.1
+
- Use `_.hasIn` in `targetBinding` to account for objects with `target` as an inherited property (eg, in synthetic DOM events)
# 1.64.0
+
- Add new native lens formats, `arrayLens` and `functionPairLens`
- Make `domLens.value` more flexible by supporting non-native onChange events (allow `targetBinding` to fall back to the provided value if `e.target[key]` is not passed in)
- Update a bunch of dev dependencies
# 1.63.1
+
- Clarify `chunkBy` description in README
# 1.63.0
+
- Add partial currying support to `mergeOverAll`
- Add `mergeOverAllWith` and `mergeOverAllArrays`
# 1.62.1
+
- Better currying for `logic` methods (`ifElse`, `when`, `whenExists`, etc)
# 1.62.0
+
- Add `getWith`, `expandObject`, and `expandObjectBy`
# 1.61.0
+
- Add `compactMap`
# 1.60.0
+
- Add `mergeOverAll`
# 1.59.1
+
- change all words regex to report full string as match rather than empty string
# 1.59.0
+
- export `anyWordToRegexp` and `wordsToRegexp`
# 1.58.1
+
- Fixed issue where `renameProperty` was not a pure function. Specifically:
- 1. The original object was mutated.
- 2. If the original object din't have the property to be renamed the function was
+
+1. The original object was mutated.
+2. If the original object din't have the property to be renamed the function was
adding the property with a value of `undefined`.
- 3. If code was relying in this incorrect behavior this will be a braking change.
+3. If code was relying in this incorrect behavior this will be a braking change.
# 1.58.0
+
- Add `uniqueString` and `uniqueStringWith`
# 1.57.0
+
- Added new `object` functions:
- `omitNil`
- `omitNull`
- `omitBlank`
- `omitEmpty`
+ `omitNil`
+ `omitNull`
+ `omitBlank`
+ `omitEmpty`
- Added new `array` functions:
- `replaceElementBy`
- `replaceElement`
+ `replaceElementBy`
+ `replaceElement`
# 1.56.0
+
- New lens helper for React users: `stateLens`
# 1.55.1
+
- Fix issue with autoLabelOption not accepting correctly falsy values as valid options
# 1.55.0
+
- Added intersperse, differentLast, toSentence and toSentenceWith.
# 1.54.0
-- Add `domLens` functions:
+
+- Add `domLens` functions:
`domLens.value`
`domLens.checkboxValues`
`domLens.hover`
@@ -169,6 +215,7 @@
`domLens.binding`
# 1.53.0
+
- Add `moveIndex`
- Add `toggleElement`
- Add `toggleElementBy`
@@ -177,190 +224,243 @@
- Make `insertAtIndex` support arrays and strings
# 1.52.0
+
- Add a default export with all methods to support `import F` instead of `import * as F`
- Also publish as `futil`!
# 1.51.0
+
- Added `_.iteratee` support to `findApply`
# 1.50.0
+
- Added `chunkBy`.
# 1.49.1
+
- Upgraded several dependencies.
# 1.49.0
+
- Fixed a webpack global variable issue.
# 1.48.0
+
- Added `stampKey`
# 1.47.1
+
- Added Runkit examples
# 1.47.0
+
- Added VERSION property to the library's API
# 1.46.0
- - Deprecated `mapProps` in favor of lodash _.update
+
+- Deprecated `mapProps` in favor of lodash \_.update
# 1.45.0
+
- Added `updateOn`
# 1.44.0
+
- Added `matchesSome`
# 1.43.4
+
- Fixed issue with `postings` when a regex lacking the `g` flag is passed
- improvements to README.md
# 1.43.3
+
Fixed webpack.config.js
# 1.43.2 (UNPUBLISHED because it breaks in NodeJS)
+
Upgraded some dependencies.
# 1.43.1
+
Fixed the conversion reference for pickBy.
# 1.43.0
+
Added pickByIndexed, and improved our conversion file performance by a
significant ammount.
# 1.42.3
+
Made tree lookup curried.
# 1.42.2
+
Remove Standard JS badge in favor of [Prettier](https://prettier.io).
# 1.42.1
+
Enable coveralls integration.
# 1.42.0
+
- Add `flurry`, a flow + curry preserving the arity of the initial function. See https://github.com/lodash/lodash/issues/3612.
# 1.41.0
+
- Add `pullOn`, `prefixes`
- Add `encoder`, `dotEncoder`, `slashEncoder`
- Add `flattenTree`, `treePath`, `propTreePath`, `treeKeys`, `treeValues`
- Expose `traverse` on `Tree`
# 1.40.3
+
- Updated eslint to version 4.16.0.
# 1.40.2
+
- Updating babel-eslint, eslint, chokidar and mocha.
# 1.40.1
+
- Add docs link
# 1.40.0
+
- [`cascade`, `cascadeIn`] added support for an optional defaultValue (last param) and iteratee support instead of just paths
# 1.39.0
+
- Add `transformTree`
- Add `keyTreeByWith`
# 1.38.0
+
- Add `allMatches`. It creates regexp and returns all matched results with
indexes.
# 1.37.0
+
- Added implicit `lensProp` support to all current lens functions (`view`,
`views`, `set`, `sets`, `flip`, `on`, `off`)
# 1.36.0
+
- Add `mergeAllArrays`, `invertByArray`, `zipObjectDeepWith`, and `flags`
# 1.35.0
+
- Add tree `treeLookup`
- Add deep path support to `lensProp`
- Add `unsetOn`
# 1.34.1
+
- Ignore browser testing errors.
- Add karma JSON reporter.
- Only watch files and record videos/screenshots for the local test.
# 1.34.0
+
- Fixed flattenObject and diffArray to properly say the paths of
arrays with only one object, by making them use a new function:
`dotJoinWith`, which is like `dotJoin` but allows you to provide a
function to select which elements to filter by.
# 1.33.2
+
- Add cross browsers testing support with `karma + webpack + saucelabs`
- Use babel-preset-latest instead of babel-preset-env
- Fixed unstable tests for mobile Safari browsers.
- Fixed unstable tests for IE9/10/11.
# 1.33.1
+
- Currying the postings and highlighting functions.
# 1.33.0
+
- Add `debounceAsync` and `defer`
# 1.32.1
+
- Add autofixing PRs with [Duti](https://github.com/smartprocure/duti)
# 1.32.0
+
- Added `diff` and `diffArray`, just like `simpleDiff` and
`simpleDiffArray`, but they also take in count removed properties.
# 1.31.0
+
- Add new utility for objects called `pickOn`, which works as `pick` in lodash but it mutates the object
# 1.30.0
+
- Add tree functions `traverse`, `walk`, `reduceTree`, `treeToArray`, `treeToArrayBy`, `leaves`, and `tree`
- Add `isBlank`, `isNotBlank`, and `isBlankDeep`
- Add `findIndexed`
-
# 1.29.9
+
- Added pushOn, like pushIn but it alters the original array.
# 1.29.8
+
- Added pushIn since `_.curry` doesn't allow us to do `F.push(_, array)`.
# 1.29.7
+
- Curried `push`
# 1.29.6
+
- Faster `matchAnyWord`
# 1.29.5
+
- Always run duti in CI
# 1.29.4
+
- Use latest duti version
# 1.29.3
+
- Fix IE 11 erroring when using a deprecated function
# 1.29.2
+
- Add missing stack reference to `deprecate`.
- Fix internal usage of deprecated functions.
- Lint and readme cleanup.
# 1.29.1
+
- 75% faster `matchallwords`.
# 1.29.0 August 11th, 2017 18:53
+
- Add arrayToObject to array.
# 1.28.4 August 10th, 2017 21:35
+
- Fix for diff functions to properly ignore things that didn't change.
# 1.28.3 August 9th, 2017 15:10
+
- Remove old dangerfile.
# 1.28.2 August 8th, 2017 20:50
+
- Use Circle 2.0 configuration.
# 1.28.1
+
- Add Duti to the repo.
# 1.28.0 August 8th, 2017 03:29
+
- Added `Indexed` conversions(`mapIndexed`, `eachIndexed`, `reduceIndexed`, `mapValuesIndexed`)
- Add `aspectSync` and `deprecate`
- Deprecated the uncap conversions that don't follow the naming convention
@@ -368,103 +468,136 @@ Enable coveralls integration.
- Add `simpleDiff` and `simpleDiffArray`
# 1.27.0 August 3rd, 2017 15:58
+
- Added `hasIn`, `cascadeProp` and `cascadePropKey`.
# 1.26.4 - August 2nd, 2017 18:21
+
- Added release dates to change log file. Downgrade danger to version 0.17.0.
# 1.26.3 - August 2nd, 2017 17:54
+
- Update danger to version 0.19.0
# 1.26.2 - August 2nd, 2017 17:54
+
- Update webpack to version 3.0.0
# 1.26.1 - August 2nd, 2017 14:37
+
- Update chai to version 4.1.0
# 1.26.0 - August 2nd, 2017 06:46
+
- Add `autoLabel`, `autoLabelOption`, and `autoLabelOptions`. Also rearranged test files a bit.
# 1.25.1 - August 2nd, 2017 06:26
+
- Fixed issue where concurrency aspect should throw Error using the string constructor. Also fixed failing unit tests.
# 1.25.0 - July 31st, 2017 19:49
+
- Add support for aspect `always`, `name`, and bug fix for processing sample aspect. Also added `tapError` and new high level aspect, `command`
# 1.24.0 - July 28th, 2017 16:07
+
- Added `trimStrings`, and our new shiny logo on the README thanks to @giulianok
# 1.23.0 - July 28th, 2017 05:40
+
- Add `setOn` (mutable set)
# 1.22.0 - July 28th, 2017 03:25
+
- Add `error` aspect example
# 1.21.0 - July 27th, 2017 21:37
+
- `aspect` now supports async `before`, `after`, and `onError`
# 1.20.0 - July 25th, 2017 20:04
+
- Add `findApply`, `isNotNil`, `exists`, `unlessExists`, `unlessTruth`, `getOrReturn`, `alias`, `cascade`, `cascadeIn`, `cascadeKey`, `isMultiple`, `append`, `composeApply`, `comply`
# 1.19.0 - July 13th, 2017 14:23
+
- Add ramda style `ifElse`, `where`, and `unless` to a new `logic` section
# 1.18.1 - July 13th, 2017 14:23
+
- Update lensOf to use reduce instead of mapValues
# 1.18.0 - June 23rd, 2017 22:01
+
- Add `callOrReturn`, `each`, and `mergeOn`
# 1.17.4 - June 23rd, 2017 21:58
+
- Made f.map uncapped
# 1.17.3 - June 9th, 2017 23:47
+
- Convert aspect to Promise instead of async/await and rip out babel-polyfill
# 1.17.2 - June 8th, 2017 21:27
+
- Pass original params to onError and after
# 1.17.1 - June 8th, 2017 19:18
+
- Include babel-polyfill in webpack build now that aspects have `async` functions
# 1.17.0 - June 7th, 2017 22:51
+
- Added `unflattenObject` and a deprecation warning about `mapProp` in favor of lodash `_.update`
# 1.16.0 - June 6th, 2017 22:30
+
- Added `aspect` and the reusable examples on `aspects` (`logs`, `errors`, `status`, and `concurrency`), as well as `throws`
# 1.15.1 - May 30th, 2017 15:57
+
- Added `views`
# 1.15.0 - May 26th, 2017 21:43
+
- Added `lens` functions `functionLens`, `objectLens`, `fnToObj`, `objToFn`, `lensProp`, `lensOf`, `view`, `set`, `sets`, `flip`, `on`, `off`
# 1.14.0 - May 24th, 2017 02:08
+
- Added a `mapProp`.
# 1.13.0 - May 16th, 2017 22:32
+
- Added a noCap conversion for `mapValues`.
# 1.12.0 - May 16th, 2017 22:11
+
- Added `boundMethod`.
# 1.11.1 - May 2nd, 2017 13:22
+
- Greenkeeper udpated the babel-loader and danger-js
# 1.11.0 - April 6th, 2017 15:47
+
- Added `cycle`
# 1.10.2 - March 30th, 2017 21:48
+
- Circle CI now help us enforce CHANGELOG.md and package.json
updates in any PR.
# 1.10.1 - March 30th, 2017 21:48
+
- Fix `testRegex`
# 1.10.0 - March 30th, 2017 18:32
+
- Add `matchAllWords`
# 1.9.0 - March 29th, 2017 17:03
+
- Added regex and postings based highlighting functions `postings`, `postingsForWords`, `highlightFromPostings`, `highlight`
- Added range manipulation funcitons `push`, `mergeRanges`, `insertAtIndex`
- `makeRegex` curried implementation of the RegExp construction.
@@ -474,6 +607,7 @@ Enable coveralls integration.
- Add regex.spec.js
# 1.8.0-1.8.3 - February 27th, 2017 20:18
+
- `map` added to seamlessly map array and plain objects.
- `deepMap` added to seamlessly map recursive arrays and plain
objects. Also optionally allows mappings to any recursive algebraic
@@ -481,50 +615,64 @@ Enable coveralls integration.
- Versions 1.8.0-1.8.3 were assimilated by the borg.
# 1.7.3 - February 21st, 2017 19:57
+
- `compareDeep` is ok with ===, and it's now tested
- Eslint, coverage and CI fixes
# 1.7.1 - February 17th, 2017 23:03
+
- Fix npm publish
# 1.7.0 - February 17th, 2017 14:23
+
- Add `defaultsOn`
# 1.6.0 - February 16th, 2017 21:35
+
- Add `extendOn`
# 1.5.1 and 1.5.2 - February 16th, 2017 21:35
+
Travis related CI stuff
# 1.5.0 - February 15th, 2017 22:11
+
- Add `pickIn`
# 1.4.1 - February 10th, 2017 23:40
+
- `maybeCall` fixed, rest params added to get the `fn` arguments
# 1.4.0 - February 10th, 2017 23:40
+
- Added Array Function `repeated`
- Added String Functions
- * `quote`
- * `parens`
- * `processQuotes`
- * `getUniqueWords`
+ - `quote`
+ - `parens`
+ - `processQuotes`
+ - `getUniqueWords`
# 1.3.0 - February 10th, 2017 23:40
+
- Added `flattenObject` and `singleObjectR`
- Split index to multiple files
# 1.2.2 - February 10th, 2017 20:14
+
- Changed filename to `futil-js` to match the current npm package name
# 1.2.1 - February 10th, 2017 16:51
+
- Changed package.json main entry point to reflect the built output
# 1.2.0 - February 9th, 2017 05:21
+
- Added unwind
# 1.1.0 - February 8th, 2017 20:04
+
- Added flowMap
# 1.0.0 - February 6th, 2017 21:16
+
- Initial Release
diff --git a/README.md b/README.md
index 306e9441..8ef4c7ce 100644
--- a/README.md
+++ b/README.md
@@ -19,20 +19,23 @@ A collection of F(unctional) Util(ities). Resistance is futile.
Mostly, these are generic utilities that could conceivably be part of a library like [lodash/fp](https://github.com/lodash/lodash/wiki/FP-Guide), but for one reason or another are not.
# Docs
+
https://smartprocure.github.io/futil-js/
# Version History/Changelog
+
See our [changelog](https://github.com/smartprocure/futil-js/blob/master/CHANGELOG.md)
# Installing
+
`npm i -S futil`
or
`npm i -S futil-js`
-
This package requires `lodash/fp`, so make sure that's available in your app.
# Usage
+
`import * as F from 'futil'`
or
`import F from 'futil'`
@@ -44,105 +47,125 @@ or
## Function
### maybeCall
+
`(fn, a, b) -> fn(a, b)`
If `fn` is a function, call the function with the passed-in arguments. Otherwise, return `false`.
### callOrReturn
+
`(fn, a, b) -> fn(a, b)`
If `fn` is a function, call the function with the passed-in arguments. Otherwise, return `fn`.
### boundMethod
+
`(a, Monoid f) -> f[a] :: f a`
Binds a function of an object to it's object.
### converge
+
`(f, [g1, g2, ...gn]) -> a -> f([g1(a), g2(a), ...])`
http://ramdajs.com/docs/#converge. Note that `f` is called on the array of the return values of `[g1, g2, ...gn]` rather than applied to it.
### comply (alias: composeApply)
+
`(f, g) -> x -> f(g(x))(x)`
A combinator that combines compose and apply. `f` should be a 2 place curried function. Useful for applying comparisons to pairs defined by some one place function, e.g. `var isShorterThanFather = F.comply(isTallerThan, fatherOf)`
### defer
+
Implement `defer`, ported from bluebird docs and used by debounceAsync
### debounceAsync
+
A `_.debounce` for async functions that ensure the returned promise is resolved with the result of the execution of the actual call. Using `_.debounce` with `await` or `.then` would result in the earlier calls never returning because they're not executed - the unit tests demonstate it failing with `_.debounce`.
### flurry
+
`(f1, f2, ...fn) -> f1Arg1 -> f1Arg2 -> ...f1ArgN -> fn(f2(f1))`
Flurry is combo of flow + curry, preserving the arity of the initial function. See https://github.com/lodash/lodash/issues/3612.
### mapArgs
-`(mapper, fn) -> (...args) -> fn(...args.map(mapper))`
-Returns a function that applies the mapping operation to all of the arguments of a function. Very similar to _.overArgs, but runs a single mapper on all of the args args.
+`(mapper, fn) -> (...args) -> fn(...args.map(mapper))`
+Returns a function that applies the mapping operation to all of the arguments of a function. Very similar to \_.overArgs, but runs a single mapper on all of the args args.
## Iterators
### differentLast
+
`handleItem -> handleLastItem -> iterator`
Creates an iterator that handles the last item differently for use in any function that passes `(value, index, list)` (e.g. `mapIndexed`, `eachIndexed`, etc). Both the two handlers and the result are iterator functions that take `(value, index, list)`.
-
## Logic
### overNone
+
`([f1, f2, ...fn]) -> !f1(x) && !f2(x) && ...!fn(x)`
Creates a function that checks if none of the array of predicates passed in returns truthy for `x`
### ifElse
+
`(condition, onTrue, onFalse, x) -> (T(condition)(x) ? onTrue(x) : onFalse(x))`
http://ramdajs.com/docs/#ifElse. The transform function T supports passing a boolean for `condition` as well as any valid argument of `_.iteratee`, e.g. `myBool = applyTest(x); F.ifElse(myBool, doSomething, doSomethingElse);`
### when
+
`(condition, onTrue, x) -> (T(condition)(x) ? onTrue(x) : _.identity(x))`
http://ramdajs.com/docs/#when. `T` extends `_.iteratee` as above.
### unless
+
`(condition, onFalse, x) -> (T(condition)(x) ? _.identity(x) : onFalse(x))`
http://ramdajs.com/docs/#unless. `T` extends `_.iteratee` as above.
### whenTruthy
+
`when` curried with `Boolean`
### whenExists
-`when` curried with `exists`
+`when` curried with `exists`
## Collection
### flowMap
+
`[f1, f2, ...fn] -> _.map(_.flow(fn))`
Maps a flow of `f1, f2, ...fn` over a collection.
### findApply
+
`f -> x -> f(find(f, x))`
A version of `find` that also applies the predicate function to the result. Useful when you have an existing function that you want to apply to a member of a collection that you can best find by applying the same function.
### map
+
`(a -> b) -> [a] -> [b]`
Maps a function over an iterable. Works by default for Arrays and Plain Objects.
### deepMap
+
`(a -> b) -> [a] -> [b]`
Maps a function over a recursive iterable. Works by default for nested Arrays, nested Plain Objects and mixed nested Arrays and Plain Objects. Also works for any other iterable data type as long as two other values are sent: a mapping function, and a type checker (See the unit tests for deepMap).
### insertAtIndex
+
`(index, val, array|string) -> array|string`
Inserts value into an array or string at `index`
Example:
+
```jsx
(1, '123', 'hi') -> 'h123i'
```
### compactMap
+
`(fn, collection) -> collection`
Maps `fn` over the input collection and compacts the result.
+## Convert(\_In)
-## Convert(_In)
lodash/fp is great, but sometimes the curry order isn't exactly what you want.
These methods provide alternative orderings that are sometimes more convenient.
@@ -150,19 +173,23 @@ These methods provide alternative orderings that are sometimes more convenient.
The idea of `In` methods is to name them by convention, so when ever you need a method that actually takes the collection first (e.g. a `get` where the data is static but the field is dynamic), you can just add `In` to the end (such as `getIn` which takes the object first)
### getIn
+
Just like `_.get`, but with `{rearg: false}` so the argument order is unchanged from non fp lodash.
### hasIn
+
Just like `_.has`, but with `{rearg: false}` so the argument order is unchanged from non fp lodash.
### pickIn
+
Just like `_.pick`, but with `{rearg: false}` so the argument order is unchanged from non fp lodash.
### includesIn
+
Just like `_.includes`, but with `{rearg: false}` so the argument order is unchanged from non fp lodash.
+## Convert(\_On)
-## Convert(_On)
lodash/fp likes to keep things pure, but sometimes JS can get pretty dirty.
These methods are alternatives for working with data that--for whatever the use case is--needs to be mutable
@@ -170,28 +197,35 @@ These methods are alternatives for working with data that--for whatever the use
Any methods that interact with mutable data will use the `On` convention (as it is some action occuring `On` some data)
### extendOn
+
Just like `_.extend`, but with `{mutable: true}` so it mutates.
### defaultsOn
+
Just like `_.defaults`, but with `{mutable: true}` so it mutates.
### mergeOn
+
Just like `_.merge`, but with `{mutable: true}` so it mutates.
### setOn
+
Just like `_.set`, but with `{mutable: true}` so it mutates.
### unsetOn
+
Just like `_.unset`, but with `{mutable: true}` so it mutates.
### pullOn
+
Just like `_.pull`, but with `{mutable: true}` so it mutates.
### updateOn
+
Just like `_.update`, but with `{mutable: true}` so it mutates.
+## Convert(\_Indexed)
-## Convert(_Indexed)
lodash/fp caps iteratees to one argument by default, but sometimes you need the index.
These methods are uncapped versions of lodash's methods.
@@ -199,207 +233,266 @@ These methods are uncapped versions of lodash's methods.
Any method with uncapped iteratee arguments will use the `Indexed` convention.
### mapIndexed
+
Just like `_.map`, but with `{cap: false}` so iteratees are not capped (e.g. indexes are passed).
### findIndexed
+
Just like `_.find`, but with `{cap: false}` so iteratees are not capped (e.g. indexes are passed).
### eachIndexed
+
Just like `_.each`, but with `{cap: false}` so iteratees are not capped (e.g. indexes are passed).
### reduceIndexed
+
Just like `_.reduce`, but with `{cap: false}` so iteratees are not capped (e.g. indexes are passed).
### pickByIndexed
+
Just like `_.pickBy`, but with `{cap: false}` so iteratees are not capped (e.g. indexes are passed).
### mapValuesIndexed
-Just like `_.mapValues`, but with `{cap: false}` so iteratees are not capped (e.g. indexes are passed).
+Just like `_.mapValues`, but with `{cap: false}` so iteratees are not capped (e.g. indexes are passed).
## Array
### compactJoin
-`joinString -> [string1, string2, ...stringN] -> string1 + joinString + string2 + joinString ... + stringN`
+
+`joinString -> [string1, string2, ...stringN] -> string1 + joinString + string2 + joinString ... + stringN`
Joins an array after compacting. Note that due to the underlying behavior of `_.curry` no default `join` value is supported -- you must pass in some string with which to perform the join.
### dotJoin
+
`[string1, string2, ...stringN] -> string1 + '.' + string2 + '.' ... + stringN`
Compacts and joins an array with `.`
### dotJoinWith
+
`filterFunction -> [string1, string2, ...stringN] -> string1 + '.' + string2 + '.' ... + stringN`
Compacts an array by the provided function, then joins it with `.`
### repeated
+
`[a] -> [a]`
Returns an array of elements that are repeated in the array.
### push
+
`(val, array) -> array`
Return `array` with `val` pushed.
### moveIndex
+
`(from, to, array) -> array`
Moves a value from one index to another
### mergeRanges
+
`([[], [], []]) -> [[], []]`
Takes any number of ranges and return the result of merging them all.
Example:
+
```jsx
[[0,7], [3,9], [11,15]] -> [[0,9], [11,15]]
```
### cycle
+
`[a, b...] -> a -> b`
Creates a function that takes an element of the original array as argument and returns the next element in the array (with wrapping). Note that (1) This will return the first element of the array for any argument not in the array and (2) due to the behavior of `_.curry` the created function will return a function equivalent to itself if called with no argument.
### arrayToObject
+
`(k, v, [a]) -> { k(a): v(a) }`
Creates an object from an array by generating a key/value pair for each element in the array using the key and value mapper functions.
### zipObjectDeepWith
+
A version of `_.zipObjectDeep` that supports passing a function to determine values intead of an array, which will be invoked for each key.
### flags
+
`[a, b] -> {a:true, b:true}`
Converts an array of strings into an object mapping to true. Useful for optimizing `includes`.
### prefixes
+
`['a', 'b', 'c'] -> [['a'], ['a', 'b'], ['a', 'b', 'c']]`
Returns a list of all prefixes. Works on strings, too. Implementations must guarantee that the orginal argument has a length property.
### encoder
+
`string -> {encode: array -> string, decode: string -> array}`
Creates an object with encode and decode functions for encoding arrays as strings. The input string is used as input for join/split.
### dotEncoder
+
`{ encode: ['a', 'b'] -> 'a.b', decode: 'a.b' -> ['a', 'b'] }`
An encoder using `.` as the separator
### slashEncoder
+
`{ encode: ['a', 'b'] -> 'a/b', decode: 'a/b' -> ['a', 'b'] }`
An encoder using `/` as the separator
### chunkBy
+
`(([a], a) -> Boolean) -> [a] -> [[a]]`
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).
The predicate is called with two arguments: the current group, and the current element. If it returns truthy, the element is appended to the current group; otherwise, it's used as the first element in a new group.
### toggleElementBy
+
`bool -> value -> list -> newList`
Just like toggleElement, but takes an iteratee to determine if it should remove or add. This is useful for example in situations where you might have a checkbox that you want to represent membership of a value in a set instead of an implicit toggle. Used by includeLens.
### toggleElement
+
`(any, array) -> array`
Removes an element from an array if it's included in the array, or pushes it in if it doesn't. Immutable (so it's a clone of the array).
### intersperse
+
`f -> array -> [array[0], f(), array[n], ....)`
Puts the result of calling `f` in between each element of the array. `f` is a standard lodash iterator taking the value, index, and list. If `f` is not a function, it will treat `f` as the value to intersperse. See https://ramdajs.com/docs/#intersperse.
Example:
+
```jsx
// Example with words (toSentence is basically this flowed into a `_.join('')`):
-F.intersperse(differentLast(() => 'or', () => 'or perhaps'), ['first', 'second', 'third'])
+F.intersperse(
+ differentLast(
+ () => "or",
+ () => "or perhaps"
+ ),
+ ["first", "second", "third"]
+)
// ['first', 'or', 'second', 'or perhaps', 'third']
// Example with React and JSX:
let results = [1, 2, 3]
-return
+)
// Output:
// **Results:**
// **1**, **2** and **3**.
```
+
**Note:** This works great with the `differentLast` iterator. Also, `intersperse` can be used with JSX components!
### replaceElementBy
+
`(fn(array_element), value, array) -> array`
Replaces an element in an array with `value` based on the boolean result of a function `fn`.
### replaceElement
+
`(target, value, array) -> array`
Replaces all elements equal to `target` in an array with `value`.
-
## Object
### singleObject
+
`(k, v) -> {k: v}`
Creates an object with a key and value.
### singleObjectR
+
`(v, k) -> {k: v}`
Flipped version of `singleObject`.
### chunkObject
+
`({a, b}) -> [{a}, {b}]`
Breaks an object into an array of objects with one key each.
### compactObject
+
Remove properties with falsey values.
Example:
+
```jsx
({ a: 1, b: null, c: false }) -> {a:1}
```
### isEmptyObject
+
Check if the variable is an empty object (`{}`).
### isNotEmptyObject
+
Check if the variable is **not** an empty object (`{}`).
### stripEmptyObjects
+
Omit properties whose values are empty objects.
Example:
+
```jsx
{ a:1, b:{}, c:2 } -> {a:1, c:2}
```
-**Note:** (*TODO* rename to `omitEmptyObjects`)
+
+**Note:** (_TODO_ rename to `omitEmptyObjects`)
### pickInto
-*TODO*
+
+_TODO_
### renameProperty
+
`sourcePropertyName -> targetPropertyName -> sourceObject -> sourceObject`
Rename a property on an object.
Example:
+
```jsx
renameProperty('a', 'b', { a: 1 }) -> { b: 1 }
```
### unwind
+
`k -> { k: [a, b] } -> [{ k: a }, { k: b }]`
Just like mongo's `$unwind`: produces an array of objects from an object and one of its array-valued properties. Each object is constructed from the original object with the array value replaced by its elements. Unwinding on a nonexistent property or a property whose value is not an array returns an empty array.
Example:
+
```jsx
-F.unwind('b', [{ a: true, b: [1, 2] }])
- //=> [{ a: true, b: 1 }, { a: true, b: 2 }]
+F.unwind("b", [{ a: true, b: [1, 2] }])
+//=> [{ a: true, b: 1 }, { a: true, b: 2 }]
```
### unwindArray
+
`k -> [{ k: [a, b] }] -> [{ k: a }, { k: b }]`
Unwinds an array of objects instead of a single object, as you might expect if you're used to mongo's `$unwind`. Alias for `(key, data) => _.flatMap(F.unwind(key), data)`
Example:
+
```jsx
-F.unwindArray('b', [{ a: true, b: [1, 2] }, { a: false, b: [3, 4] }])
+F.unwindArray("b", [
+ { a: true, b: [1, 2] },
+ { a: false, b: [3, 4] },
+])
//=> [
//=> { a: true, b: 1 },
//=> { a: true, b: 2 },
@@ -409,262 +502,323 @@ F.unwindArray('b', [{ a: true, b: [1, 2] }, { a: false, b: [3, 4] }])
```
### flattenObject
+
Flatten an object with the paths for keys.
Example:
+
```jsx
{ a: { b: { c: 1 } } } => { 'a.b.c' : 1 }
```
### unflattenObject
+
Unlatten an object with the paths for keys.
Example:
+
```jsx
{ 'a.b.c' : 1 } => { a: { b: { c: 1 } } }
```
### matchesSignature
+
Returns true if object keys are only elements from signature list. (but does not require all signature keys to be present)
### matchesSome
+
Similar to `_.matches`, except it returns true if 1 or more object properties match instead of all of them. See https://github.com/lodash/lodash/issues/3713.
### compareDeep
+
Checks if an object's property is equal to a value.
### mapProp
+
_Deprecated in favor of lodash `update`_ Applies a map function at a specific path
Example:
+
```jsx
mapProp(double, 'a', {a: 2, b: 1}) -> {a: 4, b: 1}
```
### getOrReturn
+
`_.get` that returns the target object if lookup fails
### alias
+
`_.get` that returns the prop if lookup fails
### aliasIn
+
Flipped `alias`
### cascade
+
A `_.get` that takes an array of paths (or functions to return values) and returns the value at the first path that matches. Similar to `_.overSome`, but returns the first result that matches instead of just truthy (and supports a default value)
### cascadeIn
+
Flipped cascade
### cascadeKey
+
A `_.get` that takes an array of paths and returns the first path that matched
### cascadePropKey
+
A `_.get` that takes an array of paths and returns the first path that exists
### cascadeProp
+
A `_.get` that takes an array of paths and returns the first value that has an existing path
### unkeyBy
+
`newKey -> {a:x, b:y} -> [{...x, newKey: a}, {...y, newKey: b}]`
Opposite of `_.keyBy`. Creates an array from an object where the key is merged into the values keyed by `newKey`.
Example:
+
```jsx
F.unkeyBy('_key')({ a: { status: true}, b: { status: false }) -> [{ status: true, _key: 'a' }, { status: false, _key: 'b' }]
```
+
**Note:** Passing a falsy value other than `undefined` for `newKay` will result in each object key being pushed into its corresponding return array member with itself as value, e.g. `F.unkeyBy('')({ a: { status: true}, b: { status: false }) -> [{ status: true, a: 'a' }, { status: false, b: 'b' }]`. Passing `undefined` will return another instance of F.unkeyBy.
### simpleDiff
+
`(from, to) -> simpleDiff`
Produces a simple flattened (see `flattenObject`) diff between two objects. For each (flattened) key, it produced a `from` and a `to` value. Note that this will omit any values that are not present in the deltas object.
### simpleDiffArray
+
`(from, to) -> [simpleDiffChanges]`
Same as `simpleDiff`, but produces an array of `{ field, from, to }` objects instead of `{ field: { from, to } }`
### diff
+
`(from, to) -> diff`
Same as `simpleDiff`, but also takes in count deleted properties.
**Note:** We're considering not maintaining this in the long term, so you might probably have more success with any existing library for this purpose.
### diffArray
+
`(from, to) -> [diffChanges]`
Same as `simpleDiffArray`, but also takes in count deleted properties.
**Note:** We're considering not maintaining this in the long term, so you might probably have more success with any existing library for this purpose.
### pickOn
+
A `_.pick` that mutates the object
### mergeAllArrays
+
Like `_.mergeAll`, but concats arrays instead of replacing. This is basically the example from the lodash `mergeAllWith` docs.
### invertByArray
+
`{ a: [x, y, z], b: [x] } -> { x: [a, b], y: [a], z: [a] }`
Similar to `_.invert`, but expands arrays instead of converting them to strings before making them keys.
### stampKey
+
`key -> { a: { x: 1 }, b: { y: 2 } } -> { a: { x: 1, key: 'a' }, b: { y: 2, key: 'b' } }`
Iterates over object properties and stamps their keys on the values in the field name provided.
### omitNil
+
`_.omitBy` using `_.isNil` as function argument.
### omitNull
+
`_.omitBy` using `_.isNull` as function argument.
### omitBlank
+
`_.omitBy` using `F.isBlank` as function argument.
### omitEmpty
+
`_.omitBy` using `_.isEmpty` as function argument.
### mergeOverAll
+
`([f, g], ...args) -> {...f(...args), ...g(...args)}`
Composition of `_.over` and `_.mergeAll`. Takes an array of functions and an arbitrary number of arguments, calls each function with those arguments, and merges the results. Can be called with `mergeOverAll([f, g], x, y)` or `mergeOverAll([f, g])(x, y)`.
**Note:** For functions that do not return objects, `_.merge`'s behavior is followed: for strings and arrays, the indices will be converted to keys and the result will be merged, and for all other primitives, nothing will be merged.
### mergeOverAllWith
+
`(customizer, [f, g], ...args) -> {...f(...args), ...g(...args)}`
A customizable `mergeOverAll` that takes a function of the form `(objValue, srcValue) -> newValue` as its first argument; see [`_.mergeWith`](https://lodash.com/docs/latest#mergeWith). Both the customizer and array of functions can be partially applied.
### mergeOverAllArrays
+
`([f, g], ...args) -> {...f(...args), ...g(...args)}`
A customized `mergeOverAll` that applies the array-merging behavior of `mergeAllArrays`.
### getWith
+
`(x -> y) -> k -> {k: x} -> y`
Like `_.get`, but accepts a customizer function which is called on the value to transform it before it is returned. Argument order is `(customizer, path, object)`.
### expandObject
+
`(transform: obj -> newObj) -> obj -> { ...obj, ...newObj }`
Accepts a transform function and an object. Returns the result of applying the transform function to the object, merged onto the original object. `expandObject(f, obj)` is equivalent to `mergeOverAll([_.identity, f], obj)`.
### expandObjectBy
+
`key -> (transform: x -> newObj) -> (obj: { key: x }) -> { ...obj, ...newObj }`
Expands an object by transforming the value at a single key into a new object, and merging the result with the original object. Similar to `expandObject`, but the argument order is `(key, transform, object)`, and the transform function is called on the value at that key instead of on the whole object.
### commonKeys
+
`(x, y) -> [keys]`
Takes two objects and returns the keys they have in common
### firstCommonKey
+
`(x, y) -> key`
Takes two objects and returns the first key in `y` that x also has
-
## String
### parens
+
`'asdf' -> '(asdf)'`
Wraps a string in parenthesis.
### trimStrings
+
Maps `_.trim` through all the strings of a given object or array.
### autoLabel
+
`string -> string`
Converts strings like variable names to labels (generally) suitable for GUIs, including support for acronyms and numbers. It's basically `_.startCase` with acronym and number support.
### autoLabelOption
+
`string -> {value:string, label:string}`
Creates a `{value, label}` which applies `autoLabel` the string parameter on puts it on the label property, with the original on the value property. You can also pass in an object with value or with both value and label.
### autoLabelOptions
+
`[string] -> [{value:string, label:string}]`
Applies `autoLabelOption` to a collection. Useful for working with option lists like generating select tag options from an array of strings.
### toSentenceWith
+
`(separator, lastSeparator, array) => string`
Just like `toSentence`, but with the ability to override the `separator` and `lastSeparator`
Example:
+
```jsx
(' - ', ' or ', ['a', 'b', 'c']) -> 'a - b or c'
```
### toSentence
+
`array => string`
Joins an array into a human readable string. See https://github.com/epeli/underscore.string#tosentencearray-delimiter-lastdelimiter--string
Example:
+
```jsx
['a', 'b', 'c'] -> 'a, b and c'
```
### uniqueStringWith
+
`(fn, array) -> string -> string`
Allows passing a "cachizer" function (`array -> object`) to override the way `uniqueString`'s initial array is converted into a cache object. Can be curried to create a custom `uniqueString` function, eg: `let myUniqueString = uniqueStringWith(myFunc)`
Like `uniqueString`, the resulting deduplication function exposes `cache` and `clear()` properties.
Example:
+
```jsx
let uniqueStringStripDigits = uniqueStringWith(
- _.countBy(_.replace(/(\d+)$/, ''))
+ _.countBy(_.replace(/(\d+)$/, ""))
)
-let dedupe = uniqueStringStripDigits(['foo', 'foo42', 'foo3000'])
-dedupe('foo') //-> 'foo3'
-uniqueStringWith(_.identity, dedupe.cache)('foo') //-> 'foo4'
+let dedupe = uniqueStringStripDigits(["foo", "foo42", "foo3000"])
+dedupe("foo") //-> 'foo3'
+uniqueStringWith(_.identity, dedupe.cache)("foo") //-> 'foo4'
```
### uniqueString
+
`array -> string -> string`
Returns a function that takes a string and de-duplicates it against an internal cache. Each time this function is called, the resulting deduplicated string is added to the cache. Exposes `cache` and `clear()` properties to read and clear the cache, respectively.
Example:
+
```jsx
let dedupe = uniqueString()
-_.map(dedupe, ['foo', 'foo', 'foo']) //-> ['foo', 'foo1', 'foo2']
-dedupe.cache //-> { foo: 3, foo1: 1, foo2: 1 }
+_.map(dedupe, ["foo", "foo", "foo"]) //-> ['foo', 'foo1', 'foo2']
+dedupe.cache //-> { foo: 3, foo1: 1, foo2: 1 }
dedupe.clear()
-dedupe.cache //-> {}
-dedupe('foo') //-> 'foo'
+dedupe.cache //-> {}
+dedupe("foo") //-> 'foo'
```
-
## Regex
### testRegex
+
`regex -> string -> bool`
Just like ramda test, creates a function to test a regex on a string.
### makeRegex
+
`options:string -> string -> regex`
A curried implementation of `RegExp` construction.
### makeAndTest
+
`options:string -> string -> (string -> bool)`
Makes and tests a RegExp with makeRegex and testRegex.
### matchAllWords
+
`string -> string -> bool`
Returns true if the second string matches all of the words in the first string.
### matchAnyWord
+
`string -> string -> bool`
Returns true if the second string matches any of the words in the first string.
### allMatches
+
`regex -> string -> [{text: string, start: number, end: number}]`
Returns an array of matches with start/end data
Example:
+
```jsx
F.allMatches(/a/g, 'vuhfaof') -> [ { text: 'a', start: 4, end: 5 } ]
```
### postings
+
`regex -> string -> [[number, number]]`
Returns an array of postings (position ranges) for a regex and string to test, e.g. `F.postings(/a/g, 'vuhfaof') -> [[4, 5]]`
### postingsForWords
+
`words -> string -> [[[number, number]]]`
Takes a string of words and a string to test, and returns an array of arrays of postings for each word.
Example:
+
```jsx
-F.postingsForWords('she lls', 'she sells sea shells')
+F.postingsForWords("she lls", "she sells sea shells")
// [
// [[0, 3], [14, 17]]
// [[6, 9], [17, 20]]
@@ -672,62 +826,73 @@ F.postingsForWords('she lls', 'she sells sea shells')
```
### highlight
+
`start -> end -> pattern -> input -> highlightedInput`
Wraps the matches for `pattern` found in `input` with the strings `start` and `end`. The `pattern` argument can either be a string of words to match, or a regular expression.
Example:
+
```jsx
-let braceHighlight = F.highlight('{', '}')
-braceHighlight('l o', 'hello world') //-> "he{llo} w{o}r{l}d"
-braceHighlight(/l+\w/, 'hello world') //-> "he{llo} wor{ld}"
+let braceHighlight = F.highlight("{", "}")
+braceHighlight("l o", "hello world") //-> "he{llo} w{o}r{l}d"
+braceHighlight(/l+\w/, "hello world") //-> "he{llo} wor{ld}"
```
-
## Math
### greaterThanOne
+
`number -> bool`
Returns true if number is greater than one.
-
## Lang
+
Language level utilities
### isPromise
+
`x -> bool`
A utility that checks if the argument passed in is of type promise
### throws
+
Just throws whatever it is passed.
### tapError
+
Tap error will run the provided function and then throw the first argument. It's like `_.tap` for rethrowing errors.
### exists (alias: isNotNil)
+
Negated `_.isNil`
### isMultiple
+
`(Array | string | {length}) -> bool`
Returns true if the input has a `length` property > 1, such as arrays, strings, or custom objects with a lenth property
### append
+
`(a, b) => b + a`
A curried, flipped `_.add`. The flipping matters for strings, e.g. `F.append('a')('b') -> 'ba'`
### isBlank
+
`x -> bool`
Designed to determine if something has a meaningful value, like a ux version of truthiness. It's false for everything except null, undefined, '', [], and {}. Another way of describing it is that it's the same as falsiness except 0 and false are truthy and {} is falsey. Useful for implementing "required" validation rules.
### isNotBlank
+
`x -> bool`
Opposite of `isBlank`
### isBlankDeep
+
`f -> x -> bool`
Recurses through an object's leaf properties and passes an array of booleans to the combinator, such as `_.some`, `_.every`, and `F.none`
-
## Lens
+
A lens is a getter and setter pair. You use them to write code that needs to read _and_ write a value (like a method to flip a boolean switch, or a React component that reads and writes some state) without worrying about the implementation.
Functions that operate on lenses can handle a few different "shorthand" structures. This is similar to lodash's `_.iteratee` (which allows their methods to treat strings, objects, or functions as shorthand predicates)
@@ -765,61 +930,78 @@ We've included a few example "bindings" on `F.domLens`. These take a lens and re
![lens meme](http://giphygifs.s3.amazonaws.com/media/1jnyRP4DorCh2/giphy.gif)
### functionLens
+
Takes a value and returns a function lens for that value. Mostly used for testing and mocking purposes.
### objectLens
+
Takes a value and returns a object lens for that value. Mostly used for testing and mocking purposes.
### set
+
`propertyValue -> Lens -> object.propertyName`
Sets the value of the lens, regardless of its format
### fnToObj
+
Converts a function lens an object lens. Mostly used for testing and mocking purposes.
### objToFn
+
Converts an object lens to a function lens. Mostly used for testing and mocking purposes.
### lensProp
+
`propertyName -> object -> { get: () -> object.propertyName, set: propertyValue -> object.propertyName }`
Creates an object lens for a given property on an object. `.get` returns the value at that path and `set` places a new value at that path. Supports deep paths like lodash get/set.
You typically won't use this directly since it is supported implicitly.
### lensOf
+
Takes an object and returns an object with lenses at the values of each path. Basically `mapValues(lensProp)`. Typically you would use the implicit `(key, object)` format instead.
### includeLens
+
`value -> arrayLens -> includeLens`
An include lens represents membership of a value in a set. It takes a value and lens and returns a new lens - kind of like a "writeable computed" from MobX or Knockout. The view and set functions allow you to read and write a boolean value for whether or not a value is in an array. If you change to true or false, it will set the underlying array lens with a new array either without the value or with it pushed at the end.
### view
+
`Lens -> object.propertyName`
Gets the value of the lens, regardless of its format
### views
+
`Lens -> (() -> object.propertyName)`
Returns a function that gets the value of the lens, regardless of its format
### sets
+
Creates a function that will set a lens with the provided value
### setsWith
+
Takes an iteratee and lens and creates a function that will set a lens with the result of calling the iteratee with the provided value
### flip
+
Takes a lens and negates its value
### on
+
Returns a function that will set a lens to `true`
### off
+
Returns a function that will set a lens to `false`
### domLens.value
+
`lens -> {value, onChange}`
Takes a lens and returns a value/onChange pair that views/sets the lens appropriately. `onChange` sets with `e.target.value` (or `e` if that path isn't present).
Example:
+
```jsx
let Component = () => {
let state = React.useState('')
@@ -828,31 +1010,37 @@ let Component = () => {
```
### domLens.checkboxValues
+
`(value, lens) -> {checked, onChange}`
Creates an includeLens and maps view to checked and set to `onChange` (set with `e.target.checked` or `e` if that path isn't present)
### domLens.hover
+
`lens -> { onMouseEnter, onMouseLeave }`
Takes a lens and returns on onMouseEnter which calls `on` on the lens and onMouseLeave which calls `off`. Models a mapping of "hovering" to a boolean.
### domLens.focus
+
`lens -> { onFocus, onBlur }`
Takes a lens and returns on onFocus which calls `on` on the lens and onBlur which calls `off`. Models a mapping of "focusing" to a boolean.
### domLens.targetBinding
+
`field -> lens -> {[field], onChange}`
Utility for building lens consumers like `value` and `checkboxValues`
### domLens.binding
+
`(field, getValue) -> lens -> {[field], onChange}`
Even more generic utility than targetBinding which uses `getEventValue` to as the function for a setsWith which is mapped to `onChange`.
### stateLens
+
`([value, setValue]) -> lens`
Given the popularity of React, we decided to include this little helper that converts a `useState` hook call to a lens. Ex: `let lens = stateLens(useState(false))`. You generally won't use this directly since you can pass the `[value, setter]` pair directly to lens functions
-
## Aspect
+
Aspects provide a functional oriented implementation of Aspect Oriented Programming.
An aspect wraps a function and allows you run code at various points like before and after execution.
Notably, aspects in this library allow you to have a shared state object between aspects and are very useful for automating things like status indicators, etc on functions.
@@ -869,27 +1057,29 @@ All of the provided aspects take an `extend` function to allow customizing the s
If null, they default to `defaultsOn` from `futil-js` - check the unit tests for example usage.
### aspect
+
`{options} -> f -> aspectWrapped(f)`
The aspect api takes an options object and returns a function which takes a function to wrap.
- The wrapped function will be decorated with a `state` object and is equivalent to the original function for all arguments.
+The wrapped function will be decorated with a `state` object and is equivalent to the original function for all arguments.
Options supports the following parameters:
-| Name | Description |
-| --- | --- |
-| `init: (state) -> ()` | A function for setting any inital state requirements. Should mutate the shared state object. |
-| `after: (result, state, params) -> ()` | Runs after the wrapped function executes and recieves the shared state and the result of the function. Can be async. |
-| `before: (params, state) -> ()` | Runs before the wrapped function executes and receves the shared state and the params passed to the wrapped function. Can be async. |
-| `onError: (error, state, params) -> ()` | Runs if the wrapped function throws an error. If you don't throw inside this, it will swallow any errors that happen. |
-| `always: (state, params) -> ()` | Runs after the wrapped function whether it throws an error or not, similar to a `Promise.catch` |
+| Name | Description |
+| --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
+| `init: (state) -> ()` | A function for setting any inital state requirements. Should mutate the shared state object. |
+| `after: (result, state, params) -> ()` | Runs after the wrapped function executes and recieves the shared state and the result of the function. Can be async. |
+| `before: (params, state) -> ()` | Runs before the wrapped function executes and receves the shared state and the params passed to the wrapped function. Can be async. |
+| `onError: (error, state, params) -> ()` | Runs if the wrapped function throws an error. If you don't throw inside this, it will swallow any errors that happen. |
+| `always: (state, params) -> ()` | Runs after the wrapped function whether it throws an error or not, similar to a `Promise.catch` |
Example:
+
```jsx
let exampleAspect = aspect({
- before: () => console.log('pre run'),
- after: () => console.log('post run')
+ before: () => console.log("pre run"),
+ after: () => console.log("post run"),
})
-let f = () => console.log('run')
+let f = () => console.log("run")
let wrapped = exampleAspect(f)
wrapped()
// Logs to the console:
@@ -899,115 +1089,144 @@ wrapped()
```
### aspectSync
+
This is a synchronous version of `aspect`, for situations when it's not desirable to `await` a method you're adding aspects to. The API is the same, but things like `onError` won't work if you pass an async function to the aspect.
### aspects.logs
+
Logs adds a `logs` array to the function state and just pushes in results on each run
### aspects.error
+
Captures any exceptions thrown and set it on an `error` error it puts on state
### aspects.errors
+
Captures any exceptions thrown and pushes them sequentially into an `errors` array it puts on state
### aspects.status
+
Adds a `status` property that is set to `processing` before the wrapped function runs and `succeeded` when it's done or `failed` if it threw an exception. Also adds shortcuts on state for `processing`, `succeeded`, and `failed`, which are booleans which are based on the value of `status`. Also adds a `setStatus` method which is used internally to update these properties.
### aspects.deprecate
+
Utility for marking functions as deprecated - it's just a `before` with a console.warn. Takes the name of thing being deprecated, optionally deprecation version, and optionally an alternative and returns a higher order function which you can wrap deprecated methods in. This is what's used internally to mark deprecations. Includes a partial stack trace as part of the deprecation warning.
### aspects.clearStatus
+
Sets `status` to null after provided timeout (default is 500ms) elapses. If a null timeout is passed, it will never set status to null.
### aspects.concurrency
+
Prevents a function from running if it's state has `processing` set to true at the time of invocation
### aspects.command
-Flows together `status`, `clearStatus`, `concurrency`, and `error`, taking `extend` and `timeout` as optional parameters to construct the aspect
+Flows together `status`, `clearStatus`, `concurrency`, and `error`, taking `extend` and `timeout` as optional parameters to construct the aspect
## Tree
+
All tree functions take a traversal function so that you can customize how to traverse arbitrary nested structures.
-*Note*: Be careful about cyclic structures that can result in infinite loops, such as objects with references to itself. There are cases where you'd intentionally want to visit the same node multiple times, such as traversing a directed acyclic graph (which would work just fine and eventually terminate, but would visit a node once for each parent it has connected to it) - but it's up to the user to be sure you don't create infinite loops.
+_Note_: Be careful about cyclic structures that can result in infinite loops, such as objects with references to itself. There are cases where you'd intentionally want to visit the same node multiple times, such as traversing a directed acyclic graph (which would work just fine and eventually terminate, but would visit a node once for each parent it has connected to it) - but it's up to the user to be sure you don't create infinite loops.
### isTraversable
+
`node -> bool`
A default check if something can be traversed - currently it is arrays and plain objects.
### traverse
+
`node -> [...childNodes]`
The default traversal function used in other tree methods if you don't supply one. It returns false if it's not traversable or empty, and returns the object if it is.
### walk
+
`traverse -> (pre, post=_.noop) -> tree -> x`
A depth first search which visits every node returned by `traverse` recursively. Both `pre-order` and `post-order` traversals are supported (and can be mixed freely). `walk` also supports exiting iteration early by returning a truthy value from either the `pre` or `post` functions. The returned value is also the return value of `walk`. The pre, post, and traversal functions are passed the current node as well as the parent stack (where parents[0] is the direct parent).
### walkAsync
+
`traverse -> (pre, post=_.noop) -> async tree -> x`
A version of `walk` which supports async traversals.
### transformTree
+
`traverse -> _iteratee -> tree -> newTree`
Structure preserving pre-order depth first traversal which clones, mutates, and then returns a tree. Basically `walk` with a `_.cloneDeep` first (similar to a tree map because it preserves structure). `_iteratee` can be any suitable argument to `_.iteratee` https://lodash.com/docs/4.17.5#iteratee
### reduceTree
+
`traverse -> (accumulator, initialValue, tree) -> x`
Just like `_.reduce`, but traverses over the tree with the traversal function in `pre-order`.
### mapTree
+
`(traverse, writeNode) -> f -> tree -> newTree`
Structure preserving tree map! `writeNode` informs how to write a single node, but the default will generally work for most cases. The iteratee is passed the standard `node, index, parents, parentIndexes` args and is expected to return a transformed node.
### mapTreeLeaves
+
`(traverse, writeNode) -> f -> tree -> newTree`
Like `mapTree`, but only operates on lead nodes. It is a convenience method for `mapTree(next, writeNode)(F.unless(next, mapper), tree)`
### treeToArrayBy
+
`traverse -> f -> tree -> [f(treeNode), f(treeNode), ...]`
Like `treeToArray`, but accepts a customizer to process the tree nodes before putting them in an array. The customizer is passed the standard `node, index, parents, parentIndexes` args and is expected to return a transformed node. It's `_.map` for trees - but it's not called treeMap because it does not preserve the structure as you might expect `map` to do. See `mapTree` for that behavior.
### treeToArray
+
`traverse -> tree -> [treeNode, treeNode, ...]`
Flattens the tree nodes into an array, simply recording the node values in pre-order traversal.
### leavesBy
+
`traverse -> f -> tree -> [f(treeNode), f(treeNode), ...]`
Like `leaves`, but accepts a customizer to process the leaves before putting them in an array.
### leaves
+
`traverse -> tree -> [treeNodes]`
Returns an array of the tree nodes that can't be traversed into in `pre-order`.
### treeLookup
+
`(traverse, buildIteratee) -> ([_iteratee], tree) -> treeNode`
Looks up a node matching a path, which defaults to lodash `iteratee` but can be customized with buildIteratee. The `_iteratee` members of the array can be any suitable arguments for `_.iteratee` https://lodash.com/docs/4.17.5#iteratee
### keyTreeByWith
+
`traverse -> transformer -> _iteratee -> tree -> result`
Similar to a keyBy (aka groupBy) for trees, but also transforms the grouped values (instead of filtering out tree nodes). The transformer takes three args, the current node, a boolean of if the node matches the current group, and what group is being evaluated for this iteratee. The transformer is called on each node for each grouping. `_iteratee` is any suitable argument to `_.iteratee`, as above.
### treeKeys
+
`(x, i, xs, is) => [i, ...is]`
A utility tree iteratee that returns the stack of node indexes
### treeValues
+
`(x, i, xs) => [x, ...xs]`
A utility tree iteratee that returns the stack of node values
### treePath
+
`(build, encoder) -> treePathBuilderFunction`
Creates a path builder for use in `flattenTree`. By default, the builder will look use child indexes and a dotEncoder. Encoder can be an encoding function or a futil `encoder` (an object with encode and decode functions)
### propTreePath
+
`prop -> treePathBuilderFunction`
Creates a path builder for use in `flattenTree`, using a slashEncoder and using the specified prop function as an iteratee on each node to determine the keys.
### flattenTree
+
`traverse -> buildPath -> tree -> result`
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.
### tree
+
`(traverse, buildIteratee, writeNode) -> {walk, reduce, transform, toArray, toArrayBy, leaves, leavesBy, map, mapLeaves, lookup, keyByWith, traverse, flatten, flatLeaves }`
Takes a traversal function and returns an object with all of the tree methods pre-applied with the traversal. This is useful if you want to use a few of the tree methods with a custom traversal and can provides a slightly nicer api.
Exposes provided `traverse` function as `traverse`
diff --git a/docs/beta/README.md b/docs/beta/README.md
index 2c111335..801f3585 100644
--- a/docs/beta/README.md
+++ b/docs/beta/README.md
@@ -1,4 +1,5 @@
# Futil Doc Notes
+
To run this, you'll want to run `npm run docs-site` at the root of the repo, and then `npm start` (or `npm build`, etc) here.
# Original CRA Readme
diff --git a/docs/beta/public/index.html b/docs/beta/public/index.html
index 4259f6f2..9294d38c 100644
--- a/docs/beta/public/index.html
+++ b/docs/beta/public/index.html
@@ -26,8 +26,11 @@
-->
Futil Docs
-
-
+
+
diff --git a/docs/beta/src/App.tsx b/docs/beta/src/App.tsx
index 0aca7754..bb4b27eb 100644
--- a/docs/beta/src/App.tsx
+++ b/docs/beta/src/App.tsx
@@ -1,5 +1,5 @@
-import * as React from 'react'
-import _ from 'lodash/fp'
+import * as React from "react"
+import _ from "lodash/fp"
import {
Box,
ChakraProvider,
@@ -7,22 +7,22 @@ import {
Grid,
useColorModeValue,
VStack,
-} from '@chakra-ui/react'
-import { setupHashScroll } from './utils/scroll'
-import { Doc } from './types/Doc'
+} from "@chakra-ui/react"
+import { setupHashScroll } from "./utils/scroll"
+import { Doc } from "./types/Doc"
// Components
-import Home from './components/Home'
-import { PageHeader } from './components/Header'
-import { Changelog } from './components/Changelog'
-import { TagDocs } from './components/TagDocs'
-import { MethodBox } from './components/MethodBox'
-import { Sidebar } from './components/Sidebar'
+import Home from "./components/Home"
+import { PageHeader } from "./components/Header"
+import { Changelog } from "./components/Changelog"
+import { TagDocs } from "./components/TagDocs"
+import { MethodBox } from "./components/MethodBox"
+import { Sidebar } from "./components/Sidebar"
// Data
-import docs from './data/docs.json'
-import tagDocs from './data/tag-docs.json'
-import tests from './data/tests.json'
+import docs from "./data/docs.json"
+import tagDocs from "./data/tag-docs.json"
+import tests from "./data/tests.json"
// Stamp tests on docs
_.each((doc) => {
@@ -31,15 +31,15 @@ _.each((doc) => {
let theme = extendTheme({
fonts: {
- heading: 'Lato, system-ui, sans-serif',
- body: 'Lato, system-ui, sans-serif',
+ heading: "Lato, system-ui, sans-serif",
+ body: "Lato, system-ui, sans-serif",
},
})
let headerHeight = 75
let MainContent = React.memo(() => (
-
+
{_.map(
(doc) => (
@@ -54,27 +54,27 @@ let MainContent = React.memo(() => (
))
-let initialState = { input: '', output: '', search: '', page: 'docs' }
+let initialState = { input: "", output: "", search: "", page: "docs" }
export const App = () => {
React.useEffect(setupHashScroll, [])
let [state, dispatch]: any = React.useReducer(_.merge, initialState)
let { page } = state
return (
- {page !== 'home' && }
+ {page !== "home" && }
{/* 400 is arbitrary */}
- {page === 'docs' && (
+ {page === "docs" && (
)}
- {page === 'changelog' && (
+ {page === "changelog" && (
)}
- {page === 'home' && }
+ {page === "home" && }
)
}
diff --git a/docs/beta/src/components/Badges.tsx b/docs/beta/src/components/Badges.tsx
index 93c1b3a6..95e03da1 100644
--- a/docs/beta/src/components/Badges.tsx
+++ b/docs/beta/src/components/Badges.tsx
@@ -1,5 +1,5 @@
-import _ from 'lodash/fp'
-import { Badge, HStack } from '@chakra-ui/react'
+import _ from "lodash/fp"
+import { Badge, HStack } from "@chakra-ui/react"
export let Badges = ({ badges }: { badges: string[] }) => (
diff --git a/docs/beta/src/components/Changelog.tsx b/docs/beta/src/components/Changelog.tsx
index 0bbb0482..edfdd344 100644
--- a/docs/beta/src/components/Changelog.tsx
+++ b/docs/beta/src/components/Changelog.tsx
@@ -1,16 +1,16 @@
-import { useState, useEffect, memo } from 'react'
-import _ from 'lodash/fp'
-import { Container, Heading, Link } from '@chakra-ui/react'
-import { Markdown } from './Markdown'
+import { useState, useEffect, memo } from "react"
+import _ from "lodash/fp"
+import { Container, Heading, Link } from "@chakra-ui/react"
+import { Markdown } from "./Markdown"
let fetchText = _.memoize(
async (url: string) => await (await fetch(url)).text()
)
let changelogUrl =
- 'https://raw.githubusercontent.com/smartprocure/futil-js/master/CHANGELOG.md'
+ "https://raw.githubusercontent.com/smartprocure/futil-js/master/CHANGELOG.md"
export let Changelog = memo(() => {
- let [text, setData] = useState('')
+ let [text, setData] = useState("")
useEffect(() => {
fetchText(changelogUrl).then(setData)
}, [])
diff --git a/docs/beta/src/components/CodeSnippet.tsx b/docs/beta/src/components/CodeSnippet.tsx
index 678b3afa..d3b90f35 100644
--- a/docs/beta/src/components/CodeSnippet.tsx
+++ b/docs/beta/src/components/CodeSnippet.tsx
@@ -1,7 +1,7 @@
-import { useEffect, useState, useRef, useCallback } from 'react'
-import SyntaxHighlighter from 'react-syntax-highlighter'
-import { vs2015, vs } from 'react-syntax-highlighter/dist/esm/styles/hljs'
-import { useColorMode, useColorModeValue, Flex, Button } from '@chakra-ui/react'
+import { useEffect, useState, useRef, useCallback } from "react"
+import SyntaxHighlighter from "react-syntax-highlighter"
+import { vs2015, vs } from "react-syntax-highlighter/dist/esm/styles/hljs"
+import { useColorMode, useColorModeValue, Flex, Button } from "@chakra-ui/react"
let Runkit = ({
source,
@@ -17,7 +17,7 @@ let Runkit = ({
// https://twitter.com/runkitdev/status/1110994781616799744
// atom-dark, atom-light, one-dark, one-light, solarized-dark, solarized-light, and the default runkit-light.
// let theme = useColorModeValue(undefined, 'untilted-6dtfo0ftb4ws')
- let theme = useColorModeValue('runkit-light', 'atom-dark')
+ let theme = useColorModeValue("runkit-light", "atom-dark")
let init = useCallback(() => {
if (!embed.current) {
@@ -33,17 +33,14 @@ let Runkit = ({
}
}, [preamble, source, theme])
useEffect(init, [preamble, source, theme, init])
- useEffect(
- () => {
- if (embed.current) {
- // @ts-ignore:next-line
- embed.current.destroy()
- embed.current = null
- init()
- }
- },
- [colorMode, init]
- )
+ useEffect(() => {
+ if (embed.current) {
+ // @ts-ignore:next-line
+ embed.current.destroy()
+ embed.current = null
+ init()
+ }
+ }, [colorMode, init])
return
}
@@ -59,7 +56,12 @@ type Props = {
language?: string
children?: string
}
-export const CodeSnippet = ({ forceDark, noRepl, language = 'javascript', children }: Props) => {
+export const CodeSnippet = ({
+ forceDark,
+ noRepl,
+ language = "javascript",
+ children,
+}: Props) => {
let [repl, setRepl] = useState(false)
let style = useColorModeValue(vs, vs2015)
return repl ? (
@@ -71,10 +73,11 @@ export const CodeSnippet = ({ forceDark, noRepl, language = 'javascript', childr
{!noRepl && (
-
+
)}
>
)
-
}
diff --git a/docs/beta/src/components/Header.tsx b/docs/beta/src/components/Header.tsx
index 2598bf41..b6ec42a0 100644
--- a/docs/beta/src/components/Header.tsx
+++ b/docs/beta/src/components/Header.tsx
@@ -1,4 +1,4 @@
-import _ from 'lodash/fp'
+import _ from "lodash/fp"
import {
chakra,
Grid,
@@ -16,17 +16,17 @@ import {
Tooltip,
useColorModeValue,
VStack,
-} from '@chakra-ui/react'
+} from "@chakra-ui/react"
import {
BsChevronCompactLeft,
BsChevronCompactRight,
BsJournalCode,
-} from 'react-icons/bs'
-import { FiGitPullRequest } from 'react-icons/fi'
-import { AiFillGithub, AiOutlineFunction, AiOutlineHome } from 'react-icons/ai'
-import { ColorModeSwitcher } from './ColorModeSwitcher'
-import LogoLight from '../logos/logo-light.svg'
-import LogoDark from '../logos/logo-dark.svg'
+} from "react-icons/bs"
+import { FiGitPullRequest } from "react-icons/fi"
+import { AiFillGithub, AiOutlineFunction, AiOutlineHome } from "react-icons/ai"
+import { ColorModeSwitcher } from "./ColorModeSwitcher"
+import LogoLight from "../logos/logo-light.svg"
+import LogoDark from "../logos/logo-dark.svg"
let WWTMTooltip = () => (
@@ -49,7 +49,7 @@ let NavIcon = ({ name, icon, page, dispatch }) => (
dispatch({ page: name })}
icon={icon}
aria-label={_.startCase(name)}
@@ -63,18 +63,18 @@ export let PageHeader = ({ search, input, output, page, dispatch }) => (
w="100%"
borderBottom="solid 1px"
// dark moder border is divider color
- borderColor={useColorModeValue('gray.200', 'rgba(255, 255, 255, 0.16)')}
+ borderColor={useColorModeValue("gray.200", "rgba(255, 255, 255, 0.16)")}
zIndex={10}
>
- dispatch({ page: 'home' })} cursor="pointer">
-
+ dispatch({ page: "home" })} cursor="pointer">
+ }>
diff --git a/docs/beta/src/components/Home.tsx b/docs/beta/src/components/Home.tsx
index ba9defd2..490113e9 100644
--- a/docs/beta/src/components/Home.tsx
+++ b/docs/beta/src/components/Home.tsx
@@ -1,4 +1,4 @@
-import { memo } from 'react'
+import { memo } from "react"
import {
Code,
Container,
@@ -10,10 +10,10 @@ import {
Image,
Button,
Flex,
-} from '@chakra-ui/react'
-import { CodeSnippet } from './CodeSnippet'
-import { ColorModeSwitcher } from './ColorModeSwitcher'
-import LogoDark from '../logos/logo-dark.svg'
+} from "@chakra-ui/react"
+import { CodeSnippet } from "./CodeSnippet"
+import { ColorModeSwitcher } from "./ColorModeSwitcher"
+import LogoDark from "../logos/logo-dark.svg"
type BadgeProps = {
src: string
@@ -21,7 +21,7 @@ type BadgeProps = {
href?: string
}
let Badge = ({ src, alt, href }: BadgeProps) => {
- let style = { marginRight: '5px', display: 'inline-block' }
+ let style = { marginRight: "5px", display: "inline-block" }
let image =
return href ? {image} : image
}
@@ -59,8 +59,8 @@ let Logo = () => (
// let green = 'linear(to-r, #39b54a, #8dc63f)'
// let blue = 'linear(to-r, #27aae1, #1c75bc)'
// let blue = 'linear(to-r, #1c75bc, #27aae1)'
-let gray = 'linear(to-b, gray.900, gray.700)'
-let lightGray = 'linear(225deg, gray.700, gray.900)'
+let gray = "linear(to-b, gray.900, gray.700)"
+let lightGray = "linear(225deg, gray.700, gray.900)"
let Summary = ({ dispatch }) => (
@@ -68,7 +68,7 @@ let Summary = ({ dispatch }) => (
- A collection of Functional Utilities. Resistance is{' '}
+ A collection of Functional Utilities. Resistance is{" "}
futile.
@@ -77,21 +77,21 @@ let Summary = ({ dispatch }) => (
are not.
- Designed to work with any other utility library. lodash{' '}
+ Designed to work with any other utility library. lodash{" "}
and ramda work great. lodash/fp works best.
@@ -132,7 +132,7 @@ let BrowserCoverage = () => (
{/* Browser Compatibility */}
@@ -145,8 +145,8 @@ export default memo(({ dispatch }: { dispatch: (any) => {} }) => (
@@ -155,7 +155,7 @@ export default memo(({ dispatch }: { dispatch: (any) => {} }) => (
Why futil?
- Designed to work with any other utility library. lodash{' '}
+ Designed to work with any other utility library. lodash{" "}
and ramda work great. lodash/fp works
best.
@@ -163,8 +163,8 @@ export default memo(({ dispatch }: { dispatch: (any) => {} }) => (
Brought to you by the SmartProcure/GovSpend team
diff --git a/docs/beta/src/components/Markdown.tsx b/docs/beta/src/components/Markdown.tsx
index ac6149a7..417b1e04 100644
--- a/docs/beta/src/components/Markdown.tsx
+++ b/docs/beta/src/components/Markdown.tsx
@@ -1,13 +1,13 @@
-import remarkGfm from 'remark-gfm'
-import ReactMarkdown from 'react-markdown'
-import ChakraUIRenderer from 'chakra-ui-markdown-renderer'
-import { Heading } from '@chakra-ui/react'
+import remarkGfm from "remark-gfm"
+import ReactMarkdown from "react-markdown"
+import ChakraUIRenderer from "chakra-ui-markdown-renderer"
+import { Heading } from "@chakra-ui/react"
export let Markdown = ({ children }: { children: string }) => (
(
-
+
{children}
),
diff --git a/docs/beta/src/components/MethodBox.tsx b/docs/beta/src/components/MethodBox.tsx
index 7d035ee4..3baf9d8d 100644
--- a/docs/beta/src/components/MethodBox.tsx
+++ b/docs/beta/src/components/MethodBox.tsx
@@ -11,11 +11,11 @@ import {
Tabs,
useColorModeValue,
VStack,
-} from '@chakra-ui/react'
-import { Doc } from '../types/Doc'
-import { Badges } from './Badges'
-import { Markdown } from './Markdown'
-import { CodeSnippet } from './CodeSnippet'
+} from "@chakra-ui/react"
+import { Doc } from "../types/Doc"
+import { Badges } from "./Badges"
+import { Markdown } from "./Markdown"
+import { CodeSnippet } from "./CodeSnippet"
let headerHeight = 75
@@ -25,7 +25,7 @@ export let MethodBox = ({ doc }: { doc: Doc }) => (
scrollMarginTop={headerHeight}
p={8}
rounded="md"
- bg={useColorModeValue('white', 'gray.800')}
+ bg={useColorModeValue("white", "gray.800")}
>
diff --git a/docs/beta/src/components/Sidebar.tsx b/docs/beta/src/components/Sidebar.tsx
index 75299b4b..68295bc8 100644
--- a/docs/beta/src/components/Sidebar.tsx
+++ b/docs/beta/src/components/Sidebar.tsx
@@ -1,18 +1,18 @@
-import * as React from 'react'
-import _ from 'lodash/fp'
-import F from 'futil'
+import * as React from "react"
+import _ from "lodash/fp"
+import F from "futil"
import {
Divider,
Flex,
Link,
useColorModeValue,
VStack,
-} from '@chakra-ui/react'
-import { Doc } from '../types/Doc'
-import { filterDocs } from '../utils/filterDocs'
-import { scrollToMethod } from '../utils/scroll'
-import { TextHighlight } from './TextHighlight'
-import { Badges } from './Badges'
+} from "@chakra-ui/react"
+import { Doc } from "../types/Doc"
+import { filterDocs } from "../utils/filterDocs"
+import { scrollToMethod } from "../utils/scroll"
+import { TextHighlight } from "./TextHighlight"
+import { Badges } from "./Badges"
let headerHeight = 75
@@ -33,24 +33,24 @@ export let Sidebar = ({ docs, search, input, output }: SidebarProps) => (
py={4}
borderRight="solid 1px"
// dark moder border is divider color
- borderColor={useColorModeValue('gray.200', 'rgba(255, 255, 255, 0.16)')}
+ borderColor={useColorModeValue("gray.200", "rgba(255, 255, 255, 0.16)")}
spacing={4}
_before={{
- pointerEvents: 'none',
- position: 'fixed',
+ pointerEvents: "none",
+ position: "fixed",
content: '""',
- display: 'block',
- left: '0px',
- bottom: '0px',
- width: '400px', // arbitrary sidebar width
- height: '142px', // arbitrary height
+ display: "block",
+ left: "0px",
+ bottom: "0px",
+ width: "400px", // arbitrary sidebar width
+ height: "142px", // arbitrary height
background: useColorModeValue(
// linear gradient from 0-100 opacity of bg color
- 'linear-gradient(0deg, rgba(255, 255, 255, 1) 30%, rgba(255, 255, 255, 0) 100%)',
+ "linear-gradient(0deg, rgba(255, 255, 255, 1) 30%, rgba(255, 255, 255, 0) 100%)",
// rgb values for dark body bg
- 'linear-gradient(0deg, rgba(26, 32, 44, 1) 30%, rgba(26, 32, 44, 0) 100%)'
+ "linear-gradient(0deg, rgba(26, 32, 44, 1) 30%, rgba(26, 32, 44, 0) 100%)"
),
- transition: 'opacity 1s ease 0s',
+ transition: "opacity 1s ease 0s",
}}
_hover={{ _before: { opacity: 0 } }}
>
@@ -72,9 +72,9 @@ export let Sidebar = ({ docs, search, input, output }: SidebarProps) => (
(
>
{/* Our TextHighlight seems more performant than Chakra's */}
{/* {`${
diff --git a/docs/beta/src/components/TagDocs.tsx b/docs/beta/src/components/TagDocs.tsx
index d57eebb4..272a8797 100644
--- a/docs/beta/src/components/TagDocs.tsx
+++ b/docs/beta/src/components/TagDocs.tsx
@@ -1,5 +1,5 @@
-import * as React from 'react'
-import _ from 'lodash/fp'
+import * as React from "react"
+import _ from "lodash/fp"
import {
Box,
Heading,
@@ -9,20 +9,20 @@ import {
AccordionButton,
AccordionPanel,
AccordionIcon,
-} from '@chakra-ui/react'
-import { Markdown } from './Markdown'
+} from "@chakra-ui/react"
+import { Markdown } from "./Markdown"
let TagTitle = ({ tag }) => (
{tag}
- {' '}
+ {" "}
Methods
)
export let TagDocs = ({ unseenTags, tagDocs }) => {
- let panelBg = useColorModeValue('gray.200', 'gray.600')
+ let panelBg = useColorModeValue("gray.200", "gray.600")
return (
<>
{_.map(
diff --git a/docs/beta/src/components/TextHighlight.tsx b/docs/beta/src/components/TextHighlight.tsx
index b8fb69d3..a5e40608 100644
--- a/docs/beta/src/components/TextHighlight.tsx
+++ b/docs/beta/src/components/TextHighlight.tsx
@@ -1,11 +1,11 @@
-import F from 'futil'
-import { Text } from '@chakra-ui/react'
+import F from "futil"
+import { Text } from "@chakra-ui/react"
let TextWrap = (props: any) =>
// Since start and end are the same token, splitting on it means every even element was a match
type Props = { pattern: string; text: string; Wrap?: any }
export let TextHighlight = ({ pattern, text, Wrap = TextWrap }: Props) =>
pattern
- ? F.highlight('<>', '<>', pattern, text)
- .split('<>')
+ ? F.highlight("<>", "<>", pattern, text)
+ .split("<>")
.map((x: string, i: number) => (i % 2 ? {x} : x))
: text
diff --git a/docs/beta/src/index.tsx b/docs/beta/src/index.tsx
index c28e918a..66f86af9 100644
--- a/docs/beta/src/index.tsx
+++ b/docs/beta/src/index.tsx
@@ -5,16 +5,15 @@ import { App } from "./App"
import reportWebVitals from "./reportWebVitals"
import * as serviceWorker from "./serviceWorker"
-
const container = document.getElementById("root")
-if (!container) throw new Error('Failed to find the root element');
+if (!container) throw new Error("Failed to find the root element")
const root = ReactDOM.createRoot(container)
root.render(
- ,
+
)
// If you want your app to work offline and load faster, you can change
@@ -26,4 +25,3 @@ serviceWorker.unregister()
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals()
-
diff --git a/docs/beta/src/serviceWorker.ts b/docs/beta/src/serviceWorker.ts
index 69f26b60..9ae62b3d 100644
--- a/docs/beta/src/serviceWorker.ts
+++ b/docs/beta/src/serviceWorker.ts
@@ -16,8 +16,8 @@ const isLocalhost = Boolean(
window.location.hostname === "[::1]" ||
// 127.0.0.0/8 are considered localhost for IPv4.
window.location.hostname.match(
- /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/,
- ),
+ /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
+ )
)
type Config = {
@@ -48,7 +48,7 @@ export function register(config?: Config) {
navigator.serviceWorker.ready.then(() => {
console.log(
"This web app is being served cache-first by a service " +
- "worker. To learn more, visit https://cra.link/PWA",
+ "worker. To learn more, visit https://cra.link/PWA"
)
})
} else {
@@ -76,7 +76,7 @@ function registerValidSW(swUrl: string, config?: Config) {
// content until all client tabs are closed.
console.log(
"New content is available and will be used when all " +
- "tabs for this page are closed. See https://cra.link/PWA.",
+ "tabs for this page are closed. See https://cra.link/PWA."
)
// Execute callback
@@ -128,7 +128,7 @@ function checkValidServiceWorker(swUrl: string, config?: Config) {
})
.catch(() => {
console.log(
- "No internet connection found. App is running in offline mode.",
+ "No internet connection found. App is running in offline mode."
)
})
}
diff --git a/docs/beta/src/utils/exploreAPI.js b/docs/beta/src/utils/exploreAPI.js
index 9958c2e0..249d73d0 100644
--- a/docs/beta/src/utils/exploreAPI.js
+++ b/docs/beta/src/utils/exploreAPI.js
@@ -1,5 +1,5 @@
-import F from 'futil'
-import _ from 'lodash/fp'
+import F from "futil"
+import _ from "lodash/fp"
// Needed because calling methods with unexpected parameters could cause exceptions
export let ignoreError = _.curryN(2, (f, ...args) => {
@@ -13,24 +13,21 @@ export let ignoreError = _.curryN(2, (f, ...args) => {
let suppressedEval = ignoreError(eval)
// Needed because eval({ a:1 }) returns 1
-export let tolerantEval = x => suppressedEval(`(${x})`)
-export let tolerantArrayEval = x => suppressedEval(`[${x}]`)
+export let tolerantEval = (x) => suppressedEval(`(${x})`)
+export let tolerantArrayEval = (x) => suppressedEval(`[${x}]`)
// Find _all_ keys that match
export let findKeys = (f, obj) =>
- _.flow(
- _.pickBy.convert({ cap: false })(f),
- _.keys
- )(obj)
+ _.flow(_.pickBy.convert({ cap: false })(f), _.keys)(obj)
// The main exploreAPI function
-export let exploreAPI = (lib, inputs, output, e = x => x) => {
+export let exploreAPI = (lib, inputs, output, e = (x) => x) => {
let inputValues = _.map(e, inputs)
let expected = e(output)
return findKeys(
ignoreError(
- f =>
- !_.get('state.isDeprecated', f) &&
+ (f) =>
+ !_.get("state.isDeprecated", f) &&
_.isEqual(F.maybeCall(f, ...inputValues), expected)
),
lib
diff --git a/docs/beta/src/utils/filterDocs.ts b/docs/beta/src/utils/filterDocs.ts
index 91457613..285c88fd 100644
--- a/docs/beta/src/utils/filterDocs.ts
+++ b/docs/beta/src/utils/filterDocs.ts
@@ -1,8 +1,8 @@
-import F from 'futil'
-import _ from 'lodash/fp'
-import * as R from 'ramda'
-import { Doc } from '../types/Doc'
-import { exploreAPI, tolerantEval, tolerantArrayEval } from './exploreAPI'
+import F from "futil"
+import _ from "lodash/fp"
+import * as R from "ramda"
+import { Doc } from "../types/Doc"
+import { exploreAPI, tolerantEval, tolerantArrayEval } from "./exploreAPI"
export let filterDocs = (
search: string,
@@ -20,17 +20,11 @@ export let filterDocs = (
let exploreRamda = input ? exploreAPI(R, processedInput, processedOutput) : []
return [
- ..._.filter(doc => {
+ ..._.filter((doc) => {
if (input) return _.includes(doc.name, exploreMatches)
return regex.test(doc.name) || regex.test(doc.description)
}, docs),
- ..._.map(
- name => ({ name, lib: '_', tags: ['lodash'] }),
- exploreLodash
- ),
- ..._.map(
- name => ({ name, lib: 'R', tags: ['ramda'] }),
- exploreRamda
- ),
+ ..._.map((name) => ({ name, lib: "_", tags: ["lodash"] }), exploreLodash),
+ ..._.map((name) => ({ name, lib: "R", tags: ["ramda"] }), exploreRamda),
]
}
diff --git a/docs/beta/src/utils/scroll.ts b/docs/beta/src/utils/scroll.ts
index 8957dd34..b684852d 100644
--- a/docs/beta/src/utils/scroll.ts
+++ b/docs/beta/src/utils/scroll.ts
@@ -1,15 +1,15 @@
export let scrollToMethod = (name: string) => {
let element = document.getElementById(`${name}-method`)
- element && element.scrollIntoView({ behavior: 'smooth' })
+ element && element.scrollIntoView({ behavior: "smooth" })
}
let scrollToHash = () => {
- scrollToMethod(window.location.hash.replace('#', ''))
+ scrollToMethod(window.location.hash.replace("#", ""))
}
export let setupHashScroll = () => {
scrollToHash()
- window.addEventListener('hashchange', scrollToHash)
+ window.addEventListener("hashchange", scrollToHash)
return () => {
- window.removeEventListener('hashchange', scrollToHash)
+ window.removeEventListener("hashchange", scrollToHash)
}
}
diff --git a/docs/beta/tsconfig.json b/docs/beta/tsconfig.json
index eb5e7286..ebac916a 100644
--- a/docs/beta/tsconfig.json
+++ b/docs/beta/tsconfig.json
@@ -1,11 +1,7 @@
{
"compilerOptions": {
"target": "es5",
- "lib": [
- "dom",
- "dom.iterable",
- "esnext"
- ],
+ "lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
@@ -19,9 +15,7 @@
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
- "noImplicitAny": false,
+ "noImplicitAny": false
},
- "include": [
- "src"
-, "manual-data-backup/data" ]
+ "include": ["src", "manual-data-backup/data"]
}
diff --git a/docs/index.html b/docs/index.html
index 94d408a6..0c3dbe64 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -1,4 +1,4 @@
-
+
-
-
-
-
+
+
+
+
- futil-js
+ futil-js
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-