From 395a6eb58fd0dc97b5b69b4aa722cc5c25b2a00f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 09:55:24 +0200 Subject: [PATCH 01/56] Initialize package.json --- package.json | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 package.json diff --git a/package.json b/package.json new file mode 100644 index 00000000..5a0d3f49 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "@sandstreamdev/std", + "version": "0.1.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/sandstreamdev/std.git" + }, + "keywords": [], + "author": { + "name": "Sandstream Development", + "url": "https://www.sandstream.pl/" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/sandstreamdev/std/issues" + }, + "homepage": "https://github.com/sandstreamdev/std#readme" +} From 2e1cc11425c6d3a46946078fc77c415150c3bfc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 10:09:49 +0200 Subject: [PATCH 02/56] Enable prettier --- README.md | 2 +- package-lock.json | 14 ++++++++++++++ package.json | 9 +++++++-- 3 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 package-lock.json diff --git a/README.md b/README.md index 0d24f20d..b85fd3e2 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# std \ No newline at end of file +# std diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..918666e9 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,14 @@ +{ + "name": "@sandstreamdev/std", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "prettier": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.18.2.tgz", + "integrity": "sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==", + "dev": true + } + } +} diff --git a/package.json b/package.json index 5a0d3f49..83e200b3 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,9 @@ "description": "", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "prettier": "prettier \"**/*.{js,json,md}\"", + "prettier:fix": "npm run prettier -- --write", + "prettier:check": "npm run prettier -- --check" }, "repository": { "type": "git", @@ -19,5 +21,8 @@ "bugs": { "url": "https://github.com/sandstreamdev/std/issues" }, - "homepage": "https://github.com/sandstreamdev/std#readme" + "homepage": "https://github.com/sandstreamdev/std#readme", + "devDependencies": { + "prettier": "^1.18.2" + } } From d7886e9026cec96778b246527d52c6964065adfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 10:11:15 +0200 Subject: [PATCH 03/56] Declare package type and no side effects --- package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.json b/package.json index 83e200b3..5e7d69e6 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,8 @@ "version": "0.1.0", "description": "", "main": "index.js", + "type": "module", + "sideEffects": false, "scripts": { "prettier": "prettier \"**/*.{js,json,md}\"", "prettier:fix": "npm run prettier -- --write", From 5a3d0d48b74f687ae1fd292ab30be8fffa62640d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 10:12:01 +0200 Subject: [PATCH 04/56] Add initial helpers --- array/any.js | 1 + array/are.js | 3 ++ array/differs.js | 5 ++ array/duplicates.js | 2 + array/empty.js | 1 + array/exact.js | 4 ++ array/except.js | 1 + array/filterInPlace.js | 15 ++++++ array/find.js | 4 ++ array/first.js | 1 + array/flatMap.js | 1 + array/flatten.js | 1 + array/intersection.js | 1 + array/is.js | 1 + array/last.js | 1 + array/lengthDiffers.js | 1 + array/map.js | 4 ++ array/midpoint.js | 1 + array/minMax.js | 7 +++ array/multiple.js | 1 + array/partition.js | 8 +++ array/range.js | 4 ++ array/repeat.js | 1 + array/reverse.js | 1 + array/reverseIf.js | 1 + array/rotate.js | 8 +++ array/second.js | 1 + array/secondToLast.js | 1 + array/shift.js | 2 + array/shuffle.js | 3 ++ array/shuffleInPlace.js | 8 +++ array/single.js | 1 + array/sort.js | 1 + array/sum.js | 3 ++ array/transpose.js | 1 + array/zip.js | 3 ++ array/zipWith.js | 1 + async/debounce.js | 15 ++++++ async/delay.js | 2 + async/sequence.js | 14 ++++++ date/byDateWithFallback.js | 18 +++++++ date/clamp.js | 7 +++ date/dateDiff.js | 6 +++ date/dateInRange.js | 7 +++ date/dayRange.js | 24 +++++++++ date/daysInMonths.js | 14 ++++++ date/daysInYear.js | 5 ++ date/displayTime.js | 14 ++++++ date/endOfDay.js | 9 ++++ date/formatDate.js | 19 ++++++++ date/formatDateTime.js | 8 +++ date/formatDuration.js | 16 ++++++ date/formatTime.js | 11 +++++ date/fromDays.js | 3 ++ date/fromHours.js | 3 ++ date/fromMinutes.js | 3 ++ date/fromSeconds.js | 1 + date/joinDateTime.js | 1 + date/leapYear.js | 1 + date/monthRange.js | 24 +++++++++ date/offsetByBit.js | 3 ++ date/parseHourMinutePair.js | 6 +++ date/splitDateTime.js | 1 + date/startOfDay.js | 9 ++++ date/subtractDays.js | 7 +++ date/toDate.js | 11 +++++ date/toDates.js | 1 + date/toDays.js | 3 ++ date/toHours.js | 3 ++ date/toISO.js | 1 + date/toISOFromLocalDateTime.js | 6 +++ date/toLocalDateTime.js | 2 + date/toMinutes.js | 3 ++ date/toSeconds.js | 1 + date/valid.js | 1 + date/weekRange.js | 24 +++++++++ date/yearRange.js | 24 +++++++++ debug/assert.js | 52 ++++++++++++++++++++ debug/diff.js | 83 ++++++++++++++++++++++++++++++++ encoding/base64url.js | 11 +++++ file/validName.js | 5 ++ function/compose.js | 1 + function/constant.js | 1 + function/identity.js | 1 + function/memoize.js | 4 ++ function/memoizeShallow.js | 4 ++ function/memoizeWith.js | 12 +++++ function/noOp.js | 1 + function/pipe.js | 1 + function/when.js | 5 ++ function/whenTrue.js | 3 ++ is/array.js | 1 + is/byte.js | 3 ++ is/date.js | 1 + is/defined.js | 1 + is/function.js | 1 + is/integer.js | 3 ++ is/normal.js | 3 ++ is/number.js | 1 + is/object.js | 1 + is/string.js | 1 + math/add.js | 1 + math/average.js | 3 ++ math/ceilToNearestPowerOfTwo.js | 1 + math/clamp.js | 1 + math/clampNormal.js | 3 ++ math/delta.js | 1 + math/inRectangleRange.js | 2 + math/lerp.js | 1 + math/maximumBy.js | 2 + math/median.js | 13 +++++ math/minMax.js | 1 + math/safeNormalize.js | 1 + math/sameSign.js | 9 ++++ math/standardDeviation.js | 8 +++ math/subtract.js | 1 + object/any.js | 3 ++ object/apply.js | 5 ++ object/empty.js | 1 + object/entries.js | 2 + object/enumerable.js | 2 + object/equals.js | 29 +++++++++++ object/filter.js | 5 ++ object/find.js | 4 ++ object/findKey.js | 1 + object/findValue.js | 1 + object/first.js | 1 + object/flatMapValues.js | 5 ++ object/fromEntries.js | 6 +++ object/groupBy.js | 5 ++ object/hasKey.js | 2 + object/length.js | 1 + object/map.js | 4 ++ object/mapEntries.js | 4 ++ object/mapKeys.js | 5 ++ object/mapValues.js | 3 ++ object/none.js | 3 ++ object/sort.js | 5 ++ query/parse.js | 17 +++++++ query/parsePathname.js | 32 ++++++++++++ query/read.js | 5 ++ query/serialize.js | 8 +++ range/empty.js | 1 + range/equals.js | 1 + range/length.js | 1 + range/split.js | 38 +++++++++++++++ regex/escape.js | 1 + string/containsWhitespace.js | 1 + string/empty.js | 1 + string/firstToLower.js | 1 + string/firstToUpper.js | 1 + string/includes.js | 1 + string/nbsp.js | 1 + string/nonEmpty.js | 1 + string/startsWith.js | 1 + vector2/add.js | 1 + vector2/convertSpace.js | 6 +++ vector2/cross.js | 1 + vector2/dot.js | 1 + vector2/length.js | 1 + vector2/mul.js | 4 ++ vector2/multiply.js | 8 +++ vector2/normalize.js | 6 +++ vector2/reflect.js | 4 ++ vector2/rotate.js | 20 ++++++++ vector2/scale.js | 8 +++ vector2/sub.js | 1 + vector2/transform.js | 1 + vector2/translate.js | 8 +++ web/classNames.js | 16 ++++++ web/events/cancel.js | 8 +++ web/events/openInNewTabIntent.js | 2 + web/events/prevent.js | 4 ++ web/events/stop.js | 4 ++ 174 files changed, 996 insertions(+) create mode 100644 array/any.js create mode 100644 array/are.js create mode 100644 array/differs.js create mode 100644 array/duplicates.js create mode 100644 array/empty.js create mode 100644 array/exact.js create mode 100644 array/except.js create mode 100644 array/filterInPlace.js create mode 100644 array/find.js create mode 100644 array/first.js create mode 100644 array/flatMap.js create mode 100644 array/flatten.js create mode 100644 array/intersection.js create mode 100644 array/is.js create mode 100644 array/last.js create mode 100644 array/lengthDiffers.js create mode 100644 array/map.js create mode 100644 array/midpoint.js create mode 100644 array/minMax.js create mode 100644 array/multiple.js create mode 100644 array/partition.js create mode 100644 array/range.js create mode 100644 array/repeat.js create mode 100644 array/reverse.js create mode 100644 array/reverseIf.js create mode 100644 array/rotate.js create mode 100644 array/second.js create mode 100644 array/secondToLast.js create mode 100644 array/shift.js create mode 100644 array/shuffle.js create mode 100644 array/shuffleInPlace.js create mode 100644 array/single.js create mode 100644 array/sort.js create mode 100644 array/sum.js create mode 100644 array/transpose.js create mode 100644 array/zip.js create mode 100644 array/zipWith.js create mode 100644 async/debounce.js create mode 100644 async/delay.js create mode 100644 async/sequence.js create mode 100644 date/byDateWithFallback.js create mode 100644 date/clamp.js create mode 100644 date/dateDiff.js create mode 100644 date/dateInRange.js create mode 100644 date/dayRange.js create mode 100644 date/daysInMonths.js create mode 100644 date/daysInYear.js create mode 100644 date/displayTime.js create mode 100644 date/endOfDay.js create mode 100644 date/formatDate.js create mode 100644 date/formatDateTime.js create mode 100644 date/formatDuration.js create mode 100644 date/formatTime.js create mode 100644 date/fromDays.js create mode 100644 date/fromHours.js create mode 100644 date/fromMinutes.js create mode 100644 date/fromSeconds.js create mode 100644 date/joinDateTime.js create mode 100644 date/leapYear.js create mode 100644 date/monthRange.js create mode 100644 date/offsetByBit.js create mode 100644 date/parseHourMinutePair.js create mode 100644 date/splitDateTime.js create mode 100644 date/startOfDay.js create mode 100644 date/subtractDays.js create mode 100644 date/toDate.js create mode 100644 date/toDates.js create mode 100644 date/toDays.js create mode 100644 date/toHours.js create mode 100644 date/toISO.js create mode 100644 date/toISOFromLocalDateTime.js create mode 100644 date/toLocalDateTime.js create mode 100644 date/toMinutes.js create mode 100644 date/toSeconds.js create mode 100644 date/valid.js create mode 100644 date/weekRange.js create mode 100644 date/yearRange.js create mode 100644 debug/assert.js create mode 100644 debug/diff.js create mode 100644 encoding/base64url.js create mode 100644 file/validName.js create mode 100644 function/compose.js create mode 100644 function/constant.js create mode 100644 function/identity.js create mode 100644 function/memoize.js create mode 100644 function/memoizeShallow.js create mode 100644 function/memoizeWith.js create mode 100644 function/noOp.js create mode 100644 function/pipe.js create mode 100644 function/when.js create mode 100644 function/whenTrue.js create mode 100644 is/array.js create mode 100644 is/byte.js create mode 100644 is/date.js create mode 100644 is/defined.js create mode 100644 is/function.js create mode 100644 is/integer.js create mode 100644 is/normal.js create mode 100644 is/number.js create mode 100644 is/object.js create mode 100644 is/string.js create mode 100644 math/add.js create mode 100644 math/average.js create mode 100644 math/ceilToNearestPowerOfTwo.js create mode 100644 math/clamp.js create mode 100644 math/clampNormal.js create mode 100644 math/delta.js create mode 100644 math/inRectangleRange.js create mode 100644 math/lerp.js create mode 100644 math/maximumBy.js create mode 100644 math/median.js create mode 100644 math/minMax.js create mode 100644 math/safeNormalize.js create mode 100644 math/sameSign.js create mode 100644 math/standardDeviation.js create mode 100644 math/subtract.js create mode 100644 object/any.js create mode 100644 object/apply.js create mode 100644 object/empty.js create mode 100644 object/entries.js create mode 100644 object/enumerable.js create mode 100644 object/equals.js create mode 100644 object/filter.js create mode 100644 object/find.js create mode 100644 object/findKey.js create mode 100644 object/findValue.js create mode 100644 object/first.js create mode 100644 object/flatMapValues.js create mode 100644 object/fromEntries.js create mode 100644 object/groupBy.js create mode 100644 object/hasKey.js create mode 100644 object/length.js create mode 100644 object/map.js create mode 100644 object/mapEntries.js create mode 100644 object/mapKeys.js create mode 100644 object/mapValues.js create mode 100644 object/none.js create mode 100644 object/sort.js create mode 100644 query/parse.js create mode 100644 query/parsePathname.js create mode 100644 query/read.js create mode 100644 query/serialize.js create mode 100644 range/empty.js create mode 100644 range/equals.js create mode 100644 range/length.js create mode 100644 range/split.js create mode 100644 regex/escape.js create mode 100644 string/containsWhitespace.js create mode 100644 string/empty.js create mode 100644 string/firstToLower.js create mode 100644 string/firstToUpper.js create mode 100644 string/includes.js create mode 100644 string/nbsp.js create mode 100644 string/nonEmpty.js create mode 100644 string/startsWith.js create mode 100644 vector2/add.js create mode 100644 vector2/convertSpace.js create mode 100644 vector2/cross.js create mode 100644 vector2/dot.js create mode 100644 vector2/length.js create mode 100644 vector2/mul.js create mode 100644 vector2/multiply.js create mode 100644 vector2/normalize.js create mode 100644 vector2/reflect.js create mode 100644 vector2/rotate.js create mode 100644 vector2/scale.js create mode 100644 vector2/sub.js create mode 100644 vector2/transform.js create mode 100644 vector2/translate.js create mode 100644 web/classNames.js create mode 100644 web/events/cancel.js create mode 100644 web/events/openInNewTabIntent.js create mode 100644 web/events/prevent.js create mode 100644 web/events/stop.js diff --git a/array/any.js b/array/any.js new file mode 100644 index 00000000..f9a2b66c --- /dev/null +++ b/array/any.js @@ -0,0 +1 @@ +export default xs => xs && xs.length > 0; diff --git a/array/are.js b/array/are.js new file mode 100644 index 00000000..c32dc386 --- /dev/null +++ b/array/are.js @@ -0,0 +1,3 @@ +import is from "./is"; + +export default (...xs) => xs.every(is); diff --git a/array/differs.js b/array/differs.js new file mode 100644 index 00000000..1fac6689 --- /dev/null +++ b/array/differs.js @@ -0,0 +1,5 @@ +export default (xs, ys) => + (!xs && ys) || + (!ys && xs) || + xs.length !== ys.length || + xs.some((x, index) => x !== ys[index]); diff --git a/array/duplicates.js b/array/duplicates.js new file mode 100644 index 00000000..f3ff72f7 --- /dev/null +++ b/array/duplicates.js @@ -0,0 +1,2 @@ +export default xs => + xs.filter((value, index, self) => self.indexOf(value) !== index); diff --git a/array/empty.js b/array/empty.js new file mode 100644 index 00000000..d6d1738d --- /dev/null +++ b/array/empty.js @@ -0,0 +1 @@ +export default []; diff --git a/array/exact.js b/array/exact.js new file mode 100644 index 00000000..0b6e8fac --- /dev/null +++ b/array/exact.js @@ -0,0 +1,4 @@ +export default n => source => + Array(n) + .fill() + .map((_, i) => source[i]); diff --git a/array/except.js b/array/except.js new file mode 100644 index 00000000..b721e9d4 --- /dev/null +++ b/array/except.js @@ -0,0 +1 @@ +export default y => xs => xs.filter(x => x !== y); diff --git a/array/filterInPlace.js b/array/filterInPlace.js new file mode 100644 index 00000000..375df26e --- /dev/null +++ b/array/filterInPlace.js @@ -0,0 +1,15 @@ +export default filterInPlace = f => xs => { + let i = 0; + let j = 0; + + while (i < xs.length) { + const value = xs[i]; + if (f(value, i, xs)) { + xs[j++] = value; + } + i++; + } + + xs.length = j; + return xs; +}; diff --git a/array/find.js b/array/find.js new file mode 100644 index 00000000..9e4018a0 --- /dev/null +++ b/array/find.js @@ -0,0 +1,4 @@ +export default (predicate, fallback) => xs => { + const target = xs.find(predicate); + return target !== undefined ? target : fallback; +}; diff --git a/array/first.js b/array/first.js new file mode 100644 index 00000000..089de9a1 --- /dev/null +++ b/array/first.js @@ -0,0 +1 @@ +export default first = ([x]) => x; diff --git a/array/flatMap.js b/array/flatMap.js new file mode 100644 index 00000000..00184cb9 --- /dev/null +++ b/array/flatMap.js @@ -0,0 +1 @@ +export default f => xs => xs.reduce((ys, y) => ys.concat(f(y)), []); diff --git a/array/flatten.js b/array/flatten.js new file mode 100644 index 00000000..936f23dd --- /dev/null +++ b/array/flatten.js @@ -0,0 +1 @@ +export default xs => [].concat(...xs); diff --git a/array/intersection.js b/array/intersection.js new file mode 100644 index 00000000..647ae519 --- /dev/null +++ b/array/intersection.js @@ -0,0 +1 @@ +export default (xs, ys) => xs.filter(value => ys.includes(value)); diff --git a/array/is.js b/array/is.js new file mode 100644 index 00000000..b0f97bbe --- /dev/null +++ b/array/is.js @@ -0,0 +1 @@ +export default value => Array.isArray(value); diff --git a/array/last.js b/array/last.js new file mode 100644 index 00000000..8302bdbb --- /dev/null +++ b/array/last.js @@ -0,0 +1 @@ +export default xs => xs[xs.length - 1]; diff --git a/array/lengthDiffers.js b/array/lengthDiffers.js new file mode 100644 index 00000000..f8019d11 --- /dev/null +++ b/array/lengthDiffers.js @@ -0,0 +1 @@ +export default (a, b) => a.length !== b.length; diff --git a/array/map.js b/array/map.js new file mode 100644 index 00000000..a61d5d13 --- /dev/null +++ b/array/map.js @@ -0,0 +1,4 @@ +export default (...fs) => { + const f = x => fs.reduce((x, f) => f(x), x); + return x => x.map(f); +}; diff --git a/array/midpoint.js b/array/midpoint.js new file mode 100644 index 00000000..6acdb881 --- /dev/null +++ b/array/midpoint.js @@ -0,0 +1 @@ +export default xs => xs[Math.floor(xs.length / 2)]; diff --git a/array/minMax.js b/array/minMax.js new file mode 100644 index 00000000..a1129efa --- /dev/null +++ b/array/minMax.js @@ -0,0 +1,7 @@ +const { max, min } = Math; + +export default ([head, ...tail]) => + tail.reduce(([min, max], current) => [min(min, current), max(max, current)], [ + head, + head + ]); diff --git a/array/multiple.js b/array/multiple.js new file mode 100644 index 00000000..19d1cdb0 --- /dev/null +++ b/array/multiple.js @@ -0,0 +1 @@ +export default xs => xs.length > 1; diff --git a/array/partition.js b/array/partition.js new file mode 100644 index 00000000..039a6ce7 --- /dev/null +++ b/array/partition.js @@ -0,0 +1,8 @@ +export default predicate => xs => + xs.reduce( + ([left, right], current) => { + const pass = predicate(current); + return pass ? [left, [...right, current]] : [[...left, current], right]; + }, + [[], []] + ); diff --git a/array/range.js b/array/range.js new file mode 100644 index 00000000..04a9907e --- /dev/null +++ b/array/range.js @@ -0,0 +1,4 @@ +export default n => + Array(n) + .fill() + .map((_, i) => i); diff --git a/array/repeat.js b/array/repeat.js new file mode 100644 index 00000000..8a7290ed --- /dev/null +++ b/array/repeat.js @@ -0,0 +1 @@ +export default n => value => range(n).map(() => value); diff --git a/array/reverse.js b/array/reverse.js new file mode 100644 index 00000000..75a00a68 --- /dev/null +++ b/array/reverse.js @@ -0,0 +1 @@ +export default xs => [...xs].reverse(); diff --git a/array/reverseIf.js b/array/reverseIf.js new file mode 100644 index 00000000..b718eb60 --- /dev/null +++ b/array/reverseIf.js @@ -0,0 +1 @@ +export default predicate => xs => (predicate ? reverse(xs) : xs); diff --git a/array/rotate.js b/array/rotate.js new file mode 100644 index 00000000..32a160cd --- /dev/null +++ b/array/rotate.js @@ -0,0 +1,8 @@ +export default array => angle => { + const margin = Math.PI / 8; + const angleWithMargin = angle + margin; + const unit = Math.PI / 4; + const ratio = angleWithMargin / unit; + const offset = Math.floor(ratio); + return shift(offset)(array); +}; diff --git a/array/second.js b/array/second.js new file mode 100644 index 00000000..41953d02 --- /dev/null +++ b/array/second.js @@ -0,0 +1 @@ +export default ([, x]) => x; diff --git a/array/secondToLast.js b/array/secondToLast.js new file mode 100644 index 00000000..134e4b9c --- /dev/null +++ b/array/secondToLast.js @@ -0,0 +1 @@ +export default xs => xs[xs.length - 2]; diff --git a/array/shift.js b/array/shift.js new file mode 100644 index 00000000..b0cc0987 --- /dev/null +++ b/array/shift.js @@ -0,0 +1,2 @@ +export default n => xs => + xs.map((_, index) => xs[(index + (n % xs.length) + xs.length) % xs.length]); diff --git a/array/shuffle.js b/array/shuffle.js new file mode 100644 index 00000000..cf1cf3a0 --- /dev/null +++ b/array/shuffle.js @@ -0,0 +1,3 @@ +import shuffleInPlace from "./shuffleInPlace"; + +export default xs => shuffleInPlace([...xs]); diff --git a/array/shuffleInPlace.js b/array/shuffleInPlace.js new file mode 100644 index 00000000..ae39da13 --- /dev/null +++ b/array/shuffleInPlace.js @@ -0,0 +1,8 @@ +export default xs => { + for (let i = 0; i < xs.length; i++) { + const j = Math.floor(Math.random() * (i + 1)); + [xs[i], xs[j]] = [xs[j], xs[i]]; + } + + return xs; +}; diff --git a/array/single.js b/array/single.js new file mode 100644 index 00000000..bdc53c3f --- /dev/null +++ b/array/single.js @@ -0,0 +1 @@ +export default xs => xs.length === 1; diff --git a/array/sort.js b/array/sort.js new file mode 100644 index 00000000..645230d6 --- /dev/null +++ b/array/sort.js @@ -0,0 +1 @@ +export default f => xs => [...xs].sort(f); diff --git a/array/sum.js b/array/sum.js new file mode 100644 index 00000000..3d49a4b1 --- /dev/null +++ b/array/sum.js @@ -0,0 +1,3 @@ +const add = (a, b) => a + b; + +export default xs => xs.reduce(add, 0); diff --git a/array/transpose.js b/array/transpose.js new file mode 100644 index 00000000..9da83662 --- /dev/null +++ b/array/transpose.js @@ -0,0 +1 @@ +export default xs => Object.keys(xs[0]).map(key => [xs.map(x => x[key]), key]); diff --git a/array/zip.js b/array/zip.js new file mode 100644 index 00000000..bab08804 --- /dev/null +++ b/array/zip.js @@ -0,0 +1,3 @@ +import zipWith from "./zipWith"; + +export default zipWith((x, y) => [x, y]); diff --git a/array/zipWith.js b/array/zipWith.js new file mode 100644 index 00000000..7cd6a442 --- /dev/null +++ b/array/zipWith.js @@ -0,0 +1 @@ +export default f => (xs, ys) => xs.map((x, index) => f(x, ys[index])); diff --git a/async/debounce.js b/async/debounce.js new file mode 100644 index 00000000..11423a1a --- /dev/null +++ b/async/debounce.js @@ -0,0 +1,15 @@ +export default (f, wait) => { + let timeout; + + return (...args) => { + const resolve = () => { + timeout = null; + + f(...args); + }; + + clearTimeout(timeout); + + timeout = setTimeout(resolve, wait); + }; +}; diff --git a/async/delay.js b/async/delay.js new file mode 100644 index 00000000..0c7bc064 --- /dev/null +++ b/async/delay.js @@ -0,0 +1,2 @@ +export default duration => + new Promise(resolve => setTimeout(resolve, duration)); diff --git a/async/sequence.js b/async/sequence.js new file mode 100644 index 00000000..f689e49c --- /dev/null +++ b/async/sequence.js @@ -0,0 +1,14 @@ +export default async tasks => { + const results = tasks.map(_ => undefined); + + await tasks.reduce((chain, current, i) => { + return chain.then(() => + current().then(x => { + results[i] = x; + return x; + }) + ); + }, Promise.resolve()); + + return results; +}; diff --git a/date/byDateWithFallback.js b/date/byDateWithFallback.js new file mode 100644 index 00000000..3c6c5296 --- /dev/null +++ b/date/byDateWithFallback.js @@ -0,0 +1,18 @@ +export default now => ( + { endedAt: aEnd, startedAt: aStart }, + { endedAt: bEnd, startedAt: bStart } +) => { + const aEndDate = new Date(aEnd || now); + const aStartDate = new Date(aStart || now); + const bEndDate = new Date(bEnd || now); + const bStartDate = new Date(bStart || now); + const aEndDateValue = aEndDate.valueOf(); + const aStartDateValue = aStartDate.valueOf(); + const bEndDateValue = bEndDate.valueOf(); + const bStartDateValue = bStartDate.valueOf(); + + const startDateDifference = aStartDateValue - bStartDateValue; + const startDatesEqual = startDateDifference === 0; + + return startDatesEqual ? aEndDateValue - bEndDateValue : startDateDifference; +}; diff --git a/date/clamp.js b/date/clamp.js new file mode 100644 index 00000000..8e4cf914 --- /dev/null +++ b/date/clamp.js @@ -0,0 +1,7 @@ +export default ([min, max]) => dateStringOrDate => { + const date = new Date(dateStringOrDate); + const clamped = new Date( + Math.min(max.valueOf(), Math.max(min.valueOf(), date.valueOf())) + ); + return clamped; +}; diff --git a/date/dateDiff.js b/date/dateDiff.js new file mode 100644 index 00000000..2e4d2ce6 --- /dev/null +++ b/date/dateDiff.js @@ -0,0 +1,6 @@ +export default (a, b) => { + const d1 = new Date(a); + const d2 = new Date(b); + + return d1.valueOf() - d2.valueOf(); +}; diff --git a/date/dateInRange.js b/date/dateInRange.js new file mode 100644 index 00000000..29997ef7 --- /dev/null +++ b/date/dateInRange.js @@ -0,0 +1,7 @@ +export default (from, to) => (date = new Date()) => { + const dateTime = new Date(date).getTime(); + const fromTime = new Date(from).getTime(); + const toTime = new Date(to).getTime(); + + return dateTime >= fromTime && dateTime <= toTime; +}; diff --git a/date/dayRange.js b/date/dayRange.js new file mode 100644 index 00000000..8a182b51 --- /dev/null +++ b/date/dayRange.js @@ -0,0 +1,24 @@ +import endOfDay from "./endOfDay"; +import offsetByBit from "./offsetByBit"; +import splitDateTime from "./splitDateTime"; +import startOfDay from "./startOfDay"; +import toISO from "./toISO"; +import toISOFromLocalDateTime from "./toISOFromLocalDateTime"; + +export default ({ + iso = false, + local = true, + now = new Date(), + timezoneOffset = 0 +}) => date => { + const convert = iso ? toISO : toISOFromLocalDateTime; + + const [start] = splitDateTime( + convert(startOfDay(date || now, timezoneOffset, local)) + ); + const [end] = splitDateTime( + convert(offsetByBit(endOfDay(date || now, timezoneOffset, local))) + ); + + return [start, end]; +}; diff --git a/date/daysInMonths.js b/date/daysInMonths.js new file mode 100644 index 00000000..2ad5657f --- /dev/null +++ b/date/daysInMonths.js @@ -0,0 +1,14 @@ +export default leapYear => [ + 31, + leapYear ? 29 : 28, + 31, + 30, + 31, + 30, + 31, + 31, + 30, + 31, + 30, + 31 +]; diff --git a/date/daysInYear.js b/date/daysInYear.js new file mode 100644 index 00000000..13c489da --- /dev/null +++ b/date/daysInYear.js @@ -0,0 +1,5 @@ +import sum from "../array/sum"; +import daysInMonths from "./daysInMonths"; +import leapYear from "./leapYear"; + +export default year => sum(daysInMonths(leapYear(year))); diff --git a/date/displayTime.js b/date/displayTime.js new file mode 100644 index 00000000..fc78bc18 --- /dev/null +++ b/date/displayTime.js @@ -0,0 +1,14 @@ +export default (source, showSeconds) => { + const [hours, minutes, seconds] = source.map(_ => _ + ""); + + const padded = [ + hours.padStart(2, "0"), + minutes.padStart(2, "0"), + seconds.padStart(2, "0") + ]; + + const [paddedHours, paddedMinutes] = padded; + const parts = showSeconds ? padded : [paddedHours, paddedMinutes]; + + return parts.join(":"); +}; diff --git a/date/endOfDay.js b/date/endOfDay.js new file mode 100644 index 00000000..f51306e8 --- /dev/null +++ b/date/endOfDay.js @@ -0,0 +1,9 @@ +import toLocalDateTime from "./toLocalDateTime"; + +export default (date, timezoneOffset = 0, local = true) => { + const newDate = new Date(date); + newDate.setHours(24, 0, 0, 0); + return local + ? toLocalDateTime(newDate, timezoneOffset + newDate.getTimezoneOffset()) + : newDate; +}; diff --git a/date/formatDate.js b/date/formatDate.js new file mode 100644 index 00000000..f6fcac30 --- /dev/null +++ b/date/formatDate.js @@ -0,0 +1,19 @@ +import toLocalDateTime from "./toLocalDateTime"; + +export default (sourceDate, timezoneOffset = 0) => { + const localDate = toLocalDateTime(sourceDate, timezoneOffset); + + const [m, a, y] = [ + localDate.getUTCMonth() + 1, + localDate.getUTCDate(), + localDate.getUTCFullYear() + ].map(_ => _ + ""); + + const date = [ + y.padStart(4, "0"), + m.padStart(2, "0"), + a.padStart(2, "0") + ].join("-"); + + return date; +}; diff --git a/date/formatDateTime.js b/date/formatDateTime.js new file mode 100644 index 00000000..f3aa9c00 --- /dev/null +++ b/date/formatDateTime.js @@ -0,0 +1,8 @@ +import formatDate from "./formatDate"; +import formatTime from "./formatTime"; + +export default (sourceDate, showSeconds = false, timezoneOffset = 0) => { + const date = formatDate(sourceDate, timezoneOffset); + const time = formatTime(sourceDate, showSeconds, timezoneOffset); + return `${date} ${time}`; +}; diff --git a/date/formatDuration.js b/date/formatDuration.js new file mode 100644 index 00000000..8fd96a38 --- /dev/null +++ b/date/formatDuration.js @@ -0,0 +1,16 @@ +import fromHours from "./fromHours"; +import fromMinutes from "./fromMinutes"; +import toHours from "./toHours"; +import toMinutes from "./toMinutes"; +import toSeconds from "./toSeconds"; +import displayTime from "./displayTime"; + +export default (duration, showSeconds = false) => { + const hours = Math.floor(toHours(duration)); + const minutes = Math.floor(toMinutes(duration - fromHours(hours))); + const seconds = Math.floor( + toSeconds(duration - fromHours(hours) - fromMinutes(minutes)) + ); + + return displayTime([hours, minutes, seconds], showSeconds); +}; diff --git a/date/formatTime.js b/date/formatTime.js new file mode 100644 index 00000000..7c158f82 --- /dev/null +++ b/date/formatTime.js @@ -0,0 +1,11 @@ +export default (sourceDate, showSeconds = false, timezoneOffset = 0) => { + const localDate = toLocalDateTime(sourceDate, timezoneOffset); + + const source = [ + localDate.getUTCHours(), + localDate.getUTCMinutes(), + localDate.getUTCSeconds() + ]; + + return displayTime(source, showSeconds); +}; diff --git a/date/fromDays.js b/date/fromDays.js new file mode 100644 index 00000000..ea8d490e --- /dev/null +++ b/date/fromDays.js @@ -0,0 +1,3 @@ +import fromHours from "./fromHours"; + +export default days => fromHours(days * 24); diff --git a/date/fromHours.js b/date/fromHours.js new file mode 100644 index 00000000..6a5f9617 --- /dev/null +++ b/date/fromHours.js @@ -0,0 +1,3 @@ +import fromMinutes from "./fromMinutes"; + +export default hours => fromMinutes(hours * 60); diff --git a/date/fromMinutes.js b/date/fromMinutes.js new file mode 100644 index 00000000..6e32741a --- /dev/null +++ b/date/fromMinutes.js @@ -0,0 +1,3 @@ +import fromSeconds from "./fromSeconds"; + +export default minutes => fromSeconds(minutes * 60); diff --git a/date/fromSeconds.js b/date/fromSeconds.js new file mode 100644 index 00000000..c0770d78 --- /dev/null +++ b/date/fromSeconds.js @@ -0,0 +1 @@ +export default seconds => seconds * 1000; diff --git a/date/joinDateTime.js b/date/joinDateTime.js new file mode 100644 index 00000000..328ef7c9 --- /dev/null +++ b/date/joinDateTime.js @@ -0,0 +1 @@ +export default (...xs) => xs.join("T"); diff --git a/date/leapYear.js b/date/leapYear.js new file mode 100644 index 00000000..62ab3314 --- /dev/null +++ b/date/leapYear.js @@ -0,0 +1 @@ +export default year => new Date(year, 1, 29).getMonth() === 1; diff --git a/date/monthRange.js b/date/monthRange.js new file mode 100644 index 00000000..cc52fcf8 --- /dev/null +++ b/date/monthRange.js @@ -0,0 +1,24 @@ +import endOfMonth from "./endOfMonth"; +import offsetByBit from "./offsetByBit"; +import splitDateTime from "./splitDateTime"; +import startOfMonth from "./startOfMonth"; +import toISO from "./toISO"; +import toISOFromLocalDateTime from "./toISOFromLocalDateTime"; + +export default ({ + iso = false, + local = true, + now = new Date(), + timezoneOffset = 0 +}) => date => { + const convert = iso ? toISO : toISOFromLocalDateTime; + + const [start] = splitDateTime( + convert(startOfMonth(date || now, timezoneOffset, local)) + ); + const [end] = splitDateTime( + convert(offsetByBit(endOfMonth(date || now, timezoneOffset, local))) + ); + + return [start, end]; +}; diff --git a/date/offsetByBit.js b/date/offsetByBit.js new file mode 100644 index 00000000..d492195c --- /dev/null +++ b/date/offsetByBit.js @@ -0,0 +1,3 @@ +const SECOND = fromSeconds(1); + +export default date => new Date(date - SECOND); diff --git a/date/parseHourMinutePair.js b/date/parseHourMinutePair.js new file mode 100644 index 00000000..5862c201 --- /dev/null +++ b/date/parseHourMinutePair.js @@ -0,0 +1,6 @@ +export default (text = "") => { + const [hoursString, minutesString] = text.split(":"); + const hours = parseInt(hoursString || 0, 10); + const minutes = parseInt(minutesString || 0, 10); + return [hours, minutes]; +}; diff --git a/date/splitDateTime.js b/date/splitDateTime.js new file mode 100644 index 00000000..0b871afb --- /dev/null +++ b/date/splitDateTime.js @@ -0,0 +1 @@ +export default dateTimeString => dateTimeString.split("T"); diff --git a/date/startOfDay.js b/date/startOfDay.js new file mode 100644 index 00000000..0c5805ab --- /dev/null +++ b/date/startOfDay.js @@ -0,0 +1,9 @@ +import toLocalDateTime from "./toLocalDateTime"; + +export default (date, timezoneOffset = 0, local = true) => { + const newDate = new Date(date); + newDate.setHours(0, 0, 0, 0); + return local + ? toLocalDateTime(newDate, timezoneOffset + newDate.getTimezoneOffset()) + : newDate; +}; diff --git a/date/subtractDays.js b/date/subtractDays.js new file mode 100644 index 00000000..3dbbb505 --- /dev/null +++ b/date/subtractDays.js @@ -0,0 +1,7 @@ +export default (sourceDate, numberOfDays) => { + const date = new Date(sourceDate); + + date.setDate(date.getDate() - numberOfDays); + + return date; +}; diff --git a/date/toDate.js b/date/toDate.js new file mode 100644 index 00000000..0a3c6b17 --- /dev/null +++ b/date/toDate.js @@ -0,0 +1,11 @@ +export default date => { + const day = date.getDate(); + const month = date.getMonth() + 1; + const year = date.getFullYear(); + + return [ + toString(year).padStart(4, "0"), + toString(month).padStart(2, "0"), + toString(day).padStart(2, "0") + ].join("-"); +}; diff --git a/date/toDates.js b/date/toDates.js new file mode 100644 index 00000000..8fb2e180 --- /dev/null +++ b/date/toDates.js @@ -0,0 +1 @@ +export default xs => xs.map(x => new Date(x)); diff --git a/date/toDays.js b/date/toDays.js new file mode 100644 index 00000000..1d9e7132 --- /dev/null +++ b/date/toDays.js @@ -0,0 +1,3 @@ +import toHours from "./toHours"; + +export default milliseconds => toHours(milliseconds) / 24; diff --git a/date/toHours.js b/date/toHours.js new file mode 100644 index 00000000..44509b4b --- /dev/null +++ b/date/toHours.js @@ -0,0 +1,3 @@ +import toMinutes from "./toMinutes"; + +export default milliseconds => toMinutes(milliseconds) / 60; diff --git a/date/toISO.js b/date/toISO.js new file mode 100644 index 00000000..9ac56e00 --- /dev/null +++ b/date/toISO.js @@ -0,0 +1 @@ +export default x => x.toISOString(); diff --git a/date/toISOFromLocalDateTime.js b/date/toISOFromLocalDateTime.js new file mode 100644 index 00000000..f4d527df --- /dev/null +++ b/date/toISOFromLocalDateTime.js @@ -0,0 +1,6 @@ +import fromMinutes from "./fromMinutes"; + +export default date => + new Date( + date.valueOf() - fromMinutes(date.getTimezoneOffset()) + ).toISOString(); diff --git a/date/toLocalDateTime.js b/date/toLocalDateTime.js new file mode 100644 index 00000000..c5bacd4d --- /dev/null +++ b/date/toLocalDateTime.js @@ -0,0 +1,2 @@ +export default (date, timezoneOffset = 0) => + new Date(date.valueOf() - fromMinutes(timezoneOffset)); diff --git a/date/toMinutes.js b/date/toMinutes.js new file mode 100644 index 00000000..3ef8dcca --- /dev/null +++ b/date/toMinutes.js @@ -0,0 +1,3 @@ +import toSeconds from "./toSeconds"; + +export default milliseconds => toSeconds(milliseconds) / 60; diff --git a/date/toSeconds.js b/date/toSeconds.js new file mode 100644 index 00000000..39f86994 --- /dev/null +++ b/date/toSeconds.js @@ -0,0 +1 @@ +export default milliseconds => milliseconds / 1000; diff --git a/date/valid.js b/date/valid.js new file mode 100644 index 00000000..dcd6e7fe --- /dev/null +++ b/date/valid.js @@ -0,0 +1 @@ +export default date => date && date instanceof Date && !Number.isNaN(date); diff --git a/date/weekRange.js b/date/weekRange.js new file mode 100644 index 00000000..af839bc0 --- /dev/null +++ b/date/weekRange.js @@ -0,0 +1,24 @@ +import endOfWeek from "./endOfWeek"; +import offsetByBit from "./offsetByBit"; +import splitDateTime from "./splitDateTime"; +import startOfWeek from "./startOfWeek"; +import toISO from "./toISO"; +import toISOFromLocalDateTime from "./toISOFromLocalDateTime"; + +export default ({ + iso = false, + local = true, + now = new Date(), + timezoneOffset = 0 +}) => date => { + const convert = iso ? toISO : toISOFromLocalDateTime; + + const [start] = splitDateTime( + convert(startOfWeek(date || now, timezoneOffset, local)) + ); + const [end] = splitDateTime( + convert(offsetByBit(endOfWeek(date || now, timezoneOffset, local))) + ); + + return [start, end]; +}; diff --git a/date/yearRange.js b/date/yearRange.js new file mode 100644 index 00000000..167a7740 --- /dev/null +++ b/date/yearRange.js @@ -0,0 +1,24 @@ +import endOfYear from "./endOfYear"; +import offsetByBit from "./offsetByBit"; +import splitDateTime from "./splitDateTime"; +import startOfYear from "./startOfYear"; +import toISO from "./toISO"; +import toISOFromLocalDateTime from "./toISOFromLocalDateTime"; + +export default ({ + iso = false, + local = true, + now = new Date(), + timezoneOffset = 0 +}) => date => { + const convert = iso ? toISO : toISOFromLocalDateTime; + + const [start] = splitDateTime( + convert(startOfYear(date || now, timezoneOffset, local)) + ); + const [end] = splitDateTime( + convert(offsetByBit(endOfYear(date || now, timezoneOffset, local))) + ); + + return [start, end]; +}; diff --git a/debug/assert.js b/debug/assert.js new file mode 100644 index 00000000..73f796b6 --- /dev/null +++ b/debug/assert.js @@ -0,0 +1,52 @@ +import isNumber from "../is/number"; +import isInteger from "../is/integer"; +import isByte from "../is/byte"; +import isNormal from "../is/normal"; +import isString from "../is/string"; +import isDefined from "../is/defined"; + +const assert = (condition, callbackOrMessage) => { + if (!condition) { + if (typeof callbackOrMessage === "function") { + callbackOrMessage(); + } else { + throw new TypeError( + typeof callbackOrMessage === "string" + ? callbackOrMessage + : "Assertion failed!" + ); + } + } +}; + +export const throws = f => { + try { + f(); + return undefined; + } catch (error) { + return error; + } +}; + +export const assertNumber = x => + assert(isNumber(x), `Value must be a valid number but it is ${typeof x}.`); + +export const assertInteger = x => + assertNumber(x) && assert(isInteger(x), "Value must be an integer."); + +export const assertByte = x => + assertInteger(x) && assert(isByte(x), "Value must be a byte."); + +export const assertNormal = x => + assertNumber(x) && + assert( + isNormal(x), + `Value must be a number in range of 0 to 1 inclusive but it is ${x}.` + ); + +export const assertString = x => assert(isString(x), "Value must be a string."); + +export const assertIsDefined = (x, message = "Value must be defined.") => + assert(isDefined(x), message); + +export default assert; diff --git a/debug/diff.js b/debug/diff.js new file mode 100644 index 00000000..a392cbdb --- /dev/null +++ b/debug/diff.js @@ -0,0 +1,83 @@ +import filter from "../object/filter"; +import isEmpty from "./object/isEmpty"; + +import isArray from "../is/array"; +import isDate from "../is/date"; +import isFunction from "../is/function"; +import isFunction from "../is/function"; +import isObject from "../is/object"; + +export const VALUE_CREATED = "+"; +export const VALUE_DELETED = "-"; +export const VALUE_UNCHANGED = "="; +export const VALUE_UPDATED = "~"; + +const isValue = x => !isObject(x) && !isArray(x); + +const compareValues = (value1, value2) => { + if (value1 === value2) { + return VALUE_UNCHANGED; + } + + if ( + isDate(value1) && + isDate(value2) && + value1.getTime() === value2.getTime() + ) { + return VALUE_UNCHANGED; + } + + if ("undefined" == typeof value1) { + return VALUE_CREATED; + } + + if ("undefined" == typeof value2) { + return VALUE_DELETED; + } + + return VALUE_UPDATED; +}; + +const diff = (obj1, obj2) => { + if (isFunction(obj1) || isFunction(obj2)) { + throw "Invalid argument. Function given, object expected."; + } + + if (isValue(obj1) || isValue(obj2)) { + const comparisonResult = compareValues(obj1, obj2); + return comparisonResult !== VALUE_UNCHANGED + ? { + type: comparisonResult, + data: [obj1, obj2] + } + : null; + } + + const result = {}; + for (const key in obj1) { + if (isFunction(obj1[key])) { + continue; + } + + let value2 = undefined; + if ("undefined" != typeof obj2[key]) { + value2 = obj2[key]; + } + + result[key] = diff(obj1[key], value2); + } + for (const key in obj2) { + if (isFunction(obj2[key]) || "undefined" != typeof result[key]) { + continue; + } + + result[key] = diff(undefined, obj2[key]); + } + + return filter( + value => + value !== null && !(value && "object" === typeof value && isEmpty(value)) + )(result); +}; + +export default diff; diff --git a/encoding/base64url.js b/encoding/base64url.js new file mode 100644 index 00000000..db2bd036 --- /dev/null +++ b/encoding/base64url.js @@ -0,0 +1,11 @@ +export const encode = _ => + btoa(_) + .replace(/=/g, "") + .replace(/\+/g, "-") + .replace(/\//g, "_"); + +export const toBase64Url = base64 => + base64.replace(/\+/g, "-").replace(/\//g, "_"); + +export const fromBase64Url = base64 => + base64.replace(/-/g, "+").replace(/_/g, "/"); diff --git a/file/validName.js b/file/validName.js new file mode 100644 index 00000000..57046aac --- /dev/null +++ b/file/validName.js @@ -0,0 +1,5 @@ +export default name => { + const forbiddenCharacters = /[<>:"\/\\|?*\x00-\x1F]/g; + const forbiddenNames = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$/i; + return !forbiddenCharacters.test(name) && !forbiddenNames.test(name); +}; diff --git a/function/compose.js b/function/compose.js new file mode 100644 index 00000000..5fd7d4cc --- /dev/null +++ b/function/compose.js @@ -0,0 +1 @@ +export default (...fs) => x => fs.reduceRight((x, f) => f(x), x); diff --git a/function/constant.js b/function/constant.js new file mode 100644 index 00000000..3487c0dd --- /dev/null +++ b/function/constant.js @@ -0,0 +1 @@ +export default x => () => x; diff --git a/function/identity.js b/function/identity.js new file mode 100644 index 00000000..9a800599 --- /dev/null +++ b/function/identity.js @@ -0,0 +1 @@ +export default x => x; diff --git a/function/memoize.js b/function/memoize.js new file mode 100644 index 00000000..4ae3065a --- /dev/null +++ b/function/memoize.js @@ -0,0 +1,4 @@ +import equals from "../object/equals"; +import memoizeWith from "./memoizeWith"; + +export default memoizeWith(equals); diff --git a/function/memoizeShallow.js b/function/memoizeShallow.js new file mode 100644 index 00000000..fb85b0f0 --- /dev/null +++ b/function/memoizeShallow.js @@ -0,0 +1,4 @@ +const equalsShallow = (xs, ys) => + xs.length === ys.length && xs.every((x, index) => x === ys[index]); + +export default memoizeWith(equalsShallow); diff --git a/function/memoizeWith.js b/function/memoizeWith.js new file mode 100644 index 00000000..08e3665c --- /dev/null +++ b/function/memoizeWith.js @@ -0,0 +1,12 @@ +export default equals => f => { + let memoized = undefined; + let memoizedArgs = undefined; + return (...args) => { + if (memoized && equals(args, memoizedArgs)) { + return memoized; + } + memoized = f(...args); + memoizedArgs = args; + return memoized; + }; +}; diff --git a/function/noOp.js b/function/noOp.js new file mode 100644 index 00000000..2d1ec238 --- /dev/null +++ b/function/noOp.js @@ -0,0 +1 @@ +export default () => {}; diff --git a/function/pipe.js b/function/pipe.js new file mode 100644 index 00000000..57e1e197 --- /dev/null +++ b/function/pipe.js @@ -0,0 +1 @@ +export default (...fs) => x => fs.reduce((x, f) => f(x), x); diff --git a/function/when.js b/function/when.js new file mode 100644 index 00000000..c5212ead --- /dev/null +++ b/function/when.js @@ -0,0 +1,5 @@ +export default predicate => action => (...args) => { + if (predicate(...args)) { + return action(...args); + } +}; diff --git a/function/whenTrue.js b/function/whenTrue.js new file mode 100644 index 00000000..465ae21e --- /dev/null +++ b/function/whenTrue.js @@ -0,0 +1,3 @@ +import when from "./when"; + +export default when(x => x === true); diff --git a/is/array.js b/is/array.js new file mode 100644 index 00000000..11c376b1 --- /dev/null +++ b/is/array.js @@ -0,0 +1 @@ +export default x => Array.isArray(x); diff --git a/is/byte.js b/is/byte.js new file mode 100644 index 00000000..f09023ee --- /dev/null +++ b/is/byte.js @@ -0,0 +1,3 @@ +import integer from "./integer"; + +export default x => integer(x) && x >= 0 && x <= 255; diff --git a/is/date.js b/is/date.js new file mode 100644 index 00000000..7d89cb83 --- /dev/null +++ b/is/date.js @@ -0,0 +1 @@ +export default _ => ({}.toString.apply(x) === "[object Date]"); diff --git a/is/defined.js b/is/defined.js new file mode 100644 index 00000000..23ddccd1 --- /dev/null +++ b/is/defined.js @@ -0,0 +1 @@ +export default x => x !== undefined; diff --git a/is/function.js b/is/function.js new file mode 100644 index 00000000..e136d4cc --- /dev/null +++ b/is/function.js @@ -0,0 +1 @@ +export default x => typeof x === "function"; diff --git a/is/integer.js b/is/integer.js new file mode 100644 index 00000000..ecf180b1 --- /dev/null +++ b/is/integer.js @@ -0,0 +1,3 @@ +import number from "./number"; + +export default x => number(x) && Math.floor(x) === x; diff --git a/is/normal.js b/is/normal.js new file mode 100644 index 00000000..83c0262a --- /dev/null +++ b/is/normal.js @@ -0,0 +1,3 @@ +import number from "./number"; + +export default x => number(x) && x >= 0 && x <= 1; diff --git a/is/number.js b/is/number.js new file mode 100644 index 00000000..71557dcf --- /dev/null +++ b/is/number.js @@ -0,0 +1 @@ +export default x => typeof x === "number" && !Number.isNaN(x); diff --git a/is/object.js b/is/object.js new file mode 100644 index 00000000..0f50c776 --- /dev/null +++ b/is/object.js @@ -0,0 +1 @@ +export default x => ({}.toString.apply(x) === "[object Object]"); diff --git a/is/string.js b/is/string.js new file mode 100644 index 00000000..a330f049 --- /dev/null +++ b/is/string.js @@ -0,0 +1 @@ +export default x => typeof x === "string"; diff --git a/math/add.js b/math/add.js new file mode 100644 index 00000000..fcbea415 --- /dev/null +++ b/math/add.js @@ -0,0 +1 @@ +export default (a, b) => a + b; diff --git a/math/average.js b/math/average.js new file mode 100644 index 00000000..6b06c368 --- /dev/null +++ b/math/average.js @@ -0,0 +1,3 @@ +import sum from "../array/sum"; + +export default xs => sum(xs) / xs.length; diff --git a/math/ceilToNearestPowerOfTwo.js b/math/ceilToNearestPowerOfTwo.js new file mode 100644 index 00000000..8f367cf6 --- /dev/null +++ b/math/ceilToNearestPowerOfTwo.js @@ -0,0 +1 @@ +export default x => Math.pow(2, Math.ceil(Math.log(x) / Math.log(2))); diff --git a/math/clamp.js b/math/clamp.js new file mode 100644 index 00000000..a1ca7f90 --- /dev/null +++ b/math/clamp.js @@ -0,0 +1 @@ +export default (min, max) => x => Math.max(min, Math.min(max, x)); diff --git a/math/clampNormal.js b/math/clampNormal.js new file mode 100644 index 00000000..61289821 --- /dev/null +++ b/math/clampNormal.js @@ -0,0 +1,3 @@ +import clamp from "./clamp"; + +export default clamp(0, 1); diff --git a/math/delta.js b/math/delta.js new file mode 100644 index 00000000..0f32a1e9 --- /dev/null +++ b/math/delta.js @@ -0,0 +1 @@ +export default (a, b) => Math.abs(a - b); diff --git a/math/inRectangleRange.js b/math/inRectangleRange.js new file mode 100644 index 00000000..690b6a9d --- /dev/null +++ b/math/inRectangleRange.js @@ -0,0 +1,2 @@ +export default (width, height) => (x, y) => + x >= 0 && x <= width && y >= 0 && y <= height; diff --git a/math/lerp.js b/math/lerp.js new file mode 100644 index 00000000..82ee6796 --- /dev/null +++ b/math/lerp.js @@ -0,0 +1 @@ +export default t => (a, b) => a * t + b * (1 - t); diff --git a/math/maximumBy.js b/math/maximumBy.js new file mode 100644 index 00000000..00f7e73b --- /dev/null +++ b/math/maximumBy.js @@ -0,0 +1,2 @@ +export default f => xs => + xs.reduce((acc, curr) => (f(curr) > f(acc) ? curr : acc)); diff --git a/math/median.js b/math/median.js new file mode 100644 index 00000000..bc4cf011 --- /dev/null +++ b/math/median.js @@ -0,0 +1,13 @@ +import sort from "../array/sort"; +import subtract from "./subtract"; + +export default xs => { + const sorted = sort(subtract)(xs); + const middle = Math.floor(sorted.length / 2); + + if (sorted.length % 2 === 0) { + return (sorted[middle - 1] + sorted[middle]) / 2; + } + + return sorted[middle]; +}; diff --git a/math/minMax.js b/math/minMax.js new file mode 100644 index 00000000..e5b943ce --- /dev/null +++ b/math/minMax.js @@ -0,0 +1 @@ +export default ([a, b]) => (a > b ? [b, a] : [a, b]); diff --git a/math/safeNormalize.js b/math/safeNormalize.js new file mode 100644 index 00000000..cc7a2b57 --- /dev/null +++ b/math/safeNormalize.js @@ -0,0 +1 @@ +export default x => (x !== 0 ? x / Math.abs(x) : 0); diff --git a/math/sameSign.js b/math/sameSign.js new file mode 100644 index 00000000..ab69865e --- /dev/null +++ b/math/sameSign.js @@ -0,0 +1,9 @@ +const filterOutZeros = xs => xs.filter(_ => _ !== 0); + +export default xs => { + const filteredXs = filterOutZeros(xs); + + return ( + Math.abs(filteredXs.map(safeNormalize).reduce(add, 0)) === filteredXs.length + ); +}; diff --git a/math/standardDeviation.js b/math/standardDeviation.js new file mode 100644 index 00000000..3202d84b --- /dev/null +++ b/math/standardDeviation.js @@ -0,0 +1,8 @@ +export default (xs, origin = average(data)) => { + const sumOfSquareDifferences = xs.reduce( + (squareDiffs, x) => squareDiffs + Math.pow(x - origin, 2), + 0 + ); + + return Math.sqrt(sumOfSquareDifferences / (xs.length - 1)); +}; diff --git a/math/subtract.js b/math/subtract.js new file mode 100644 index 00000000..ae5f7e86 --- /dev/null +++ b/math/subtract.js @@ -0,0 +1 @@ +export default (a, b) => a - b; diff --git a/object/any.js b/object/any.js new file mode 100644 index 00000000..2364a56e --- /dev/null +++ b/object/any.js @@ -0,0 +1,3 @@ +import length from "./length"; + +export default xs => length(xs) > 0; diff --git a/object/apply.js b/object/apply.js new file mode 100644 index 00000000..24674ef4 --- /dev/null +++ b/object/apply.js @@ -0,0 +1,5 @@ +import entries from "./entries"; +import fromEntries from "./fromEntries"; + +export default fs => (...xs) => + fromEntries(entries(fs).map(([key, value]) => [key, value(...xs)])); diff --git a/object/empty.js b/object/empty.js new file mode 100644 index 00000000..ff8b4c56 --- /dev/null +++ b/object/empty.js @@ -0,0 +1 @@ +export default {}; diff --git a/object/entries.js b/object/entries.js new file mode 100644 index 00000000..dc4dd62e --- /dev/null +++ b/object/entries.js @@ -0,0 +1,2 @@ +export default Object.entries || + (object => Object.keys(object).map(key => [key, object[key]])); diff --git a/object/enumerable.js b/object/enumerable.js new file mode 100644 index 00000000..a1e0d87a --- /dev/null +++ b/object/enumerable.js @@ -0,0 +1,2 @@ +export default (...xs) => + xs.reduce((acc, curr) => ({ ...acc, [curr]: curr }), {}); diff --git a/object/equals.js b/object/equals.js new file mode 100644 index 00000000..5d6526c1 --- /dev/null +++ b/object/equals.js @@ -0,0 +1,29 @@ +import isObject from "../is/object"; +import areArrays from "../array/are"; +import lengthDiffers from "../array/lengthDiffers"; + +const keySet = (a, b) => [...new Set([...keys(a), ...keys(b)])]; + +export const equalsDeep = (a, b) => { + if (areArrays(a, b)) { + return ( + !lengthDiffers(a, b) && a.every(a, (_, key) => equalsDeep(_, b[key])) + ); + } + return isObject(a) && isObject(b) + ? a === b || keySet(a, b).every(key => equalsDeep(a[key], b[key])) + : _isEqual(a, b); +}; + +export const equalsDeepWith = f => (a, b) => { + if (areArrays(a, b)) { + return ( + !lengthDiffers(a, b) && a.every((_, key) => equalsDeepWith(f)(_, b[key])) + ); + } + return isObject(a) && isObject(b) + ? a === b || keySet(a, b).every(key => equalsDeepWith(f)(a[key], b[key])) + : f(a, b); +}; + +export default equalsDeep; diff --git a/object/filter.js b/object/filter.js new file mode 100644 index 00000000..ff8765fc --- /dev/null +++ b/object/filter.js @@ -0,0 +1,5 @@ +import entries from "./entries"; +import fromEntries from "./fromEntries"; + +export default f => xs => + fromEntries(entries(xs).filter(([key, value]) => f(value, key, xs))); diff --git a/object/find.js b/object/find.js new file mode 100644 index 00000000..e384204e --- /dev/null +++ b/object/find.js @@ -0,0 +1,4 @@ +import entries from "./entries"; + +export default predicate => xs => + entries(xs).find(([key, value]) => predicate(value, key, xs)); diff --git a/object/findKey.js b/object/findKey.js new file mode 100644 index 00000000..0947503b --- /dev/null +++ b/object/findKey.js @@ -0,0 +1 @@ +export default predicate => xs => (find(predicate)(xs) || [])[0]; diff --git a/object/findValue.js b/object/findValue.js new file mode 100644 index 00000000..849893a0 --- /dev/null +++ b/object/findValue.js @@ -0,0 +1 @@ +export default predicate => xs => (find(predicate)(xs) || [])[1]; diff --git a/object/first.js b/object/first.js new file mode 100644 index 00000000..9fafa098 --- /dev/null +++ b/object/first.js @@ -0,0 +1 @@ +export default xs => Object.values(xs)[0]; diff --git a/object/flatMapValues.js b/object/flatMapValues.js new file mode 100644 index 00000000..4c7be2f5 --- /dev/null +++ b/object/flatMapValues.js @@ -0,0 +1,5 @@ +import flatMap from "../array/flatMap"; +import entries from "./entries"; + +export default f => xs => + flatMap(([key, value]) => f(value, key, xs))(entries(xs)); diff --git a/object/fromEntries.js b/object/fromEntries.js new file mode 100644 index 00000000..6b566045 --- /dev/null +++ b/object/fromEntries.js @@ -0,0 +1,6 @@ +export default Object.fromEntries || + (keyValuePairs => + keyValuePairs.reduce( + (acc, [key, value]) => ({ ...acc, [key]: value }), + {} + )); diff --git a/object/groupBy.js b/object/groupBy.js new file mode 100644 index 00000000..25eb4b32 --- /dev/null +++ b/object/groupBy.js @@ -0,0 +1,5 @@ +export default selector => xs => + xs.reduce((acc, x) => { + const key = selector(x); + return { ...acc, [key]: [...(acc[key] || []), x] }; + }, {}); diff --git a/object/hasKey.js b/object/hasKey.js new file mode 100644 index 00000000..5d9b2b74 --- /dev/null +++ b/object/hasKey.js @@ -0,0 +1,2 @@ +export default key => xs => + xs ? Object.prototype.hasOwnProperty.call(xs, key) : false; diff --git a/object/length.js b/object/length.js new file mode 100644 index 00000000..186433f4 --- /dev/null +++ b/object/length.js @@ -0,0 +1 @@ +export default xs => Object.keys(xs).length; diff --git a/object/map.js b/object/map.js new file mode 100644 index 00000000..db4a6985 --- /dev/null +++ b/object/map.js @@ -0,0 +1,4 @@ +import fromEntries from "./fromEntries"; +import mapEntries from "./mapEntries"; + +export default f => xs => fromEntries(mapEntries(f)(xs)); diff --git a/object/mapEntries.js b/object/mapEntries.js new file mode 100644 index 00000000..a603faab --- /dev/null +++ b/object/mapEntries.js @@ -0,0 +1,4 @@ +import entries from "./entries"; + +export default f => xs => + entries(xs).map(([key, value]) => [key, f(value, key, xs)]); diff --git a/object/mapKeys.js b/object/mapKeys.js new file mode 100644 index 00000000..7d16a2a7 --- /dev/null +++ b/object/mapKeys.js @@ -0,0 +1,5 @@ +import entries from "./entries"; +import fromEntries from "./fromEntries"; + +export default f => xs => + fromEntries(entries(xs).map(([key, value]) => [f(value, key, xs), value])); diff --git a/object/mapValues.js b/object/mapValues.js new file mode 100644 index 00000000..b20f87e9 --- /dev/null +++ b/object/mapValues.js @@ -0,0 +1,3 @@ +import entries from "./entries"; + +export default f => xs => entries(xs).map(([key, value]) => f(value, key, xs)); diff --git a/object/none.js b/object/none.js new file mode 100644 index 00000000..928c3271 --- /dev/null +++ b/object/none.js @@ -0,0 +1,3 @@ +import any from "./any"; + +export default xs => !any(xs); diff --git a/object/sort.js b/object/sort.js new file mode 100644 index 00000000..21007566 --- /dev/null +++ b/object/sort.js @@ -0,0 +1,5 @@ +import entries from "./entries"; +import fromEntries from "./fromEntries"; + +export default f => xs => + fromEntries(sort(([, a], [, b]) => f(a, b))(entries(xs))); diff --git a/query/parse.js b/query/parse.js new file mode 100644 index 00000000..a49ae955 --- /dev/null +++ b/query/parse.js @@ -0,0 +1,17 @@ +import fromEntries from "../object/fromEntries"; +import startsWith from "../string/startsWith"; + +const startsWithQuestionMark = startsWith("?"); + +const queryFromMaybeSearchString = x => + startsWithQuestionMark(x) ? x.substring(1) : x; + +export default (xs = "") => + fromEntries( + queryFromMaybeSearchString(xs) + .split("&") + .map(xs => { + const [key, value] = xs.split("="); + return [key, value !== undefined ? decodeURIComponent(value) : true]; + }) + ); diff --git a/query/parsePathname.js b/query/parsePathname.js new file mode 100644 index 00000000..1924d222 --- /dev/null +++ b/query/parsePathname.js @@ -0,0 +1,32 @@ +const extractPath = url => { + const match = url.match(/^(https?:)?\/\/[^/]*/); + return match == null ? url : url.substring(match[0].length); +}; + +export default url => { + let pathname = extractPath(url); + let search = ""; + let hash = ""; + + const hashIndex = pathname.indexOf("#"); + if (hashIndex !== -1) { + hash = pathname.substring(hashIndex); + pathname = pathname.substring(0, hashIndex); + } + + const searchIndex = pathname.indexOf("?"); + if (searchIndex !== -1) { + search = pathname.substring(searchIndex); + pathname = pathname.substring(0, searchIndex); + } + + if (pathname === "") { + pathname = "/"; + } + + return { + pathname, + search, + hash + }; +}; diff --git a/query/read.js b/query/read.js new file mode 100644 index 00000000..799c7496 --- /dev/null +++ b/query/read.js @@ -0,0 +1,5 @@ +export default source => + [...new URLSearchParams(source).entries()].reduce( + (q, [k, v]) => ({ ...q, ...{ [k]: v } }), + {} + ); diff --git a/query/serialize.js b/query/serialize.js new file mode 100644 index 00000000..f0051748 --- /dev/null +++ b/query/serialize.js @@ -0,0 +1,8 @@ +import entries from "../object/entries"; + +export default (xs = {}) => + entries(xs) + .filter(([, value]) => Boolean(value) || value === 0) + .map(pair => pair.map(encodeURIComponent)) + .reduce((acc, [key, value]) => [...acc, `${key}=${value}`], []) + .join("&"); diff --git a/range/empty.js b/range/empty.js new file mode 100644 index 00000000..71065567 --- /dev/null +++ b/range/empty.js @@ -0,0 +1 @@ +export default ([min, max]) => min === max; diff --git a/range/equals.js b/range/equals.js new file mode 100644 index 00000000..ab5c1860 --- /dev/null +++ b/range/equals.js @@ -0,0 +1 @@ +export default ([a, b], [c, d]) => a === c && b === d; diff --git a/range/length.js b/range/length.js new file mode 100644 index 00000000..3961ffcd --- /dev/null +++ b/range/length.js @@ -0,0 +1 @@ +export default ([min, max]) => max - min; diff --git a/range/split.js b/range/split.js new file mode 100644 index 00000000..8f924120 --- /dev/null +++ b/range/split.js @@ -0,0 +1,38 @@ +import { isNotNaN } from "../is"; +import clamp from "../math/clamp"; +import empty from "./empty"; + +export const split = (used, sourceRange = [-Infinity, Infinity]) => range => { + if (empty(range) || !range.every(isNotNaN)) { + return []; + } + + if (!used || used.length === 0) { + return [range]; + } + + const [x, ...xs] = used; + const [usedMin, usedMax] = x; + + if (empty(x)) { + return split(xs, sourceRange)(range); + } + + const [sourceMin, sourceMax] = sourceRange; + const clampToSourceRange = clamp(sourceRange); + + const freeLeft = [sourceMin, usedMin].map(clampToSourceRange); + const freeRight = [usedMax, sourceMax].map(clampToSourceRange); + + const clampLeft = clamp(freeLeft); + const clampedLeft = range.map(clampLeft); + + const lefts = split(xs, sourceRange)(clampedLeft); + + const clampRight = clamp(freeRight); + const clampedRight = range.map(clampRight); + + const rights = split(xs, sourceRange)(clampedRight); + + return [...lefts, ...rights].filter(range => !empty(range)); +}; diff --git a/regex/escape.js b/regex/escape.js new file mode 100644 index 00000000..b9233880 --- /dev/null +++ b/regex/escape.js @@ -0,0 +1 @@ +export default string => string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&"); diff --git a/string/containsWhitespace.js b/string/containsWhitespace.js new file mode 100644 index 00000000..a2a288b0 --- /dev/null +++ b/string/containsWhitespace.js @@ -0,0 +1 @@ +export default x => /\s/.test(x); diff --git a/string/empty.js b/string/empty.js new file mode 100644 index 00000000..9cf3c27e --- /dev/null +++ b/string/empty.js @@ -0,0 +1 @@ +export default ""; diff --git a/string/firstToLower.js b/string/firstToLower.js new file mode 100644 index 00000000..0a54fdd4 --- /dev/null +++ b/string/firstToLower.js @@ -0,0 +1 @@ +export default ([first, ...rest]) => [first.toLowerCase(), ...rest].join(""); diff --git a/string/firstToUpper.js b/string/firstToUpper.js new file mode 100644 index 00000000..7b9b4cba --- /dev/null +++ b/string/firstToUpper.js @@ -0,0 +1 @@ +export default ([first, ...rest]) => [first.toUpperCase(), ...rest].join(""); diff --git a/string/includes.js b/string/includes.js new file mode 100644 index 00000000..e9c27210 --- /dev/null +++ b/string/includes.js @@ -0,0 +1 @@ +export default search => xs => xs.indexOf(search) !== -1; diff --git a/string/nbsp.js b/string/nbsp.js new file mode 100644 index 00000000..f5632c43 --- /dev/null +++ b/string/nbsp.js @@ -0,0 +1 @@ +export default "\u00A0"; diff --git a/string/nonEmpty.js b/string/nonEmpty.js new file mode 100644 index 00000000..a66c5d72 --- /dev/null +++ b/string/nonEmpty.js @@ -0,0 +1 @@ +export default x => x && x.trim(); diff --git a/string/startsWith.js b/string/startsWith.js new file mode 100644 index 00000000..8997cd33 --- /dev/null +++ b/string/startsWith.js @@ -0,0 +1 @@ +export default prefix => xs => xs.indexOf(prefix) === 0; diff --git a/vector2/add.js b/vector2/add.js new file mode 100644 index 00000000..6995faae --- /dev/null +++ b/vector2/add.js @@ -0,0 +1 @@ +export default ([x1, y1], [x2, y2]) => [x1 + x2, y1 + y2]; diff --git a/vector2/convertSpace.js b/vector2/convertSpace.js new file mode 100644 index 00000000..8425499d --- /dev/null +++ b/vector2/convertSpace.js @@ -0,0 +1,6 @@ +import mul from "./mul"; + +export default space => ([x, y]) => { + const [outX, outY] = mul(space, [x, y]); + return [outX, outY]; +}; diff --git a/vector2/cross.js b/vector2/cross.js new file mode 100644 index 00000000..327ae4d7 --- /dev/null +++ b/vector2/cross.js @@ -0,0 +1 @@ +export default ([a, b], [c, d]) => a * d - b * c; diff --git a/vector2/dot.js b/vector2/dot.js new file mode 100644 index 00000000..c18e85fe --- /dev/null +++ b/vector2/dot.js @@ -0,0 +1 @@ +export default ([a, b], [c, d]) => a * c + b * d; diff --git a/vector2/length.js b/vector2/length.js new file mode 100644 index 00000000..ac12d13b --- /dev/null +++ b/vector2/length.js @@ -0,0 +1 @@ +export default ([x, y]) => Math.sqrt(x ** 2 + y ** 2); diff --git a/vector2/mul.js b/vector2/mul.js new file mode 100644 index 00000000..7ce615f1 --- /dev/null +++ b/vector2/mul.js @@ -0,0 +1,4 @@ +export default (matrix, point) => [ + matrix.a * point[0] + matrix.c * point[1] + matrix.e, + matrix.b * point[0] + matrix.d * point[1] + matrix.f +]; diff --git a/vector2/multiply.js b/vector2/multiply.js new file mode 100644 index 00000000..3102465f --- /dev/null +++ b/vector2/multiply.js @@ -0,0 +1,8 @@ +export default (m1, m2) => ({ + a: m1.a * m2.a + m1.c * m2.b, + c: m1.a * m2.c + m1.c * m2.d, + e: m1.a * m2.e + m1.c * m2.f + m1.e, + b: m1.b * m2.a + m1.d * m2.b, + d: m1.b * m2.c + m1.d * m2.d, + f: m1.b * m2.e + m1.d * m2.f + m1.f +}); diff --git a/vector2/normalize.js b/vector2/normalize.js new file mode 100644 index 00000000..cdbcbeff --- /dev/null +++ b/vector2/normalize.js @@ -0,0 +1,6 @@ +import length from "./length"; + +export default vector => { + const magnitude = length(vector); + return magnitude !== 0 ? vector.map(_ => _ / magnitude) : vector; +}; diff --git a/vector2/reflect.js b/vector2/reflect.js new file mode 100644 index 00000000..2465e0f6 --- /dev/null +++ b/vector2/reflect.js @@ -0,0 +1,4 @@ +import sub from "./sub"; +import dot from "./dot"; + +export default (a, v) => sub(v, a.map(_ => (_ * 2 * dot(v, a)) / dot(a, a))); diff --git a/vector2/rotate.js b/vector2/rotate.js new file mode 100644 index 00000000..227b12c8 --- /dev/null +++ b/vector2/rotate.js @@ -0,0 +1,20 @@ +import transform from "./transform"; +import translate from "./translate"; + +const { cos, sin } = Math; + +export default (angle = 0, cx = 0, cy = 0) => { + const cosAngle = cos(angle); + const sinAngle = sin(angle); + + const rotationMatrix = { + a: cosAngle, + c: -sinAngle, + e: 0, + b: sinAngle, + d: cosAngle, + f: 0 + }; + + return transform(translate(cx, cy), rotationMatrix, translate(-cx, -cy)); +}; diff --git a/vector2/scale.js b/vector2/scale.js new file mode 100644 index 00000000..d4aa6aba --- /dev/null +++ b/vector2/scale.js @@ -0,0 +1,8 @@ +export default (sx = 1, sy = sx) => ({ + a: sx, + c: 0, + e: 0, + b: 0, + d: sy, + f: 0 +}); diff --git a/vector2/sub.js b/vector2/sub.js new file mode 100644 index 00000000..5f40a0c4 --- /dev/null +++ b/vector2/sub.js @@ -0,0 +1 @@ +export default ([x1, y1], [x2, y2]) => [x1 - x2, y1 - y2]; diff --git a/vector2/transform.js b/vector2/transform.js new file mode 100644 index 00000000..0fc27235 --- /dev/null +++ b/vector2/transform.js @@ -0,0 +1 @@ +export default (...matrices) => matrices.reduce(multiply); diff --git a/vector2/translate.js b/vector2/translate.js new file mode 100644 index 00000000..2c2048ad --- /dev/null +++ b/vector2/translate.js @@ -0,0 +1,8 @@ +export default (tx = 0, ty = 0) => ({ + a: 1, + c: 0, + e: tx, + b: 0, + d: 1, + f: ty +}); diff --git a/web/classNames.js b/web/classNames.js new file mode 100644 index 00000000..cfff3d8a --- /dev/null +++ b/web/classNames.js @@ -0,0 +1,16 @@ +import entries from "../object/entries"; +import isString from "../is/string"; + +const booleanKeys = x => + entries(x) + .filter(([, value]) => Boolean(value)) + .map(([key]) => key); + +export default (...xs) => + xs + .filter(Boolean) + .reduce((acc, curr) => { + const names = isString(curr) ? [curr] : booleanKeys(curr); + return [...acc, ...names]; + }, []) + .join(" "); diff --git a/web/events/cancel.js b/web/events/cancel.js new file mode 100644 index 00000000..3464d7e7 --- /dev/null +++ b/web/events/cancel.js @@ -0,0 +1,8 @@ +import prevent from "./prevent"; +import stop from "./stop"; + +export default event => { + prevent(event); + stop(event); + return false; +}; diff --git a/web/events/openInNewTabIntent.js b/web/events/openInNewTabIntent.js new file mode 100644 index 00000000..bf0f619f --- /dev/null +++ b/web/events/openInNewTabIntent.js @@ -0,0 +1,2 @@ +export default ({ button, ctrlKey, metaKey, shiftKey }) => + ctrlKey || shiftKey || metaKey || button === 1; diff --git a/web/events/prevent.js b/web/events/prevent.js new file mode 100644 index 00000000..f475eecb --- /dev/null +++ b/web/events/prevent.js @@ -0,0 +1,4 @@ +export default event => { + event.preventDefault(); + return false; +}; diff --git a/web/events/stop.js b/web/events/stop.js new file mode 100644 index 00000000..cadf59cc --- /dev/null +++ b/web/events/stop.js @@ -0,0 +1,4 @@ +export default event => { + event.stopPropagation(); + return false; +}; From 512d777e243b7e31ac8a7519b0b26def385a5853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 10:50:48 +0200 Subject: [PATCH 05/56] Use proper file extensions for import statements --- array/are.js | 2 +- array/shuffle.js | 2 +- array/zip.js | 2 +- date/dayRange.js | 12 ++++++------ date/daysInYear.js | 6 +++--- date/endOfDay.js | 2 +- date/formatDate.js | 2 +- date/formatDateTime.js | 4 ++-- date/formatDuration.js | 12 ++++++------ date/fromDays.js | 2 +- date/fromHours.js | 2 +- date/fromMinutes.js | 2 +- date/monthRange.js | 12 ++++++------ date/startOfDay.js | 2 +- date/toDays.js | 2 +- date/toHours.js | 2 +- date/toISOFromLocalDateTime.js | 2 +- date/toMinutes.js | 2 +- date/weekRange.js | 12 ++++++------ date/yearRange.js | 12 ++++++------ debug/assert.js | 12 ++++++------ debug/diff.js | 16 ++++++++-------- function/memoize.js | 4 ++-- function/whenTrue.js | 2 +- is/byte.js | 2 +- is/integer.js | 2 +- is/normal.js | 2 +- math/average.js | 2 +- math/clampNormal.js | 2 +- math/median.js | 4 ++-- object/any.js | 2 +- object/apply.js | 4 ++-- object/equals.js | 6 +++--- object/filter.js | 4 ++-- object/find.js | 2 +- object/flatMapValues.js | 4 ++-- object/map.js | 4 ++-- object/mapEntries.js | 2 +- object/mapKeys.js | 4 ++-- object/mapValues.js | 2 +- object/none.js | 2 +- object/sort.js | 4 ++-- query/parse.js | 4 ++-- query/serialize.js | 2 +- range/split.js | 6 +++--- vector2/convertSpace.js | 2 +- vector2/normalize.js | 2 +- vector2/reflect.js | 4 ++-- vector2/rotate.js | 4 ++-- web/classNames.js | 4 ++-- web/events/cancel.js | 4 ++-- 51 files changed, 108 insertions(+), 108 deletions(-) diff --git a/array/are.js b/array/are.js index c32dc386..ba83b30e 100644 --- a/array/are.js +++ b/array/are.js @@ -1,3 +1,3 @@ -import is from "./is"; +import is from "./is.js"; export default (...xs) => xs.every(is); diff --git a/array/shuffle.js b/array/shuffle.js index cf1cf3a0..66db53c0 100644 --- a/array/shuffle.js +++ b/array/shuffle.js @@ -1,3 +1,3 @@ -import shuffleInPlace from "./shuffleInPlace"; +import shuffleInPlace from "./shuffleInPlace.js"; export default xs => shuffleInPlace([...xs]); diff --git a/array/zip.js b/array/zip.js index bab08804..dcd8e433 100644 --- a/array/zip.js +++ b/array/zip.js @@ -1,3 +1,3 @@ -import zipWith from "./zipWith"; +import zipWith from "./zipWith.js"; export default zipWith((x, y) => [x, y]); diff --git a/date/dayRange.js b/date/dayRange.js index 8a182b51..2cea4450 100644 --- a/date/dayRange.js +++ b/date/dayRange.js @@ -1,9 +1,9 @@ -import endOfDay from "./endOfDay"; -import offsetByBit from "./offsetByBit"; -import splitDateTime from "./splitDateTime"; -import startOfDay from "./startOfDay"; -import toISO from "./toISO"; -import toISOFromLocalDateTime from "./toISOFromLocalDateTime"; +import endOfDay from "./endOfDay.js"; +import offsetByBit from "./offsetByBit.js"; +import splitDateTime from "./splitDateTime.js"; +import startOfDay from "./startOfDay.js"; +import toISO from "./toISO.js"; +import toISOFromLocalDateTime from "./toISOFromLocalDateTime.js"; export default ({ iso = false, diff --git a/date/daysInYear.js b/date/daysInYear.js index 13c489da..6df73661 100644 --- a/date/daysInYear.js +++ b/date/daysInYear.js @@ -1,5 +1,5 @@ -import sum from "../array/sum"; -import daysInMonths from "./daysInMonths"; -import leapYear from "./leapYear"; +import sum from "../array/sum.js"; +import daysInMonths from "./daysInMonths.js"; +import leapYear from "./leapYear.js"; export default year => sum(daysInMonths(leapYear(year))); diff --git a/date/endOfDay.js b/date/endOfDay.js index f51306e8..475fed53 100644 --- a/date/endOfDay.js +++ b/date/endOfDay.js @@ -1,4 +1,4 @@ -import toLocalDateTime from "./toLocalDateTime"; +import toLocalDateTime from "./toLocalDateTime.js"; export default (date, timezoneOffset = 0, local = true) => { const newDate = new Date(date); diff --git a/date/formatDate.js b/date/formatDate.js index f6fcac30..af16eabc 100644 --- a/date/formatDate.js +++ b/date/formatDate.js @@ -1,4 +1,4 @@ -import toLocalDateTime from "./toLocalDateTime"; +import toLocalDateTime from "./toLocalDateTime.js"; export default (sourceDate, timezoneOffset = 0) => { const localDate = toLocalDateTime(sourceDate, timezoneOffset); diff --git a/date/formatDateTime.js b/date/formatDateTime.js index f3aa9c00..6aeb2266 100644 --- a/date/formatDateTime.js +++ b/date/formatDateTime.js @@ -1,5 +1,5 @@ -import formatDate from "./formatDate"; -import formatTime from "./formatTime"; +import formatDate from "./formatDate.js"; +import formatTime from "./formatTime.js"; export default (sourceDate, showSeconds = false, timezoneOffset = 0) => { const date = formatDate(sourceDate, timezoneOffset); diff --git a/date/formatDuration.js b/date/formatDuration.js index 8fd96a38..1a8ef6f9 100644 --- a/date/formatDuration.js +++ b/date/formatDuration.js @@ -1,9 +1,9 @@ -import fromHours from "./fromHours"; -import fromMinutes from "./fromMinutes"; -import toHours from "./toHours"; -import toMinutes from "./toMinutes"; -import toSeconds from "./toSeconds"; -import displayTime from "./displayTime"; +import fromHours from "./fromHours.js"; +import fromMinutes from "./fromMinutes.js"; +import toHours from "./toHours.js"; +import toMinutes from "./toMinutes.js"; +import toSeconds from "./toSeconds.js"; +import displayTime from "./displayTime.js"; export default (duration, showSeconds = false) => { const hours = Math.floor(toHours(duration)); diff --git a/date/fromDays.js b/date/fromDays.js index ea8d490e..7961f32d 100644 --- a/date/fromDays.js +++ b/date/fromDays.js @@ -1,3 +1,3 @@ -import fromHours from "./fromHours"; +import fromHours from "./fromHours.js"; export default days => fromHours(days * 24); diff --git a/date/fromHours.js b/date/fromHours.js index 6a5f9617..07aba8a0 100644 --- a/date/fromHours.js +++ b/date/fromHours.js @@ -1,3 +1,3 @@ -import fromMinutes from "./fromMinutes"; +import fromMinutes from "./fromMinutes.js"; export default hours => fromMinutes(hours * 60); diff --git a/date/fromMinutes.js b/date/fromMinutes.js index 6e32741a..53408542 100644 --- a/date/fromMinutes.js +++ b/date/fromMinutes.js @@ -1,3 +1,3 @@ -import fromSeconds from "./fromSeconds"; +import fromSeconds from "./fromSeconds.js"; export default minutes => fromSeconds(minutes * 60); diff --git a/date/monthRange.js b/date/monthRange.js index cc52fcf8..9176477a 100644 --- a/date/monthRange.js +++ b/date/monthRange.js @@ -1,9 +1,9 @@ -import endOfMonth from "./endOfMonth"; -import offsetByBit from "./offsetByBit"; -import splitDateTime from "./splitDateTime"; -import startOfMonth from "./startOfMonth"; -import toISO from "./toISO"; -import toISOFromLocalDateTime from "./toISOFromLocalDateTime"; +import endOfMonth from "./endOfMonth.js"; +import offsetByBit from "./offsetByBit.js"; +import splitDateTime from "./splitDateTime.js"; +import startOfMonth from "./startOfMonth.js"; +import toISO from "./toISO.js"; +import toISOFromLocalDateTime from "./toISOFromLocalDateTime.js"; export default ({ iso = false, diff --git a/date/startOfDay.js b/date/startOfDay.js index 0c5805ab..0e9d3395 100644 --- a/date/startOfDay.js +++ b/date/startOfDay.js @@ -1,4 +1,4 @@ -import toLocalDateTime from "./toLocalDateTime"; +import toLocalDateTime from "./toLocalDateTime.js"; export default (date, timezoneOffset = 0, local = true) => { const newDate = new Date(date); diff --git a/date/toDays.js b/date/toDays.js index 1d9e7132..ba5e7a90 100644 --- a/date/toDays.js +++ b/date/toDays.js @@ -1,3 +1,3 @@ -import toHours from "./toHours"; +import toHours from "./toHours.js"; export default milliseconds => toHours(milliseconds) / 24; diff --git a/date/toHours.js b/date/toHours.js index 44509b4b..5ed4eadf 100644 --- a/date/toHours.js +++ b/date/toHours.js @@ -1,3 +1,3 @@ -import toMinutes from "./toMinutes"; +import toMinutes from "./toMinutes.js"; export default milliseconds => toMinutes(milliseconds) / 60; diff --git a/date/toISOFromLocalDateTime.js b/date/toISOFromLocalDateTime.js index f4d527df..6d8480d3 100644 --- a/date/toISOFromLocalDateTime.js +++ b/date/toISOFromLocalDateTime.js @@ -1,4 +1,4 @@ -import fromMinutes from "./fromMinutes"; +import fromMinutes from "./fromMinutes.js"; export default date => new Date( diff --git a/date/toMinutes.js b/date/toMinutes.js index 3ef8dcca..30cfa8ae 100644 --- a/date/toMinutes.js +++ b/date/toMinutes.js @@ -1,3 +1,3 @@ -import toSeconds from "./toSeconds"; +import toSeconds from "./toSeconds.js"; export default milliseconds => toSeconds(milliseconds) / 60; diff --git a/date/weekRange.js b/date/weekRange.js index af839bc0..64a8487a 100644 --- a/date/weekRange.js +++ b/date/weekRange.js @@ -1,9 +1,9 @@ -import endOfWeek from "./endOfWeek"; -import offsetByBit from "./offsetByBit"; -import splitDateTime from "./splitDateTime"; -import startOfWeek from "./startOfWeek"; -import toISO from "./toISO"; -import toISOFromLocalDateTime from "./toISOFromLocalDateTime"; +import endOfWeek from "./endOfWeek.js"; +import offsetByBit from "./offsetByBit.js"; +import splitDateTime from "./splitDateTime.js"; +import startOfWeek from "./startOfWeek.js"; +import toISO from "./toISO.js"; +import toISOFromLocalDateTime from "./toISOFromLocalDateTime.js"; export default ({ iso = false, diff --git a/date/yearRange.js b/date/yearRange.js index 167a7740..e87d1143 100644 --- a/date/yearRange.js +++ b/date/yearRange.js @@ -1,9 +1,9 @@ -import endOfYear from "./endOfYear"; -import offsetByBit from "./offsetByBit"; -import splitDateTime from "./splitDateTime"; -import startOfYear from "./startOfYear"; -import toISO from "./toISO"; -import toISOFromLocalDateTime from "./toISOFromLocalDateTime"; +import endOfYear from "./endOfYear.js"; +import offsetByBit from "./offsetByBit.js"; +import splitDateTime from "./splitDateTime.js"; +import startOfYear from "./startOfYear.js"; +import toISO from "./toISO.js"; +import toISOFromLocalDateTime from "./toISOFromLocalDateTime.js"; export default ({ iso = false, diff --git a/debug/assert.js b/debug/assert.js index 73f796b6..38668ae7 100644 --- a/debug/assert.js +++ b/debug/assert.js @@ -1,9 +1,9 @@ -import isNumber from "../is/number"; -import isInteger from "../is/integer"; -import isByte from "../is/byte"; -import isNormal from "../is/normal"; -import isString from "../is/string"; -import isDefined from "../is/defined"; +import isNumber from "../is/number.js"; +import isInteger from "../is/integer.js"; +import isByte from "../is/byte.js"; +import isNormal from "../is/normal.js"; +import isString from "../is/string.js"; +import isDefined from "../is/defined.js"; const assert = (condition, callbackOrMessage) => { if (!condition) { diff --git a/debug/diff.js b/debug/diff.js index a392cbdb..9315143b 100644 --- a/debug/diff.js +++ b/debug/diff.js @@ -1,11 +1,11 @@ -import filter from "../object/filter"; -import isEmpty from "./object/isEmpty"; - -import isArray from "../is/array"; -import isDate from "../is/date"; -import isFunction from "../is/function"; -import isFunction from "../is/function"; -import isObject from "../is/object"; +import filter from "../object/filter.js"; +import isEmpty from "./object/isEmpty.js"; + +import isArray from "../is/array.js"; +import isDate from "../is/date.js"; +import isFunction from "../is/function.js"; +import isFunction from "../is/function.js"; +import isObject from "../is/object.js"; export const VALUE_CREATED = "+"; export const VALUE_DELETED = "-"; diff --git a/function/memoize.js b/function/memoize.js index 4ae3065a..4ef07411 100644 --- a/function/memoize.js +++ b/function/memoize.js @@ -1,4 +1,4 @@ -import equals from "../object/equals"; -import memoizeWith from "./memoizeWith"; +import equals from "../object/equals.js"; +import memoizeWith from "./memoizeWith.js"; export default memoizeWith(equals); diff --git a/function/whenTrue.js b/function/whenTrue.js index 465ae21e..0870c5cb 100644 --- a/function/whenTrue.js +++ b/function/whenTrue.js @@ -1,3 +1,3 @@ -import when from "./when"; +import when from "./when.js"; export default when(x => x === true); diff --git a/is/byte.js b/is/byte.js index f09023ee..b25231df 100644 --- a/is/byte.js +++ b/is/byte.js @@ -1,3 +1,3 @@ -import integer from "./integer"; +import integer from "./integer.js"; export default x => integer(x) && x >= 0 && x <= 255; diff --git a/is/integer.js b/is/integer.js index ecf180b1..b79db0fd 100644 --- a/is/integer.js +++ b/is/integer.js @@ -1,3 +1,3 @@ -import number from "./number"; +import number from "./number.js"; export default x => number(x) && Math.floor(x) === x; diff --git a/is/normal.js b/is/normal.js index 83c0262a..284b2b93 100644 --- a/is/normal.js +++ b/is/normal.js @@ -1,3 +1,3 @@ -import number from "./number"; +import number from "./number.js"; export default x => number(x) && x >= 0 && x <= 1; diff --git a/math/average.js b/math/average.js index 6b06c368..a75f2b0f 100644 --- a/math/average.js +++ b/math/average.js @@ -1,3 +1,3 @@ -import sum from "../array/sum"; +import sum from "../array/sum.js"; export default xs => sum(xs) / xs.length; diff --git a/math/clampNormal.js b/math/clampNormal.js index 61289821..5be86e87 100644 --- a/math/clampNormal.js +++ b/math/clampNormal.js @@ -1,3 +1,3 @@ -import clamp from "./clamp"; +import clamp from "./clamp.js"; export default clamp(0, 1); diff --git a/math/median.js b/math/median.js index bc4cf011..4a4e6fad 100644 --- a/math/median.js +++ b/math/median.js @@ -1,5 +1,5 @@ -import sort from "../array/sort"; -import subtract from "./subtract"; +import sort from "../array/sort.js"; +import subtract from "./subtract.js"; export default xs => { const sorted = sort(subtract)(xs); diff --git a/object/any.js b/object/any.js index 2364a56e..39db7f9d 100644 --- a/object/any.js +++ b/object/any.js @@ -1,3 +1,3 @@ -import length from "./length"; +import length from "./length.js"; export default xs => length(xs) > 0; diff --git a/object/apply.js b/object/apply.js index 24674ef4..93526e28 100644 --- a/object/apply.js +++ b/object/apply.js @@ -1,5 +1,5 @@ -import entries from "./entries"; -import fromEntries from "./fromEntries"; +import entries from "./entries.js"; +import fromEntries from "./fromEntries.js"; export default fs => (...xs) => fromEntries(entries(fs).map(([key, value]) => [key, value(...xs)])); diff --git a/object/equals.js b/object/equals.js index 5d6526c1..9a38c174 100644 --- a/object/equals.js +++ b/object/equals.js @@ -1,6 +1,6 @@ -import isObject from "../is/object"; -import areArrays from "../array/are"; -import lengthDiffers from "../array/lengthDiffers"; +import isObject from "../is/object.js"; +import areArrays from "../array/are.js"; +import lengthDiffers from "../array/lengthDiffers.js"; const keySet = (a, b) => [...new Set([...keys(a), ...keys(b)])]; diff --git a/object/filter.js b/object/filter.js index ff8765fc..9209dcae 100644 --- a/object/filter.js +++ b/object/filter.js @@ -1,5 +1,5 @@ -import entries from "./entries"; -import fromEntries from "./fromEntries"; +import entries from "./entries.js"; +import fromEntries from "./fromEntries.js"; export default f => xs => fromEntries(entries(xs).filter(([key, value]) => f(value, key, xs))); diff --git a/object/find.js b/object/find.js index e384204e..bbf04ad0 100644 --- a/object/find.js +++ b/object/find.js @@ -1,4 +1,4 @@ -import entries from "./entries"; +import entries from "./entries.js"; export default predicate => xs => entries(xs).find(([key, value]) => predicate(value, key, xs)); diff --git a/object/flatMapValues.js b/object/flatMapValues.js index 4c7be2f5..3318507f 100644 --- a/object/flatMapValues.js +++ b/object/flatMapValues.js @@ -1,5 +1,5 @@ -import flatMap from "../array/flatMap"; -import entries from "./entries"; +import flatMap from "../array/flatMap.js"; +import entries from "./entries.js"; export default f => xs => flatMap(([key, value]) => f(value, key, xs))(entries(xs)); diff --git a/object/map.js b/object/map.js index db4a6985..8590e36b 100644 --- a/object/map.js +++ b/object/map.js @@ -1,4 +1,4 @@ -import fromEntries from "./fromEntries"; -import mapEntries from "./mapEntries"; +import fromEntries from "./fromEntries.js"; +import mapEntries from "./mapEntries.js"; export default f => xs => fromEntries(mapEntries(f)(xs)); diff --git a/object/mapEntries.js b/object/mapEntries.js index a603faab..854de72e 100644 --- a/object/mapEntries.js +++ b/object/mapEntries.js @@ -1,4 +1,4 @@ -import entries from "./entries"; +import entries from "./entries.js"; export default f => xs => entries(xs).map(([key, value]) => [key, f(value, key, xs)]); diff --git a/object/mapKeys.js b/object/mapKeys.js index 7d16a2a7..a8f5465b 100644 --- a/object/mapKeys.js +++ b/object/mapKeys.js @@ -1,5 +1,5 @@ -import entries from "./entries"; -import fromEntries from "./fromEntries"; +import entries from "./entries.js"; +import fromEntries from "./fromEntries.js"; export default f => xs => fromEntries(entries(xs).map(([key, value]) => [f(value, key, xs), value])); diff --git a/object/mapValues.js b/object/mapValues.js index b20f87e9..8230ab66 100644 --- a/object/mapValues.js +++ b/object/mapValues.js @@ -1,3 +1,3 @@ -import entries from "./entries"; +import entries from "./entries.js"; export default f => xs => entries(xs).map(([key, value]) => f(value, key, xs)); diff --git a/object/none.js b/object/none.js index 928c3271..307b11e6 100644 --- a/object/none.js +++ b/object/none.js @@ -1,3 +1,3 @@ -import any from "./any"; +import any from "./any.js"; export default xs => !any(xs); diff --git a/object/sort.js b/object/sort.js index 21007566..a52812d3 100644 --- a/object/sort.js +++ b/object/sort.js @@ -1,5 +1,5 @@ -import entries from "./entries"; -import fromEntries from "./fromEntries"; +import entries from "./entries.js"; +import fromEntries from "./fromEntries.js"; export default f => xs => fromEntries(sort(([, a], [, b]) => f(a, b))(entries(xs))); diff --git a/query/parse.js b/query/parse.js index a49ae955..3e2fb4f6 100644 --- a/query/parse.js +++ b/query/parse.js @@ -1,5 +1,5 @@ -import fromEntries from "../object/fromEntries"; -import startsWith from "../string/startsWith"; +import fromEntries from "../object/fromEntries.js"; +import startsWith from "../string/startsWith.js"; const startsWithQuestionMark = startsWith("?"); diff --git a/query/serialize.js b/query/serialize.js index f0051748..12f23f5f 100644 --- a/query/serialize.js +++ b/query/serialize.js @@ -1,4 +1,4 @@ -import entries from "../object/entries"; +import entries from "../object/entries.js"; export default (xs = {}) => entries(xs) diff --git a/range/split.js b/range/split.js index 8f924120..6e8bb2c3 100644 --- a/range/split.js +++ b/range/split.js @@ -1,6 +1,6 @@ -import { isNotNaN } from "../is"; -import clamp from "../math/clamp"; -import empty from "./empty"; +import { isNotNaN } from "../is.js"; +import clamp from "../math/clamp.js"; +import empty from "./empty.js"; export const split = (used, sourceRange = [-Infinity, Infinity]) => range => { if (empty(range) || !range.every(isNotNaN)) { diff --git a/vector2/convertSpace.js b/vector2/convertSpace.js index 8425499d..7d50c019 100644 --- a/vector2/convertSpace.js +++ b/vector2/convertSpace.js @@ -1,4 +1,4 @@ -import mul from "./mul"; +import mul from "./mul.js"; export default space => ([x, y]) => { const [outX, outY] = mul(space, [x, y]); diff --git a/vector2/normalize.js b/vector2/normalize.js index cdbcbeff..c00359af 100644 --- a/vector2/normalize.js +++ b/vector2/normalize.js @@ -1,4 +1,4 @@ -import length from "./length"; +import length from "./length.js"; export default vector => { const magnitude = length(vector); diff --git a/vector2/reflect.js b/vector2/reflect.js index 2465e0f6..6ee82a82 100644 --- a/vector2/reflect.js +++ b/vector2/reflect.js @@ -1,4 +1,4 @@ -import sub from "./sub"; -import dot from "./dot"; +import sub from "./sub.js"; +import dot from "./dot.js"; export default (a, v) => sub(v, a.map(_ => (_ * 2 * dot(v, a)) / dot(a, a))); diff --git a/vector2/rotate.js b/vector2/rotate.js index 227b12c8..2d1dc708 100644 --- a/vector2/rotate.js +++ b/vector2/rotate.js @@ -1,5 +1,5 @@ -import transform from "./transform"; -import translate from "./translate"; +import transform from "./transform.js"; +import translate from "./translate.js"; const { cos, sin } = Math; diff --git a/web/classNames.js b/web/classNames.js index cfff3d8a..190d8ed5 100644 --- a/web/classNames.js +++ b/web/classNames.js @@ -1,5 +1,5 @@ -import entries from "../object/entries"; -import isString from "../is/string"; +import entries from "../object/entries.js"; +import isString from "../is/string.js"; const booleanKeys = x => entries(x) diff --git a/web/events/cancel.js b/web/events/cancel.js index 3464d7e7..e2c2c023 100644 --- a/web/events/cancel.js +++ b/web/events/cancel.js @@ -1,5 +1,5 @@ -import prevent from "./prevent"; -import stop from "./stop"; +import prevent from "./prevent.js"; +import stop from "./stop.js"; export default event => { prevent(event); From f94f7ab4f73d8d7032cf357427de7f2763d6684f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 12:29:46 +0200 Subject: [PATCH 06/56] Remove duplicated import --- debug/diff.js | 1 - 1 file changed, 1 deletion(-) diff --git a/debug/diff.js b/debug/diff.js index 9315143b..cfb16253 100644 --- a/debug/diff.js +++ b/debug/diff.js @@ -4,7 +4,6 @@ import isEmpty from "./object/isEmpty.js"; import isArray from "../is/array.js"; import isDate from "../is/date.js"; import isFunction from "../is/function.js"; -import isFunction from "../is/function.js"; import isObject from "../is/object.js"; export const VALUE_CREATED = "+"; From e5f22dfd0049e56bba4d2a5d16d2560ecf4d780b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 12:30:26 +0200 Subject: [PATCH 07/56] Generate indices --- array/index.js | 117 ++++++++++++++++++++++++++++++++++++++++++++ async/index.js | 7 +++ date/index.js | 117 ++++++++++++++++++++++++++++++++++++++++++++ debug/index.js | 6 +++ encoding/index.js | 5 ++ file/index.js | 5 ++ function/index.js | 36 ++++++++++++++ index.js | 54 ++++++++++++++++++++ is/index.js | 36 ++++++++++++++ math/index.js | 51 +++++++++++++++++++ object/index.js | 72 +++++++++++++++++++++++++++ query/index.js | 8 +++ range/index.js | 8 +++ regex/index.js | 5 ++ string/index.js | 30 ++++++++++++ vector2/index.js | 48 ++++++++++++++++++ web/events/index.js | 8 +++ web/index.js | 6 +++ 18 files changed, 619 insertions(+) create mode 100644 array/index.js create mode 100644 async/index.js create mode 100644 date/index.js create mode 100644 debug/index.js create mode 100644 encoding/index.js create mode 100644 file/index.js create mode 100644 function/index.js create mode 100644 index.js create mode 100644 is/index.js create mode 100644 math/index.js create mode 100644 object/index.js create mode 100644 query/index.js create mode 100644 range/index.js create mode 100644 regex/index.js create mode 100644 string/index.js create mode 100644 vector2/index.js create mode 100644 web/events/index.js create mode 100644 web/index.js diff --git a/array/index.js b/array/index.js new file mode 100644 index 00000000..59d65c30 --- /dev/null +++ b/array/index.js @@ -0,0 +1,117 @@ +import any from "./any.js"; +import are from "./are.js"; +import differs from "./differs.js"; +import duplicates from "./duplicates.js"; +import empty from "./empty.js"; +import exact from "./exact.js"; +import except from "./except.js"; +import filterInPlace from "./filterInPlace.js"; +import find from "./find.js"; +import first from "./first.js"; +import flatMap from "./flatMap.js"; +import flatten from "./flatten.js"; +import intersection from "./intersection.js"; +import is from "./is.js"; +import last from "./last.js"; +import lengthDiffers from "./lengthDiffers.js"; +import map from "./map.js"; +import midpoint from "./midpoint.js"; +import minMax from "./minMax.js"; +import multiple from "./multiple.js"; +import partition from "./partition.js"; +import range from "./range.js"; +import repeat from "./repeat.js"; +import reverse from "./reverse.js"; +import reverseIf from "./reverseIf.js"; +import rotate from "./rotate.js"; +import second from "./second.js"; +import secondToLast from "./secondToLast.js"; +import shift from "./shift.js"; +import shuffle from "./shuffle.js"; +import shuffleInPlace from "./shuffleInPlace.js"; +import single from "./single.js"; +import sort from "./sort.js"; +import sum from "./sum.js"; +import transpose from "./transpose.js"; +import zip from "./zip.js"; +import zipWith from "./zipWith.js"; + +export { + any, + are, + differs, + duplicates, + empty, + exact, + except, + filterInPlace, + find, + first, + flatMap, + flatten, + intersection, + is, + last, + lengthDiffers, + map, + midpoint, + minMax, + multiple, + partition, + range, + repeat, + reverse, + reverseIf, + rotate, + second, + secondToLast, + shift, + shuffle, + shuffleInPlace, + single, + sort, + sum, + transpose, + zip, + zipWith +}; + +export default { + any, + are, + differs, + duplicates, + empty, + exact, + except, + filterInPlace, + find, + first, + flatMap, + flatten, + intersection, + is, + last, + lengthDiffers, + map, + midpoint, + minMax, + multiple, + partition, + range, + repeat, + reverse, + reverseIf, + rotate, + second, + secondToLast, + shift, + shuffle, + shuffleInPlace, + single, + sort, + sum, + transpose, + zip, + zipWith +}; diff --git a/async/index.js b/async/index.js new file mode 100644 index 00000000..8c3a3d37 --- /dev/null +++ b/async/index.js @@ -0,0 +1,7 @@ +import debounce from "./debounce.js"; +import delay from "./delay.js"; +import sequence from "./sequence.js"; + +export { debounce, delay, sequence }; + +export default { debounce, delay, sequence }; diff --git a/date/index.js b/date/index.js new file mode 100644 index 00000000..478521b0 --- /dev/null +++ b/date/index.js @@ -0,0 +1,117 @@ +import byDateWithFallback from "./byDateWithFallback.js"; +import clamp from "./clamp.js"; +import dateDiff from "./dateDiff.js"; +import dateInRange from "./dateInRange.js"; +import dayRange from "./dayRange.js"; +import daysInMonths from "./daysInMonths.js"; +import daysInYear from "./daysInYear.js"; +import displayTime from "./displayTime.js"; +import endOfDay from "./endOfDay.js"; +import formatDate from "./formatDate.js"; +import formatDateTime from "./formatDateTime.js"; +import formatDuration from "./formatDuration.js"; +import formatTime from "./formatTime.js"; +import fromDays from "./fromDays.js"; +import fromHours from "./fromHours.js"; +import fromMinutes from "./fromMinutes.js"; +import fromSeconds from "./fromSeconds.js"; +import joinDateTime from "./joinDateTime.js"; +import leapYear from "./leapYear.js"; +import monthRange from "./monthRange.js"; +import offsetByBit from "./offsetByBit.js"; +import parseHourMinutePair from "./parseHourMinutePair.js"; +import splitDateTime from "./splitDateTime.js"; +import startOfDay from "./startOfDay.js"; +import subtractDays from "./subtractDays.js"; +import toDate from "./toDate.js"; +import toDates from "./toDates.js"; +import toDays from "./toDays.js"; +import toHours from "./toHours.js"; +import toISO from "./toISO.js"; +import toISOFromLocalDateTime from "./toISOFromLocalDateTime.js"; +import toLocalDateTime from "./toLocalDateTime.js"; +import toMinutes from "./toMinutes.js"; +import toSeconds from "./toSeconds.js"; +import valid from "./valid.js"; +import weekRange from "./weekRange.js"; +import yearRange from "./yearRange.js"; + +export { + byDateWithFallback, + clamp, + dateDiff, + dateInRange, + dayRange, + daysInMonths, + daysInYear, + displayTime, + endOfDay, + formatDate, + formatDateTime, + formatDuration, + formatTime, + fromDays, + fromHours, + fromMinutes, + fromSeconds, + joinDateTime, + leapYear, + monthRange, + offsetByBit, + parseHourMinutePair, + splitDateTime, + startOfDay, + subtractDays, + toDate, + toDates, + toDays, + toHours, + toISO, + toISOFromLocalDateTime, + toLocalDateTime, + toMinutes, + toSeconds, + valid, + weekRange, + yearRange +}; + +export default { + byDateWithFallback, + clamp, + dateDiff, + dateInRange, + dayRange, + daysInMonths, + daysInYear, + displayTime, + endOfDay, + formatDate, + formatDateTime, + formatDuration, + formatTime, + fromDays, + fromHours, + fromMinutes, + fromSeconds, + joinDateTime, + leapYear, + monthRange, + offsetByBit, + parseHourMinutePair, + splitDateTime, + startOfDay, + subtractDays, + toDate, + toDates, + toDays, + toHours, + toISO, + toISOFromLocalDateTime, + toLocalDateTime, + toMinutes, + toSeconds, + valid, + weekRange, + yearRange +}; diff --git a/debug/index.js b/debug/index.js new file mode 100644 index 00000000..f85332b7 --- /dev/null +++ b/debug/index.js @@ -0,0 +1,6 @@ +import assert from "./assert.js"; +import diff from "./diff.js"; + +export { assert, diff }; + +export default { assert, diff }; diff --git a/encoding/index.js b/encoding/index.js new file mode 100644 index 00000000..78553ab2 --- /dev/null +++ b/encoding/index.js @@ -0,0 +1,5 @@ +import base64url from "./base64url.js"; + +export { base64url }; + +export default { base64url }; diff --git a/file/index.js b/file/index.js new file mode 100644 index 00000000..bbddc8ea --- /dev/null +++ b/file/index.js @@ -0,0 +1,5 @@ +import validName from "./validName.js"; + +export { validName }; + +export default { validName }; diff --git a/function/index.js b/function/index.js new file mode 100644 index 00000000..d6b94b43 --- /dev/null +++ b/function/index.js @@ -0,0 +1,36 @@ +import compose from "./compose.js"; +import constant from "./constant.js"; +import identity from "./identity.js"; +import memoize from "./memoize.js"; +import memoizeShallow from "./memoizeShallow.js"; +import memoizeWith from "./memoizeWith.js"; +import noOp from "./noOp.js"; +import pipe from "./pipe.js"; +import when from "./when.js"; +import whenTrue from "./whenTrue.js"; + +export { + compose, + constant, + identity, + memoize, + memoizeShallow, + memoizeWith, + noOp, + pipe, + when, + whenTrue +}; + +export default { + compose, + constant, + identity, + memoize, + memoizeShallow, + memoizeWith, + noOp, + pipe, + when, + whenTrue +}; diff --git a/index.js b/index.js new file mode 100644 index 00000000..9cc7a9bb --- /dev/null +++ b/index.js @@ -0,0 +1,54 @@ +import array from "./array"; +import async from "./async"; +import date from "./date"; +import debug from "./debug"; +import encoding from "./encoding"; +import file from "./file"; +import _function from "./function"; +import is from "./is"; +import math from "./math"; +import object from "./object"; +import query from "./query"; +import range from "./range"; +import regex from "./regex"; +import string from "./string"; +import vector2 from "./vector2"; +import web from "./web"; + +export { + array, + async, + date, + debug, + encoding, + file, + _function, + is, + math, + object, + query, + range, + regex, + string, + vector2, + web +}; + +export default { + array, + async, + date, + debug, + encoding, + file, + _function, + is, + math, + object, + query, + range, + regex, + string, + vector2, + web +}; diff --git a/is/index.js b/is/index.js new file mode 100644 index 00000000..2880557e --- /dev/null +++ b/is/index.js @@ -0,0 +1,36 @@ +import array from "./array.js"; +import byte from "./byte.js"; +import date from "./date.js"; +import defined from "./defined.js"; +import _function from "./function.js"; +import integer from "./integer.js"; +import normal from "./normal.js"; +import number from "./number.js"; +import object from "./object.js"; +import string from "./string.js"; + +export { + array, + byte, + date, + defined, + _function, + integer, + normal, + number, + object, + string +}; + +export default { + array, + byte, + date, + defined, + _function, + integer, + normal, + number, + object, + string +}; diff --git a/math/index.js b/math/index.js new file mode 100644 index 00000000..ea1e5db5 --- /dev/null +++ b/math/index.js @@ -0,0 +1,51 @@ +import add from "./add.js"; +import average from "./average.js"; +import ceilToNearestPowerOfTwo from "./ceilToNearestPowerOfTwo.js"; +import clamp from "./clamp.js"; +import clampNormal from "./clampNormal.js"; +import delta from "./delta.js"; +import inRectangleRange from "./inRectangleRange.js"; +import lerp from "./lerp.js"; +import maximumBy from "./maximumBy.js"; +import median from "./median.js"; +import minMax from "./minMax.js"; +import safeNormalize from "./safeNormalize.js"; +import sameSign from "./sameSign.js"; +import standardDeviation from "./standardDeviation.js"; +import subtract from "./subtract.js"; + +export { + add, + average, + ceilToNearestPowerOfTwo, + clamp, + clampNormal, + delta, + inRectangleRange, + lerp, + maximumBy, + median, + minMax, + safeNormalize, + sameSign, + standardDeviation, + subtract +}; + +export default { + add, + average, + ceilToNearestPowerOfTwo, + clamp, + clampNormal, + delta, + inRectangleRange, + lerp, + maximumBy, + median, + minMax, + safeNormalize, + sameSign, + standardDeviation, + subtract +}; diff --git a/object/index.js b/object/index.js new file mode 100644 index 00000000..ed337bb8 --- /dev/null +++ b/object/index.js @@ -0,0 +1,72 @@ +import any from "./any.js"; +import apply from "./apply.js"; +import empty from "./empty.js"; +import entries from "./entries.js"; +import enumerable from "./enumerable.js"; +import equals from "./equals.js"; +import filter from "./filter.js"; +import find from "./find.js"; +import findKey from "./findKey.js"; +import findValue from "./findValue.js"; +import first from "./first.js"; +import flatMapValues from "./flatMapValues.js"; +import fromEntries from "./fromEntries.js"; +import groupBy from "./groupBy.js"; +import hasKey from "./hasKey.js"; +import length from "./length.js"; +import map from "./map.js"; +import mapEntries from "./mapEntries.js"; +import mapKeys from "./mapKeys.js"; +import mapValues from "./mapValues.js"; +import none from "./none.js"; +import sort from "./sort.js"; + +export { + any, + apply, + empty, + entries, + enumerable, + equals, + filter, + find, + findKey, + findValue, + first, + flatMapValues, + fromEntries, + groupBy, + hasKey, + length, + map, + mapEntries, + mapKeys, + mapValues, + none, + sort +}; + +export default { + any, + apply, + empty, + entries, + enumerable, + equals, + filter, + find, + findKey, + findValue, + first, + flatMapValues, + fromEntries, + groupBy, + hasKey, + length, + map, + mapEntries, + mapKeys, + mapValues, + none, + sort +}; diff --git a/query/index.js b/query/index.js new file mode 100644 index 00000000..558489ce --- /dev/null +++ b/query/index.js @@ -0,0 +1,8 @@ +import parse from "./parse.js"; +import parsePathname from "./parsePathname.js"; +import read from "./read.js"; +import serialize from "./serialize.js"; + +export { parse, parsePathname, read, serialize }; + +export default { parse, parsePathname, read, serialize }; diff --git a/range/index.js b/range/index.js new file mode 100644 index 00000000..a0e7a341 --- /dev/null +++ b/range/index.js @@ -0,0 +1,8 @@ +import empty from "./empty.js"; +import equals from "./equals.js"; +import length from "./length.js"; +import split from "./split.js"; + +export { empty, equals, length, split }; + +export default { empty, equals, length, split }; diff --git a/regex/index.js b/regex/index.js new file mode 100644 index 00000000..231e89cb --- /dev/null +++ b/regex/index.js @@ -0,0 +1,5 @@ +import escape from "./escape.js"; + +export { escape }; + +export default { escape }; diff --git a/string/index.js b/string/index.js new file mode 100644 index 00000000..af2f7705 --- /dev/null +++ b/string/index.js @@ -0,0 +1,30 @@ +import containsWhitespace from "./containsWhitespace.js"; +import empty from "./empty.js"; +import firstToLower from "./firstToLower.js"; +import firstToUpper from "./firstToUpper.js"; +import includes from "./includes.js"; +import nbsp from "./nbsp.js"; +import nonEmpty from "./nonEmpty.js"; +import startsWith from "./startsWith.js"; + +export { + containsWhitespace, + empty, + firstToLower, + firstToUpper, + includes, + nbsp, + nonEmpty, + startsWith +}; + +export default { + containsWhitespace, + empty, + firstToLower, + firstToUpper, + includes, + nbsp, + nonEmpty, + startsWith +}; diff --git a/vector2/index.js b/vector2/index.js new file mode 100644 index 00000000..b88aa8d8 --- /dev/null +++ b/vector2/index.js @@ -0,0 +1,48 @@ +import add from "./add.js"; +import convertSpace from "./convertSpace.js"; +import cross from "./cross.js"; +import dot from "./dot.js"; +import length from "./length.js"; +import mul from "./mul.js"; +import multiply from "./multiply.js"; +import normalize from "./normalize.js"; +import reflect from "./reflect.js"; +import rotate from "./rotate.js"; +import scale from "./scale.js"; +import sub from "./sub.js"; +import transform from "./transform.js"; +import translate from "./translate.js"; + +export { + add, + convertSpace, + cross, + dot, + length, + mul, + multiply, + normalize, + reflect, + rotate, + scale, + sub, + transform, + translate +}; + +export default { + add, + convertSpace, + cross, + dot, + length, + mul, + multiply, + normalize, + reflect, + rotate, + scale, + sub, + transform, + translate +}; diff --git a/web/events/index.js b/web/events/index.js new file mode 100644 index 00000000..0809d31a --- /dev/null +++ b/web/events/index.js @@ -0,0 +1,8 @@ +import cancel from "./cancel.js"; +import openInNewTabIntent from "./openInNewTabIntent.js"; +import prevent from "./prevent.js"; +import stop from "./stop.js"; + +export { cancel, openInNewTabIntent, prevent, stop }; + +export default { cancel, openInNewTabIntent, prevent, stop }; diff --git a/web/index.js b/web/index.js new file mode 100644 index 00000000..16d28c77 --- /dev/null +++ b/web/index.js @@ -0,0 +1,6 @@ +import classNames from "./classNames.js"; +import events from "./events"; + +export { classNames, events }; + +export default { classNames, events }; From cffbcd787379e87f4629704d97df71379b10ca25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 12:31:09 +0200 Subject: [PATCH 08/56] Point module field to index file --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 5e7d69e6..7d3e8940 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "0.1.0", "description": "", "main": "index.js", + "module": "index.js", "type": "module", "sideEffects": false, "scripts": { From 02760fd6dcdf533ae0ed31cea7b2b9e30aeba2b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 12:41:13 +0200 Subject: [PATCH 09/56] Remove not ready modules --- date/index.js | 13 ++----------- date/monthRange.js | 24 ------------------------ date/weekRange.js | 24 ------------------------ date/yearRange.js | 24 ------------------------ 4 files changed, 2 insertions(+), 83 deletions(-) delete mode 100644 date/monthRange.js delete mode 100644 date/weekRange.js delete mode 100644 date/yearRange.js diff --git a/date/index.js b/date/index.js index 478521b0..6dfdc1fc 100644 --- a/date/index.js +++ b/date/index.js @@ -17,7 +17,6 @@ import fromMinutes from "./fromMinutes.js"; import fromSeconds from "./fromSeconds.js"; import joinDateTime from "./joinDateTime.js"; import leapYear from "./leapYear.js"; -import monthRange from "./monthRange.js"; import offsetByBit from "./offsetByBit.js"; import parseHourMinutePair from "./parseHourMinutePair.js"; import splitDateTime from "./splitDateTime.js"; @@ -33,8 +32,6 @@ import toLocalDateTime from "./toLocalDateTime.js"; import toMinutes from "./toMinutes.js"; import toSeconds from "./toSeconds.js"; import valid from "./valid.js"; -import weekRange from "./weekRange.js"; -import yearRange from "./yearRange.js"; export { byDateWithFallback, @@ -56,7 +53,6 @@ export { fromSeconds, joinDateTime, leapYear, - monthRange, offsetByBit, parseHourMinutePair, splitDateTime, @@ -71,9 +67,7 @@ export { toLocalDateTime, toMinutes, toSeconds, - valid, - weekRange, - yearRange + valid }; export default { @@ -96,7 +90,6 @@ export default { fromSeconds, joinDateTime, leapYear, - monthRange, offsetByBit, parseHourMinutePair, splitDateTime, @@ -111,7 +104,5 @@ export default { toLocalDateTime, toMinutes, toSeconds, - valid, - weekRange, - yearRange + valid }; diff --git a/date/monthRange.js b/date/monthRange.js deleted file mode 100644 index 9176477a..00000000 --- a/date/monthRange.js +++ /dev/null @@ -1,24 +0,0 @@ -import endOfMonth from "./endOfMonth.js"; -import offsetByBit from "./offsetByBit.js"; -import splitDateTime from "./splitDateTime.js"; -import startOfMonth from "./startOfMonth.js"; -import toISO from "./toISO.js"; -import toISOFromLocalDateTime from "./toISOFromLocalDateTime.js"; - -export default ({ - iso = false, - local = true, - now = new Date(), - timezoneOffset = 0 -}) => date => { - const convert = iso ? toISO : toISOFromLocalDateTime; - - const [start] = splitDateTime( - convert(startOfMonth(date || now, timezoneOffset, local)) - ); - const [end] = splitDateTime( - convert(offsetByBit(endOfMonth(date || now, timezoneOffset, local))) - ); - - return [start, end]; -}; diff --git a/date/weekRange.js b/date/weekRange.js deleted file mode 100644 index 64a8487a..00000000 --- a/date/weekRange.js +++ /dev/null @@ -1,24 +0,0 @@ -import endOfWeek from "./endOfWeek.js"; -import offsetByBit from "./offsetByBit.js"; -import splitDateTime from "./splitDateTime.js"; -import startOfWeek from "./startOfWeek.js"; -import toISO from "./toISO.js"; -import toISOFromLocalDateTime from "./toISOFromLocalDateTime.js"; - -export default ({ - iso = false, - local = true, - now = new Date(), - timezoneOffset = 0 -}) => date => { - const convert = iso ? toISO : toISOFromLocalDateTime; - - const [start] = splitDateTime( - convert(startOfWeek(date || now, timezoneOffset, local)) - ); - const [end] = splitDateTime( - convert(offsetByBit(endOfWeek(date || now, timezoneOffset, local))) - ); - - return [start, end]; -}; diff --git a/date/yearRange.js b/date/yearRange.js deleted file mode 100644 index e87d1143..00000000 --- a/date/yearRange.js +++ /dev/null @@ -1,24 +0,0 @@ -import endOfYear from "./endOfYear.js"; -import offsetByBit from "./offsetByBit.js"; -import splitDateTime from "./splitDateTime.js"; -import startOfYear from "./startOfYear.js"; -import toISO from "./toISO.js"; -import toISOFromLocalDateTime from "./toISOFromLocalDateTime.js"; - -export default ({ - iso = false, - local = true, - now = new Date(), - timezoneOffset = 0 -}) => date => { - const convert = iso ? toISO : toISOFromLocalDateTime; - - const [start] = splitDateTime( - convert(startOfYear(date || now, timezoneOffset, local)) - ); - const [end] = splitDateTime( - convert(offsetByBit(endOfYear(date || now, timezoneOffset, local))) - ); - - return [start, end]; -}; From 230067399e6fa37d02755b66fda7b46478ef7b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 13:02:39 +0200 Subject: [PATCH 10/56] Use strict equal comparison --- object/equals.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/object/equals.js b/object/equals.js index 9a38c174..b5d64c4e 100644 --- a/object/equals.js +++ b/object/equals.js @@ -12,7 +12,7 @@ export const equalsDeep = (a, b) => { } return isObject(a) && isObject(b) ? a === b || keySet(a, b).every(key => equalsDeep(a[key], b[key])) - : _isEqual(a, b); + : a === b; }; export const equalsDeepWith = f => (a, b) => { From 83fe1f5e972d4d8624ae0b00713e4ef559f1bdf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 13:28:32 +0200 Subject: [PATCH 11/56] Prepare package build scripts and setup --- .gitignore | 3 ++ .npmignore | 1 + package-lock.json | 29 ++++++++++++++++ package.json | 15 ++++++--- regenerate.js | 84 +++++++++++++++++++++++++++++++++++++++++++++++ rollup.config.js | 15 +++++++++ 6 files changed, 142 insertions(+), 5 deletions(-) create mode 100644 .npmignore create mode 100644 regenerate.js create mode 100644 rollup.config.js diff --git a/.gitignore b/.gitignore index ad46b308..2b0ef73d 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,6 @@ typings/ # next.js build output .next + +index.cjs.js +index.umd.js diff --git a/.npmignore b/.npmignore new file mode 100644 index 00000000..eb4647a4 --- /dev/null +++ b/.npmignore @@ -0,0 +1 @@ +regenerate.js diff --git a/package-lock.json b/package-lock.json index 918666e9..a56ea7c2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,11 +4,40 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "@types/node": { + "version": "12.7.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.9.tgz", + "integrity": "sha512-P57oKTJ/vYivL2BCfxCC5tQjlS8qW31pbOL6qt99Yrjm95YdHgNZwjrTTjMBh+C2/y6PXIX4oz253+jUzxKKfQ==", + "dev": true + }, + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true + }, "prettier": { "version": "1.18.2", "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.18.2.tgz", "integrity": "sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==", "dev": true + }, + "rollup": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.22.0.tgz", + "integrity": "sha512-x4l4ZrV/Mr/x/jvFTmwROdEAhbZjx16yDRTVSKWh/i4oJDuW2dVEbECT853mybYCz7BAitU8ElGlhx7dNjw3qQ==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/node": "*", + "acorn": "^7.1.0" + } } } } diff --git a/package.json b/package.json index 7d3e8940..44bbcc25 100644 --- a/package.json +++ b/package.json @@ -2,14 +2,18 @@ "name": "@sandstreamdev/std", "version": "0.1.0", "description": "", - "main": "index.js", - "module": "index.js", "type": "module", + "module": "index.js", + "main": "index.cjs.js", + "browser": "index.umd.js", "sideEffects": false, "scripts": { - "prettier": "prettier \"**/*.{js,json,md}\"", + "build": "npm run regenerate && rollup -c", + "prepare": "npm run build", + "prettier:check": "npm run prettier -- --check", "prettier:fix": "npm run prettier -- --write", - "prettier:check": "npm run prettier -- --check" + "prettier": "prettier \"**/*.{js,json,md}\"", + "regenerate": "node --experimental-modules regenerate.js && npm run prettier:fix" }, "repository": { "type": "git", @@ -26,6 +30,7 @@ }, "homepage": "https://github.com/sandstreamdev/std#readme", "devDependencies": { - "prettier": "^1.18.2" + "prettier": "^1.18.2", + "rollup": "^1.22.0" } } diff --git a/regenerate.js b/regenerate.js new file mode 100644 index 00000000..db4e1034 --- /dev/null +++ b/regenerate.js @@ -0,0 +1,84 @@ +import { promises } from "fs"; +import path from "path"; + +const { readdir: readDirectoryAsync, writeFile: writeFileAsync } = promises; + +const [, , cwd = process.cwd()] = process.argv; + +const mapping = { + function: "_function" +}; + +const ignoredFiles = [ + ".gitignore", + "index.js", + "LICENSE", + "package-lock.json", + "package.json", + "README.md", + "regenerate.js", + "rollup.config.js" +]; + +const ignoredDirectories = [".git", "node_modules"]; + +const identifier = name => mapping[name] || name; + +const main = async cwd => { + console.log(`Indexing files in ${cwd}...`); + + const entries = await readDirectoryAsync(cwd, { withFileTypes: true }); + const files = entries + .filter(x => x.isFile()) + .map(x => x.name) + .filter(x => !ignoredFiles.includes(x)); + const directories = entries + .filter(x => x.isDirectory()) + .map(x => x.name) + .filter(x => !ignoredDirectories.includes(x)); + + for (const directory of directories) { + await main(path.join(cwd, directory)); + } + + const submodules = files.map(filePath => { + const { base: fileName } = path.parse(filePath); + const splitted = fileName.split("."); + const id = identifier(splitted.slice(0, splitted.length - 1).join("_")); + const extension = `.${splitted[splitted.length - 1]}`; + + return [fileName, id, extension]; + }); + + const dependencies = [ + ...submodules, + ...directories.map(x => [`${x}/index.js`, identifier(x), ""]) + ]; + + const importDeclarations = dependencies + .map(([fileName, id]) => + id !== "index" ? `import ${id} from './${fileName}'` : "" + ) + .join("\r\n"); + + const exportDeclarationBody = dependencies + .map(([, id]) => (id !== "index" ? id : "")) + .join(", "); + + const exportDeclaration = `export { ${exportDeclarationBody} }`; + const defaultExport = `export default { ${exportDeclarationBody} }`; + + console.log(`Indexed files in ${cwd}:`); + + const moduleContents = [ + importDeclarations, + exportDeclaration, + defaultExport + ].join("\r\n\r\n"); + + console.log(moduleContents); + + await writeFileAsync(path.join(cwd, "index.js"), moduleContents); +}; + +main(cwd); diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 00000000..f38843aa --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,15 @@ +export default { + input: "index.js", + output: [ + { + exports: "named", + file: "index.cjs.js", + format: "cjs" + }, + { + file: "index.umd.js", + format: "umd", + name: "@sandstreamdev/std" + } + ] +}; From d21606fff5dc9c1468fbcf4b00acc792726399d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 13:29:15 +0200 Subject: [PATCH 12/56] Fix broken and missing imports/exports --- debug/diff.js | 4 ++-- encoding/base64url.js | 2 ++ index.js | 32 ++++++++++++++++---------------- range/split.js | 6 +++--- web/index.js | 2 +- 5 files changed, 24 insertions(+), 22 deletions(-) diff --git a/debug/diff.js b/debug/diff.js index cfb16253..80a1c0ee 100644 --- a/debug/diff.js +++ b/debug/diff.js @@ -1,5 +1,5 @@ import filter from "../object/filter.js"; -import isEmpty from "./object/isEmpty.js"; +import none from "../object/none.js"; import isArray from "../is/array.js"; import isDate from "../is/date.js"; @@ -75,7 +75,7 @@ const diff = (obj1, obj2) => { return filter( value => - value !== null && !(value && "object" === typeof value && isEmpty(value)) + value !== null && !(value && "object" === typeof value && none(value)) )(result); }; diff --git a/encoding/base64url.js b/encoding/base64url.js index db2bd036..b053ef7b 100644 --- a/encoding/base64url.js +++ b/encoding/base64url.js @@ -9,3 +9,5 @@ export const toBase64Url = base64 => export const fromBase64Url = base64 => base64.replace(/-/g, "+").replace(/_/g, "/"); + +export default { encode }; diff --git a/index.js b/index.js index 9cc7a9bb..a908ee7f 100644 --- a/index.js +++ b/index.js @@ -1,19 +1,19 @@ -import array from "./array"; -import async from "./async"; -import date from "./date"; -import debug from "./debug"; -import encoding from "./encoding"; -import file from "./file"; -import _function from "./function"; -import is from "./is"; -import math from "./math"; -import object from "./object"; -import query from "./query"; -import range from "./range"; -import regex from "./regex"; -import string from "./string"; -import vector2 from "./vector2"; -import web from "./web"; +import array from "./array/index.js"; +import async from "./async/index.js"; +import date from "./date/index.js"; +import debug from "./debug/index.js"; +import encoding from "./encoding/index.js"; +import file from "./file/index.js"; +import _function from "./function/index.js"; +import is from "./is/index.js"; +import math from "./math/index.js"; +import object from "./object/index.js"; +import query from "./query/index.js"; +import range from "./range/index.js"; +import regex from "./regex/index.js"; +import string from "./string/index.js"; +import vector2 from "./vector2/index.js"; +import web from "./web/index.js"; export { array, diff --git a/range/split.js b/range/split.js index 6e8bb2c3..164e04d9 100644 --- a/range/split.js +++ b/range/split.js @@ -1,9 +1,9 @@ -import { isNotNaN } from "../is.js"; +import isNumber from "../is/number.js"; import clamp from "../math/clamp.js"; import empty from "./empty.js"; -export const split = (used, sourceRange = [-Infinity, Infinity]) => range => { - if (empty(range) || !range.every(isNotNaN)) { +export default (used, sourceRange = [-Infinity, Infinity]) => range => { + if (empty(range) || !range.every(isNumber)) { return []; } diff --git a/web/index.js b/web/index.js index 16d28c77..e75e558b 100644 --- a/web/index.js +++ b/web/index.js @@ -1,5 +1,5 @@ import classNames from "./classNames.js"; -import events from "./events"; +import events from "./events/index.js"; export { classNames, events }; From bf6bb954966d025bdebace4454f583129d4dffa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 13:34:12 +0200 Subject: [PATCH 13/56] Ignore build output files --- regenerate.js | 3 +++ rollup.config.js | 1 + 2 files changed, 4 insertions(+) diff --git a/regenerate.js b/regenerate.js index db4e1034..6d8a40fe 100644 --- a/regenerate.js +++ b/regenerate.js @@ -11,7 +11,10 @@ const mapping = { const ignoredFiles = [ ".gitignore", + ".npmignore", + "index.cjs.js", "index.js", + "index.umd.js", "LICENSE", "package-lock.json", "package.json", diff --git a/rollup.config.js b/rollup.config.js index f38843aa..3dabf215 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -7,6 +7,7 @@ export default { format: "cjs" }, { + exports: "named", file: "index.umd.js", format: "umd", name: "@sandstreamdev/std" From bca83641838097cd8c30667a6ce92c6df1eda086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 13:48:02 +0200 Subject: [PATCH 14/56] Fix broken default exports and add missing import --- array/filterInPlace.js | 2 +- array/first.js | 2 +- date/offsetByBit.js | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/array/filterInPlace.js b/array/filterInPlace.js index 375df26e..8b065931 100644 --- a/array/filterInPlace.js +++ b/array/filterInPlace.js @@ -1,4 +1,4 @@ -export default filterInPlace = f => xs => { +export default f => xs => { let i = 0; let j = 0; diff --git a/array/first.js b/array/first.js index 089de9a1..42b96520 100644 --- a/array/first.js +++ b/array/first.js @@ -1 +1 @@ -export default first = ([x]) => x; +export default ([x]) => x; diff --git a/date/offsetByBit.js b/date/offsetByBit.js index d492195c..6df9dd14 100644 --- a/date/offsetByBit.js +++ b/date/offsetByBit.js @@ -1,3 +1,5 @@ +import fromSeconds from "./fromSeconds"; + const SECOND = fromSeconds(1); export default date => new Date(date - SECOND); From 6d903abe6caac2cd85997437d997e53fa564b0da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 13:51:47 +0200 Subject: [PATCH 15/56] Add another missing import --- function/memoizeShallow.js | 2 ++ function/memoizeWith.js | 3 +++ 2 files changed, 5 insertions(+) diff --git a/function/memoizeShallow.js b/function/memoizeShallow.js index fb85b0f0..31528d8d 100644 --- a/function/memoizeShallow.js +++ b/function/memoizeShallow.js @@ -1,3 +1,5 @@ +import memoizeWith from "./memoizeWith"; + const equalsShallow = (xs, ys) => xs.length === ys.length && xs.every((x, index) => x === ys[index]); diff --git a/function/memoizeWith.js b/function/memoizeWith.js index 08e3665c..83481bb0 100644 --- a/function/memoizeWith.js +++ b/function/memoizeWith.js @@ -1,12 +1,15 @@ export default equals => f => { let memoized = undefined; let memoizedArgs = undefined; + return (...args) => { if (memoized && equals(args, memoizedArgs)) { return memoized; } + memoized = f(...args); memoizedArgs = args; + return memoized; }; }; From 446452dc4b0d22cba8283748d9acbc77af935e6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Fri, 4 Oct 2019 08:31:30 +0200 Subject: [PATCH 16/56] Add missing helpers --- date/displayMonth.js | 3 +++ date/formatDisplayDate.js | 13 +++++++++++++ date/index.js | 9 +++++++++ date/monthNames.js | 14 ++++++++++++++ math/clampPercentage.js | 3 +++ math/index.js | 3 +++ 6 files changed, 45 insertions(+) create mode 100644 date/displayMonth.js create mode 100644 date/formatDisplayDate.js create mode 100644 date/monthNames.js create mode 100644 math/clampPercentage.js diff --git a/date/displayMonth.js b/date/displayMonth.js new file mode 100644 index 00000000..83a1e0b6 --- /dev/null +++ b/date/displayMonth.js @@ -0,0 +1,3 @@ +import monthNames from "./monthNames"; + +export default monthIndex => monthNames[monthIndex % 12]; diff --git a/date/formatDisplayDate.js b/date/formatDisplayDate.js new file mode 100644 index 00000000..c3d06b8a --- /dev/null +++ b/date/formatDisplayDate.js @@ -0,0 +1,13 @@ +import toLocalDateTime from "./toLocalDateTime.js"; +import displayMonth from "./displayMonth.js"; + +export default (sourceDate, showDay = false, timezoneOffset = 0) => { + const localDate = toLocalDateTime(sourceDate, timezoneOffset); + const day = localDate.getDate(); + const monthIndex = localDate.getMonth(); + const year = localDate.getFullYear(); + + return [showDay && day, displayMonth(monthIndex), year] + .filter(Boolean) + .join(" "); +}; diff --git a/date/index.js b/date/index.js index 6dfdc1fc..bdaf6cbc 100644 --- a/date/index.js +++ b/date/index.js @@ -5,10 +5,12 @@ import dateInRange from "./dateInRange.js"; import dayRange from "./dayRange.js"; import daysInMonths from "./daysInMonths.js"; import daysInYear from "./daysInYear.js"; +import displayMonth from "./displayMonth.js"; import displayTime from "./displayTime.js"; import endOfDay from "./endOfDay.js"; import formatDate from "./formatDate.js"; import formatDateTime from "./formatDateTime.js"; +import formatDisplayDate from "./formatDisplayDate.js"; import formatDuration from "./formatDuration.js"; import formatTime from "./formatTime.js"; import fromDays from "./fromDays.js"; @@ -17,6 +19,7 @@ import fromMinutes from "./fromMinutes.js"; import fromSeconds from "./fromSeconds.js"; import joinDateTime from "./joinDateTime.js"; import leapYear from "./leapYear.js"; +import monthNames from "./monthNames.js"; import offsetByBit from "./offsetByBit.js"; import parseHourMinutePair from "./parseHourMinutePair.js"; import splitDateTime from "./splitDateTime.js"; @@ -41,10 +44,12 @@ export { dayRange, daysInMonths, daysInYear, + displayMonth, displayTime, endOfDay, formatDate, formatDateTime, + formatDisplayDate, formatDuration, formatTime, fromDays, @@ -53,6 +58,7 @@ export { fromSeconds, joinDateTime, leapYear, + monthNames, offsetByBit, parseHourMinutePair, splitDateTime, @@ -78,10 +84,12 @@ export default { dayRange, daysInMonths, daysInYear, + displayMonth, displayTime, endOfDay, formatDate, formatDateTime, + formatDisplayDate, formatDuration, formatTime, fromDays, @@ -90,6 +98,7 @@ export default { fromSeconds, joinDateTime, leapYear, + monthNames, offsetByBit, parseHourMinutePair, splitDateTime, diff --git a/date/monthNames.js b/date/monthNames.js new file mode 100644 index 00000000..c870f165 --- /dev/null +++ b/date/monthNames.js @@ -0,0 +1,14 @@ +export default [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" +]; diff --git a/math/clampPercentage.js b/math/clampPercentage.js new file mode 100644 index 00000000..d331be17 --- /dev/null +++ b/math/clampPercentage.js @@ -0,0 +1,3 @@ +import clamp from "./clamp.js"; + +export default clamp(0, 100); diff --git a/math/index.js b/math/index.js index ea1e5db5..596c8fe1 100644 --- a/math/index.js +++ b/math/index.js @@ -3,6 +3,7 @@ import average from "./average.js"; import ceilToNearestPowerOfTwo from "./ceilToNearestPowerOfTwo.js"; import clamp from "./clamp.js"; import clampNormal from "./clampNormal.js"; +import clampPercentage from "./clampPercentage.js"; import delta from "./delta.js"; import inRectangleRange from "./inRectangleRange.js"; import lerp from "./lerp.js"; @@ -20,6 +21,7 @@ export { ceilToNearestPowerOfTwo, clamp, clampNormal, + clampPercentage, delta, inRectangleRange, lerp, @@ -38,6 +40,7 @@ export default { ceilToNearestPowerOfTwo, clamp, clampNormal, + clampPercentage, delta, inRectangleRange, lerp, From c3aef80b77ce9844ba3534cf91620b14c44b31fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Fri, 4 Oct 2019 08:41:04 +0200 Subject: [PATCH 17/56] Add missing import --- date/toLocalDateTime.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/date/toLocalDateTime.js b/date/toLocalDateTime.js index c5bacd4d..90379f1a 100644 --- a/date/toLocalDateTime.js +++ b/date/toLocalDateTime.js @@ -1,2 +1,4 @@ +import fromMinutes from "./fromMinutes.js"; + export default (date, timezoneOffset = 0) => new Date(date.valueOf() - fromMinutes(timezoneOffset)); From a67a1115e99b130a36cd9a476b8718047c1bd63e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Fri, 4 Oct 2019 08:45:41 +0200 Subject: [PATCH 18/56] Add missing imports --- date/formatTime.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/date/formatTime.js b/date/formatTime.js index 7c158f82..6c01768f 100644 --- a/date/formatTime.js +++ b/date/formatTime.js @@ -1,3 +1,6 @@ +import toLocalDateTime from "./toLocalDateTime.js"; +import displayTime from "./displayTime.js"; + export default (sourceDate, showSeconds = false, timezoneOffset = 0) => { const localDate = toLocalDateTime(sourceDate, timezoneOffset); From c31632d1a13d2d3f20d05b0da2d8fe2a56703f07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Fri, 4 Oct 2019 08:57:57 +0200 Subject: [PATCH 19/56] Add missing range import for repeat --- array/repeat.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/array/repeat.js b/array/repeat.js index 8a7290ed..18cb69c5 100644 --- a/array/repeat.js +++ b/array/repeat.js @@ -1 +1,3 @@ +import range from "./range.js"; + export default n => value => range(n).map(() => value); From f3dc2a26570c070b9aaa5acdfd26c73aa8c0cba7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Fri, 4 Oct 2019 09:11:20 +0200 Subject: [PATCH 20/56] Fix range/split recursion and make clamp calls consistent --- date/clamp.js | 2 +- range/split.js | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/date/clamp.js b/date/clamp.js index 8e4cf914..70e2c31a 100644 --- a/date/clamp.js +++ b/date/clamp.js @@ -1,4 +1,4 @@ -export default ([min, max]) => dateStringOrDate => { +export default (min, max) => dateStringOrDate => { const date = new Date(dateStringOrDate); const clamped = new Date( Math.min(max.valueOf(), Math.max(min.valueOf(), date.valueOf())) diff --git a/range/split.js b/range/split.js index 164e04d9..05ed309d 100644 --- a/range/split.js +++ b/range/split.js @@ -2,7 +2,7 @@ import isNumber from "../is/number.js"; import clamp from "../math/clamp.js"; import empty from "./empty.js"; -export default (used, sourceRange = [-Infinity, Infinity]) => range => { +const split = (used, sourceRange = [-Infinity, Infinity]) => range => { if (empty(range) || !range.every(isNumber)) { return []; } @@ -19,20 +19,22 @@ export default (used, sourceRange = [-Infinity, Infinity]) => range => { } const [sourceMin, sourceMax] = sourceRange; - const clampToSourceRange = clamp(sourceRange); + const clampToSourceRange = clamp(...sourceRange); const freeLeft = [sourceMin, usedMin].map(clampToSourceRange); const freeRight = [usedMax, sourceMax].map(clampToSourceRange); - const clampLeft = clamp(freeLeft); + const clampLeft = clamp(...freeLeft); const clampedLeft = range.map(clampLeft); const lefts = split(xs, sourceRange)(clampedLeft); - const clampRight = clamp(freeRight); + const clampRight = clamp(...freeRight); const clampedRight = range.map(clampRight); const rights = split(xs, sourceRange)(clampedRight); return [...lefts, ...rights].filter(range => !empty(range)); }; + +export default split; From 4bf3101938435579457feb884fb20e88ee735471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Fri, 4 Oct 2019 13:14:11 +0200 Subject: [PATCH 21/56] Fix missing toString helper issue --- date/toDate.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/date/toDate.js b/date/toDate.js index 0a3c6b17..04b7bb21 100644 --- a/date/toDate.js +++ b/date/toDate.js @@ -4,8 +4,8 @@ export default date => { const year = date.getFullYear(); return [ - toString(year).padStart(4, "0"), - toString(month).padStart(2, "0"), - toString(day).padStart(2, "0") + `${year}`.padStart(4, "0"), + `${month}`.padStart(2, "0"), + `${day}`.padStart(2, "0") ].join("-"); }; From 477c240bf70468583ef67983effc4caed47572b5 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2019 08:43:07 +0000 Subject: [PATCH 22/56] docs: update README.md --- README.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0d24f20d..ab62b743 100644 --- a/README.md +++ b/README.md @@ -1 +1,17 @@ -# std \ No newline at end of file +# std +[![All Contributors](https://img.shields.io/badge/all_contributors-1-orange.svg?style=flat-square)](#contributors) +## Contributors ✨ + +Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): + + + + + + + +
sandstreamdevelopment
sandstreamdevelopment

💼 💵 🤔
+ + + +This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! \ No newline at end of file From 62dfd9f11293ae0ada843e5e48dad9f48e166a38 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2019 08:43:08 +0000 Subject: [PATCH 23/56] docs: create .all-contributorsrc --- .all-contributorsrc | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .all-contributorsrc diff --git a/.all-contributorsrc b/.all-contributorsrc new file mode 100644 index 00000000..d0cbda79 --- /dev/null +++ b/.all-contributorsrc @@ -0,0 +1,25 @@ +{ + "files": [ + "README.md" + ], + "imageSize": 100, + "commit": false, + "contributors": [ + { + "login": "sandstreamdevelopment", + "name": "sandstreamdevelopment", + "avatar_url": "https://avatars2.githubusercontent.com/u/44231396?v=4", + "profile": "https://github.com/sandstreamdevelopment", + "contributions": [ + "business", + "financial", + "ideas" + ] + } + ], + "contributorsPerLine": 7, + "projectName": "std", + "projectOwner": "sandstreamdev", + "repoType": "github", + "repoHost": "https://github.com" +} From b39b5c40a7fe0a737050a7c69139dcd21e9c3084 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Mon, 7 Oct 2019 18:38:08 +0200 Subject: [PATCH 24/56] Use Array.fill directly to generate repeated values --- array/repeat.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/array/repeat.js b/array/repeat.js index 18cb69c5..e90082e8 100644 --- a/array/repeat.js +++ b/array/repeat.js @@ -1,3 +1 @@ -import range from "./range.js"; - -export default n => value => range(n).map(() => value); +export default n => value => Array(n).fill(value); From 19c987ca4ae40503db0c5ccb15ebf170385838a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Mon, 7 Oct 2019 18:38:53 +0200 Subject: [PATCH 25/56] Use consistent any/none object and array APIs --- array/index.js | 3 +++ array/none.js | 3 +++ object/any.js | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 array/none.js diff --git a/array/index.js b/array/index.js index 59d65c30..70f2c678 100644 --- a/array/index.js +++ b/array/index.js @@ -18,6 +18,7 @@ import map from "./map.js"; import midpoint from "./midpoint.js"; import minMax from "./minMax.js"; import multiple from "./multiple.js"; +import none from "./none.js"; import partition from "./partition.js"; import range from "./range.js"; import repeat from "./repeat.js"; @@ -57,6 +58,7 @@ export { midpoint, minMax, multiple, + none, partition, range, repeat, @@ -97,6 +99,7 @@ export default { midpoint, minMax, multiple, + none, partition, range, repeat, diff --git a/array/none.js b/array/none.js new file mode 100644 index 00000000..307b11e6 --- /dev/null +++ b/array/none.js @@ -0,0 +1,3 @@ +import any from "./any.js"; + +export default xs => !any(xs); diff --git a/object/any.js b/object/any.js index 39db7f9d..0d0edf9b 100644 --- a/object/any.js +++ b/object/any.js @@ -1,3 +1,3 @@ import length from "./length.js"; -export default xs => length(xs) > 0; +export default xs => xs && length(xs) > 0; From 83f23daae33cc9d393dae70ebd9fcbca4000cd43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Mon, 7 Oct 2019 18:39:40 +0200 Subject: [PATCH 26/56] Improve adjust exact and range implementation --- array/exact.js | 7 +++---- array/range.js | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/array/exact.js b/array/exact.js index 0b6e8fac..c5080095 100644 --- a/array/exact.js +++ b/array/exact.js @@ -1,4 +1,3 @@ -export default n => source => - Array(n) - .fill() - .map((_, i) => source[i]); +import range from "./range.js"; + +export default n => xs => range(n).map(index => xs[index]); diff --git a/array/range.js b/array/range.js index 04a9907e..837dd682 100644 --- a/array/range.js +++ b/array/range.js @@ -1,4 +1,4 @@ export default n => Array(n) .fill() - .map((_, i) => i); + .map((_, index) => index); From b40fc5c7640da03bbfc244118ba76a4d64650299 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Mon, 7 Oct 2019 18:39:50 +0200 Subject: [PATCH 27/56] Add missing import --- array/reverseIf.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/array/reverseIf.js b/array/reverseIf.js index b718eb60..dacd1541 100644 --- a/array/reverseIf.js +++ b/array/reverseIf.js @@ -1 +1,3 @@ +import reverse from "./reverse.js"; + export default predicate => xs => (predicate ? reverse(xs) : xs); From 175ae7b6cee061f5b5db4416169c612be5d77167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Mon, 7 Oct 2019 18:40:19 +0200 Subject: [PATCH 28/56] Use isDefined helper --- debug/diff.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/debug/diff.js b/debug/diff.js index 80a1c0ee..1aa28eaf 100644 --- a/debug/diff.js +++ b/debug/diff.js @@ -1,6 +1,7 @@ import filter from "../object/filter.js"; import none from "../object/none.js"; +import isDefined from "../is/defined.js"; import isArray from "../is/array.js"; import isDate from "../is/date.js"; import isFunction from "../is/function.js"; @@ -26,11 +27,11 @@ const compareValues = (value1, value2) => { return VALUE_UNCHANGED; } - if ("undefined" == typeof value1) { + if (!isDefined(value1)) { return VALUE_CREATED; } - if ("undefined" == typeof value2) { + if (!isDefined(value2)) { return VALUE_DELETED; } @@ -53,20 +54,23 @@ const diff = (obj1, obj2) => { } const result = {}; + for (const key in obj1) { if (isFunction(obj1[key])) { continue; } let value2 = undefined; - if ("undefined" != typeof obj2[key]) { + + if (isDefined(obj2[key])) { value2 = obj2[key]; } result[key] = diff(obj1[key], value2); } + for (const key in obj2) { - if (isFunction(obj2[key]) || "undefined" != typeof result[key]) { + if (isFunction(obj2[key]) || isDefined(result[key])) { continue; } @@ -74,8 +78,7 @@ const diff = (obj1, obj2) => { } return filter( - value => - value !== null && !(value && "object" === typeof value && none(value)) + value => value !== null && !(value && isObject(value) && none(value)) )(result); }; From 288bafde9a3b4a9ad207cdc38c8313a420595f1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 09:55:24 +0200 Subject: [PATCH 29/56] Initialize package.json --- package.json | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 package.json diff --git a/package.json b/package.json new file mode 100644 index 00000000..5a0d3f49 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "@sandstreamdev/std", + "version": "0.1.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/sandstreamdev/std.git" + }, + "keywords": [], + "author": { + "name": "Sandstream Development", + "url": "https://www.sandstream.pl/" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/sandstreamdev/std/issues" + }, + "homepage": "https://github.com/sandstreamdev/std#readme" +} From 036d35b080458dfbb48474044b9e55b00a5475ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 10:09:49 +0200 Subject: [PATCH 30/56] Enable prettier --- README.md | 2 +- package-lock.json | 14 ++++++++++++++ package.json | 9 +++++++-- 3 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 package-lock.json diff --git a/README.md b/README.md index ab62b743..de4bf536 100644 --- a/README.md +++ b/README.md @@ -14,4 +14,4 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d -This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! \ No newline at end of file +This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..918666e9 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,14 @@ +{ + "name": "@sandstreamdev/std", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "prettier": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.18.2.tgz", + "integrity": "sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==", + "dev": true + } + } +} diff --git a/package.json b/package.json index 5a0d3f49..83e200b3 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,9 @@ "description": "", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "prettier": "prettier \"**/*.{js,json,md}\"", + "prettier:fix": "npm run prettier -- --write", + "prettier:check": "npm run prettier -- --check" }, "repository": { "type": "git", @@ -19,5 +21,8 @@ "bugs": { "url": "https://github.com/sandstreamdev/std/issues" }, - "homepage": "https://github.com/sandstreamdev/std#readme" + "homepage": "https://github.com/sandstreamdev/std#readme", + "devDependencies": { + "prettier": "^1.18.2" + } } From e8c6b69736eb777251cd59e736d059aaf5e55b11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 10:11:15 +0200 Subject: [PATCH 31/56] Declare package type and no side effects --- package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.json b/package.json index 83e200b3..5e7d69e6 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,8 @@ "version": "0.1.0", "description": "", "main": "index.js", + "type": "module", + "sideEffects": false, "scripts": { "prettier": "prettier \"**/*.{js,json,md}\"", "prettier:fix": "npm run prettier -- --write", From 1f919ff89cf59fdf4c0358d54e766bfbd2526083 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 10:12:01 +0200 Subject: [PATCH 32/56] Add initial helpers --- array/any.js | 1 + array/are.js | 3 ++ array/differs.js | 5 ++ array/duplicates.js | 2 + array/empty.js | 1 + array/exact.js | 4 ++ array/except.js | 1 + array/filterInPlace.js | 15 ++++++ array/find.js | 4 ++ array/first.js | 1 + array/flatMap.js | 1 + array/flatten.js | 1 + array/intersection.js | 1 + array/is.js | 1 + array/last.js | 1 + array/lengthDiffers.js | 1 + array/map.js | 4 ++ array/midpoint.js | 1 + array/minMax.js | 7 +++ array/multiple.js | 1 + array/partition.js | 8 +++ array/range.js | 4 ++ array/repeat.js | 1 + array/reverse.js | 1 + array/reverseIf.js | 1 + array/rotate.js | 8 +++ array/second.js | 1 + array/secondToLast.js | 1 + array/shift.js | 2 + array/shuffle.js | 3 ++ array/shuffleInPlace.js | 8 +++ array/single.js | 1 + array/sort.js | 1 + array/sum.js | 3 ++ array/transpose.js | 1 + array/zip.js | 3 ++ array/zipWith.js | 1 + async/debounce.js | 15 ++++++ async/delay.js | 2 + async/sequence.js | 14 ++++++ date/byDateWithFallback.js | 18 +++++++ date/clamp.js | 7 +++ date/dateDiff.js | 6 +++ date/dateInRange.js | 7 +++ date/dayRange.js | 24 +++++++++ date/daysInMonths.js | 14 ++++++ date/daysInYear.js | 5 ++ date/displayTime.js | 14 ++++++ date/endOfDay.js | 9 ++++ date/formatDate.js | 19 ++++++++ date/formatDateTime.js | 8 +++ date/formatDuration.js | 16 ++++++ date/formatTime.js | 11 +++++ date/fromDays.js | 3 ++ date/fromHours.js | 3 ++ date/fromMinutes.js | 3 ++ date/fromSeconds.js | 1 + date/joinDateTime.js | 1 + date/leapYear.js | 1 + date/monthRange.js | 24 +++++++++ date/offsetByBit.js | 3 ++ date/parseHourMinutePair.js | 6 +++ date/splitDateTime.js | 1 + date/startOfDay.js | 9 ++++ date/subtractDays.js | 7 +++ date/toDate.js | 11 +++++ date/toDates.js | 1 + date/toDays.js | 3 ++ date/toHours.js | 3 ++ date/toISO.js | 1 + date/toISOFromLocalDateTime.js | 6 +++ date/toLocalDateTime.js | 2 + date/toMinutes.js | 3 ++ date/toSeconds.js | 1 + date/valid.js | 1 + date/weekRange.js | 24 +++++++++ date/yearRange.js | 24 +++++++++ debug/assert.js | 52 ++++++++++++++++++++ debug/diff.js | 83 ++++++++++++++++++++++++++++++++ encoding/base64url.js | 11 +++++ file/validName.js | 5 ++ function/compose.js | 1 + function/constant.js | 1 + function/identity.js | 1 + function/memoize.js | 4 ++ function/memoizeShallow.js | 4 ++ function/memoizeWith.js | 12 +++++ function/noOp.js | 1 + function/pipe.js | 1 + function/when.js | 5 ++ function/whenTrue.js | 3 ++ is/array.js | 1 + is/byte.js | 3 ++ is/date.js | 1 + is/defined.js | 1 + is/function.js | 1 + is/integer.js | 3 ++ is/normal.js | 3 ++ is/number.js | 1 + is/object.js | 1 + is/string.js | 1 + math/add.js | 1 + math/average.js | 3 ++ math/ceilToNearestPowerOfTwo.js | 1 + math/clamp.js | 1 + math/clampNormal.js | 3 ++ math/delta.js | 1 + math/inRectangleRange.js | 2 + math/lerp.js | 1 + math/maximumBy.js | 2 + math/median.js | 13 +++++ math/minMax.js | 1 + math/safeNormalize.js | 1 + math/sameSign.js | 9 ++++ math/standardDeviation.js | 8 +++ math/subtract.js | 1 + object/any.js | 3 ++ object/apply.js | 5 ++ object/empty.js | 1 + object/entries.js | 2 + object/enumerable.js | 2 + object/equals.js | 29 +++++++++++ object/filter.js | 5 ++ object/find.js | 4 ++ object/findKey.js | 1 + object/findValue.js | 1 + object/first.js | 1 + object/flatMapValues.js | 5 ++ object/fromEntries.js | 6 +++ object/groupBy.js | 5 ++ object/hasKey.js | 2 + object/length.js | 1 + object/map.js | 4 ++ object/mapEntries.js | 4 ++ object/mapKeys.js | 5 ++ object/mapValues.js | 3 ++ object/none.js | 3 ++ object/sort.js | 5 ++ query/parse.js | 17 +++++++ query/parsePathname.js | 32 ++++++++++++ query/read.js | 5 ++ query/serialize.js | 8 +++ range/empty.js | 1 + range/equals.js | 1 + range/length.js | 1 + range/split.js | 38 +++++++++++++++ regex/escape.js | 1 + string/containsWhitespace.js | 1 + string/empty.js | 1 + string/firstToLower.js | 1 + string/firstToUpper.js | 1 + string/includes.js | 1 + string/nbsp.js | 1 + string/nonEmpty.js | 1 + string/startsWith.js | 1 + vector2/add.js | 1 + vector2/convertSpace.js | 6 +++ vector2/cross.js | 1 + vector2/dot.js | 1 + vector2/length.js | 1 + vector2/mul.js | 4 ++ vector2/multiply.js | 8 +++ vector2/normalize.js | 6 +++ vector2/reflect.js | 4 ++ vector2/rotate.js | 20 ++++++++ vector2/scale.js | 8 +++ vector2/sub.js | 1 + vector2/transform.js | 1 + vector2/translate.js | 8 +++ web/classNames.js | 16 ++++++ web/events/cancel.js | 8 +++ web/events/openInNewTabIntent.js | 2 + web/events/prevent.js | 4 ++ web/events/stop.js | 4 ++ 174 files changed, 996 insertions(+) create mode 100644 array/any.js create mode 100644 array/are.js create mode 100644 array/differs.js create mode 100644 array/duplicates.js create mode 100644 array/empty.js create mode 100644 array/exact.js create mode 100644 array/except.js create mode 100644 array/filterInPlace.js create mode 100644 array/find.js create mode 100644 array/first.js create mode 100644 array/flatMap.js create mode 100644 array/flatten.js create mode 100644 array/intersection.js create mode 100644 array/is.js create mode 100644 array/last.js create mode 100644 array/lengthDiffers.js create mode 100644 array/map.js create mode 100644 array/midpoint.js create mode 100644 array/minMax.js create mode 100644 array/multiple.js create mode 100644 array/partition.js create mode 100644 array/range.js create mode 100644 array/repeat.js create mode 100644 array/reverse.js create mode 100644 array/reverseIf.js create mode 100644 array/rotate.js create mode 100644 array/second.js create mode 100644 array/secondToLast.js create mode 100644 array/shift.js create mode 100644 array/shuffle.js create mode 100644 array/shuffleInPlace.js create mode 100644 array/single.js create mode 100644 array/sort.js create mode 100644 array/sum.js create mode 100644 array/transpose.js create mode 100644 array/zip.js create mode 100644 array/zipWith.js create mode 100644 async/debounce.js create mode 100644 async/delay.js create mode 100644 async/sequence.js create mode 100644 date/byDateWithFallback.js create mode 100644 date/clamp.js create mode 100644 date/dateDiff.js create mode 100644 date/dateInRange.js create mode 100644 date/dayRange.js create mode 100644 date/daysInMonths.js create mode 100644 date/daysInYear.js create mode 100644 date/displayTime.js create mode 100644 date/endOfDay.js create mode 100644 date/formatDate.js create mode 100644 date/formatDateTime.js create mode 100644 date/formatDuration.js create mode 100644 date/formatTime.js create mode 100644 date/fromDays.js create mode 100644 date/fromHours.js create mode 100644 date/fromMinutes.js create mode 100644 date/fromSeconds.js create mode 100644 date/joinDateTime.js create mode 100644 date/leapYear.js create mode 100644 date/monthRange.js create mode 100644 date/offsetByBit.js create mode 100644 date/parseHourMinutePair.js create mode 100644 date/splitDateTime.js create mode 100644 date/startOfDay.js create mode 100644 date/subtractDays.js create mode 100644 date/toDate.js create mode 100644 date/toDates.js create mode 100644 date/toDays.js create mode 100644 date/toHours.js create mode 100644 date/toISO.js create mode 100644 date/toISOFromLocalDateTime.js create mode 100644 date/toLocalDateTime.js create mode 100644 date/toMinutes.js create mode 100644 date/toSeconds.js create mode 100644 date/valid.js create mode 100644 date/weekRange.js create mode 100644 date/yearRange.js create mode 100644 debug/assert.js create mode 100644 debug/diff.js create mode 100644 encoding/base64url.js create mode 100644 file/validName.js create mode 100644 function/compose.js create mode 100644 function/constant.js create mode 100644 function/identity.js create mode 100644 function/memoize.js create mode 100644 function/memoizeShallow.js create mode 100644 function/memoizeWith.js create mode 100644 function/noOp.js create mode 100644 function/pipe.js create mode 100644 function/when.js create mode 100644 function/whenTrue.js create mode 100644 is/array.js create mode 100644 is/byte.js create mode 100644 is/date.js create mode 100644 is/defined.js create mode 100644 is/function.js create mode 100644 is/integer.js create mode 100644 is/normal.js create mode 100644 is/number.js create mode 100644 is/object.js create mode 100644 is/string.js create mode 100644 math/add.js create mode 100644 math/average.js create mode 100644 math/ceilToNearestPowerOfTwo.js create mode 100644 math/clamp.js create mode 100644 math/clampNormal.js create mode 100644 math/delta.js create mode 100644 math/inRectangleRange.js create mode 100644 math/lerp.js create mode 100644 math/maximumBy.js create mode 100644 math/median.js create mode 100644 math/minMax.js create mode 100644 math/safeNormalize.js create mode 100644 math/sameSign.js create mode 100644 math/standardDeviation.js create mode 100644 math/subtract.js create mode 100644 object/any.js create mode 100644 object/apply.js create mode 100644 object/empty.js create mode 100644 object/entries.js create mode 100644 object/enumerable.js create mode 100644 object/equals.js create mode 100644 object/filter.js create mode 100644 object/find.js create mode 100644 object/findKey.js create mode 100644 object/findValue.js create mode 100644 object/first.js create mode 100644 object/flatMapValues.js create mode 100644 object/fromEntries.js create mode 100644 object/groupBy.js create mode 100644 object/hasKey.js create mode 100644 object/length.js create mode 100644 object/map.js create mode 100644 object/mapEntries.js create mode 100644 object/mapKeys.js create mode 100644 object/mapValues.js create mode 100644 object/none.js create mode 100644 object/sort.js create mode 100644 query/parse.js create mode 100644 query/parsePathname.js create mode 100644 query/read.js create mode 100644 query/serialize.js create mode 100644 range/empty.js create mode 100644 range/equals.js create mode 100644 range/length.js create mode 100644 range/split.js create mode 100644 regex/escape.js create mode 100644 string/containsWhitespace.js create mode 100644 string/empty.js create mode 100644 string/firstToLower.js create mode 100644 string/firstToUpper.js create mode 100644 string/includes.js create mode 100644 string/nbsp.js create mode 100644 string/nonEmpty.js create mode 100644 string/startsWith.js create mode 100644 vector2/add.js create mode 100644 vector2/convertSpace.js create mode 100644 vector2/cross.js create mode 100644 vector2/dot.js create mode 100644 vector2/length.js create mode 100644 vector2/mul.js create mode 100644 vector2/multiply.js create mode 100644 vector2/normalize.js create mode 100644 vector2/reflect.js create mode 100644 vector2/rotate.js create mode 100644 vector2/scale.js create mode 100644 vector2/sub.js create mode 100644 vector2/transform.js create mode 100644 vector2/translate.js create mode 100644 web/classNames.js create mode 100644 web/events/cancel.js create mode 100644 web/events/openInNewTabIntent.js create mode 100644 web/events/prevent.js create mode 100644 web/events/stop.js diff --git a/array/any.js b/array/any.js new file mode 100644 index 00000000..f9a2b66c --- /dev/null +++ b/array/any.js @@ -0,0 +1 @@ +export default xs => xs && xs.length > 0; diff --git a/array/are.js b/array/are.js new file mode 100644 index 00000000..c32dc386 --- /dev/null +++ b/array/are.js @@ -0,0 +1,3 @@ +import is from "./is"; + +export default (...xs) => xs.every(is); diff --git a/array/differs.js b/array/differs.js new file mode 100644 index 00000000..1fac6689 --- /dev/null +++ b/array/differs.js @@ -0,0 +1,5 @@ +export default (xs, ys) => + (!xs && ys) || + (!ys && xs) || + xs.length !== ys.length || + xs.some((x, index) => x !== ys[index]); diff --git a/array/duplicates.js b/array/duplicates.js new file mode 100644 index 00000000..f3ff72f7 --- /dev/null +++ b/array/duplicates.js @@ -0,0 +1,2 @@ +export default xs => + xs.filter((value, index, self) => self.indexOf(value) !== index); diff --git a/array/empty.js b/array/empty.js new file mode 100644 index 00000000..d6d1738d --- /dev/null +++ b/array/empty.js @@ -0,0 +1 @@ +export default []; diff --git a/array/exact.js b/array/exact.js new file mode 100644 index 00000000..0b6e8fac --- /dev/null +++ b/array/exact.js @@ -0,0 +1,4 @@ +export default n => source => + Array(n) + .fill() + .map((_, i) => source[i]); diff --git a/array/except.js b/array/except.js new file mode 100644 index 00000000..b721e9d4 --- /dev/null +++ b/array/except.js @@ -0,0 +1 @@ +export default y => xs => xs.filter(x => x !== y); diff --git a/array/filterInPlace.js b/array/filterInPlace.js new file mode 100644 index 00000000..375df26e --- /dev/null +++ b/array/filterInPlace.js @@ -0,0 +1,15 @@ +export default filterInPlace = f => xs => { + let i = 0; + let j = 0; + + while (i < xs.length) { + const value = xs[i]; + if (f(value, i, xs)) { + xs[j++] = value; + } + i++; + } + + xs.length = j; + return xs; +}; diff --git a/array/find.js b/array/find.js new file mode 100644 index 00000000..9e4018a0 --- /dev/null +++ b/array/find.js @@ -0,0 +1,4 @@ +export default (predicate, fallback) => xs => { + const target = xs.find(predicate); + return target !== undefined ? target : fallback; +}; diff --git a/array/first.js b/array/first.js new file mode 100644 index 00000000..089de9a1 --- /dev/null +++ b/array/first.js @@ -0,0 +1 @@ +export default first = ([x]) => x; diff --git a/array/flatMap.js b/array/flatMap.js new file mode 100644 index 00000000..00184cb9 --- /dev/null +++ b/array/flatMap.js @@ -0,0 +1 @@ +export default f => xs => xs.reduce((ys, y) => ys.concat(f(y)), []); diff --git a/array/flatten.js b/array/flatten.js new file mode 100644 index 00000000..936f23dd --- /dev/null +++ b/array/flatten.js @@ -0,0 +1 @@ +export default xs => [].concat(...xs); diff --git a/array/intersection.js b/array/intersection.js new file mode 100644 index 00000000..647ae519 --- /dev/null +++ b/array/intersection.js @@ -0,0 +1 @@ +export default (xs, ys) => xs.filter(value => ys.includes(value)); diff --git a/array/is.js b/array/is.js new file mode 100644 index 00000000..b0f97bbe --- /dev/null +++ b/array/is.js @@ -0,0 +1 @@ +export default value => Array.isArray(value); diff --git a/array/last.js b/array/last.js new file mode 100644 index 00000000..8302bdbb --- /dev/null +++ b/array/last.js @@ -0,0 +1 @@ +export default xs => xs[xs.length - 1]; diff --git a/array/lengthDiffers.js b/array/lengthDiffers.js new file mode 100644 index 00000000..f8019d11 --- /dev/null +++ b/array/lengthDiffers.js @@ -0,0 +1 @@ +export default (a, b) => a.length !== b.length; diff --git a/array/map.js b/array/map.js new file mode 100644 index 00000000..a61d5d13 --- /dev/null +++ b/array/map.js @@ -0,0 +1,4 @@ +export default (...fs) => { + const f = x => fs.reduce((x, f) => f(x), x); + return x => x.map(f); +}; diff --git a/array/midpoint.js b/array/midpoint.js new file mode 100644 index 00000000..6acdb881 --- /dev/null +++ b/array/midpoint.js @@ -0,0 +1 @@ +export default xs => xs[Math.floor(xs.length / 2)]; diff --git a/array/minMax.js b/array/minMax.js new file mode 100644 index 00000000..a1129efa --- /dev/null +++ b/array/minMax.js @@ -0,0 +1,7 @@ +const { max, min } = Math; + +export default ([head, ...tail]) => + tail.reduce(([min, max], current) => [min(min, current), max(max, current)], [ + head, + head + ]); diff --git a/array/multiple.js b/array/multiple.js new file mode 100644 index 00000000..19d1cdb0 --- /dev/null +++ b/array/multiple.js @@ -0,0 +1 @@ +export default xs => xs.length > 1; diff --git a/array/partition.js b/array/partition.js new file mode 100644 index 00000000..039a6ce7 --- /dev/null +++ b/array/partition.js @@ -0,0 +1,8 @@ +export default predicate => xs => + xs.reduce( + ([left, right], current) => { + const pass = predicate(current); + return pass ? [left, [...right, current]] : [[...left, current], right]; + }, + [[], []] + ); diff --git a/array/range.js b/array/range.js new file mode 100644 index 00000000..04a9907e --- /dev/null +++ b/array/range.js @@ -0,0 +1,4 @@ +export default n => + Array(n) + .fill() + .map((_, i) => i); diff --git a/array/repeat.js b/array/repeat.js new file mode 100644 index 00000000..8a7290ed --- /dev/null +++ b/array/repeat.js @@ -0,0 +1 @@ +export default n => value => range(n).map(() => value); diff --git a/array/reverse.js b/array/reverse.js new file mode 100644 index 00000000..75a00a68 --- /dev/null +++ b/array/reverse.js @@ -0,0 +1 @@ +export default xs => [...xs].reverse(); diff --git a/array/reverseIf.js b/array/reverseIf.js new file mode 100644 index 00000000..b718eb60 --- /dev/null +++ b/array/reverseIf.js @@ -0,0 +1 @@ +export default predicate => xs => (predicate ? reverse(xs) : xs); diff --git a/array/rotate.js b/array/rotate.js new file mode 100644 index 00000000..32a160cd --- /dev/null +++ b/array/rotate.js @@ -0,0 +1,8 @@ +export default array => angle => { + const margin = Math.PI / 8; + const angleWithMargin = angle + margin; + const unit = Math.PI / 4; + const ratio = angleWithMargin / unit; + const offset = Math.floor(ratio); + return shift(offset)(array); +}; diff --git a/array/second.js b/array/second.js new file mode 100644 index 00000000..41953d02 --- /dev/null +++ b/array/second.js @@ -0,0 +1 @@ +export default ([, x]) => x; diff --git a/array/secondToLast.js b/array/secondToLast.js new file mode 100644 index 00000000..134e4b9c --- /dev/null +++ b/array/secondToLast.js @@ -0,0 +1 @@ +export default xs => xs[xs.length - 2]; diff --git a/array/shift.js b/array/shift.js new file mode 100644 index 00000000..b0cc0987 --- /dev/null +++ b/array/shift.js @@ -0,0 +1,2 @@ +export default n => xs => + xs.map((_, index) => xs[(index + (n % xs.length) + xs.length) % xs.length]); diff --git a/array/shuffle.js b/array/shuffle.js new file mode 100644 index 00000000..cf1cf3a0 --- /dev/null +++ b/array/shuffle.js @@ -0,0 +1,3 @@ +import shuffleInPlace from "./shuffleInPlace"; + +export default xs => shuffleInPlace([...xs]); diff --git a/array/shuffleInPlace.js b/array/shuffleInPlace.js new file mode 100644 index 00000000..ae39da13 --- /dev/null +++ b/array/shuffleInPlace.js @@ -0,0 +1,8 @@ +export default xs => { + for (let i = 0; i < xs.length; i++) { + const j = Math.floor(Math.random() * (i + 1)); + [xs[i], xs[j]] = [xs[j], xs[i]]; + } + + return xs; +}; diff --git a/array/single.js b/array/single.js new file mode 100644 index 00000000..bdc53c3f --- /dev/null +++ b/array/single.js @@ -0,0 +1 @@ +export default xs => xs.length === 1; diff --git a/array/sort.js b/array/sort.js new file mode 100644 index 00000000..645230d6 --- /dev/null +++ b/array/sort.js @@ -0,0 +1 @@ +export default f => xs => [...xs].sort(f); diff --git a/array/sum.js b/array/sum.js new file mode 100644 index 00000000..3d49a4b1 --- /dev/null +++ b/array/sum.js @@ -0,0 +1,3 @@ +const add = (a, b) => a + b; + +export default xs => xs.reduce(add, 0); diff --git a/array/transpose.js b/array/transpose.js new file mode 100644 index 00000000..9da83662 --- /dev/null +++ b/array/transpose.js @@ -0,0 +1 @@ +export default xs => Object.keys(xs[0]).map(key => [xs.map(x => x[key]), key]); diff --git a/array/zip.js b/array/zip.js new file mode 100644 index 00000000..bab08804 --- /dev/null +++ b/array/zip.js @@ -0,0 +1,3 @@ +import zipWith from "./zipWith"; + +export default zipWith((x, y) => [x, y]); diff --git a/array/zipWith.js b/array/zipWith.js new file mode 100644 index 00000000..7cd6a442 --- /dev/null +++ b/array/zipWith.js @@ -0,0 +1 @@ +export default f => (xs, ys) => xs.map((x, index) => f(x, ys[index])); diff --git a/async/debounce.js b/async/debounce.js new file mode 100644 index 00000000..11423a1a --- /dev/null +++ b/async/debounce.js @@ -0,0 +1,15 @@ +export default (f, wait) => { + let timeout; + + return (...args) => { + const resolve = () => { + timeout = null; + + f(...args); + }; + + clearTimeout(timeout); + + timeout = setTimeout(resolve, wait); + }; +}; diff --git a/async/delay.js b/async/delay.js new file mode 100644 index 00000000..0c7bc064 --- /dev/null +++ b/async/delay.js @@ -0,0 +1,2 @@ +export default duration => + new Promise(resolve => setTimeout(resolve, duration)); diff --git a/async/sequence.js b/async/sequence.js new file mode 100644 index 00000000..f689e49c --- /dev/null +++ b/async/sequence.js @@ -0,0 +1,14 @@ +export default async tasks => { + const results = tasks.map(_ => undefined); + + await tasks.reduce((chain, current, i) => { + return chain.then(() => + current().then(x => { + results[i] = x; + return x; + }) + ); + }, Promise.resolve()); + + return results; +}; diff --git a/date/byDateWithFallback.js b/date/byDateWithFallback.js new file mode 100644 index 00000000..3c6c5296 --- /dev/null +++ b/date/byDateWithFallback.js @@ -0,0 +1,18 @@ +export default now => ( + { endedAt: aEnd, startedAt: aStart }, + { endedAt: bEnd, startedAt: bStart } +) => { + const aEndDate = new Date(aEnd || now); + const aStartDate = new Date(aStart || now); + const bEndDate = new Date(bEnd || now); + const bStartDate = new Date(bStart || now); + const aEndDateValue = aEndDate.valueOf(); + const aStartDateValue = aStartDate.valueOf(); + const bEndDateValue = bEndDate.valueOf(); + const bStartDateValue = bStartDate.valueOf(); + + const startDateDifference = aStartDateValue - bStartDateValue; + const startDatesEqual = startDateDifference === 0; + + return startDatesEqual ? aEndDateValue - bEndDateValue : startDateDifference; +}; diff --git a/date/clamp.js b/date/clamp.js new file mode 100644 index 00000000..8e4cf914 --- /dev/null +++ b/date/clamp.js @@ -0,0 +1,7 @@ +export default ([min, max]) => dateStringOrDate => { + const date = new Date(dateStringOrDate); + const clamped = new Date( + Math.min(max.valueOf(), Math.max(min.valueOf(), date.valueOf())) + ); + return clamped; +}; diff --git a/date/dateDiff.js b/date/dateDiff.js new file mode 100644 index 00000000..2e4d2ce6 --- /dev/null +++ b/date/dateDiff.js @@ -0,0 +1,6 @@ +export default (a, b) => { + const d1 = new Date(a); + const d2 = new Date(b); + + return d1.valueOf() - d2.valueOf(); +}; diff --git a/date/dateInRange.js b/date/dateInRange.js new file mode 100644 index 00000000..29997ef7 --- /dev/null +++ b/date/dateInRange.js @@ -0,0 +1,7 @@ +export default (from, to) => (date = new Date()) => { + const dateTime = new Date(date).getTime(); + const fromTime = new Date(from).getTime(); + const toTime = new Date(to).getTime(); + + return dateTime >= fromTime && dateTime <= toTime; +}; diff --git a/date/dayRange.js b/date/dayRange.js new file mode 100644 index 00000000..8a182b51 --- /dev/null +++ b/date/dayRange.js @@ -0,0 +1,24 @@ +import endOfDay from "./endOfDay"; +import offsetByBit from "./offsetByBit"; +import splitDateTime from "./splitDateTime"; +import startOfDay from "./startOfDay"; +import toISO from "./toISO"; +import toISOFromLocalDateTime from "./toISOFromLocalDateTime"; + +export default ({ + iso = false, + local = true, + now = new Date(), + timezoneOffset = 0 +}) => date => { + const convert = iso ? toISO : toISOFromLocalDateTime; + + const [start] = splitDateTime( + convert(startOfDay(date || now, timezoneOffset, local)) + ); + const [end] = splitDateTime( + convert(offsetByBit(endOfDay(date || now, timezoneOffset, local))) + ); + + return [start, end]; +}; diff --git a/date/daysInMonths.js b/date/daysInMonths.js new file mode 100644 index 00000000..2ad5657f --- /dev/null +++ b/date/daysInMonths.js @@ -0,0 +1,14 @@ +export default leapYear => [ + 31, + leapYear ? 29 : 28, + 31, + 30, + 31, + 30, + 31, + 31, + 30, + 31, + 30, + 31 +]; diff --git a/date/daysInYear.js b/date/daysInYear.js new file mode 100644 index 00000000..13c489da --- /dev/null +++ b/date/daysInYear.js @@ -0,0 +1,5 @@ +import sum from "../array/sum"; +import daysInMonths from "./daysInMonths"; +import leapYear from "./leapYear"; + +export default year => sum(daysInMonths(leapYear(year))); diff --git a/date/displayTime.js b/date/displayTime.js new file mode 100644 index 00000000..fc78bc18 --- /dev/null +++ b/date/displayTime.js @@ -0,0 +1,14 @@ +export default (source, showSeconds) => { + const [hours, minutes, seconds] = source.map(_ => _ + ""); + + const padded = [ + hours.padStart(2, "0"), + minutes.padStart(2, "0"), + seconds.padStart(2, "0") + ]; + + const [paddedHours, paddedMinutes] = padded; + const parts = showSeconds ? padded : [paddedHours, paddedMinutes]; + + return parts.join(":"); +}; diff --git a/date/endOfDay.js b/date/endOfDay.js new file mode 100644 index 00000000..f51306e8 --- /dev/null +++ b/date/endOfDay.js @@ -0,0 +1,9 @@ +import toLocalDateTime from "./toLocalDateTime"; + +export default (date, timezoneOffset = 0, local = true) => { + const newDate = new Date(date); + newDate.setHours(24, 0, 0, 0); + return local + ? toLocalDateTime(newDate, timezoneOffset + newDate.getTimezoneOffset()) + : newDate; +}; diff --git a/date/formatDate.js b/date/formatDate.js new file mode 100644 index 00000000..f6fcac30 --- /dev/null +++ b/date/formatDate.js @@ -0,0 +1,19 @@ +import toLocalDateTime from "./toLocalDateTime"; + +export default (sourceDate, timezoneOffset = 0) => { + const localDate = toLocalDateTime(sourceDate, timezoneOffset); + + const [m, a, y] = [ + localDate.getUTCMonth() + 1, + localDate.getUTCDate(), + localDate.getUTCFullYear() + ].map(_ => _ + ""); + + const date = [ + y.padStart(4, "0"), + m.padStart(2, "0"), + a.padStart(2, "0") + ].join("-"); + + return date; +}; diff --git a/date/formatDateTime.js b/date/formatDateTime.js new file mode 100644 index 00000000..f3aa9c00 --- /dev/null +++ b/date/formatDateTime.js @@ -0,0 +1,8 @@ +import formatDate from "./formatDate"; +import formatTime from "./formatTime"; + +export default (sourceDate, showSeconds = false, timezoneOffset = 0) => { + const date = formatDate(sourceDate, timezoneOffset); + const time = formatTime(sourceDate, showSeconds, timezoneOffset); + return `${date} ${time}`; +}; diff --git a/date/formatDuration.js b/date/formatDuration.js new file mode 100644 index 00000000..8fd96a38 --- /dev/null +++ b/date/formatDuration.js @@ -0,0 +1,16 @@ +import fromHours from "./fromHours"; +import fromMinutes from "./fromMinutes"; +import toHours from "./toHours"; +import toMinutes from "./toMinutes"; +import toSeconds from "./toSeconds"; +import displayTime from "./displayTime"; + +export default (duration, showSeconds = false) => { + const hours = Math.floor(toHours(duration)); + const minutes = Math.floor(toMinutes(duration - fromHours(hours))); + const seconds = Math.floor( + toSeconds(duration - fromHours(hours) - fromMinutes(minutes)) + ); + + return displayTime([hours, minutes, seconds], showSeconds); +}; diff --git a/date/formatTime.js b/date/formatTime.js new file mode 100644 index 00000000..7c158f82 --- /dev/null +++ b/date/formatTime.js @@ -0,0 +1,11 @@ +export default (sourceDate, showSeconds = false, timezoneOffset = 0) => { + const localDate = toLocalDateTime(sourceDate, timezoneOffset); + + const source = [ + localDate.getUTCHours(), + localDate.getUTCMinutes(), + localDate.getUTCSeconds() + ]; + + return displayTime(source, showSeconds); +}; diff --git a/date/fromDays.js b/date/fromDays.js new file mode 100644 index 00000000..ea8d490e --- /dev/null +++ b/date/fromDays.js @@ -0,0 +1,3 @@ +import fromHours from "./fromHours"; + +export default days => fromHours(days * 24); diff --git a/date/fromHours.js b/date/fromHours.js new file mode 100644 index 00000000..6a5f9617 --- /dev/null +++ b/date/fromHours.js @@ -0,0 +1,3 @@ +import fromMinutes from "./fromMinutes"; + +export default hours => fromMinutes(hours * 60); diff --git a/date/fromMinutes.js b/date/fromMinutes.js new file mode 100644 index 00000000..6e32741a --- /dev/null +++ b/date/fromMinutes.js @@ -0,0 +1,3 @@ +import fromSeconds from "./fromSeconds"; + +export default minutes => fromSeconds(minutes * 60); diff --git a/date/fromSeconds.js b/date/fromSeconds.js new file mode 100644 index 00000000..c0770d78 --- /dev/null +++ b/date/fromSeconds.js @@ -0,0 +1 @@ +export default seconds => seconds * 1000; diff --git a/date/joinDateTime.js b/date/joinDateTime.js new file mode 100644 index 00000000..328ef7c9 --- /dev/null +++ b/date/joinDateTime.js @@ -0,0 +1 @@ +export default (...xs) => xs.join("T"); diff --git a/date/leapYear.js b/date/leapYear.js new file mode 100644 index 00000000..62ab3314 --- /dev/null +++ b/date/leapYear.js @@ -0,0 +1 @@ +export default year => new Date(year, 1, 29).getMonth() === 1; diff --git a/date/monthRange.js b/date/monthRange.js new file mode 100644 index 00000000..cc52fcf8 --- /dev/null +++ b/date/monthRange.js @@ -0,0 +1,24 @@ +import endOfMonth from "./endOfMonth"; +import offsetByBit from "./offsetByBit"; +import splitDateTime from "./splitDateTime"; +import startOfMonth from "./startOfMonth"; +import toISO from "./toISO"; +import toISOFromLocalDateTime from "./toISOFromLocalDateTime"; + +export default ({ + iso = false, + local = true, + now = new Date(), + timezoneOffset = 0 +}) => date => { + const convert = iso ? toISO : toISOFromLocalDateTime; + + const [start] = splitDateTime( + convert(startOfMonth(date || now, timezoneOffset, local)) + ); + const [end] = splitDateTime( + convert(offsetByBit(endOfMonth(date || now, timezoneOffset, local))) + ); + + return [start, end]; +}; diff --git a/date/offsetByBit.js b/date/offsetByBit.js new file mode 100644 index 00000000..d492195c --- /dev/null +++ b/date/offsetByBit.js @@ -0,0 +1,3 @@ +const SECOND = fromSeconds(1); + +export default date => new Date(date - SECOND); diff --git a/date/parseHourMinutePair.js b/date/parseHourMinutePair.js new file mode 100644 index 00000000..5862c201 --- /dev/null +++ b/date/parseHourMinutePair.js @@ -0,0 +1,6 @@ +export default (text = "") => { + const [hoursString, minutesString] = text.split(":"); + const hours = parseInt(hoursString || 0, 10); + const minutes = parseInt(minutesString || 0, 10); + return [hours, minutes]; +}; diff --git a/date/splitDateTime.js b/date/splitDateTime.js new file mode 100644 index 00000000..0b871afb --- /dev/null +++ b/date/splitDateTime.js @@ -0,0 +1 @@ +export default dateTimeString => dateTimeString.split("T"); diff --git a/date/startOfDay.js b/date/startOfDay.js new file mode 100644 index 00000000..0c5805ab --- /dev/null +++ b/date/startOfDay.js @@ -0,0 +1,9 @@ +import toLocalDateTime from "./toLocalDateTime"; + +export default (date, timezoneOffset = 0, local = true) => { + const newDate = new Date(date); + newDate.setHours(0, 0, 0, 0); + return local + ? toLocalDateTime(newDate, timezoneOffset + newDate.getTimezoneOffset()) + : newDate; +}; diff --git a/date/subtractDays.js b/date/subtractDays.js new file mode 100644 index 00000000..3dbbb505 --- /dev/null +++ b/date/subtractDays.js @@ -0,0 +1,7 @@ +export default (sourceDate, numberOfDays) => { + const date = new Date(sourceDate); + + date.setDate(date.getDate() - numberOfDays); + + return date; +}; diff --git a/date/toDate.js b/date/toDate.js new file mode 100644 index 00000000..0a3c6b17 --- /dev/null +++ b/date/toDate.js @@ -0,0 +1,11 @@ +export default date => { + const day = date.getDate(); + const month = date.getMonth() + 1; + const year = date.getFullYear(); + + return [ + toString(year).padStart(4, "0"), + toString(month).padStart(2, "0"), + toString(day).padStart(2, "0") + ].join("-"); +}; diff --git a/date/toDates.js b/date/toDates.js new file mode 100644 index 00000000..8fb2e180 --- /dev/null +++ b/date/toDates.js @@ -0,0 +1 @@ +export default xs => xs.map(x => new Date(x)); diff --git a/date/toDays.js b/date/toDays.js new file mode 100644 index 00000000..1d9e7132 --- /dev/null +++ b/date/toDays.js @@ -0,0 +1,3 @@ +import toHours from "./toHours"; + +export default milliseconds => toHours(milliseconds) / 24; diff --git a/date/toHours.js b/date/toHours.js new file mode 100644 index 00000000..44509b4b --- /dev/null +++ b/date/toHours.js @@ -0,0 +1,3 @@ +import toMinutes from "./toMinutes"; + +export default milliseconds => toMinutes(milliseconds) / 60; diff --git a/date/toISO.js b/date/toISO.js new file mode 100644 index 00000000..9ac56e00 --- /dev/null +++ b/date/toISO.js @@ -0,0 +1 @@ +export default x => x.toISOString(); diff --git a/date/toISOFromLocalDateTime.js b/date/toISOFromLocalDateTime.js new file mode 100644 index 00000000..f4d527df --- /dev/null +++ b/date/toISOFromLocalDateTime.js @@ -0,0 +1,6 @@ +import fromMinutes from "./fromMinutes"; + +export default date => + new Date( + date.valueOf() - fromMinutes(date.getTimezoneOffset()) + ).toISOString(); diff --git a/date/toLocalDateTime.js b/date/toLocalDateTime.js new file mode 100644 index 00000000..c5bacd4d --- /dev/null +++ b/date/toLocalDateTime.js @@ -0,0 +1,2 @@ +export default (date, timezoneOffset = 0) => + new Date(date.valueOf() - fromMinutes(timezoneOffset)); diff --git a/date/toMinutes.js b/date/toMinutes.js new file mode 100644 index 00000000..3ef8dcca --- /dev/null +++ b/date/toMinutes.js @@ -0,0 +1,3 @@ +import toSeconds from "./toSeconds"; + +export default milliseconds => toSeconds(milliseconds) / 60; diff --git a/date/toSeconds.js b/date/toSeconds.js new file mode 100644 index 00000000..39f86994 --- /dev/null +++ b/date/toSeconds.js @@ -0,0 +1 @@ +export default milliseconds => milliseconds / 1000; diff --git a/date/valid.js b/date/valid.js new file mode 100644 index 00000000..dcd6e7fe --- /dev/null +++ b/date/valid.js @@ -0,0 +1 @@ +export default date => date && date instanceof Date && !Number.isNaN(date); diff --git a/date/weekRange.js b/date/weekRange.js new file mode 100644 index 00000000..af839bc0 --- /dev/null +++ b/date/weekRange.js @@ -0,0 +1,24 @@ +import endOfWeek from "./endOfWeek"; +import offsetByBit from "./offsetByBit"; +import splitDateTime from "./splitDateTime"; +import startOfWeek from "./startOfWeek"; +import toISO from "./toISO"; +import toISOFromLocalDateTime from "./toISOFromLocalDateTime"; + +export default ({ + iso = false, + local = true, + now = new Date(), + timezoneOffset = 0 +}) => date => { + const convert = iso ? toISO : toISOFromLocalDateTime; + + const [start] = splitDateTime( + convert(startOfWeek(date || now, timezoneOffset, local)) + ); + const [end] = splitDateTime( + convert(offsetByBit(endOfWeek(date || now, timezoneOffset, local))) + ); + + return [start, end]; +}; diff --git a/date/yearRange.js b/date/yearRange.js new file mode 100644 index 00000000..167a7740 --- /dev/null +++ b/date/yearRange.js @@ -0,0 +1,24 @@ +import endOfYear from "./endOfYear"; +import offsetByBit from "./offsetByBit"; +import splitDateTime from "./splitDateTime"; +import startOfYear from "./startOfYear"; +import toISO from "./toISO"; +import toISOFromLocalDateTime from "./toISOFromLocalDateTime"; + +export default ({ + iso = false, + local = true, + now = new Date(), + timezoneOffset = 0 +}) => date => { + const convert = iso ? toISO : toISOFromLocalDateTime; + + const [start] = splitDateTime( + convert(startOfYear(date || now, timezoneOffset, local)) + ); + const [end] = splitDateTime( + convert(offsetByBit(endOfYear(date || now, timezoneOffset, local))) + ); + + return [start, end]; +}; diff --git a/debug/assert.js b/debug/assert.js new file mode 100644 index 00000000..73f796b6 --- /dev/null +++ b/debug/assert.js @@ -0,0 +1,52 @@ +import isNumber from "../is/number"; +import isInteger from "../is/integer"; +import isByte from "../is/byte"; +import isNormal from "../is/normal"; +import isString from "../is/string"; +import isDefined from "../is/defined"; + +const assert = (condition, callbackOrMessage) => { + if (!condition) { + if (typeof callbackOrMessage === "function") { + callbackOrMessage(); + } else { + throw new TypeError( + typeof callbackOrMessage === "string" + ? callbackOrMessage + : "Assertion failed!" + ); + } + } +}; + +export const throws = f => { + try { + f(); + return undefined; + } catch (error) { + return error; + } +}; + +export const assertNumber = x => + assert(isNumber(x), `Value must be a valid number but it is ${typeof x}.`); + +export const assertInteger = x => + assertNumber(x) && assert(isInteger(x), "Value must be an integer."); + +export const assertByte = x => + assertInteger(x) && assert(isByte(x), "Value must be a byte."); + +export const assertNormal = x => + assertNumber(x) && + assert( + isNormal(x), + `Value must be a number in range of 0 to 1 inclusive but it is ${x}.` + ); + +export const assertString = x => assert(isString(x), "Value must be a string."); + +export const assertIsDefined = (x, message = "Value must be defined.") => + assert(isDefined(x), message); + +export default assert; diff --git a/debug/diff.js b/debug/diff.js new file mode 100644 index 00000000..a392cbdb --- /dev/null +++ b/debug/diff.js @@ -0,0 +1,83 @@ +import filter from "../object/filter"; +import isEmpty from "./object/isEmpty"; + +import isArray from "../is/array"; +import isDate from "../is/date"; +import isFunction from "../is/function"; +import isFunction from "../is/function"; +import isObject from "../is/object"; + +export const VALUE_CREATED = "+"; +export const VALUE_DELETED = "-"; +export const VALUE_UNCHANGED = "="; +export const VALUE_UPDATED = "~"; + +const isValue = x => !isObject(x) && !isArray(x); + +const compareValues = (value1, value2) => { + if (value1 === value2) { + return VALUE_UNCHANGED; + } + + if ( + isDate(value1) && + isDate(value2) && + value1.getTime() === value2.getTime() + ) { + return VALUE_UNCHANGED; + } + + if ("undefined" == typeof value1) { + return VALUE_CREATED; + } + + if ("undefined" == typeof value2) { + return VALUE_DELETED; + } + + return VALUE_UPDATED; +}; + +const diff = (obj1, obj2) => { + if (isFunction(obj1) || isFunction(obj2)) { + throw "Invalid argument. Function given, object expected."; + } + + if (isValue(obj1) || isValue(obj2)) { + const comparisonResult = compareValues(obj1, obj2); + return comparisonResult !== VALUE_UNCHANGED + ? { + type: comparisonResult, + data: [obj1, obj2] + } + : null; + } + + const result = {}; + for (const key in obj1) { + if (isFunction(obj1[key])) { + continue; + } + + let value2 = undefined; + if ("undefined" != typeof obj2[key]) { + value2 = obj2[key]; + } + + result[key] = diff(obj1[key], value2); + } + for (const key in obj2) { + if (isFunction(obj2[key]) || "undefined" != typeof result[key]) { + continue; + } + + result[key] = diff(undefined, obj2[key]); + } + + return filter( + value => + value !== null && !(value && "object" === typeof value && isEmpty(value)) + )(result); +}; + +export default diff; diff --git a/encoding/base64url.js b/encoding/base64url.js new file mode 100644 index 00000000..db2bd036 --- /dev/null +++ b/encoding/base64url.js @@ -0,0 +1,11 @@ +export const encode = _ => + btoa(_) + .replace(/=/g, "") + .replace(/\+/g, "-") + .replace(/\//g, "_"); + +export const toBase64Url = base64 => + base64.replace(/\+/g, "-").replace(/\//g, "_"); + +export const fromBase64Url = base64 => + base64.replace(/-/g, "+").replace(/_/g, "/"); diff --git a/file/validName.js b/file/validName.js new file mode 100644 index 00000000..57046aac --- /dev/null +++ b/file/validName.js @@ -0,0 +1,5 @@ +export default name => { + const forbiddenCharacters = /[<>:"\/\\|?*\x00-\x1F]/g; + const forbiddenNames = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$/i; + return !forbiddenCharacters.test(name) && !forbiddenNames.test(name); +}; diff --git a/function/compose.js b/function/compose.js new file mode 100644 index 00000000..5fd7d4cc --- /dev/null +++ b/function/compose.js @@ -0,0 +1 @@ +export default (...fs) => x => fs.reduceRight((x, f) => f(x), x); diff --git a/function/constant.js b/function/constant.js new file mode 100644 index 00000000..3487c0dd --- /dev/null +++ b/function/constant.js @@ -0,0 +1 @@ +export default x => () => x; diff --git a/function/identity.js b/function/identity.js new file mode 100644 index 00000000..9a800599 --- /dev/null +++ b/function/identity.js @@ -0,0 +1 @@ +export default x => x; diff --git a/function/memoize.js b/function/memoize.js new file mode 100644 index 00000000..4ae3065a --- /dev/null +++ b/function/memoize.js @@ -0,0 +1,4 @@ +import equals from "../object/equals"; +import memoizeWith from "./memoizeWith"; + +export default memoizeWith(equals); diff --git a/function/memoizeShallow.js b/function/memoizeShallow.js new file mode 100644 index 00000000..fb85b0f0 --- /dev/null +++ b/function/memoizeShallow.js @@ -0,0 +1,4 @@ +const equalsShallow = (xs, ys) => + xs.length === ys.length && xs.every((x, index) => x === ys[index]); + +export default memoizeWith(equalsShallow); diff --git a/function/memoizeWith.js b/function/memoizeWith.js new file mode 100644 index 00000000..08e3665c --- /dev/null +++ b/function/memoizeWith.js @@ -0,0 +1,12 @@ +export default equals => f => { + let memoized = undefined; + let memoizedArgs = undefined; + return (...args) => { + if (memoized && equals(args, memoizedArgs)) { + return memoized; + } + memoized = f(...args); + memoizedArgs = args; + return memoized; + }; +}; diff --git a/function/noOp.js b/function/noOp.js new file mode 100644 index 00000000..2d1ec238 --- /dev/null +++ b/function/noOp.js @@ -0,0 +1 @@ +export default () => {}; diff --git a/function/pipe.js b/function/pipe.js new file mode 100644 index 00000000..57e1e197 --- /dev/null +++ b/function/pipe.js @@ -0,0 +1 @@ +export default (...fs) => x => fs.reduce((x, f) => f(x), x); diff --git a/function/when.js b/function/when.js new file mode 100644 index 00000000..c5212ead --- /dev/null +++ b/function/when.js @@ -0,0 +1,5 @@ +export default predicate => action => (...args) => { + if (predicate(...args)) { + return action(...args); + } +}; diff --git a/function/whenTrue.js b/function/whenTrue.js new file mode 100644 index 00000000..465ae21e --- /dev/null +++ b/function/whenTrue.js @@ -0,0 +1,3 @@ +import when from "./when"; + +export default when(x => x === true); diff --git a/is/array.js b/is/array.js new file mode 100644 index 00000000..11c376b1 --- /dev/null +++ b/is/array.js @@ -0,0 +1 @@ +export default x => Array.isArray(x); diff --git a/is/byte.js b/is/byte.js new file mode 100644 index 00000000..f09023ee --- /dev/null +++ b/is/byte.js @@ -0,0 +1,3 @@ +import integer from "./integer"; + +export default x => integer(x) && x >= 0 && x <= 255; diff --git a/is/date.js b/is/date.js new file mode 100644 index 00000000..7d89cb83 --- /dev/null +++ b/is/date.js @@ -0,0 +1 @@ +export default _ => ({}.toString.apply(x) === "[object Date]"); diff --git a/is/defined.js b/is/defined.js new file mode 100644 index 00000000..23ddccd1 --- /dev/null +++ b/is/defined.js @@ -0,0 +1 @@ +export default x => x !== undefined; diff --git a/is/function.js b/is/function.js new file mode 100644 index 00000000..e136d4cc --- /dev/null +++ b/is/function.js @@ -0,0 +1 @@ +export default x => typeof x === "function"; diff --git a/is/integer.js b/is/integer.js new file mode 100644 index 00000000..ecf180b1 --- /dev/null +++ b/is/integer.js @@ -0,0 +1,3 @@ +import number from "./number"; + +export default x => number(x) && Math.floor(x) === x; diff --git a/is/normal.js b/is/normal.js new file mode 100644 index 00000000..83c0262a --- /dev/null +++ b/is/normal.js @@ -0,0 +1,3 @@ +import number from "./number"; + +export default x => number(x) && x >= 0 && x <= 1; diff --git a/is/number.js b/is/number.js new file mode 100644 index 00000000..71557dcf --- /dev/null +++ b/is/number.js @@ -0,0 +1 @@ +export default x => typeof x === "number" && !Number.isNaN(x); diff --git a/is/object.js b/is/object.js new file mode 100644 index 00000000..0f50c776 --- /dev/null +++ b/is/object.js @@ -0,0 +1 @@ +export default x => ({}.toString.apply(x) === "[object Object]"); diff --git a/is/string.js b/is/string.js new file mode 100644 index 00000000..a330f049 --- /dev/null +++ b/is/string.js @@ -0,0 +1 @@ +export default x => typeof x === "string"; diff --git a/math/add.js b/math/add.js new file mode 100644 index 00000000..fcbea415 --- /dev/null +++ b/math/add.js @@ -0,0 +1 @@ +export default (a, b) => a + b; diff --git a/math/average.js b/math/average.js new file mode 100644 index 00000000..6b06c368 --- /dev/null +++ b/math/average.js @@ -0,0 +1,3 @@ +import sum from "../array/sum"; + +export default xs => sum(xs) / xs.length; diff --git a/math/ceilToNearestPowerOfTwo.js b/math/ceilToNearestPowerOfTwo.js new file mode 100644 index 00000000..8f367cf6 --- /dev/null +++ b/math/ceilToNearestPowerOfTwo.js @@ -0,0 +1 @@ +export default x => Math.pow(2, Math.ceil(Math.log(x) / Math.log(2))); diff --git a/math/clamp.js b/math/clamp.js new file mode 100644 index 00000000..a1ca7f90 --- /dev/null +++ b/math/clamp.js @@ -0,0 +1 @@ +export default (min, max) => x => Math.max(min, Math.min(max, x)); diff --git a/math/clampNormal.js b/math/clampNormal.js new file mode 100644 index 00000000..61289821 --- /dev/null +++ b/math/clampNormal.js @@ -0,0 +1,3 @@ +import clamp from "./clamp"; + +export default clamp(0, 1); diff --git a/math/delta.js b/math/delta.js new file mode 100644 index 00000000..0f32a1e9 --- /dev/null +++ b/math/delta.js @@ -0,0 +1 @@ +export default (a, b) => Math.abs(a - b); diff --git a/math/inRectangleRange.js b/math/inRectangleRange.js new file mode 100644 index 00000000..690b6a9d --- /dev/null +++ b/math/inRectangleRange.js @@ -0,0 +1,2 @@ +export default (width, height) => (x, y) => + x >= 0 && x <= width && y >= 0 && y <= height; diff --git a/math/lerp.js b/math/lerp.js new file mode 100644 index 00000000..82ee6796 --- /dev/null +++ b/math/lerp.js @@ -0,0 +1 @@ +export default t => (a, b) => a * t + b * (1 - t); diff --git a/math/maximumBy.js b/math/maximumBy.js new file mode 100644 index 00000000..00f7e73b --- /dev/null +++ b/math/maximumBy.js @@ -0,0 +1,2 @@ +export default f => xs => + xs.reduce((acc, curr) => (f(curr) > f(acc) ? curr : acc)); diff --git a/math/median.js b/math/median.js new file mode 100644 index 00000000..bc4cf011 --- /dev/null +++ b/math/median.js @@ -0,0 +1,13 @@ +import sort from "../array/sort"; +import subtract from "./subtract"; + +export default xs => { + const sorted = sort(subtract)(xs); + const middle = Math.floor(sorted.length / 2); + + if (sorted.length % 2 === 0) { + return (sorted[middle - 1] + sorted[middle]) / 2; + } + + return sorted[middle]; +}; diff --git a/math/minMax.js b/math/minMax.js new file mode 100644 index 00000000..e5b943ce --- /dev/null +++ b/math/minMax.js @@ -0,0 +1 @@ +export default ([a, b]) => (a > b ? [b, a] : [a, b]); diff --git a/math/safeNormalize.js b/math/safeNormalize.js new file mode 100644 index 00000000..cc7a2b57 --- /dev/null +++ b/math/safeNormalize.js @@ -0,0 +1 @@ +export default x => (x !== 0 ? x / Math.abs(x) : 0); diff --git a/math/sameSign.js b/math/sameSign.js new file mode 100644 index 00000000..ab69865e --- /dev/null +++ b/math/sameSign.js @@ -0,0 +1,9 @@ +const filterOutZeros = xs => xs.filter(_ => _ !== 0); + +export default xs => { + const filteredXs = filterOutZeros(xs); + + return ( + Math.abs(filteredXs.map(safeNormalize).reduce(add, 0)) === filteredXs.length + ); +}; diff --git a/math/standardDeviation.js b/math/standardDeviation.js new file mode 100644 index 00000000..3202d84b --- /dev/null +++ b/math/standardDeviation.js @@ -0,0 +1,8 @@ +export default (xs, origin = average(data)) => { + const sumOfSquareDifferences = xs.reduce( + (squareDiffs, x) => squareDiffs + Math.pow(x - origin, 2), + 0 + ); + + return Math.sqrt(sumOfSquareDifferences / (xs.length - 1)); +}; diff --git a/math/subtract.js b/math/subtract.js new file mode 100644 index 00000000..ae5f7e86 --- /dev/null +++ b/math/subtract.js @@ -0,0 +1 @@ +export default (a, b) => a - b; diff --git a/object/any.js b/object/any.js new file mode 100644 index 00000000..2364a56e --- /dev/null +++ b/object/any.js @@ -0,0 +1,3 @@ +import length from "./length"; + +export default xs => length(xs) > 0; diff --git a/object/apply.js b/object/apply.js new file mode 100644 index 00000000..24674ef4 --- /dev/null +++ b/object/apply.js @@ -0,0 +1,5 @@ +import entries from "./entries"; +import fromEntries from "./fromEntries"; + +export default fs => (...xs) => + fromEntries(entries(fs).map(([key, value]) => [key, value(...xs)])); diff --git a/object/empty.js b/object/empty.js new file mode 100644 index 00000000..ff8b4c56 --- /dev/null +++ b/object/empty.js @@ -0,0 +1 @@ +export default {}; diff --git a/object/entries.js b/object/entries.js new file mode 100644 index 00000000..dc4dd62e --- /dev/null +++ b/object/entries.js @@ -0,0 +1,2 @@ +export default Object.entries || + (object => Object.keys(object).map(key => [key, object[key]])); diff --git a/object/enumerable.js b/object/enumerable.js new file mode 100644 index 00000000..a1e0d87a --- /dev/null +++ b/object/enumerable.js @@ -0,0 +1,2 @@ +export default (...xs) => + xs.reduce((acc, curr) => ({ ...acc, [curr]: curr }), {}); diff --git a/object/equals.js b/object/equals.js new file mode 100644 index 00000000..5d6526c1 --- /dev/null +++ b/object/equals.js @@ -0,0 +1,29 @@ +import isObject from "../is/object"; +import areArrays from "../array/are"; +import lengthDiffers from "../array/lengthDiffers"; + +const keySet = (a, b) => [...new Set([...keys(a), ...keys(b)])]; + +export const equalsDeep = (a, b) => { + if (areArrays(a, b)) { + return ( + !lengthDiffers(a, b) && a.every(a, (_, key) => equalsDeep(_, b[key])) + ); + } + return isObject(a) && isObject(b) + ? a === b || keySet(a, b).every(key => equalsDeep(a[key], b[key])) + : _isEqual(a, b); +}; + +export const equalsDeepWith = f => (a, b) => { + if (areArrays(a, b)) { + return ( + !lengthDiffers(a, b) && a.every((_, key) => equalsDeepWith(f)(_, b[key])) + ); + } + return isObject(a) && isObject(b) + ? a === b || keySet(a, b).every(key => equalsDeepWith(f)(a[key], b[key])) + : f(a, b); +}; + +export default equalsDeep; diff --git a/object/filter.js b/object/filter.js new file mode 100644 index 00000000..ff8765fc --- /dev/null +++ b/object/filter.js @@ -0,0 +1,5 @@ +import entries from "./entries"; +import fromEntries from "./fromEntries"; + +export default f => xs => + fromEntries(entries(xs).filter(([key, value]) => f(value, key, xs))); diff --git a/object/find.js b/object/find.js new file mode 100644 index 00000000..e384204e --- /dev/null +++ b/object/find.js @@ -0,0 +1,4 @@ +import entries from "./entries"; + +export default predicate => xs => + entries(xs).find(([key, value]) => predicate(value, key, xs)); diff --git a/object/findKey.js b/object/findKey.js new file mode 100644 index 00000000..0947503b --- /dev/null +++ b/object/findKey.js @@ -0,0 +1 @@ +export default predicate => xs => (find(predicate)(xs) || [])[0]; diff --git a/object/findValue.js b/object/findValue.js new file mode 100644 index 00000000..849893a0 --- /dev/null +++ b/object/findValue.js @@ -0,0 +1 @@ +export default predicate => xs => (find(predicate)(xs) || [])[1]; diff --git a/object/first.js b/object/first.js new file mode 100644 index 00000000..9fafa098 --- /dev/null +++ b/object/first.js @@ -0,0 +1 @@ +export default xs => Object.values(xs)[0]; diff --git a/object/flatMapValues.js b/object/flatMapValues.js new file mode 100644 index 00000000..4c7be2f5 --- /dev/null +++ b/object/flatMapValues.js @@ -0,0 +1,5 @@ +import flatMap from "../array/flatMap"; +import entries from "./entries"; + +export default f => xs => + flatMap(([key, value]) => f(value, key, xs))(entries(xs)); diff --git a/object/fromEntries.js b/object/fromEntries.js new file mode 100644 index 00000000..6b566045 --- /dev/null +++ b/object/fromEntries.js @@ -0,0 +1,6 @@ +export default Object.fromEntries || + (keyValuePairs => + keyValuePairs.reduce( + (acc, [key, value]) => ({ ...acc, [key]: value }), + {} + )); diff --git a/object/groupBy.js b/object/groupBy.js new file mode 100644 index 00000000..25eb4b32 --- /dev/null +++ b/object/groupBy.js @@ -0,0 +1,5 @@ +export default selector => xs => + xs.reduce((acc, x) => { + const key = selector(x); + return { ...acc, [key]: [...(acc[key] || []), x] }; + }, {}); diff --git a/object/hasKey.js b/object/hasKey.js new file mode 100644 index 00000000..5d9b2b74 --- /dev/null +++ b/object/hasKey.js @@ -0,0 +1,2 @@ +export default key => xs => + xs ? Object.prototype.hasOwnProperty.call(xs, key) : false; diff --git a/object/length.js b/object/length.js new file mode 100644 index 00000000..186433f4 --- /dev/null +++ b/object/length.js @@ -0,0 +1 @@ +export default xs => Object.keys(xs).length; diff --git a/object/map.js b/object/map.js new file mode 100644 index 00000000..db4a6985 --- /dev/null +++ b/object/map.js @@ -0,0 +1,4 @@ +import fromEntries from "./fromEntries"; +import mapEntries from "./mapEntries"; + +export default f => xs => fromEntries(mapEntries(f)(xs)); diff --git a/object/mapEntries.js b/object/mapEntries.js new file mode 100644 index 00000000..a603faab --- /dev/null +++ b/object/mapEntries.js @@ -0,0 +1,4 @@ +import entries from "./entries"; + +export default f => xs => + entries(xs).map(([key, value]) => [key, f(value, key, xs)]); diff --git a/object/mapKeys.js b/object/mapKeys.js new file mode 100644 index 00000000..7d16a2a7 --- /dev/null +++ b/object/mapKeys.js @@ -0,0 +1,5 @@ +import entries from "./entries"; +import fromEntries from "./fromEntries"; + +export default f => xs => + fromEntries(entries(xs).map(([key, value]) => [f(value, key, xs), value])); diff --git a/object/mapValues.js b/object/mapValues.js new file mode 100644 index 00000000..b20f87e9 --- /dev/null +++ b/object/mapValues.js @@ -0,0 +1,3 @@ +import entries from "./entries"; + +export default f => xs => entries(xs).map(([key, value]) => f(value, key, xs)); diff --git a/object/none.js b/object/none.js new file mode 100644 index 00000000..928c3271 --- /dev/null +++ b/object/none.js @@ -0,0 +1,3 @@ +import any from "./any"; + +export default xs => !any(xs); diff --git a/object/sort.js b/object/sort.js new file mode 100644 index 00000000..21007566 --- /dev/null +++ b/object/sort.js @@ -0,0 +1,5 @@ +import entries from "./entries"; +import fromEntries from "./fromEntries"; + +export default f => xs => + fromEntries(sort(([, a], [, b]) => f(a, b))(entries(xs))); diff --git a/query/parse.js b/query/parse.js new file mode 100644 index 00000000..a49ae955 --- /dev/null +++ b/query/parse.js @@ -0,0 +1,17 @@ +import fromEntries from "../object/fromEntries"; +import startsWith from "../string/startsWith"; + +const startsWithQuestionMark = startsWith("?"); + +const queryFromMaybeSearchString = x => + startsWithQuestionMark(x) ? x.substring(1) : x; + +export default (xs = "") => + fromEntries( + queryFromMaybeSearchString(xs) + .split("&") + .map(xs => { + const [key, value] = xs.split("="); + return [key, value !== undefined ? decodeURIComponent(value) : true]; + }) + ); diff --git a/query/parsePathname.js b/query/parsePathname.js new file mode 100644 index 00000000..1924d222 --- /dev/null +++ b/query/parsePathname.js @@ -0,0 +1,32 @@ +const extractPath = url => { + const match = url.match(/^(https?:)?\/\/[^/]*/); + return match == null ? url : url.substring(match[0].length); +}; + +export default url => { + let pathname = extractPath(url); + let search = ""; + let hash = ""; + + const hashIndex = pathname.indexOf("#"); + if (hashIndex !== -1) { + hash = pathname.substring(hashIndex); + pathname = pathname.substring(0, hashIndex); + } + + const searchIndex = pathname.indexOf("?"); + if (searchIndex !== -1) { + search = pathname.substring(searchIndex); + pathname = pathname.substring(0, searchIndex); + } + + if (pathname === "") { + pathname = "/"; + } + + return { + pathname, + search, + hash + }; +}; diff --git a/query/read.js b/query/read.js new file mode 100644 index 00000000..799c7496 --- /dev/null +++ b/query/read.js @@ -0,0 +1,5 @@ +export default source => + [...new URLSearchParams(source).entries()].reduce( + (q, [k, v]) => ({ ...q, ...{ [k]: v } }), + {} + ); diff --git a/query/serialize.js b/query/serialize.js new file mode 100644 index 00000000..f0051748 --- /dev/null +++ b/query/serialize.js @@ -0,0 +1,8 @@ +import entries from "../object/entries"; + +export default (xs = {}) => + entries(xs) + .filter(([, value]) => Boolean(value) || value === 0) + .map(pair => pair.map(encodeURIComponent)) + .reduce((acc, [key, value]) => [...acc, `${key}=${value}`], []) + .join("&"); diff --git a/range/empty.js b/range/empty.js new file mode 100644 index 00000000..71065567 --- /dev/null +++ b/range/empty.js @@ -0,0 +1 @@ +export default ([min, max]) => min === max; diff --git a/range/equals.js b/range/equals.js new file mode 100644 index 00000000..ab5c1860 --- /dev/null +++ b/range/equals.js @@ -0,0 +1 @@ +export default ([a, b], [c, d]) => a === c && b === d; diff --git a/range/length.js b/range/length.js new file mode 100644 index 00000000..3961ffcd --- /dev/null +++ b/range/length.js @@ -0,0 +1 @@ +export default ([min, max]) => max - min; diff --git a/range/split.js b/range/split.js new file mode 100644 index 00000000..8f924120 --- /dev/null +++ b/range/split.js @@ -0,0 +1,38 @@ +import { isNotNaN } from "../is"; +import clamp from "../math/clamp"; +import empty from "./empty"; + +export const split = (used, sourceRange = [-Infinity, Infinity]) => range => { + if (empty(range) || !range.every(isNotNaN)) { + return []; + } + + if (!used || used.length === 0) { + return [range]; + } + + const [x, ...xs] = used; + const [usedMin, usedMax] = x; + + if (empty(x)) { + return split(xs, sourceRange)(range); + } + + const [sourceMin, sourceMax] = sourceRange; + const clampToSourceRange = clamp(sourceRange); + + const freeLeft = [sourceMin, usedMin].map(clampToSourceRange); + const freeRight = [usedMax, sourceMax].map(clampToSourceRange); + + const clampLeft = clamp(freeLeft); + const clampedLeft = range.map(clampLeft); + + const lefts = split(xs, sourceRange)(clampedLeft); + + const clampRight = clamp(freeRight); + const clampedRight = range.map(clampRight); + + const rights = split(xs, sourceRange)(clampedRight); + + return [...lefts, ...rights].filter(range => !empty(range)); +}; diff --git a/regex/escape.js b/regex/escape.js new file mode 100644 index 00000000..b9233880 --- /dev/null +++ b/regex/escape.js @@ -0,0 +1 @@ +export default string => string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&"); diff --git a/string/containsWhitespace.js b/string/containsWhitespace.js new file mode 100644 index 00000000..a2a288b0 --- /dev/null +++ b/string/containsWhitespace.js @@ -0,0 +1 @@ +export default x => /\s/.test(x); diff --git a/string/empty.js b/string/empty.js new file mode 100644 index 00000000..9cf3c27e --- /dev/null +++ b/string/empty.js @@ -0,0 +1 @@ +export default ""; diff --git a/string/firstToLower.js b/string/firstToLower.js new file mode 100644 index 00000000..0a54fdd4 --- /dev/null +++ b/string/firstToLower.js @@ -0,0 +1 @@ +export default ([first, ...rest]) => [first.toLowerCase(), ...rest].join(""); diff --git a/string/firstToUpper.js b/string/firstToUpper.js new file mode 100644 index 00000000..7b9b4cba --- /dev/null +++ b/string/firstToUpper.js @@ -0,0 +1 @@ +export default ([first, ...rest]) => [first.toUpperCase(), ...rest].join(""); diff --git a/string/includes.js b/string/includes.js new file mode 100644 index 00000000..e9c27210 --- /dev/null +++ b/string/includes.js @@ -0,0 +1 @@ +export default search => xs => xs.indexOf(search) !== -1; diff --git a/string/nbsp.js b/string/nbsp.js new file mode 100644 index 00000000..f5632c43 --- /dev/null +++ b/string/nbsp.js @@ -0,0 +1 @@ +export default "\u00A0"; diff --git a/string/nonEmpty.js b/string/nonEmpty.js new file mode 100644 index 00000000..a66c5d72 --- /dev/null +++ b/string/nonEmpty.js @@ -0,0 +1 @@ +export default x => x && x.trim(); diff --git a/string/startsWith.js b/string/startsWith.js new file mode 100644 index 00000000..8997cd33 --- /dev/null +++ b/string/startsWith.js @@ -0,0 +1 @@ +export default prefix => xs => xs.indexOf(prefix) === 0; diff --git a/vector2/add.js b/vector2/add.js new file mode 100644 index 00000000..6995faae --- /dev/null +++ b/vector2/add.js @@ -0,0 +1 @@ +export default ([x1, y1], [x2, y2]) => [x1 + x2, y1 + y2]; diff --git a/vector2/convertSpace.js b/vector2/convertSpace.js new file mode 100644 index 00000000..8425499d --- /dev/null +++ b/vector2/convertSpace.js @@ -0,0 +1,6 @@ +import mul from "./mul"; + +export default space => ([x, y]) => { + const [outX, outY] = mul(space, [x, y]); + return [outX, outY]; +}; diff --git a/vector2/cross.js b/vector2/cross.js new file mode 100644 index 00000000..327ae4d7 --- /dev/null +++ b/vector2/cross.js @@ -0,0 +1 @@ +export default ([a, b], [c, d]) => a * d - b * c; diff --git a/vector2/dot.js b/vector2/dot.js new file mode 100644 index 00000000..c18e85fe --- /dev/null +++ b/vector2/dot.js @@ -0,0 +1 @@ +export default ([a, b], [c, d]) => a * c + b * d; diff --git a/vector2/length.js b/vector2/length.js new file mode 100644 index 00000000..ac12d13b --- /dev/null +++ b/vector2/length.js @@ -0,0 +1 @@ +export default ([x, y]) => Math.sqrt(x ** 2 + y ** 2); diff --git a/vector2/mul.js b/vector2/mul.js new file mode 100644 index 00000000..7ce615f1 --- /dev/null +++ b/vector2/mul.js @@ -0,0 +1,4 @@ +export default (matrix, point) => [ + matrix.a * point[0] + matrix.c * point[1] + matrix.e, + matrix.b * point[0] + matrix.d * point[1] + matrix.f +]; diff --git a/vector2/multiply.js b/vector2/multiply.js new file mode 100644 index 00000000..3102465f --- /dev/null +++ b/vector2/multiply.js @@ -0,0 +1,8 @@ +export default (m1, m2) => ({ + a: m1.a * m2.a + m1.c * m2.b, + c: m1.a * m2.c + m1.c * m2.d, + e: m1.a * m2.e + m1.c * m2.f + m1.e, + b: m1.b * m2.a + m1.d * m2.b, + d: m1.b * m2.c + m1.d * m2.d, + f: m1.b * m2.e + m1.d * m2.f + m1.f +}); diff --git a/vector2/normalize.js b/vector2/normalize.js new file mode 100644 index 00000000..cdbcbeff --- /dev/null +++ b/vector2/normalize.js @@ -0,0 +1,6 @@ +import length from "./length"; + +export default vector => { + const magnitude = length(vector); + return magnitude !== 0 ? vector.map(_ => _ / magnitude) : vector; +}; diff --git a/vector2/reflect.js b/vector2/reflect.js new file mode 100644 index 00000000..2465e0f6 --- /dev/null +++ b/vector2/reflect.js @@ -0,0 +1,4 @@ +import sub from "./sub"; +import dot from "./dot"; + +export default (a, v) => sub(v, a.map(_ => (_ * 2 * dot(v, a)) / dot(a, a))); diff --git a/vector2/rotate.js b/vector2/rotate.js new file mode 100644 index 00000000..227b12c8 --- /dev/null +++ b/vector2/rotate.js @@ -0,0 +1,20 @@ +import transform from "./transform"; +import translate from "./translate"; + +const { cos, sin } = Math; + +export default (angle = 0, cx = 0, cy = 0) => { + const cosAngle = cos(angle); + const sinAngle = sin(angle); + + const rotationMatrix = { + a: cosAngle, + c: -sinAngle, + e: 0, + b: sinAngle, + d: cosAngle, + f: 0 + }; + + return transform(translate(cx, cy), rotationMatrix, translate(-cx, -cy)); +}; diff --git a/vector2/scale.js b/vector2/scale.js new file mode 100644 index 00000000..d4aa6aba --- /dev/null +++ b/vector2/scale.js @@ -0,0 +1,8 @@ +export default (sx = 1, sy = sx) => ({ + a: sx, + c: 0, + e: 0, + b: 0, + d: sy, + f: 0 +}); diff --git a/vector2/sub.js b/vector2/sub.js new file mode 100644 index 00000000..5f40a0c4 --- /dev/null +++ b/vector2/sub.js @@ -0,0 +1 @@ +export default ([x1, y1], [x2, y2]) => [x1 - x2, y1 - y2]; diff --git a/vector2/transform.js b/vector2/transform.js new file mode 100644 index 00000000..0fc27235 --- /dev/null +++ b/vector2/transform.js @@ -0,0 +1 @@ +export default (...matrices) => matrices.reduce(multiply); diff --git a/vector2/translate.js b/vector2/translate.js new file mode 100644 index 00000000..2c2048ad --- /dev/null +++ b/vector2/translate.js @@ -0,0 +1,8 @@ +export default (tx = 0, ty = 0) => ({ + a: 1, + c: 0, + e: tx, + b: 0, + d: 1, + f: ty +}); diff --git a/web/classNames.js b/web/classNames.js new file mode 100644 index 00000000..cfff3d8a --- /dev/null +++ b/web/classNames.js @@ -0,0 +1,16 @@ +import entries from "../object/entries"; +import isString from "../is/string"; + +const booleanKeys = x => + entries(x) + .filter(([, value]) => Boolean(value)) + .map(([key]) => key); + +export default (...xs) => + xs + .filter(Boolean) + .reduce((acc, curr) => { + const names = isString(curr) ? [curr] : booleanKeys(curr); + return [...acc, ...names]; + }, []) + .join(" "); diff --git a/web/events/cancel.js b/web/events/cancel.js new file mode 100644 index 00000000..3464d7e7 --- /dev/null +++ b/web/events/cancel.js @@ -0,0 +1,8 @@ +import prevent from "./prevent"; +import stop from "./stop"; + +export default event => { + prevent(event); + stop(event); + return false; +}; diff --git a/web/events/openInNewTabIntent.js b/web/events/openInNewTabIntent.js new file mode 100644 index 00000000..bf0f619f --- /dev/null +++ b/web/events/openInNewTabIntent.js @@ -0,0 +1,2 @@ +export default ({ button, ctrlKey, metaKey, shiftKey }) => + ctrlKey || shiftKey || metaKey || button === 1; diff --git a/web/events/prevent.js b/web/events/prevent.js new file mode 100644 index 00000000..f475eecb --- /dev/null +++ b/web/events/prevent.js @@ -0,0 +1,4 @@ +export default event => { + event.preventDefault(); + return false; +}; diff --git a/web/events/stop.js b/web/events/stop.js new file mode 100644 index 00000000..cadf59cc --- /dev/null +++ b/web/events/stop.js @@ -0,0 +1,4 @@ +export default event => { + event.stopPropagation(); + return false; +}; From 476327aaa398b21c995c0a859435dac572c77c17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 10:50:48 +0200 Subject: [PATCH 33/56] Use proper file extensions for import statements --- array/are.js | 2 +- array/shuffle.js | 2 +- array/zip.js | 2 +- date/dayRange.js | 12 ++++++------ date/daysInYear.js | 6 +++--- date/endOfDay.js | 2 +- date/formatDate.js | 2 +- date/formatDateTime.js | 4 ++-- date/formatDuration.js | 12 ++++++------ date/fromDays.js | 2 +- date/fromHours.js | 2 +- date/fromMinutes.js | 2 +- date/monthRange.js | 12 ++++++------ date/startOfDay.js | 2 +- date/toDays.js | 2 +- date/toHours.js | 2 +- date/toISOFromLocalDateTime.js | 2 +- date/toMinutes.js | 2 +- date/weekRange.js | 12 ++++++------ date/yearRange.js | 12 ++++++------ debug/assert.js | 12 ++++++------ debug/diff.js | 16 ++++++++-------- function/memoize.js | 4 ++-- function/whenTrue.js | 2 +- is/byte.js | 2 +- is/integer.js | 2 +- is/normal.js | 2 +- math/average.js | 2 +- math/clampNormal.js | 2 +- math/median.js | 4 ++-- object/any.js | 2 +- object/apply.js | 4 ++-- object/equals.js | 6 +++--- object/filter.js | 4 ++-- object/find.js | 2 +- object/flatMapValues.js | 4 ++-- object/map.js | 4 ++-- object/mapEntries.js | 2 +- object/mapKeys.js | 4 ++-- object/mapValues.js | 2 +- object/none.js | 2 +- object/sort.js | 4 ++-- query/parse.js | 4 ++-- query/serialize.js | 2 +- range/split.js | 6 +++--- vector2/convertSpace.js | 2 +- vector2/normalize.js | 2 +- vector2/reflect.js | 4 ++-- vector2/rotate.js | 4 ++-- web/classNames.js | 4 ++-- web/events/cancel.js | 4 ++-- 51 files changed, 108 insertions(+), 108 deletions(-) diff --git a/array/are.js b/array/are.js index c32dc386..ba83b30e 100644 --- a/array/are.js +++ b/array/are.js @@ -1,3 +1,3 @@ -import is from "./is"; +import is from "./is.js"; export default (...xs) => xs.every(is); diff --git a/array/shuffle.js b/array/shuffle.js index cf1cf3a0..66db53c0 100644 --- a/array/shuffle.js +++ b/array/shuffle.js @@ -1,3 +1,3 @@ -import shuffleInPlace from "./shuffleInPlace"; +import shuffleInPlace from "./shuffleInPlace.js"; export default xs => shuffleInPlace([...xs]); diff --git a/array/zip.js b/array/zip.js index bab08804..dcd8e433 100644 --- a/array/zip.js +++ b/array/zip.js @@ -1,3 +1,3 @@ -import zipWith from "./zipWith"; +import zipWith from "./zipWith.js"; export default zipWith((x, y) => [x, y]); diff --git a/date/dayRange.js b/date/dayRange.js index 8a182b51..2cea4450 100644 --- a/date/dayRange.js +++ b/date/dayRange.js @@ -1,9 +1,9 @@ -import endOfDay from "./endOfDay"; -import offsetByBit from "./offsetByBit"; -import splitDateTime from "./splitDateTime"; -import startOfDay from "./startOfDay"; -import toISO from "./toISO"; -import toISOFromLocalDateTime from "./toISOFromLocalDateTime"; +import endOfDay from "./endOfDay.js"; +import offsetByBit from "./offsetByBit.js"; +import splitDateTime from "./splitDateTime.js"; +import startOfDay from "./startOfDay.js"; +import toISO from "./toISO.js"; +import toISOFromLocalDateTime from "./toISOFromLocalDateTime.js"; export default ({ iso = false, diff --git a/date/daysInYear.js b/date/daysInYear.js index 13c489da..6df73661 100644 --- a/date/daysInYear.js +++ b/date/daysInYear.js @@ -1,5 +1,5 @@ -import sum from "../array/sum"; -import daysInMonths from "./daysInMonths"; -import leapYear from "./leapYear"; +import sum from "../array/sum.js"; +import daysInMonths from "./daysInMonths.js"; +import leapYear from "./leapYear.js"; export default year => sum(daysInMonths(leapYear(year))); diff --git a/date/endOfDay.js b/date/endOfDay.js index f51306e8..475fed53 100644 --- a/date/endOfDay.js +++ b/date/endOfDay.js @@ -1,4 +1,4 @@ -import toLocalDateTime from "./toLocalDateTime"; +import toLocalDateTime from "./toLocalDateTime.js"; export default (date, timezoneOffset = 0, local = true) => { const newDate = new Date(date); diff --git a/date/formatDate.js b/date/formatDate.js index f6fcac30..af16eabc 100644 --- a/date/formatDate.js +++ b/date/formatDate.js @@ -1,4 +1,4 @@ -import toLocalDateTime from "./toLocalDateTime"; +import toLocalDateTime from "./toLocalDateTime.js"; export default (sourceDate, timezoneOffset = 0) => { const localDate = toLocalDateTime(sourceDate, timezoneOffset); diff --git a/date/formatDateTime.js b/date/formatDateTime.js index f3aa9c00..6aeb2266 100644 --- a/date/formatDateTime.js +++ b/date/formatDateTime.js @@ -1,5 +1,5 @@ -import formatDate from "./formatDate"; -import formatTime from "./formatTime"; +import formatDate from "./formatDate.js"; +import formatTime from "./formatTime.js"; export default (sourceDate, showSeconds = false, timezoneOffset = 0) => { const date = formatDate(sourceDate, timezoneOffset); diff --git a/date/formatDuration.js b/date/formatDuration.js index 8fd96a38..1a8ef6f9 100644 --- a/date/formatDuration.js +++ b/date/formatDuration.js @@ -1,9 +1,9 @@ -import fromHours from "./fromHours"; -import fromMinutes from "./fromMinutes"; -import toHours from "./toHours"; -import toMinutes from "./toMinutes"; -import toSeconds from "./toSeconds"; -import displayTime from "./displayTime"; +import fromHours from "./fromHours.js"; +import fromMinutes from "./fromMinutes.js"; +import toHours from "./toHours.js"; +import toMinutes from "./toMinutes.js"; +import toSeconds from "./toSeconds.js"; +import displayTime from "./displayTime.js"; export default (duration, showSeconds = false) => { const hours = Math.floor(toHours(duration)); diff --git a/date/fromDays.js b/date/fromDays.js index ea8d490e..7961f32d 100644 --- a/date/fromDays.js +++ b/date/fromDays.js @@ -1,3 +1,3 @@ -import fromHours from "./fromHours"; +import fromHours from "./fromHours.js"; export default days => fromHours(days * 24); diff --git a/date/fromHours.js b/date/fromHours.js index 6a5f9617..07aba8a0 100644 --- a/date/fromHours.js +++ b/date/fromHours.js @@ -1,3 +1,3 @@ -import fromMinutes from "./fromMinutes"; +import fromMinutes from "./fromMinutes.js"; export default hours => fromMinutes(hours * 60); diff --git a/date/fromMinutes.js b/date/fromMinutes.js index 6e32741a..53408542 100644 --- a/date/fromMinutes.js +++ b/date/fromMinutes.js @@ -1,3 +1,3 @@ -import fromSeconds from "./fromSeconds"; +import fromSeconds from "./fromSeconds.js"; export default minutes => fromSeconds(minutes * 60); diff --git a/date/monthRange.js b/date/monthRange.js index cc52fcf8..9176477a 100644 --- a/date/monthRange.js +++ b/date/monthRange.js @@ -1,9 +1,9 @@ -import endOfMonth from "./endOfMonth"; -import offsetByBit from "./offsetByBit"; -import splitDateTime from "./splitDateTime"; -import startOfMonth from "./startOfMonth"; -import toISO from "./toISO"; -import toISOFromLocalDateTime from "./toISOFromLocalDateTime"; +import endOfMonth from "./endOfMonth.js"; +import offsetByBit from "./offsetByBit.js"; +import splitDateTime from "./splitDateTime.js"; +import startOfMonth from "./startOfMonth.js"; +import toISO from "./toISO.js"; +import toISOFromLocalDateTime from "./toISOFromLocalDateTime.js"; export default ({ iso = false, diff --git a/date/startOfDay.js b/date/startOfDay.js index 0c5805ab..0e9d3395 100644 --- a/date/startOfDay.js +++ b/date/startOfDay.js @@ -1,4 +1,4 @@ -import toLocalDateTime from "./toLocalDateTime"; +import toLocalDateTime from "./toLocalDateTime.js"; export default (date, timezoneOffset = 0, local = true) => { const newDate = new Date(date); diff --git a/date/toDays.js b/date/toDays.js index 1d9e7132..ba5e7a90 100644 --- a/date/toDays.js +++ b/date/toDays.js @@ -1,3 +1,3 @@ -import toHours from "./toHours"; +import toHours from "./toHours.js"; export default milliseconds => toHours(milliseconds) / 24; diff --git a/date/toHours.js b/date/toHours.js index 44509b4b..5ed4eadf 100644 --- a/date/toHours.js +++ b/date/toHours.js @@ -1,3 +1,3 @@ -import toMinutes from "./toMinutes"; +import toMinutes from "./toMinutes.js"; export default milliseconds => toMinutes(milliseconds) / 60; diff --git a/date/toISOFromLocalDateTime.js b/date/toISOFromLocalDateTime.js index f4d527df..6d8480d3 100644 --- a/date/toISOFromLocalDateTime.js +++ b/date/toISOFromLocalDateTime.js @@ -1,4 +1,4 @@ -import fromMinutes from "./fromMinutes"; +import fromMinutes from "./fromMinutes.js"; export default date => new Date( diff --git a/date/toMinutes.js b/date/toMinutes.js index 3ef8dcca..30cfa8ae 100644 --- a/date/toMinutes.js +++ b/date/toMinutes.js @@ -1,3 +1,3 @@ -import toSeconds from "./toSeconds"; +import toSeconds from "./toSeconds.js"; export default milliseconds => toSeconds(milliseconds) / 60; diff --git a/date/weekRange.js b/date/weekRange.js index af839bc0..64a8487a 100644 --- a/date/weekRange.js +++ b/date/weekRange.js @@ -1,9 +1,9 @@ -import endOfWeek from "./endOfWeek"; -import offsetByBit from "./offsetByBit"; -import splitDateTime from "./splitDateTime"; -import startOfWeek from "./startOfWeek"; -import toISO from "./toISO"; -import toISOFromLocalDateTime from "./toISOFromLocalDateTime"; +import endOfWeek from "./endOfWeek.js"; +import offsetByBit from "./offsetByBit.js"; +import splitDateTime from "./splitDateTime.js"; +import startOfWeek from "./startOfWeek.js"; +import toISO from "./toISO.js"; +import toISOFromLocalDateTime from "./toISOFromLocalDateTime.js"; export default ({ iso = false, diff --git a/date/yearRange.js b/date/yearRange.js index 167a7740..e87d1143 100644 --- a/date/yearRange.js +++ b/date/yearRange.js @@ -1,9 +1,9 @@ -import endOfYear from "./endOfYear"; -import offsetByBit from "./offsetByBit"; -import splitDateTime from "./splitDateTime"; -import startOfYear from "./startOfYear"; -import toISO from "./toISO"; -import toISOFromLocalDateTime from "./toISOFromLocalDateTime"; +import endOfYear from "./endOfYear.js"; +import offsetByBit from "./offsetByBit.js"; +import splitDateTime from "./splitDateTime.js"; +import startOfYear from "./startOfYear.js"; +import toISO from "./toISO.js"; +import toISOFromLocalDateTime from "./toISOFromLocalDateTime.js"; export default ({ iso = false, diff --git a/debug/assert.js b/debug/assert.js index 73f796b6..38668ae7 100644 --- a/debug/assert.js +++ b/debug/assert.js @@ -1,9 +1,9 @@ -import isNumber from "../is/number"; -import isInteger from "../is/integer"; -import isByte from "../is/byte"; -import isNormal from "../is/normal"; -import isString from "../is/string"; -import isDefined from "../is/defined"; +import isNumber from "../is/number.js"; +import isInteger from "../is/integer.js"; +import isByte from "../is/byte.js"; +import isNormal from "../is/normal.js"; +import isString from "../is/string.js"; +import isDefined from "../is/defined.js"; const assert = (condition, callbackOrMessage) => { if (!condition) { diff --git a/debug/diff.js b/debug/diff.js index a392cbdb..9315143b 100644 --- a/debug/diff.js +++ b/debug/diff.js @@ -1,11 +1,11 @@ -import filter from "../object/filter"; -import isEmpty from "./object/isEmpty"; - -import isArray from "../is/array"; -import isDate from "../is/date"; -import isFunction from "../is/function"; -import isFunction from "../is/function"; -import isObject from "../is/object"; +import filter from "../object/filter.js"; +import isEmpty from "./object/isEmpty.js"; + +import isArray from "../is/array.js"; +import isDate from "../is/date.js"; +import isFunction from "../is/function.js"; +import isFunction from "../is/function.js"; +import isObject from "../is/object.js"; export const VALUE_CREATED = "+"; export const VALUE_DELETED = "-"; diff --git a/function/memoize.js b/function/memoize.js index 4ae3065a..4ef07411 100644 --- a/function/memoize.js +++ b/function/memoize.js @@ -1,4 +1,4 @@ -import equals from "../object/equals"; -import memoizeWith from "./memoizeWith"; +import equals from "../object/equals.js"; +import memoizeWith from "./memoizeWith.js"; export default memoizeWith(equals); diff --git a/function/whenTrue.js b/function/whenTrue.js index 465ae21e..0870c5cb 100644 --- a/function/whenTrue.js +++ b/function/whenTrue.js @@ -1,3 +1,3 @@ -import when from "./when"; +import when from "./when.js"; export default when(x => x === true); diff --git a/is/byte.js b/is/byte.js index f09023ee..b25231df 100644 --- a/is/byte.js +++ b/is/byte.js @@ -1,3 +1,3 @@ -import integer from "./integer"; +import integer from "./integer.js"; export default x => integer(x) && x >= 0 && x <= 255; diff --git a/is/integer.js b/is/integer.js index ecf180b1..b79db0fd 100644 --- a/is/integer.js +++ b/is/integer.js @@ -1,3 +1,3 @@ -import number from "./number"; +import number from "./number.js"; export default x => number(x) && Math.floor(x) === x; diff --git a/is/normal.js b/is/normal.js index 83c0262a..284b2b93 100644 --- a/is/normal.js +++ b/is/normal.js @@ -1,3 +1,3 @@ -import number from "./number"; +import number from "./number.js"; export default x => number(x) && x >= 0 && x <= 1; diff --git a/math/average.js b/math/average.js index 6b06c368..a75f2b0f 100644 --- a/math/average.js +++ b/math/average.js @@ -1,3 +1,3 @@ -import sum from "../array/sum"; +import sum from "../array/sum.js"; export default xs => sum(xs) / xs.length; diff --git a/math/clampNormal.js b/math/clampNormal.js index 61289821..5be86e87 100644 --- a/math/clampNormal.js +++ b/math/clampNormal.js @@ -1,3 +1,3 @@ -import clamp from "./clamp"; +import clamp from "./clamp.js"; export default clamp(0, 1); diff --git a/math/median.js b/math/median.js index bc4cf011..4a4e6fad 100644 --- a/math/median.js +++ b/math/median.js @@ -1,5 +1,5 @@ -import sort from "../array/sort"; -import subtract from "./subtract"; +import sort from "../array/sort.js"; +import subtract from "./subtract.js"; export default xs => { const sorted = sort(subtract)(xs); diff --git a/object/any.js b/object/any.js index 2364a56e..39db7f9d 100644 --- a/object/any.js +++ b/object/any.js @@ -1,3 +1,3 @@ -import length from "./length"; +import length from "./length.js"; export default xs => length(xs) > 0; diff --git a/object/apply.js b/object/apply.js index 24674ef4..93526e28 100644 --- a/object/apply.js +++ b/object/apply.js @@ -1,5 +1,5 @@ -import entries from "./entries"; -import fromEntries from "./fromEntries"; +import entries from "./entries.js"; +import fromEntries from "./fromEntries.js"; export default fs => (...xs) => fromEntries(entries(fs).map(([key, value]) => [key, value(...xs)])); diff --git a/object/equals.js b/object/equals.js index 5d6526c1..9a38c174 100644 --- a/object/equals.js +++ b/object/equals.js @@ -1,6 +1,6 @@ -import isObject from "../is/object"; -import areArrays from "../array/are"; -import lengthDiffers from "../array/lengthDiffers"; +import isObject from "../is/object.js"; +import areArrays from "../array/are.js"; +import lengthDiffers from "../array/lengthDiffers.js"; const keySet = (a, b) => [...new Set([...keys(a), ...keys(b)])]; diff --git a/object/filter.js b/object/filter.js index ff8765fc..9209dcae 100644 --- a/object/filter.js +++ b/object/filter.js @@ -1,5 +1,5 @@ -import entries from "./entries"; -import fromEntries from "./fromEntries"; +import entries from "./entries.js"; +import fromEntries from "./fromEntries.js"; export default f => xs => fromEntries(entries(xs).filter(([key, value]) => f(value, key, xs))); diff --git a/object/find.js b/object/find.js index e384204e..bbf04ad0 100644 --- a/object/find.js +++ b/object/find.js @@ -1,4 +1,4 @@ -import entries from "./entries"; +import entries from "./entries.js"; export default predicate => xs => entries(xs).find(([key, value]) => predicate(value, key, xs)); diff --git a/object/flatMapValues.js b/object/flatMapValues.js index 4c7be2f5..3318507f 100644 --- a/object/flatMapValues.js +++ b/object/flatMapValues.js @@ -1,5 +1,5 @@ -import flatMap from "../array/flatMap"; -import entries from "./entries"; +import flatMap from "../array/flatMap.js"; +import entries from "./entries.js"; export default f => xs => flatMap(([key, value]) => f(value, key, xs))(entries(xs)); diff --git a/object/map.js b/object/map.js index db4a6985..8590e36b 100644 --- a/object/map.js +++ b/object/map.js @@ -1,4 +1,4 @@ -import fromEntries from "./fromEntries"; -import mapEntries from "./mapEntries"; +import fromEntries from "./fromEntries.js"; +import mapEntries from "./mapEntries.js"; export default f => xs => fromEntries(mapEntries(f)(xs)); diff --git a/object/mapEntries.js b/object/mapEntries.js index a603faab..854de72e 100644 --- a/object/mapEntries.js +++ b/object/mapEntries.js @@ -1,4 +1,4 @@ -import entries from "./entries"; +import entries from "./entries.js"; export default f => xs => entries(xs).map(([key, value]) => [key, f(value, key, xs)]); diff --git a/object/mapKeys.js b/object/mapKeys.js index 7d16a2a7..a8f5465b 100644 --- a/object/mapKeys.js +++ b/object/mapKeys.js @@ -1,5 +1,5 @@ -import entries from "./entries"; -import fromEntries from "./fromEntries"; +import entries from "./entries.js"; +import fromEntries from "./fromEntries.js"; export default f => xs => fromEntries(entries(xs).map(([key, value]) => [f(value, key, xs), value])); diff --git a/object/mapValues.js b/object/mapValues.js index b20f87e9..8230ab66 100644 --- a/object/mapValues.js +++ b/object/mapValues.js @@ -1,3 +1,3 @@ -import entries from "./entries"; +import entries from "./entries.js"; export default f => xs => entries(xs).map(([key, value]) => f(value, key, xs)); diff --git a/object/none.js b/object/none.js index 928c3271..307b11e6 100644 --- a/object/none.js +++ b/object/none.js @@ -1,3 +1,3 @@ -import any from "./any"; +import any from "./any.js"; export default xs => !any(xs); diff --git a/object/sort.js b/object/sort.js index 21007566..a52812d3 100644 --- a/object/sort.js +++ b/object/sort.js @@ -1,5 +1,5 @@ -import entries from "./entries"; -import fromEntries from "./fromEntries"; +import entries from "./entries.js"; +import fromEntries from "./fromEntries.js"; export default f => xs => fromEntries(sort(([, a], [, b]) => f(a, b))(entries(xs))); diff --git a/query/parse.js b/query/parse.js index a49ae955..3e2fb4f6 100644 --- a/query/parse.js +++ b/query/parse.js @@ -1,5 +1,5 @@ -import fromEntries from "../object/fromEntries"; -import startsWith from "../string/startsWith"; +import fromEntries from "../object/fromEntries.js"; +import startsWith from "../string/startsWith.js"; const startsWithQuestionMark = startsWith("?"); diff --git a/query/serialize.js b/query/serialize.js index f0051748..12f23f5f 100644 --- a/query/serialize.js +++ b/query/serialize.js @@ -1,4 +1,4 @@ -import entries from "../object/entries"; +import entries from "../object/entries.js"; export default (xs = {}) => entries(xs) diff --git a/range/split.js b/range/split.js index 8f924120..6e8bb2c3 100644 --- a/range/split.js +++ b/range/split.js @@ -1,6 +1,6 @@ -import { isNotNaN } from "../is"; -import clamp from "../math/clamp"; -import empty from "./empty"; +import { isNotNaN } from "../is.js"; +import clamp from "../math/clamp.js"; +import empty from "./empty.js"; export const split = (used, sourceRange = [-Infinity, Infinity]) => range => { if (empty(range) || !range.every(isNotNaN)) { diff --git a/vector2/convertSpace.js b/vector2/convertSpace.js index 8425499d..7d50c019 100644 --- a/vector2/convertSpace.js +++ b/vector2/convertSpace.js @@ -1,4 +1,4 @@ -import mul from "./mul"; +import mul from "./mul.js"; export default space => ([x, y]) => { const [outX, outY] = mul(space, [x, y]); diff --git a/vector2/normalize.js b/vector2/normalize.js index cdbcbeff..c00359af 100644 --- a/vector2/normalize.js +++ b/vector2/normalize.js @@ -1,4 +1,4 @@ -import length from "./length"; +import length from "./length.js"; export default vector => { const magnitude = length(vector); diff --git a/vector2/reflect.js b/vector2/reflect.js index 2465e0f6..6ee82a82 100644 --- a/vector2/reflect.js +++ b/vector2/reflect.js @@ -1,4 +1,4 @@ -import sub from "./sub"; -import dot from "./dot"; +import sub from "./sub.js"; +import dot from "./dot.js"; export default (a, v) => sub(v, a.map(_ => (_ * 2 * dot(v, a)) / dot(a, a))); diff --git a/vector2/rotate.js b/vector2/rotate.js index 227b12c8..2d1dc708 100644 --- a/vector2/rotate.js +++ b/vector2/rotate.js @@ -1,5 +1,5 @@ -import transform from "./transform"; -import translate from "./translate"; +import transform from "./transform.js"; +import translate from "./translate.js"; const { cos, sin } = Math; diff --git a/web/classNames.js b/web/classNames.js index cfff3d8a..190d8ed5 100644 --- a/web/classNames.js +++ b/web/classNames.js @@ -1,5 +1,5 @@ -import entries from "../object/entries"; -import isString from "../is/string"; +import entries from "../object/entries.js"; +import isString from "../is/string.js"; const booleanKeys = x => entries(x) diff --git a/web/events/cancel.js b/web/events/cancel.js index 3464d7e7..e2c2c023 100644 --- a/web/events/cancel.js +++ b/web/events/cancel.js @@ -1,5 +1,5 @@ -import prevent from "./prevent"; -import stop from "./stop"; +import prevent from "./prevent.js"; +import stop from "./stop.js"; export default event => { prevent(event); From 329dab5bce163311078802c7b234f794106db808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 12:29:46 +0200 Subject: [PATCH 34/56] Remove duplicated import --- debug/diff.js | 1 - 1 file changed, 1 deletion(-) diff --git a/debug/diff.js b/debug/diff.js index 9315143b..cfb16253 100644 --- a/debug/diff.js +++ b/debug/diff.js @@ -4,7 +4,6 @@ import isEmpty from "./object/isEmpty.js"; import isArray from "../is/array.js"; import isDate from "../is/date.js"; import isFunction from "../is/function.js"; -import isFunction from "../is/function.js"; import isObject from "../is/object.js"; export const VALUE_CREATED = "+"; From e995e9f45b1e11d5ba9cd3ff8f11fd08809774e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 12:30:26 +0200 Subject: [PATCH 35/56] Generate indices --- array/index.js | 117 ++++++++++++++++++++++++++++++++++++++++++++ async/index.js | 7 +++ date/index.js | 117 ++++++++++++++++++++++++++++++++++++++++++++ debug/index.js | 6 +++ encoding/index.js | 5 ++ file/index.js | 5 ++ function/index.js | 36 ++++++++++++++ index.js | 54 ++++++++++++++++++++ is/index.js | 36 ++++++++++++++ math/index.js | 51 +++++++++++++++++++ object/index.js | 72 +++++++++++++++++++++++++++ query/index.js | 8 +++ range/index.js | 8 +++ regex/index.js | 5 ++ string/index.js | 30 ++++++++++++ vector2/index.js | 48 ++++++++++++++++++ web/events/index.js | 8 +++ web/index.js | 6 +++ 18 files changed, 619 insertions(+) create mode 100644 array/index.js create mode 100644 async/index.js create mode 100644 date/index.js create mode 100644 debug/index.js create mode 100644 encoding/index.js create mode 100644 file/index.js create mode 100644 function/index.js create mode 100644 index.js create mode 100644 is/index.js create mode 100644 math/index.js create mode 100644 object/index.js create mode 100644 query/index.js create mode 100644 range/index.js create mode 100644 regex/index.js create mode 100644 string/index.js create mode 100644 vector2/index.js create mode 100644 web/events/index.js create mode 100644 web/index.js diff --git a/array/index.js b/array/index.js new file mode 100644 index 00000000..59d65c30 --- /dev/null +++ b/array/index.js @@ -0,0 +1,117 @@ +import any from "./any.js"; +import are from "./are.js"; +import differs from "./differs.js"; +import duplicates from "./duplicates.js"; +import empty from "./empty.js"; +import exact from "./exact.js"; +import except from "./except.js"; +import filterInPlace from "./filterInPlace.js"; +import find from "./find.js"; +import first from "./first.js"; +import flatMap from "./flatMap.js"; +import flatten from "./flatten.js"; +import intersection from "./intersection.js"; +import is from "./is.js"; +import last from "./last.js"; +import lengthDiffers from "./lengthDiffers.js"; +import map from "./map.js"; +import midpoint from "./midpoint.js"; +import minMax from "./minMax.js"; +import multiple from "./multiple.js"; +import partition from "./partition.js"; +import range from "./range.js"; +import repeat from "./repeat.js"; +import reverse from "./reverse.js"; +import reverseIf from "./reverseIf.js"; +import rotate from "./rotate.js"; +import second from "./second.js"; +import secondToLast from "./secondToLast.js"; +import shift from "./shift.js"; +import shuffle from "./shuffle.js"; +import shuffleInPlace from "./shuffleInPlace.js"; +import single from "./single.js"; +import sort from "./sort.js"; +import sum from "./sum.js"; +import transpose from "./transpose.js"; +import zip from "./zip.js"; +import zipWith from "./zipWith.js"; + +export { + any, + are, + differs, + duplicates, + empty, + exact, + except, + filterInPlace, + find, + first, + flatMap, + flatten, + intersection, + is, + last, + lengthDiffers, + map, + midpoint, + minMax, + multiple, + partition, + range, + repeat, + reverse, + reverseIf, + rotate, + second, + secondToLast, + shift, + shuffle, + shuffleInPlace, + single, + sort, + sum, + transpose, + zip, + zipWith +}; + +export default { + any, + are, + differs, + duplicates, + empty, + exact, + except, + filterInPlace, + find, + first, + flatMap, + flatten, + intersection, + is, + last, + lengthDiffers, + map, + midpoint, + minMax, + multiple, + partition, + range, + repeat, + reverse, + reverseIf, + rotate, + second, + secondToLast, + shift, + shuffle, + shuffleInPlace, + single, + sort, + sum, + transpose, + zip, + zipWith +}; diff --git a/async/index.js b/async/index.js new file mode 100644 index 00000000..8c3a3d37 --- /dev/null +++ b/async/index.js @@ -0,0 +1,7 @@ +import debounce from "./debounce.js"; +import delay from "./delay.js"; +import sequence from "./sequence.js"; + +export { debounce, delay, sequence }; + +export default { debounce, delay, sequence }; diff --git a/date/index.js b/date/index.js new file mode 100644 index 00000000..478521b0 --- /dev/null +++ b/date/index.js @@ -0,0 +1,117 @@ +import byDateWithFallback from "./byDateWithFallback.js"; +import clamp from "./clamp.js"; +import dateDiff from "./dateDiff.js"; +import dateInRange from "./dateInRange.js"; +import dayRange from "./dayRange.js"; +import daysInMonths from "./daysInMonths.js"; +import daysInYear from "./daysInYear.js"; +import displayTime from "./displayTime.js"; +import endOfDay from "./endOfDay.js"; +import formatDate from "./formatDate.js"; +import formatDateTime from "./formatDateTime.js"; +import formatDuration from "./formatDuration.js"; +import formatTime from "./formatTime.js"; +import fromDays from "./fromDays.js"; +import fromHours from "./fromHours.js"; +import fromMinutes from "./fromMinutes.js"; +import fromSeconds from "./fromSeconds.js"; +import joinDateTime from "./joinDateTime.js"; +import leapYear from "./leapYear.js"; +import monthRange from "./monthRange.js"; +import offsetByBit from "./offsetByBit.js"; +import parseHourMinutePair from "./parseHourMinutePair.js"; +import splitDateTime from "./splitDateTime.js"; +import startOfDay from "./startOfDay.js"; +import subtractDays from "./subtractDays.js"; +import toDate from "./toDate.js"; +import toDates from "./toDates.js"; +import toDays from "./toDays.js"; +import toHours from "./toHours.js"; +import toISO from "./toISO.js"; +import toISOFromLocalDateTime from "./toISOFromLocalDateTime.js"; +import toLocalDateTime from "./toLocalDateTime.js"; +import toMinutes from "./toMinutes.js"; +import toSeconds from "./toSeconds.js"; +import valid from "./valid.js"; +import weekRange from "./weekRange.js"; +import yearRange from "./yearRange.js"; + +export { + byDateWithFallback, + clamp, + dateDiff, + dateInRange, + dayRange, + daysInMonths, + daysInYear, + displayTime, + endOfDay, + formatDate, + formatDateTime, + formatDuration, + formatTime, + fromDays, + fromHours, + fromMinutes, + fromSeconds, + joinDateTime, + leapYear, + monthRange, + offsetByBit, + parseHourMinutePair, + splitDateTime, + startOfDay, + subtractDays, + toDate, + toDates, + toDays, + toHours, + toISO, + toISOFromLocalDateTime, + toLocalDateTime, + toMinutes, + toSeconds, + valid, + weekRange, + yearRange +}; + +export default { + byDateWithFallback, + clamp, + dateDiff, + dateInRange, + dayRange, + daysInMonths, + daysInYear, + displayTime, + endOfDay, + formatDate, + formatDateTime, + formatDuration, + formatTime, + fromDays, + fromHours, + fromMinutes, + fromSeconds, + joinDateTime, + leapYear, + monthRange, + offsetByBit, + parseHourMinutePair, + splitDateTime, + startOfDay, + subtractDays, + toDate, + toDates, + toDays, + toHours, + toISO, + toISOFromLocalDateTime, + toLocalDateTime, + toMinutes, + toSeconds, + valid, + weekRange, + yearRange +}; diff --git a/debug/index.js b/debug/index.js new file mode 100644 index 00000000..f85332b7 --- /dev/null +++ b/debug/index.js @@ -0,0 +1,6 @@ +import assert from "./assert.js"; +import diff from "./diff.js"; + +export { assert, diff }; + +export default { assert, diff }; diff --git a/encoding/index.js b/encoding/index.js new file mode 100644 index 00000000..78553ab2 --- /dev/null +++ b/encoding/index.js @@ -0,0 +1,5 @@ +import base64url from "./base64url.js"; + +export { base64url }; + +export default { base64url }; diff --git a/file/index.js b/file/index.js new file mode 100644 index 00000000..bbddc8ea --- /dev/null +++ b/file/index.js @@ -0,0 +1,5 @@ +import validName from "./validName.js"; + +export { validName }; + +export default { validName }; diff --git a/function/index.js b/function/index.js new file mode 100644 index 00000000..d6b94b43 --- /dev/null +++ b/function/index.js @@ -0,0 +1,36 @@ +import compose from "./compose.js"; +import constant from "./constant.js"; +import identity from "./identity.js"; +import memoize from "./memoize.js"; +import memoizeShallow from "./memoizeShallow.js"; +import memoizeWith from "./memoizeWith.js"; +import noOp from "./noOp.js"; +import pipe from "./pipe.js"; +import when from "./when.js"; +import whenTrue from "./whenTrue.js"; + +export { + compose, + constant, + identity, + memoize, + memoizeShallow, + memoizeWith, + noOp, + pipe, + when, + whenTrue +}; + +export default { + compose, + constant, + identity, + memoize, + memoizeShallow, + memoizeWith, + noOp, + pipe, + when, + whenTrue +}; diff --git a/index.js b/index.js new file mode 100644 index 00000000..9cc7a9bb --- /dev/null +++ b/index.js @@ -0,0 +1,54 @@ +import array from "./array"; +import async from "./async"; +import date from "./date"; +import debug from "./debug"; +import encoding from "./encoding"; +import file from "./file"; +import _function from "./function"; +import is from "./is"; +import math from "./math"; +import object from "./object"; +import query from "./query"; +import range from "./range"; +import regex from "./regex"; +import string from "./string"; +import vector2 from "./vector2"; +import web from "./web"; + +export { + array, + async, + date, + debug, + encoding, + file, + _function, + is, + math, + object, + query, + range, + regex, + string, + vector2, + web +}; + +export default { + array, + async, + date, + debug, + encoding, + file, + _function, + is, + math, + object, + query, + range, + regex, + string, + vector2, + web +}; diff --git a/is/index.js b/is/index.js new file mode 100644 index 00000000..2880557e --- /dev/null +++ b/is/index.js @@ -0,0 +1,36 @@ +import array from "./array.js"; +import byte from "./byte.js"; +import date from "./date.js"; +import defined from "./defined.js"; +import _function from "./function.js"; +import integer from "./integer.js"; +import normal from "./normal.js"; +import number from "./number.js"; +import object from "./object.js"; +import string from "./string.js"; + +export { + array, + byte, + date, + defined, + _function, + integer, + normal, + number, + object, + string +}; + +export default { + array, + byte, + date, + defined, + _function, + integer, + normal, + number, + object, + string +}; diff --git a/math/index.js b/math/index.js new file mode 100644 index 00000000..ea1e5db5 --- /dev/null +++ b/math/index.js @@ -0,0 +1,51 @@ +import add from "./add.js"; +import average from "./average.js"; +import ceilToNearestPowerOfTwo from "./ceilToNearestPowerOfTwo.js"; +import clamp from "./clamp.js"; +import clampNormal from "./clampNormal.js"; +import delta from "./delta.js"; +import inRectangleRange from "./inRectangleRange.js"; +import lerp from "./lerp.js"; +import maximumBy from "./maximumBy.js"; +import median from "./median.js"; +import minMax from "./minMax.js"; +import safeNormalize from "./safeNormalize.js"; +import sameSign from "./sameSign.js"; +import standardDeviation from "./standardDeviation.js"; +import subtract from "./subtract.js"; + +export { + add, + average, + ceilToNearestPowerOfTwo, + clamp, + clampNormal, + delta, + inRectangleRange, + lerp, + maximumBy, + median, + minMax, + safeNormalize, + sameSign, + standardDeviation, + subtract +}; + +export default { + add, + average, + ceilToNearestPowerOfTwo, + clamp, + clampNormal, + delta, + inRectangleRange, + lerp, + maximumBy, + median, + minMax, + safeNormalize, + sameSign, + standardDeviation, + subtract +}; diff --git a/object/index.js b/object/index.js new file mode 100644 index 00000000..ed337bb8 --- /dev/null +++ b/object/index.js @@ -0,0 +1,72 @@ +import any from "./any.js"; +import apply from "./apply.js"; +import empty from "./empty.js"; +import entries from "./entries.js"; +import enumerable from "./enumerable.js"; +import equals from "./equals.js"; +import filter from "./filter.js"; +import find from "./find.js"; +import findKey from "./findKey.js"; +import findValue from "./findValue.js"; +import first from "./first.js"; +import flatMapValues from "./flatMapValues.js"; +import fromEntries from "./fromEntries.js"; +import groupBy from "./groupBy.js"; +import hasKey from "./hasKey.js"; +import length from "./length.js"; +import map from "./map.js"; +import mapEntries from "./mapEntries.js"; +import mapKeys from "./mapKeys.js"; +import mapValues from "./mapValues.js"; +import none from "./none.js"; +import sort from "./sort.js"; + +export { + any, + apply, + empty, + entries, + enumerable, + equals, + filter, + find, + findKey, + findValue, + first, + flatMapValues, + fromEntries, + groupBy, + hasKey, + length, + map, + mapEntries, + mapKeys, + mapValues, + none, + sort +}; + +export default { + any, + apply, + empty, + entries, + enumerable, + equals, + filter, + find, + findKey, + findValue, + first, + flatMapValues, + fromEntries, + groupBy, + hasKey, + length, + map, + mapEntries, + mapKeys, + mapValues, + none, + sort +}; diff --git a/query/index.js b/query/index.js new file mode 100644 index 00000000..558489ce --- /dev/null +++ b/query/index.js @@ -0,0 +1,8 @@ +import parse from "./parse.js"; +import parsePathname from "./parsePathname.js"; +import read from "./read.js"; +import serialize from "./serialize.js"; + +export { parse, parsePathname, read, serialize }; + +export default { parse, parsePathname, read, serialize }; diff --git a/range/index.js b/range/index.js new file mode 100644 index 00000000..a0e7a341 --- /dev/null +++ b/range/index.js @@ -0,0 +1,8 @@ +import empty from "./empty.js"; +import equals from "./equals.js"; +import length from "./length.js"; +import split from "./split.js"; + +export { empty, equals, length, split }; + +export default { empty, equals, length, split }; diff --git a/regex/index.js b/regex/index.js new file mode 100644 index 00000000..231e89cb --- /dev/null +++ b/regex/index.js @@ -0,0 +1,5 @@ +import escape from "./escape.js"; + +export { escape }; + +export default { escape }; diff --git a/string/index.js b/string/index.js new file mode 100644 index 00000000..af2f7705 --- /dev/null +++ b/string/index.js @@ -0,0 +1,30 @@ +import containsWhitespace from "./containsWhitespace.js"; +import empty from "./empty.js"; +import firstToLower from "./firstToLower.js"; +import firstToUpper from "./firstToUpper.js"; +import includes from "./includes.js"; +import nbsp from "./nbsp.js"; +import nonEmpty from "./nonEmpty.js"; +import startsWith from "./startsWith.js"; + +export { + containsWhitespace, + empty, + firstToLower, + firstToUpper, + includes, + nbsp, + nonEmpty, + startsWith +}; + +export default { + containsWhitespace, + empty, + firstToLower, + firstToUpper, + includes, + nbsp, + nonEmpty, + startsWith +}; diff --git a/vector2/index.js b/vector2/index.js new file mode 100644 index 00000000..b88aa8d8 --- /dev/null +++ b/vector2/index.js @@ -0,0 +1,48 @@ +import add from "./add.js"; +import convertSpace from "./convertSpace.js"; +import cross from "./cross.js"; +import dot from "./dot.js"; +import length from "./length.js"; +import mul from "./mul.js"; +import multiply from "./multiply.js"; +import normalize from "./normalize.js"; +import reflect from "./reflect.js"; +import rotate from "./rotate.js"; +import scale from "./scale.js"; +import sub from "./sub.js"; +import transform from "./transform.js"; +import translate from "./translate.js"; + +export { + add, + convertSpace, + cross, + dot, + length, + mul, + multiply, + normalize, + reflect, + rotate, + scale, + sub, + transform, + translate +}; + +export default { + add, + convertSpace, + cross, + dot, + length, + mul, + multiply, + normalize, + reflect, + rotate, + scale, + sub, + transform, + translate +}; diff --git a/web/events/index.js b/web/events/index.js new file mode 100644 index 00000000..0809d31a --- /dev/null +++ b/web/events/index.js @@ -0,0 +1,8 @@ +import cancel from "./cancel.js"; +import openInNewTabIntent from "./openInNewTabIntent.js"; +import prevent from "./prevent.js"; +import stop from "./stop.js"; + +export { cancel, openInNewTabIntent, prevent, stop }; + +export default { cancel, openInNewTabIntent, prevent, stop }; diff --git a/web/index.js b/web/index.js new file mode 100644 index 00000000..16d28c77 --- /dev/null +++ b/web/index.js @@ -0,0 +1,6 @@ +import classNames from "./classNames.js"; +import events from "./events"; + +export { classNames, events }; + +export default { classNames, events }; From 4b83314bb75c8090b9ae15bcb35ab993d5be0a2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 12:31:09 +0200 Subject: [PATCH 36/56] Point module field to index file --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 5e7d69e6..7d3e8940 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "0.1.0", "description": "", "main": "index.js", + "module": "index.js", "type": "module", "sideEffects": false, "scripts": { From bd6b135147ba467059c090b8467116b5bae9ad95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 12:41:13 +0200 Subject: [PATCH 37/56] Remove not ready modules --- date/index.js | 13 ++----------- date/monthRange.js | 24 ------------------------ date/weekRange.js | 24 ------------------------ date/yearRange.js | 24 ------------------------ 4 files changed, 2 insertions(+), 83 deletions(-) delete mode 100644 date/monthRange.js delete mode 100644 date/weekRange.js delete mode 100644 date/yearRange.js diff --git a/date/index.js b/date/index.js index 478521b0..6dfdc1fc 100644 --- a/date/index.js +++ b/date/index.js @@ -17,7 +17,6 @@ import fromMinutes from "./fromMinutes.js"; import fromSeconds from "./fromSeconds.js"; import joinDateTime from "./joinDateTime.js"; import leapYear from "./leapYear.js"; -import monthRange from "./monthRange.js"; import offsetByBit from "./offsetByBit.js"; import parseHourMinutePair from "./parseHourMinutePair.js"; import splitDateTime from "./splitDateTime.js"; @@ -33,8 +32,6 @@ import toLocalDateTime from "./toLocalDateTime.js"; import toMinutes from "./toMinutes.js"; import toSeconds from "./toSeconds.js"; import valid from "./valid.js"; -import weekRange from "./weekRange.js"; -import yearRange from "./yearRange.js"; export { byDateWithFallback, @@ -56,7 +53,6 @@ export { fromSeconds, joinDateTime, leapYear, - monthRange, offsetByBit, parseHourMinutePair, splitDateTime, @@ -71,9 +67,7 @@ export { toLocalDateTime, toMinutes, toSeconds, - valid, - weekRange, - yearRange + valid }; export default { @@ -96,7 +90,6 @@ export default { fromSeconds, joinDateTime, leapYear, - monthRange, offsetByBit, parseHourMinutePair, splitDateTime, @@ -111,7 +104,5 @@ export default { toLocalDateTime, toMinutes, toSeconds, - valid, - weekRange, - yearRange + valid }; diff --git a/date/monthRange.js b/date/monthRange.js deleted file mode 100644 index 9176477a..00000000 --- a/date/monthRange.js +++ /dev/null @@ -1,24 +0,0 @@ -import endOfMonth from "./endOfMonth.js"; -import offsetByBit from "./offsetByBit.js"; -import splitDateTime from "./splitDateTime.js"; -import startOfMonth from "./startOfMonth.js"; -import toISO from "./toISO.js"; -import toISOFromLocalDateTime from "./toISOFromLocalDateTime.js"; - -export default ({ - iso = false, - local = true, - now = new Date(), - timezoneOffset = 0 -}) => date => { - const convert = iso ? toISO : toISOFromLocalDateTime; - - const [start] = splitDateTime( - convert(startOfMonth(date || now, timezoneOffset, local)) - ); - const [end] = splitDateTime( - convert(offsetByBit(endOfMonth(date || now, timezoneOffset, local))) - ); - - return [start, end]; -}; diff --git a/date/weekRange.js b/date/weekRange.js deleted file mode 100644 index 64a8487a..00000000 --- a/date/weekRange.js +++ /dev/null @@ -1,24 +0,0 @@ -import endOfWeek from "./endOfWeek.js"; -import offsetByBit from "./offsetByBit.js"; -import splitDateTime from "./splitDateTime.js"; -import startOfWeek from "./startOfWeek.js"; -import toISO from "./toISO.js"; -import toISOFromLocalDateTime from "./toISOFromLocalDateTime.js"; - -export default ({ - iso = false, - local = true, - now = new Date(), - timezoneOffset = 0 -}) => date => { - const convert = iso ? toISO : toISOFromLocalDateTime; - - const [start] = splitDateTime( - convert(startOfWeek(date || now, timezoneOffset, local)) - ); - const [end] = splitDateTime( - convert(offsetByBit(endOfWeek(date || now, timezoneOffset, local))) - ); - - return [start, end]; -}; diff --git a/date/yearRange.js b/date/yearRange.js deleted file mode 100644 index e87d1143..00000000 --- a/date/yearRange.js +++ /dev/null @@ -1,24 +0,0 @@ -import endOfYear from "./endOfYear.js"; -import offsetByBit from "./offsetByBit.js"; -import splitDateTime from "./splitDateTime.js"; -import startOfYear from "./startOfYear.js"; -import toISO from "./toISO.js"; -import toISOFromLocalDateTime from "./toISOFromLocalDateTime.js"; - -export default ({ - iso = false, - local = true, - now = new Date(), - timezoneOffset = 0 -}) => date => { - const convert = iso ? toISO : toISOFromLocalDateTime; - - const [start] = splitDateTime( - convert(startOfYear(date || now, timezoneOffset, local)) - ); - const [end] = splitDateTime( - convert(offsetByBit(endOfYear(date || now, timezoneOffset, local))) - ); - - return [start, end]; -}; From ea8a3ba9e3c039775c08945085bc431406cd6ea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 13:02:39 +0200 Subject: [PATCH 38/56] Use strict equal comparison --- object/equals.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/object/equals.js b/object/equals.js index 9a38c174..b5d64c4e 100644 --- a/object/equals.js +++ b/object/equals.js @@ -12,7 +12,7 @@ export const equalsDeep = (a, b) => { } return isObject(a) && isObject(b) ? a === b || keySet(a, b).every(key => equalsDeep(a[key], b[key])) - : _isEqual(a, b); + : a === b; }; export const equalsDeepWith = f => (a, b) => { From c3470ecace49633ed63d71f42e46b650ac54e6f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 13:28:32 +0200 Subject: [PATCH 39/56] Prepare package build scripts and setup --- .gitignore | 3 ++ .npmignore | 1 + package-lock.json | 29 ++++++++++++++++ package.json | 15 ++++++--- regenerate.js | 84 +++++++++++++++++++++++++++++++++++++++++++++++ rollup.config.js | 15 +++++++++ 6 files changed, 142 insertions(+), 5 deletions(-) create mode 100644 .npmignore create mode 100644 regenerate.js create mode 100644 rollup.config.js diff --git a/.gitignore b/.gitignore index ad46b308..2b0ef73d 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,6 @@ typings/ # next.js build output .next + +index.cjs.js +index.umd.js diff --git a/.npmignore b/.npmignore new file mode 100644 index 00000000..eb4647a4 --- /dev/null +++ b/.npmignore @@ -0,0 +1 @@ +regenerate.js diff --git a/package-lock.json b/package-lock.json index 918666e9..a56ea7c2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,11 +4,40 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "@types/node": { + "version": "12.7.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.9.tgz", + "integrity": "sha512-P57oKTJ/vYivL2BCfxCC5tQjlS8qW31pbOL6qt99Yrjm95YdHgNZwjrTTjMBh+C2/y6PXIX4oz253+jUzxKKfQ==", + "dev": true + }, + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true + }, "prettier": { "version": "1.18.2", "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.18.2.tgz", "integrity": "sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==", "dev": true + }, + "rollup": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.22.0.tgz", + "integrity": "sha512-x4l4ZrV/Mr/x/jvFTmwROdEAhbZjx16yDRTVSKWh/i4oJDuW2dVEbECT853mybYCz7BAitU8ElGlhx7dNjw3qQ==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/node": "*", + "acorn": "^7.1.0" + } } } } diff --git a/package.json b/package.json index 7d3e8940..44bbcc25 100644 --- a/package.json +++ b/package.json @@ -2,14 +2,18 @@ "name": "@sandstreamdev/std", "version": "0.1.0", "description": "", - "main": "index.js", - "module": "index.js", "type": "module", + "module": "index.js", + "main": "index.cjs.js", + "browser": "index.umd.js", "sideEffects": false, "scripts": { - "prettier": "prettier \"**/*.{js,json,md}\"", + "build": "npm run regenerate && rollup -c", + "prepare": "npm run build", + "prettier:check": "npm run prettier -- --check", "prettier:fix": "npm run prettier -- --write", - "prettier:check": "npm run prettier -- --check" + "prettier": "prettier \"**/*.{js,json,md}\"", + "regenerate": "node --experimental-modules regenerate.js && npm run prettier:fix" }, "repository": { "type": "git", @@ -26,6 +30,7 @@ }, "homepage": "https://github.com/sandstreamdev/std#readme", "devDependencies": { - "prettier": "^1.18.2" + "prettier": "^1.18.2", + "rollup": "^1.22.0" } } diff --git a/regenerate.js b/regenerate.js new file mode 100644 index 00000000..db4e1034 --- /dev/null +++ b/regenerate.js @@ -0,0 +1,84 @@ +import { promises } from "fs"; +import path from "path"; + +const { readdir: readDirectoryAsync, writeFile: writeFileAsync } = promises; + +const [, , cwd = process.cwd()] = process.argv; + +const mapping = { + function: "_function" +}; + +const ignoredFiles = [ + ".gitignore", + "index.js", + "LICENSE", + "package-lock.json", + "package.json", + "README.md", + "regenerate.js", + "rollup.config.js" +]; + +const ignoredDirectories = [".git", "node_modules"]; + +const identifier = name => mapping[name] || name; + +const main = async cwd => { + console.log(`Indexing files in ${cwd}...`); + + const entries = await readDirectoryAsync(cwd, { withFileTypes: true }); + const files = entries + .filter(x => x.isFile()) + .map(x => x.name) + .filter(x => !ignoredFiles.includes(x)); + const directories = entries + .filter(x => x.isDirectory()) + .map(x => x.name) + .filter(x => !ignoredDirectories.includes(x)); + + for (const directory of directories) { + await main(path.join(cwd, directory)); + } + + const submodules = files.map(filePath => { + const { base: fileName } = path.parse(filePath); + const splitted = fileName.split("."); + const id = identifier(splitted.slice(0, splitted.length - 1).join("_")); + const extension = `.${splitted[splitted.length - 1]}`; + + return [fileName, id, extension]; + }); + + const dependencies = [ + ...submodules, + ...directories.map(x => [`${x}/index.js`, identifier(x), ""]) + ]; + + const importDeclarations = dependencies + .map(([fileName, id]) => + id !== "index" ? `import ${id} from './${fileName}'` : "" + ) + .join("\r\n"); + + const exportDeclarationBody = dependencies + .map(([, id]) => (id !== "index" ? id : "")) + .join(", "); + + const exportDeclaration = `export { ${exportDeclarationBody} }`; + const defaultExport = `export default { ${exportDeclarationBody} }`; + + console.log(`Indexed files in ${cwd}:`); + + const moduleContents = [ + importDeclarations, + exportDeclaration, + defaultExport + ].join("\r\n\r\n"); + + console.log(moduleContents); + + await writeFileAsync(path.join(cwd, "index.js"), moduleContents); +}; + +main(cwd); diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 00000000..f38843aa --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,15 @@ +export default { + input: "index.js", + output: [ + { + exports: "named", + file: "index.cjs.js", + format: "cjs" + }, + { + file: "index.umd.js", + format: "umd", + name: "@sandstreamdev/std" + } + ] +}; From ba709d0910586b495bf8307d2eadc35b2d7541db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 13:29:15 +0200 Subject: [PATCH 40/56] Fix broken and missing imports/exports --- debug/diff.js | 4 ++-- encoding/base64url.js | 2 ++ index.js | 32 ++++++++++++++++---------------- range/split.js | 6 +++--- web/index.js | 2 +- 5 files changed, 24 insertions(+), 22 deletions(-) diff --git a/debug/diff.js b/debug/diff.js index cfb16253..80a1c0ee 100644 --- a/debug/diff.js +++ b/debug/diff.js @@ -1,5 +1,5 @@ import filter from "../object/filter.js"; -import isEmpty from "./object/isEmpty.js"; +import none from "../object/none.js"; import isArray from "../is/array.js"; import isDate from "../is/date.js"; @@ -75,7 +75,7 @@ const diff = (obj1, obj2) => { return filter( value => - value !== null && !(value && "object" === typeof value && isEmpty(value)) + value !== null && !(value && "object" === typeof value && none(value)) )(result); }; diff --git a/encoding/base64url.js b/encoding/base64url.js index db2bd036..b053ef7b 100644 --- a/encoding/base64url.js +++ b/encoding/base64url.js @@ -9,3 +9,5 @@ export const toBase64Url = base64 => export const fromBase64Url = base64 => base64.replace(/-/g, "+").replace(/_/g, "/"); + +export default { encode }; diff --git a/index.js b/index.js index 9cc7a9bb..a908ee7f 100644 --- a/index.js +++ b/index.js @@ -1,19 +1,19 @@ -import array from "./array"; -import async from "./async"; -import date from "./date"; -import debug from "./debug"; -import encoding from "./encoding"; -import file from "./file"; -import _function from "./function"; -import is from "./is"; -import math from "./math"; -import object from "./object"; -import query from "./query"; -import range from "./range"; -import regex from "./regex"; -import string from "./string"; -import vector2 from "./vector2"; -import web from "./web"; +import array from "./array/index.js"; +import async from "./async/index.js"; +import date from "./date/index.js"; +import debug from "./debug/index.js"; +import encoding from "./encoding/index.js"; +import file from "./file/index.js"; +import _function from "./function/index.js"; +import is from "./is/index.js"; +import math from "./math/index.js"; +import object from "./object/index.js"; +import query from "./query/index.js"; +import range from "./range/index.js"; +import regex from "./regex/index.js"; +import string from "./string/index.js"; +import vector2 from "./vector2/index.js"; +import web from "./web/index.js"; export { array, diff --git a/range/split.js b/range/split.js index 6e8bb2c3..164e04d9 100644 --- a/range/split.js +++ b/range/split.js @@ -1,9 +1,9 @@ -import { isNotNaN } from "../is.js"; +import isNumber from "../is/number.js"; import clamp from "../math/clamp.js"; import empty from "./empty.js"; -export const split = (used, sourceRange = [-Infinity, Infinity]) => range => { - if (empty(range) || !range.every(isNotNaN)) { +export default (used, sourceRange = [-Infinity, Infinity]) => range => { + if (empty(range) || !range.every(isNumber)) { return []; } diff --git a/web/index.js b/web/index.js index 16d28c77..e75e558b 100644 --- a/web/index.js +++ b/web/index.js @@ -1,5 +1,5 @@ import classNames from "./classNames.js"; -import events from "./events"; +import events from "./events/index.js"; export { classNames, events }; From 8e883fb1fd38b1d211256ef92eb5ff90a31a1226 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 13:34:12 +0200 Subject: [PATCH 41/56] Ignore build output files --- regenerate.js | 3 +++ rollup.config.js | 1 + 2 files changed, 4 insertions(+) diff --git a/regenerate.js b/regenerate.js index db4e1034..6d8a40fe 100644 --- a/regenerate.js +++ b/regenerate.js @@ -11,7 +11,10 @@ const mapping = { const ignoredFiles = [ ".gitignore", + ".npmignore", + "index.cjs.js", "index.js", + "index.umd.js", "LICENSE", "package-lock.json", "package.json", diff --git a/rollup.config.js b/rollup.config.js index f38843aa..3dabf215 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -7,6 +7,7 @@ export default { format: "cjs" }, { + exports: "named", file: "index.umd.js", format: "umd", name: "@sandstreamdev/std" From de232d912fb55ff70f41070d1cc201d7ed26e59f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 13:48:02 +0200 Subject: [PATCH 42/56] Fix broken default exports and add missing import --- array/filterInPlace.js | 2 +- array/first.js | 2 +- date/offsetByBit.js | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/array/filterInPlace.js b/array/filterInPlace.js index 375df26e..8b065931 100644 --- a/array/filterInPlace.js +++ b/array/filterInPlace.js @@ -1,4 +1,4 @@ -export default filterInPlace = f => xs => { +export default f => xs => { let i = 0; let j = 0; diff --git a/array/first.js b/array/first.js index 089de9a1..42b96520 100644 --- a/array/first.js +++ b/array/first.js @@ -1 +1 @@ -export default first = ([x]) => x; +export default ([x]) => x; diff --git a/date/offsetByBit.js b/date/offsetByBit.js index d492195c..6df9dd14 100644 --- a/date/offsetByBit.js +++ b/date/offsetByBit.js @@ -1,3 +1,5 @@ +import fromSeconds from "./fromSeconds"; + const SECOND = fromSeconds(1); export default date => new Date(date - SECOND); From 0e569d06b5acd3880d8e5f6046368a7df262986d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Thu, 3 Oct 2019 13:51:47 +0200 Subject: [PATCH 43/56] Add another missing import --- function/memoizeShallow.js | 2 ++ function/memoizeWith.js | 3 +++ 2 files changed, 5 insertions(+) diff --git a/function/memoizeShallow.js b/function/memoizeShallow.js index fb85b0f0..31528d8d 100644 --- a/function/memoizeShallow.js +++ b/function/memoizeShallow.js @@ -1,3 +1,5 @@ +import memoizeWith from "./memoizeWith"; + const equalsShallow = (xs, ys) => xs.length === ys.length && xs.every((x, index) => x === ys[index]); diff --git a/function/memoizeWith.js b/function/memoizeWith.js index 08e3665c..83481bb0 100644 --- a/function/memoizeWith.js +++ b/function/memoizeWith.js @@ -1,12 +1,15 @@ export default equals => f => { let memoized = undefined; let memoizedArgs = undefined; + return (...args) => { if (memoized && equals(args, memoizedArgs)) { return memoized; } + memoized = f(...args); memoizedArgs = args; + return memoized; }; }; From 4881f5fc3f919fae45061d0ef5204ee87d144f4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Fri, 4 Oct 2019 08:31:30 +0200 Subject: [PATCH 44/56] Add missing helpers --- date/displayMonth.js | 3 +++ date/formatDisplayDate.js | 13 +++++++++++++ date/index.js | 9 +++++++++ date/monthNames.js | 14 ++++++++++++++ math/clampPercentage.js | 3 +++ math/index.js | 3 +++ 6 files changed, 45 insertions(+) create mode 100644 date/displayMonth.js create mode 100644 date/formatDisplayDate.js create mode 100644 date/monthNames.js create mode 100644 math/clampPercentage.js diff --git a/date/displayMonth.js b/date/displayMonth.js new file mode 100644 index 00000000..83a1e0b6 --- /dev/null +++ b/date/displayMonth.js @@ -0,0 +1,3 @@ +import monthNames from "./monthNames"; + +export default monthIndex => monthNames[monthIndex % 12]; diff --git a/date/formatDisplayDate.js b/date/formatDisplayDate.js new file mode 100644 index 00000000..c3d06b8a --- /dev/null +++ b/date/formatDisplayDate.js @@ -0,0 +1,13 @@ +import toLocalDateTime from "./toLocalDateTime.js"; +import displayMonth from "./displayMonth.js"; + +export default (sourceDate, showDay = false, timezoneOffset = 0) => { + const localDate = toLocalDateTime(sourceDate, timezoneOffset); + const day = localDate.getDate(); + const monthIndex = localDate.getMonth(); + const year = localDate.getFullYear(); + + return [showDay && day, displayMonth(monthIndex), year] + .filter(Boolean) + .join(" "); +}; diff --git a/date/index.js b/date/index.js index 6dfdc1fc..bdaf6cbc 100644 --- a/date/index.js +++ b/date/index.js @@ -5,10 +5,12 @@ import dateInRange from "./dateInRange.js"; import dayRange from "./dayRange.js"; import daysInMonths from "./daysInMonths.js"; import daysInYear from "./daysInYear.js"; +import displayMonth from "./displayMonth.js"; import displayTime from "./displayTime.js"; import endOfDay from "./endOfDay.js"; import formatDate from "./formatDate.js"; import formatDateTime from "./formatDateTime.js"; +import formatDisplayDate from "./formatDisplayDate.js"; import formatDuration from "./formatDuration.js"; import formatTime from "./formatTime.js"; import fromDays from "./fromDays.js"; @@ -17,6 +19,7 @@ import fromMinutes from "./fromMinutes.js"; import fromSeconds from "./fromSeconds.js"; import joinDateTime from "./joinDateTime.js"; import leapYear from "./leapYear.js"; +import monthNames from "./monthNames.js"; import offsetByBit from "./offsetByBit.js"; import parseHourMinutePair from "./parseHourMinutePair.js"; import splitDateTime from "./splitDateTime.js"; @@ -41,10 +44,12 @@ export { dayRange, daysInMonths, daysInYear, + displayMonth, displayTime, endOfDay, formatDate, formatDateTime, + formatDisplayDate, formatDuration, formatTime, fromDays, @@ -53,6 +58,7 @@ export { fromSeconds, joinDateTime, leapYear, + monthNames, offsetByBit, parseHourMinutePair, splitDateTime, @@ -78,10 +84,12 @@ export default { dayRange, daysInMonths, daysInYear, + displayMonth, displayTime, endOfDay, formatDate, formatDateTime, + formatDisplayDate, formatDuration, formatTime, fromDays, @@ -90,6 +98,7 @@ export default { fromSeconds, joinDateTime, leapYear, + monthNames, offsetByBit, parseHourMinutePair, splitDateTime, diff --git a/date/monthNames.js b/date/monthNames.js new file mode 100644 index 00000000..c870f165 --- /dev/null +++ b/date/monthNames.js @@ -0,0 +1,14 @@ +export default [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" +]; diff --git a/math/clampPercentage.js b/math/clampPercentage.js new file mode 100644 index 00000000..d331be17 --- /dev/null +++ b/math/clampPercentage.js @@ -0,0 +1,3 @@ +import clamp from "./clamp.js"; + +export default clamp(0, 100); diff --git a/math/index.js b/math/index.js index ea1e5db5..596c8fe1 100644 --- a/math/index.js +++ b/math/index.js @@ -3,6 +3,7 @@ import average from "./average.js"; import ceilToNearestPowerOfTwo from "./ceilToNearestPowerOfTwo.js"; import clamp from "./clamp.js"; import clampNormal from "./clampNormal.js"; +import clampPercentage from "./clampPercentage.js"; import delta from "./delta.js"; import inRectangleRange from "./inRectangleRange.js"; import lerp from "./lerp.js"; @@ -20,6 +21,7 @@ export { ceilToNearestPowerOfTwo, clamp, clampNormal, + clampPercentage, delta, inRectangleRange, lerp, @@ -38,6 +40,7 @@ export default { ceilToNearestPowerOfTwo, clamp, clampNormal, + clampPercentage, delta, inRectangleRange, lerp, From 8911d90fe2f6a33f870277446552845c30f41828 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Fri, 4 Oct 2019 08:41:04 +0200 Subject: [PATCH 45/56] Add missing import --- date/toLocalDateTime.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/date/toLocalDateTime.js b/date/toLocalDateTime.js index c5bacd4d..90379f1a 100644 --- a/date/toLocalDateTime.js +++ b/date/toLocalDateTime.js @@ -1,2 +1,4 @@ +import fromMinutes from "./fromMinutes.js"; + export default (date, timezoneOffset = 0) => new Date(date.valueOf() - fromMinutes(timezoneOffset)); From 990589d4aa01d408cfdbb858f90a31c35d7e81b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Fri, 4 Oct 2019 08:45:41 +0200 Subject: [PATCH 46/56] Add missing imports --- date/formatTime.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/date/formatTime.js b/date/formatTime.js index 7c158f82..6c01768f 100644 --- a/date/formatTime.js +++ b/date/formatTime.js @@ -1,3 +1,6 @@ +import toLocalDateTime from "./toLocalDateTime.js"; +import displayTime from "./displayTime.js"; + export default (sourceDate, showSeconds = false, timezoneOffset = 0) => { const localDate = toLocalDateTime(sourceDate, timezoneOffset); From 13ffd95dc6aae5f87682aa317608558e74755a85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Fri, 4 Oct 2019 08:57:57 +0200 Subject: [PATCH 47/56] Add missing range import for repeat --- array/repeat.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/array/repeat.js b/array/repeat.js index 8a7290ed..18cb69c5 100644 --- a/array/repeat.js +++ b/array/repeat.js @@ -1 +1,3 @@ +import range from "./range.js"; + export default n => value => range(n).map(() => value); From d798b98e4edc579c2d57a326630ed55246e0b585 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Fri, 4 Oct 2019 09:11:20 +0200 Subject: [PATCH 48/56] Fix range/split recursion and make clamp calls consistent --- date/clamp.js | 2 +- range/split.js | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/date/clamp.js b/date/clamp.js index 8e4cf914..70e2c31a 100644 --- a/date/clamp.js +++ b/date/clamp.js @@ -1,4 +1,4 @@ -export default ([min, max]) => dateStringOrDate => { +export default (min, max) => dateStringOrDate => { const date = new Date(dateStringOrDate); const clamped = new Date( Math.min(max.valueOf(), Math.max(min.valueOf(), date.valueOf())) diff --git a/range/split.js b/range/split.js index 164e04d9..05ed309d 100644 --- a/range/split.js +++ b/range/split.js @@ -2,7 +2,7 @@ import isNumber from "../is/number.js"; import clamp from "../math/clamp.js"; import empty from "./empty.js"; -export default (used, sourceRange = [-Infinity, Infinity]) => range => { +const split = (used, sourceRange = [-Infinity, Infinity]) => range => { if (empty(range) || !range.every(isNumber)) { return []; } @@ -19,20 +19,22 @@ export default (used, sourceRange = [-Infinity, Infinity]) => range => { } const [sourceMin, sourceMax] = sourceRange; - const clampToSourceRange = clamp(sourceRange); + const clampToSourceRange = clamp(...sourceRange); const freeLeft = [sourceMin, usedMin].map(clampToSourceRange); const freeRight = [usedMax, sourceMax].map(clampToSourceRange); - const clampLeft = clamp(freeLeft); + const clampLeft = clamp(...freeLeft); const clampedLeft = range.map(clampLeft); const lefts = split(xs, sourceRange)(clampedLeft); - const clampRight = clamp(freeRight); + const clampRight = clamp(...freeRight); const clampedRight = range.map(clampRight); const rights = split(xs, sourceRange)(clampedRight); return [...lefts, ...rights].filter(range => !empty(range)); }; + +export default split; From b299bb82c2267e7b3aed5cd8735c1bc7b01fc8d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Fri, 4 Oct 2019 13:14:11 +0200 Subject: [PATCH 49/56] Fix missing toString helper issue --- date/toDate.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/date/toDate.js b/date/toDate.js index 0a3c6b17..04b7bb21 100644 --- a/date/toDate.js +++ b/date/toDate.js @@ -4,8 +4,8 @@ export default date => { const year = date.getFullYear(); return [ - toString(year).padStart(4, "0"), - toString(month).padStart(2, "0"), - toString(day).padStart(2, "0") + `${year}`.padStart(4, "0"), + `${month}`.padStart(2, "0"), + `${day}`.padStart(2, "0") ].join("-"); }; From 56357f5fd4e83f257ffe1818aa65760851035c30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Mon, 7 Oct 2019 18:38:08 +0200 Subject: [PATCH 50/56] Use Array.fill directly to generate repeated values --- array/repeat.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/array/repeat.js b/array/repeat.js index 18cb69c5..e90082e8 100644 --- a/array/repeat.js +++ b/array/repeat.js @@ -1,3 +1 @@ -import range from "./range.js"; - -export default n => value => range(n).map(() => value); +export default n => value => Array(n).fill(value); From c056f7e2becac319e32e4aece9142f3fbdaff5b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Mon, 7 Oct 2019 18:38:53 +0200 Subject: [PATCH 51/56] Use consistent any/none object and array APIs --- array/index.js | 3 +++ array/none.js | 3 +++ object/any.js | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 array/none.js diff --git a/array/index.js b/array/index.js index 59d65c30..70f2c678 100644 --- a/array/index.js +++ b/array/index.js @@ -18,6 +18,7 @@ import map from "./map.js"; import midpoint from "./midpoint.js"; import minMax from "./minMax.js"; import multiple from "./multiple.js"; +import none from "./none.js"; import partition from "./partition.js"; import range from "./range.js"; import repeat from "./repeat.js"; @@ -57,6 +58,7 @@ export { midpoint, minMax, multiple, + none, partition, range, repeat, @@ -97,6 +99,7 @@ export default { midpoint, minMax, multiple, + none, partition, range, repeat, diff --git a/array/none.js b/array/none.js new file mode 100644 index 00000000..307b11e6 --- /dev/null +++ b/array/none.js @@ -0,0 +1,3 @@ +import any from "./any.js"; + +export default xs => !any(xs); diff --git a/object/any.js b/object/any.js index 39db7f9d..0d0edf9b 100644 --- a/object/any.js +++ b/object/any.js @@ -1,3 +1,3 @@ import length from "./length.js"; -export default xs => length(xs) > 0; +export default xs => xs && length(xs) > 0; From 89488a44a089ec387da35b606c43268cbd775366 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Mon, 7 Oct 2019 18:39:40 +0200 Subject: [PATCH 52/56] Improve adjust exact and range implementation --- array/exact.js | 7 +++---- array/range.js | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/array/exact.js b/array/exact.js index 0b6e8fac..c5080095 100644 --- a/array/exact.js +++ b/array/exact.js @@ -1,4 +1,3 @@ -export default n => source => - Array(n) - .fill() - .map((_, i) => source[i]); +import range from "./range.js"; + +export default n => xs => range(n).map(index => xs[index]); diff --git a/array/range.js b/array/range.js index 04a9907e..837dd682 100644 --- a/array/range.js +++ b/array/range.js @@ -1,4 +1,4 @@ export default n => Array(n) .fill() - .map((_, i) => i); + .map((_, index) => index); From f31a2e0a072ee919fbb5d2df394bdf2dca7000ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Mon, 7 Oct 2019 18:39:50 +0200 Subject: [PATCH 53/56] Add missing import --- array/reverseIf.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/array/reverseIf.js b/array/reverseIf.js index b718eb60..dacd1541 100644 --- a/array/reverseIf.js +++ b/array/reverseIf.js @@ -1 +1,3 @@ +import reverse from "./reverse.js"; + export default predicate => xs => (predicate ? reverse(xs) : xs); From 1088a053e462f214163769fccd232c1183774dd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Mon, 7 Oct 2019 18:40:19 +0200 Subject: [PATCH 54/56] Use isDefined helper --- debug/diff.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/debug/diff.js b/debug/diff.js index 80a1c0ee..1aa28eaf 100644 --- a/debug/diff.js +++ b/debug/diff.js @@ -1,6 +1,7 @@ import filter from "../object/filter.js"; import none from "../object/none.js"; +import isDefined from "../is/defined.js"; import isArray from "../is/array.js"; import isDate from "../is/date.js"; import isFunction from "../is/function.js"; @@ -26,11 +27,11 @@ const compareValues = (value1, value2) => { return VALUE_UNCHANGED; } - if ("undefined" == typeof value1) { + if (!isDefined(value1)) { return VALUE_CREATED; } - if ("undefined" == typeof value2) { + if (!isDefined(value2)) { return VALUE_DELETED; } @@ -53,20 +54,23 @@ const diff = (obj1, obj2) => { } const result = {}; + for (const key in obj1) { if (isFunction(obj1[key])) { continue; } let value2 = undefined; - if ("undefined" != typeof obj2[key]) { + + if (isDefined(obj2[key])) { value2 = obj2[key]; } result[key] = diff(obj1[key], value2); } + for (const key in obj2) { - if (isFunction(obj2[key]) || "undefined" != typeof result[key]) { + if (isFunction(obj2[key]) || isDefined(result[key])) { continue; } @@ -74,8 +78,7 @@ const diff = (obj1, obj2) => { } return filter( - value => - value !== null && !(value && "object" === typeof value && none(value)) + value => value !== null && !(value && isObject(value) && none(value)) )(result); }; From 011e83aea5d1a307bcc9e190702d3db891aab49b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Tue, 8 Oct 2019 07:57:29 +0200 Subject: [PATCH 55/56] Add array difference and boolean function inversion --- array/difference.js | 5 +++++ array/index.js | 3 +++ function/index.js | 3 +++ function/not.js | 1 + 4 files changed, 12 insertions(+) create mode 100644 array/difference.js create mode 100644 function/not.js diff --git a/array/difference.js b/array/difference.js new file mode 100644 index 00000000..63a40ba6 --- /dev/null +++ b/array/difference.js @@ -0,0 +1,5 @@ +export default (xs, ys) => { + const zs = new Set(ys); + + return xs.filter(x => !zs.has(x)); +}; diff --git a/array/index.js b/array/index.js index 70f2c678..b87ae6d6 100644 --- a/array/index.js +++ b/array/index.js @@ -1,5 +1,6 @@ import any from "./any.js"; import are from "./are.js"; +import difference from "./difference.js"; import differs from "./differs.js"; import duplicates from "./duplicates.js"; import empty from "./empty.js"; @@ -40,6 +41,7 @@ import zipWith from "./zipWith.js"; export { any, are, + difference, differs, duplicates, empty, @@ -81,6 +83,7 @@ export { export default { any, are, + difference, differs, duplicates, empty, diff --git a/function/index.js b/function/index.js index d6b94b43..cec9a17c 100644 --- a/function/index.js +++ b/function/index.js @@ -5,6 +5,7 @@ import memoize from "./memoize.js"; import memoizeShallow from "./memoizeShallow.js"; import memoizeWith from "./memoizeWith.js"; import noOp from "./noOp.js"; +import not from "./not.js"; import pipe from "./pipe.js"; import when from "./when.js"; import whenTrue from "./whenTrue.js"; @@ -17,6 +18,7 @@ export { memoizeShallow, memoizeWith, noOp, + not, pipe, when, whenTrue @@ -30,6 +32,7 @@ export default { memoizeShallow, memoizeWith, noOp, + not, pipe, when, whenTrue diff --git a/function/not.js b/function/not.js new file mode 100644 index 00000000..c3411fce --- /dev/null +++ b/function/not.js @@ -0,0 +1 @@ +export default f => (...args) => !f(...args); From e101e40f681da0f3220de50b310b1acefe34181d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zalewski?= Date: Tue, 8 Oct 2019 08:05:54 +0200 Subject: [PATCH 56/56] Add unique helper --- array/index.js | 3 +++ array/unique.js | 1 + 2 files changed, 4 insertions(+) create mode 100644 array/unique.js diff --git a/array/index.js b/array/index.js index b87ae6d6..db09ff73 100644 --- a/array/index.js +++ b/array/index.js @@ -35,6 +35,7 @@ import single from "./single.js"; import sort from "./sort.js"; import sum from "./sum.js"; import transpose from "./transpose.js"; +import unique from "./unique.js"; import zip from "./zip.js"; import zipWith from "./zipWith.js"; @@ -76,6 +77,7 @@ export { sort, sum, transpose, + unique, zip, zipWith }; @@ -118,6 +120,7 @@ export default { sort, sum, transpose, + unique, zip, zipWith }; diff --git a/array/unique.js b/array/unique.js new file mode 100644 index 00000000..f03af709 --- /dev/null +++ b/array/unique.js @@ -0,0 +1 @@ +export default xs => [...new Set(xs)];