mirror of
https://github.com/toss/es-toolkit.git
synced 2024-11-23 10:06:47 +03:00
1.0.0
This commit is contained in:
commit
7203b56367
98
.circleci/config.yml
Normal file
98
.circleci/config.yml
Normal file
@ -0,0 +1,98 @@
|
||||
version: 2.1
|
||||
|
||||
parameters:
|
||||
pull_request:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
orbs:
|
||||
slack: circleci/slack@4.5.0
|
||||
|
||||
commands:
|
||||
setup:
|
||||
steps:
|
||||
- run:
|
||||
name: Install yarn
|
||||
command: |
|
||||
COREPACK_PATH=$HOME/.local/bin
|
||||
|
||||
mkdir -p $COREPACK_PATH
|
||||
eval "$(echo PATH=$COREPACK_PATH:\$PATH | tee -a $BASH_ENV)"
|
||||
|
||||
corepack enable --install-directory $COREPACK_PATH
|
||||
yarn install
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
docker:
|
||||
- image: cimg/node:20.12
|
||||
steps:
|
||||
- checkout
|
||||
- setup
|
||||
- run:
|
||||
name: Lint
|
||||
command: yarn eslint -c .eslintrc.js $(git diff --name-only --diff-filter=ACMRUXB origin/main | grep -E "(.js$|.ts$|.tsx$)")
|
||||
typecheck:
|
||||
docker:
|
||||
- image: cimg/node:20.12
|
||||
steps:
|
||||
- checkout
|
||||
- setup
|
||||
- run:
|
||||
name: Typecheck
|
||||
command: yarn tsc --noEmit
|
||||
pre-pack:
|
||||
docker:
|
||||
- image: cimg/node:20.12
|
||||
steps:
|
||||
- checkout
|
||||
- setup
|
||||
- run:
|
||||
name: Build
|
||||
command: yarn build
|
||||
check-peer:
|
||||
docker:
|
||||
- image: cimg/node:20.12
|
||||
steps:
|
||||
- checkout
|
||||
- setup
|
||||
- run:
|
||||
name: Check Peer Dependency
|
||||
command: ./.scripts/check-peer.sh || (echo "Peer Dependency 오류가 발생했습니다."; exit -1)
|
||||
test:
|
||||
docker:
|
||||
- image: cimg/node:20.12
|
||||
steps:
|
||||
- checkout
|
||||
- setup
|
||||
- run:
|
||||
name: vitest
|
||||
command: yarn vitest --reporter=junit > ./.junit
|
||||
- store_test_results:
|
||||
path: ./.junit
|
||||
- store_artifacts:
|
||||
path: ./.junit
|
||||
|
||||
workflows:
|
||||
main:
|
||||
jobs:
|
||||
- test:
|
||||
filters:
|
||||
branches:
|
||||
ignore: main
|
||||
- lint:
|
||||
filters:
|
||||
branches:
|
||||
ignore: main
|
||||
- typecheck:
|
||||
filters:
|
||||
branches:
|
||||
ignore: main
|
||||
- pre-pack:
|
||||
filters:
|
||||
branches:
|
||||
ignore: main
|
||||
- check-peer:
|
||||
filters:
|
||||
branches:
|
||||
ignore: main
|
65
.eslintrc.js
Normal file
65
.eslintrc.js
Normal file
@ -0,0 +1,65 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
|
||||
env: {
|
||||
es6: true,
|
||||
node: true,
|
||||
browser: true,
|
||||
jest: true,
|
||||
'shared-node-browser': true,
|
||||
},
|
||||
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
ecmaFeatures: { jsx: true },
|
||||
},
|
||||
|
||||
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
|
||||
plugins: ['@typescript-eslint'],
|
||||
rules: {
|
||||
'no-implicit-coercion': 'error',
|
||||
'no-warning-comments': [
|
||||
'warn',
|
||||
{
|
||||
terms: ['TODO', 'FIXME', 'XXX', 'BUG'],
|
||||
location: 'anywhere',
|
||||
},
|
||||
],
|
||||
curly: ['error', 'all'],
|
||||
eqeqeq: ['error', 'always', { null: 'ignore' }],
|
||||
|
||||
'@typescript-eslint/no-use-before-define': 'off',
|
||||
'@typescript-eslint/no-empty-interface': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/no-parameter-properties': 'off',
|
||||
'@typescript-eslint/no-var-requires': 'warn',
|
||||
'@typescript-eslint/no-non-null-asserted-optional-chain': 'warn',
|
||||
'@typescript-eslint/no-inferrable-types': 'warn',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
'@typescript-eslint/naming-convention': [
|
||||
'error',
|
||||
{ format: ['camelCase', 'UPPER_CASE', 'PascalCase'], selector: 'variable', leadingUnderscore: 'allow' },
|
||||
{ format: ['camelCase', 'PascalCase'], selector: 'function' },
|
||||
{ format: ['PascalCase'], selector: 'interface' },
|
||||
{ format: ['PascalCase'], selector: 'typeAlias' },
|
||||
],
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/array-type': ['error', { default: 'array-simple' }],
|
||||
'@typescript-eslint/no-unused-vars': ['error', { ignoreRestSiblings: true }],
|
||||
'@typescript-eslint/member-ordering': [
|
||||
'error',
|
||||
{
|
||||
default: [
|
||||
'public-static-field',
|
||||
'private-static-field',
|
||||
'public-instance-field',
|
||||
'private-instance-field',
|
||||
'public-constructor',
|
||||
'private-constructor',
|
||||
'public-instance-method',
|
||||
'private-instance-method',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
38
.github/CODE_OF_CONDUCT.md
vendored
Normal file
38
.github/CODE_OF_CONDUCT.md
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
Contributor Covenant Code of Conduct
|
||||
Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
Using welcoming and inclusive language
|
||||
Being respectful of differing viewpoints and experiences
|
||||
Gracefully accepting constructive criticism
|
||||
Focusing on what is best for the community
|
||||
Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
Public or private harassment
|
||||
Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at frontend.devops@toss.im. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
Attribution
|
||||
|
||||
This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at http://contributor-covenant.org/version/1/4
|
78
.github/CONTRIBUTING.md
vendored
Normal file
78
.github/CONTRIBUTING.md
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
# Contributing to es-toolkit
|
||||
|
||||
We welcome contribution from everyone in the community. All communications in this repository will be in English.
|
||||
|
||||
> Every contributor to es-toolkit should adhere to our Code of Conduct. Please read the [full text](./CODE_OF_CONDUCT.md) to understand what actions will and will not be tolerated.
|
||||
|
||||
## 1. Our Design Priniciples
|
||||
|
||||
Note that we value performance, simplicity of implementation, and detailed documentations. We do not aim for supporting a variety of features and options. Our goal is to provide a small set of performant and well-functioning utilities.
|
||||
|
||||
### 1.1 Performance
|
||||
|
||||
All functions es-toolkit provides should be more performant than or similar with that of alternative libraries provide.
|
||||
|
||||
We measure the performance of our library every time our code is edited. We are using [vitest's benchmark feature](https://vitest.dev/api/#bench). For our benchmark code, please refer to our [benchmark directory](https://github.com/toss/es-toolkit/tree/main/benchmarks).
|
||||
|
||||
When a new functionality is added, a benchmark code should be added. Please add screenshots of the benchmarks when opening a pull request for easy reference and history tracking.
|
||||
|
||||
### 1.2 Simplicity
|
||||
|
||||
We value implementation and interface simplicity over a variety of features for performance, code readability, and easy maintenance. Our functions will not provide complex options to suit every usecase.
|
||||
|
||||
In this manner, instead of having complex options of making full use of overloading, etc, to support edge cases, we aim to provide the most simplest interface and implementation for the most common 85% usecases.
|
||||
|
||||
### 1.3 Documentation
|
||||
|
||||
All of our functions should be documented in detail for easy reference. All functions should have the jsdoc and corresponding documents [in our documentation directory](https://github.com/toss/es-toolkit/tree/main/docs) for all of their features.
|
||||
|
||||
We use English as our primary language, but we aim to support Korean documents in our best effort. If you have difficulties writing Korean documents, please let our contributors know so that we can provide the corresponding Korean documents for you.
|
||||
|
||||
## 2. Issues
|
||||
|
||||
You can contribute to es-toolkit via:
|
||||
|
||||
- Improving our [docs](https://es-toolkit.slash.page)
|
||||
- [Reporting a bug in our issues tab](https://github.com/toss/es-toolkit/issues/new/choose)
|
||||
- [Requesting a new feature or package](https://github.com/toss/es-toolkit/issues/new/choose)
|
||||
- [Having a look at our issue list](https://github.com/toss/es-toolkit/issues) to see what's to be fixed
|
||||
|
||||
## 3. Pull Requests
|
||||
|
||||
> [Opening a pull request](https://github.com/toss/es-toolkit/compare) <br/>
|
||||
|
||||
You can raise your own pull request. The title of your pull request should match the following format:
|
||||
|
||||
```
|
||||
<type>[function names]: <description>
|
||||
```
|
||||
|
||||
> We do not care about the number, or style of commits in your history, because we squash merge every PR into main. <br/>
|
||||
> Feel free to commit in whatever style you feel comfortable with.
|
||||
|
||||
### 3.1 Type
|
||||
|
||||
**Type must be one of those**
|
||||
|
||||
if you changed shipped code :
|
||||
|
||||
- feat - for any new functionality additions
|
||||
- fix - for any fixes that don't add new functionality
|
||||
|
||||
if you haven't changed shipped code :
|
||||
|
||||
- docs - if you only change documentation
|
||||
- test - if you only change tests
|
||||
|
||||
other :
|
||||
|
||||
- chore - anything else
|
||||
|
||||
### 3.2 Function Names
|
||||
|
||||
The name of function that you made changes. (ex: debounce, throttle)<br/>
|
||||
If you made changes across multiple packages, writing package scope is optional.
|
||||
|
||||
### 3.3 Description
|
||||
|
||||
A clear and concise description of what the pr is about.
|
21
.github/workflows/broken-link-checker.yml
vendored
Normal file
21
.github/workflows/broken-link-checker.yml
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
name: Broken link checker
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 5 * * 1-5'
|
||||
workflow_dispatch:
|
||||
inputs: { url: { description: 'URL to check', required: false, default: 'https://es-toolkit.slash.page' } }
|
||||
|
||||
jobs:
|
||||
broken-link-checker:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: corepack enable
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: "yarn"
|
||||
cache-dependency-path: "yarn.lock"
|
||||
node-version-file: ".nvmrc"
|
||||
- run: yarn install
|
||||
- run: yarn blc ${{ github.event.inputs.url }} --ro
|
68
.github/workflows/release.yml
vendored
Normal file
68
.github/workflows/release.yml
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "*"
|
||||
tags:
|
||||
- "v*.*.*"
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
deployments: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- run: corepack enable
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: "yarn"
|
||||
cache-dependency-path: "yarn.lock"
|
||||
node-version-file: ".nvmrc"
|
||||
- if: github.ref_type == 'branch'
|
||||
run: |
|
||||
jq \
|
||||
--arg build "$GITHUB_RUN_NUMBER" \
|
||||
--arg commit "${GITHUB_SHA::8}" \
|
||||
'.version = .version + "-dev." + $build + "+" + $commit' \
|
||||
package.json > package.json.tmp
|
||||
mv package.json.tmp package.json
|
||||
- run: yarn install
|
||||
- run: 'mkdir -p out && yarn pack --out out/%s-%v.tgz'
|
||||
- id: extract-changelog
|
||||
uses: dahlia/submark@5a5ff0a58382fb812616a5801402f5aef00f90ce
|
||||
with:
|
||||
input-file: CHANGELOG.md
|
||||
heading-level: 2
|
||||
heading-title-text: version ${{ github.ref_name }}
|
||||
ignore-case: true
|
||||
omit-heading: true
|
||||
- run: "cat ${{ steps.extract-changelog.outputs.output-file }}"
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
body_path: ${{ steps.extract-changelog.outputs.output-file }}
|
||||
repository: toss/es-toolkit
|
||||
generate_release_notes: false
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
files: out/*.tgz
|
||||
- if: |
|
||||
github.event_name == 'push' &&
|
||||
(github.ref_type == 'tag' || github.ref == 'refs/heads/main')
|
||||
run: |
|
||||
set -ex
|
||||
npm config set //registry.npmjs.org/:_authToken "$NPM_AUTH_TOKEN"
|
||||
npm whoami
|
||||
if [[ "$GITHUB_REF_TYPE" = "tag" ]]; then
|
||||
npm publish --access public *.tgz
|
||||
else
|
||||
npm publish --access public --tag dev *.tgz
|
||||
fi
|
||||
env:
|
||||
NPM_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
working-directory: ${{ github.workspace }}/out/
|
18
.gitignore
vendored
Normal file
18
.gitignore
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
.DS_Store
|
||||
|
||||
.yarn/*
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/sdks
|
||||
!.yarn/versions
|
||||
|
||||
.pnp.cjs
|
||||
.pnp.loader.mjs
|
||||
|
||||
node_modules
|
||||
coverage
|
||||
dist
|
||||
esm
|
||||
.junit
|
||||
out
|
1
.npmignore
Normal file
1
.npmignore
Normal file
@ -0,0 +1 @@
|
||||
.nvmrc
|
8
.scripts/check-peer.sh
Executable file
8
.scripts/check-peer.sh
Executable file
@ -0,0 +1,8 @@
|
||||
OUT=$(yarn | grep -E "(YN0002|YN0059|YN0060)" | grep -E $1)
|
||||
if [ -z "$OUT" ]; then
|
||||
echo "No Peer Dependency Errors Found."
|
||||
else
|
||||
echo "$OUT"
|
||||
echo "Some peer dependencies are incorrectly met; run yarn explain peer-requirements <hash> for details, where <hash> is the six-letter p-prefixed code"
|
||||
exit 1
|
||||
fi
|
7
.vscode/extensions.json
vendored
Normal file
7
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"arcanis.vscode-zipfs",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"esbenp.prettier-vscode"
|
||||
]
|
||||
}
|
10
.vscode/settings.json
vendored
Normal file
10
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"search.exclude": {
|
||||
"**/.yarn": true,
|
||||
"**/.pnp.*": true
|
||||
},
|
||||
"eslint.nodePath": ".yarn/sdks",
|
||||
"prettier.prettierPath": ".yarn/sdks/prettier/index.cjs",
|
||||
"typescript.tsdk": ".yarn/sdks/typescript/lib",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true
|
||||
}
|
20
.yarn/sdks/eslint/bin/eslint.js
vendored
Executable file
20
.yarn/sdks/eslint/bin/eslint.js
vendored
Executable file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
|
||||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require eslint/bin/eslint.js
|
||||
require(absPnpApiPath).setup();
|
||||
}
|
||||
}
|
||||
|
||||
// Defer to the real eslint/bin/eslint.js your application uses
|
||||
module.exports = absRequire(`eslint/bin/eslint.js`);
|
20
.yarn/sdks/eslint/lib/api.js
vendored
Normal file
20
.yarn/sdks/eslint/lib/api.js
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
|
||||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require eslint
|
||||
require(absPnpApiPath).setup();
|
||||
}
|
||||
}
|
||||
|
||||
// Defer to the real eslint your application uses
|
||||
module.exports = absRequire(`eslint`);
|
20
.yarn/sdks/eslint/lib/unsupported-api.js
vendored
Normal file
20
.yarn/sdks/eslint/lib/unsupported-api.js
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
|
||||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require eslint/use-at-your-own-risk
|
||||
require(absPnpApiPath).setup();
|
||||
}
|
||||
}
|
||||
|
||||
// Defer to the real eslint/use-at-your-own-risk your application uses
|
||||
module.exports = absRequire(`eslint/use-at-your-own-risk`);
|
14
.yarn/sdks/eslint/package.json
vendored
Normal file
14
.yarn/sdks/eslint/package.json
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "eslint",
|
||||
"version": "8.57.0-sdk",
|
||||
"main": "./lib/api.js",
|
||||
"type": "commonjs",
|
||||
"bin": {
|
||||
"eslint": "./bin/eslint.js"
|
||||
},
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": "./lib/api.js",
|
||||
"./use-at-your-own-risk": "./lib/unsupported-api.js"
|
||||
}
|
||||
}
|
5
.yarn/sdks/integrations.yml
vendored
Normal file
5
.yarn/sdks/integrations.yml
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
# This file is automatically generated by @yarnpkg/sdks.
|
||||
# Manual changes might be lost!
|
||||
|
||||
integrations:
|
||||
- vscode
|
20
.yarn/sdks/prettier/bin/prettier.cjs
vendored
Executable file
20
.yarn/sdks/prettier/bin/prettier.cjs
vendored
Executable file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
|
||||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require prettier/bin/prettier.cjs
|
||||
require(absPnpApiPath).setup();
|
||||
}
|
||||
}
|
||||
|
||||
// Defer to the real prettier/bin/prettier.cjs your application uses
|
||||
module.exports = absRequire(`prettier/bin/prettier.cjs`);
|
20
.yarn/sdks/prettier/index.cjs
vendored
Normal file
20
.yarn/sdks/prettier/index.cjs
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
|
||||
const relPnpApiPath = "../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require prettier
|
||||
require(absPnpApiPath).setup();
|
||||
}
|
||||
}
|
||||
|
||||
// Defer to the real prettier your application uses
|
||||
module.exports = absRequire(`prettier`);
|
7
.yarn/sdks/prettier/package.json
vendored
Normal file
7
.yarn/sdks/prettier/package.json
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "prettier",
|
||||
"version": "3.2.5-sdk",
|
||||
"main": "./index.cjs",
|
||||
"type": "commonjs",
|
||||
"bin": "./bin/prettier.cjs"
|
||||
}
|
20
.yarn/sdks/typescript/bin/tsc
vendored
Executable file
20
.yarn/sdks/typescript/bin/tsc
vendored
Executable file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
|
||||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require typescript/bin/tsc
|
||||
require(absPnpApiPath).setup();
|
||||
}
|
||||
}
|
||||
|
||||
// Defer to the real typescript/bin/tsc your application uses
|
||||
module.exports = absRequire(`typescript/bin/tsc`);
|
20
.yarn/sdks/typescript/bin/tsserver
vendored
Executable file
20
.yarn/sdks/typescript/bin/tsserver
vendored
Executable file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
|
||||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require typescript/bin/tsserver
|
||||
require(absPnpApiPath).setup();
|
||||
}
|
||||
}
|
||||
|
||||
// Defer to the real typescript/bin/tsserver your application uses
|
||||
module.exports = absRequire(`typescript/bin/tsserver`);
|
20
.yarn/sdks/typescript/lib/tsc.js
vendored
Normal file
20
.yarn/sdks/typescript/lib/tsc.js
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
|
||||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require typescript/lib/tsc.js
|
||||
require(absPnpApiPath).setup();
|
||||
}
|
||||
}
|
||||
|
||||
// Defer to the real typescript/lib/tsc.js your application uses
|
||||
module.exports = absRequire(`typescript/lib/tsc.js`);
|
225
.yarn/sdks/typescript/lib/tsserver.js
vendored
Normal file
225
.yarn/sdks/typescript/lib/tsserver.js
vendored
Normal file
@ -0,0 +1,225 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
|
||||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const moduleWrapper = tsserver => {
|
||||
if (!process.versions.pnp) {
|
||||
return tsserver;
|
||||
}
|
||||
|
||||
const {isAbsolute} = require(`path`);
|
||||
const pnpApi = require(`pnpapi`);
|
||||
|
||||
const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
|
||||
const isPortal = str => str.startsWith("portal:/");
|
||||
const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
|
||||
|
||||
const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
|
||||
return `${locator.name}@${locator.reference}`;
|
||||
}));
|
||||
|
||||
// VSCode sends the zip paths to TS using the "zip://" prefix, that TS
|
||||
// doesn't understand. This layer makes sure to remove the protocol
|
||||
// before forwarding it to TS, and to add it back on all returned paths.
|
||||
|
||||
function toEditorPath(str) {
|
||||
// We add the `zip:` prefix to both `.zip/` paths and virtual paths
|
||||
if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) {
|
||||
// We also take the opportunity to turn virtual paths into physical ones;
|
||||
// this makes it much easier to work with workspaces that list peer
|
||||
// dependencies, since otherwise Ctrl+Click would bring us to the virtual
|
||||
// file instances instead of the real ones.
|
||||
//
|
||||
// We only do this to modules owned by the the dependency tree roots.
|
||||
// This avoids breaking the resolution when jumping inside a vendor
|
||||
// with peer dep (otherwise jumping into react-dom would show resolution
|
||||
// errors on react).
|
||||
//
|
||||
const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
|
||||
if (resolved) {
|
||||
const locator = pnpApi.findPackageLocator(resolved);
|
||||
if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) {
|
||||
str = resolved;
|
||||
}
|
||||
}
|
||||
|
||||
str = normalize(str);
|
||||
|
||||
if (str.match(/\.zip\//)) {
|
||||
switch (hostInfo) {
|
||||
// Absolute VSCode `Uri.fsPath`s need to start with a slash.
|
||||
// VSCode only adds it automatically for supported schemes,
|
||||
// so we have to do it manually for the `zip` scheme.
|
||||
// The path needs to start with a caret otherwise VSCode doesn't handle the protocol
|
||||
//
|
||||
// Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
|
||||
//
|
||||
// 2021-10-08: VSCode changed the format in 1.61.
|
||||
// Before | ^zip:/c:/foo/bar.zip/package.json
|
||||
// After | ^/zip//c:/foo/bar.zip/package.json
|
||||
//
|
||||
// 2022-04-06: VSCode changed the format in 1.66.
|
||||
// Before | ^/zip//c:/foo/bar.zip/package.json
|
||||
// After | ^/zip/c:/foo/bar.zip/package.json
|
||||
//
|
||||
// 2022-05-06: VSCode changed the format in 1.68
|
||||
// Before | ^/zip/c:/foo/bar.zip/package.json
|
||||
// After | ^/zip//c:/foo/bar.zip/package.json
|
||||
//
|
||||
case `vscode <1.61`: {
|
||||
str = `^zip:${str}`;
|
||||
} break;
|
||||
|
||||
case `vscode <1.66`: {
|
||||
str = `^/zip/${str}`;
|
||||
} break;
|
||||
|
||||
case `vscode <1.68`: {
|
||||
str = `^/zip${str}`;
|
||||
} break;
|
||||
|
||||
case `vscode`: {
|
||||
str = `^/zip/${str}`;
|
||||
} break;
|
||||
|
||||
// To make "go to definition" work,
|
||||
// We have to resolve the actual file system path from virtual path
|
||||
// and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
|
||||
case `coc-nvim`: {
|
||||
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
|
||||
str = resolve(`zipfile:${str}`);
|
||||
} break;
|
||||
|
||||
// Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server)
|
||||
// We have to resolve the actual file system path from virtual path,
|
||||
// everything else is up to neovim
|
||||
case `neovim`: {
|
||||
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
|
||||
str = `zipfile://${str}`;
|
||||
} break;
|
||||
|
||||
default: {
|
||||
str = `zip:${str}`;
|
||||
} break;
|
||||
}
|
||||
} else {
|
||||
str = str.replace(/^\/?/, process.platform === `win32` ? `` : `/`);
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
function fromEditorPath(str) {
|
||||
switch (hostInfo) {
|
||||
case `coc-nvim`: {
|
||||
str = str.replace(/\.zip::/, `.zip/`);
|
||||
// The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
|
||||
// So in order to convert it back, we use .* to match all the thing
|
||||
// before `zipfile:`
|
||||
return process.platform === `win32`
|
||||
? str.replace(/^.*zipfile:\//, ``)
|
||||
: str.replace(/^.*zipfile:/, ``);
|
||||
} break;
|
||||
|
||||
case `neovim`: {
|
||||
str = str.replace(/\.zip::/, `.zip/`);
|
||||
// The path for neovim is in format of zipfile:///<pwd>/.yarn/...
|
||||
return str.replace(/^zipfile:\/\//, ``);
|
||||
} break;
|
||||
|
||||
case `vscode`:
|
||||
default: {
|
||||
return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`)
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
// Force enable 'allowLocalPluginLoads'
|
||||
// TypeScript tries to resolve plugins using a path relative to itself
|
||||
// which doesn't work when using the global cache
|
||||
// https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238
|
||||
// VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but
|
||||
// TypeScript already does local loads and if this code is running the user trusts the workspace
|
||||
// https://github.com/microsoft/vscode/issues/45856
|
||||
const ConfiguredProject = tsserver.server.ConfiguredProject;
|
||||
const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype;
|
||||
ConfiguredProject.prototype.enablePluginsWithOptions = function() {
|
||||
this.projectService.allowLocalPluginLoads = true;
|
||||
return originalEnablePluginsWithOptions.apply(this, arguments);
|
||||
};
|
||||
|
||||
// And here is the point where we hijack the VSCode <-> TS communications
|
||||
// by adding ourselves in the middle. We locate everything that looks
|
||||
// like an absolute path of ours and normalize it.
|
||||
|
||||
const Session = tsserver.server.Session;
|
||||
const {onMessage: originalOnMessage, send: originalSend} = Session.prototype;
|
||||
let hostInfo = `unknown`;
|
||||
|
||||
Object.assign(Session.prototype, {
|
||||
onMessage(/** @type {string | object} */ message) {
|
||||
const isStringMessage = typeof message === 'string';
|
||||
const parsedMessage = isStringMessage ? JSON.parse(message) : message;
|
||||
|
||||
if (
|
||||
parsedMessage != null &&
|
||||
typeof parsedMessage === `object` &&
|
||||
parsedMessage.arguments &&
|
||||
typeof parsedMessage.arguments.hostInfo === `string`
|
||||
) {
|
||||
hostInfo = parsedMessage.arguments.hostInfo;
|
||||
if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) {
|
||||
const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match(
|
||||
// The RegExp from https://semver.org/ but without the caret at the start
|
||||
/(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
|
||||
) ?? []).map(Number)
|
||||
|
||||
if (major === 1) {
|
||||
if (minor < 61) {
|
||||
hostInfo += ` <1.61`;
|
||||
} else if (minor < 66) {
|
||||
hostInfo += ` <1.66`;
|
||||
} else if (minor < 68) {
|
||||
hostInfo += ` <1.68`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
|
||||
return typeof value === 'string' ? fromEditorPath(value) : value;
|
||||
});
|
||||
|
||||
return originalOnMessage.call(
|
||||
this,
|
||||
isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON)
|
||||
);
|
||||
},
|
||||
|
||||
send(/** @type {any} */ msg) {
|
||||
return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => {
|
||||
return typeof value === `string` ? toEditorPath(value) : value;
|
||||
})));
|
||||
}
|
||||
});
|
||||
|
||||
return tsserver;
|
||||
};
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require typescript/lib/tsserver.js
|
||||
require(absPnpApiPath).setup();
|
||||
}
|
||||
}
|
||||
|
||||
// Defer to the real typescript/lib/tsserver.js your application uses
|
||||
module.exports = moduleWrapper(absRequire(`typescript/lib/tsserver.js`));
|
225
.yarn/sdks/typescript/lib/tsserverlibrary.js
vendored
Normal file
225
.yarn/sdks/typescript/lib/tsserverlibrary.js
vendored
Normal file
@ -0,0 +1,225 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
|
||||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const moduleWrapper = tsserver => {
|
||||
if (!process.versions.pnp) {
|
||||
return tsserver;
|
||||
}
|
||||
|
||||
const {isAbsolute} = require(`path`);
|
||||
const pnpApi = require(`pnpapi`);
|
||||
|
||||
const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
|
||||
const isPortal = str => str.startsWith("portal:/");
|
||||
const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
|
||||
|
||||
const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
|
||||
return `${locator.name}@${locator.reference}`;
|
||||
}));
|
||||
|
||||
// VSCode sends the zip paths to TS using the "zip://" prefix, that TS
|
||||
// doesn't understand. This layer makes sure to remove the protocol
|
||||
// before forwarding it to TS, and to add it back on all returned paths.
|
||||
|
||||
function toEditorPath(str) {
|
||||
// We add the `zip:` prefix to both `.zip/` paths and virtual paths
|
||||
if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) {
|
||||
// We also take the opportunity to turn virtual paths into physical ones;
|
||||
// this makes it much easier to work with workspaces that list peer
|
||||
// dependencies, since otherwise Ctrl+Click would bring us to the virtual
|
||||
// file instances instead of the real ones.
|
||||
//
|
||||
// We only do this to modules owned by the the dependency tree roots.
|
||||
// This avoids breaking the resolution when jumping inside a vendor
|
||||
// with peer dep (otherwise jumping into react-dom would show resolution
|
||||
// errors on react).
|
||||
//
|
||||
const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
|
||||
if (resolved) {
|
||||
const locator = pnpApi.findPackageLocator(resolved);
|
||||
if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) {
|
||||
str = resolved;
|
||||
}
|
||||
}
|
||||
|
||||
str = normalize(str);
|
||||
|
||||
if (str.match(/\.zip\//)) {
|
||||
switch (hostInfo) {
|
||||
// Absolute VSCode `Uri.fsPath`s need to start with a slash.
|
||||
// VSCode only adds it automatically for supported schemes,
|
||||
// so we have to do it manually for the `zip` scheme.
|
||||
// The path needs to start with a caret otherwise VSCode doesn't handle the protocol
|
||||
//
|
||||
// Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
|
||||
//
|
||||
// 2021-10-08: VSCode changed the format in 1.61.
|
||||
// Before | ^zip:/c:/foo/bar.zip/package.json
|
||||
// After | ^/zip//c:/foo/bar.zip/package.json
|
||||
//
|
||||
// 2022-04-06: VSCode changed the format in 1.66.
|
||||
// Before | ^/zip//c:/foo/bar.zip/package.json
|
||||
// After | ^/zip/c:/foo/bar.zip/package.json
|
||||
//
|
||||
// 2022-05-06: VSCode changed the format in 1.68
|
||||
// Before | ^/zip/c:/foo/bar.zip/package.json
|
||||
// After | ^/zip//c:/foo/bar.zip/package.json
|
||||
//
|
||||
case `vscode <1.61`: {
|
||||
str = `^zip:${str}`;
|
||||
} break;
|
||||
|
||||
case `vscode <1.66`: {
|
||||
str = `^/zip/${str}`;
|
||||
} break;
|
||||
|
||||
case `vscode <1.68`: {
|
||||
str = `^/zip${str}`;
|
||||
} break;
|
||||
|
||||
case `vscode`: {
|
||||
str = `^/zip/${str}`;
|
||||
} break;
|
||||
|
||||
// To make "go to definition" work,
|
||||
// We have to resolve the actual file system path from virtual path
|
||||
// and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
|
||||
case `coc-nvim`: {
|
||||
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
|
||||
str = resolve(`zipfile:${str}`);
|
||||
} break;
|
||||
|
||||
// Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server)
|
||||
// We have to resolve the actual file system path from virtual path,
|
||||
// everything else is up to neovim
|
||||
case `neovim`: {
|
||||
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
|
||||
str = `zipfile://${str}`;
|
||||
} break;
|
||||
|
||||
default: {
|
||||
str = `zip:${str}`;
|
||||
} break;
|
||||
}
|
||||
} else {
|
||||
str = str.replace(/^\/?/, process.platform === `win32` ? `` : `/`);
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
function fromEditorPath(str) {
|
||||
switch (hostInfo) {
|
||||
case `coc-nvim`: {
|
||||
str = str.replace(/\.zip::/, `.zip/`);
|
||||
// The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
|
||||
// So in order to convert it back, we use .* to match all the thing
|
||||
// before `zipfile:`
|
||||
return process.platform === `win32`
|
||||
? str.replace(/^.*zipfile:\//, ``)
|
||||
: str.replace(/^.*zipfile:/, ``);
|
||||
} break;
|
||||
|
||||
case `neovim`: {
|
||||
str = str.replace(/\.zip::/, `.zip/`);
|
||||
// The path for neovim is in format of zipfile:///<pwd>/.yarn/...
|
||||
return str.replace(/^zipfile:\/\//, ``);
|
||||
} break;
|
||||
|
||||
case `vscode`:
|
||||
default: {
|
||||
return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`)
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
// Force enable 'allowLocalPluginLoads'
|
||||
// TypeScript tries to resolve plugins using a path relative to itself
|
||||
// which doesn't work when using the global cache
|
||||
// https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238
|
||||
// VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but
|
||||
// TypeScript already does local loads and if this code is running the user trusts the workspace
|
||||
// https://github.com/microsoft/vscode/issues/45856
|
||||
const ConfiguredProject = tsserver.server.ConfiguredProject;
|
||||
const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype;
|
||||
ConfiguredProject.prototype.enablePluginsWithOptions = function() {
|
||||
this.projectService.allowLocalPluginLoads = true;
|
||||
return originalEnablePluginsWithOptions.apply(this, arguments);
|
||||
};
|
||||
|
||||
// And here is the point where we hijack the VSCode <-> TS communications
|
||||
// by adding ourselves in the middle. We locate everything that looks
|
||||
// like an absolute path of ours and normalize it.
|
||||
|
||||
const Session = tsserver.server.Session;
|
||||
const {onMessage: originalOnMessage, send: originalSend} = Session.prototype;
|
||||
let hostInfo = `unknown`;
|
||||
|
||||
Object.assign(Session.prototype, {
|
||||
onMessage(/** @type {string | object} */ message) {
|
||||
const isStringMessage = typeof message === 'string';
|
||||
const parsedMessage = isStringMessage ? JSON.parse(message) : message;
|
||||
|
||||
if (
|
||||
parsedMessage != null &&
|
||||
typeof parsedMessage === `object` &&
|
||||
parsedMessage.arguments &&
|
||||
typeof parsedMessage.arguments.hostInfo === `string`
|
||||
) {
|
||||
hostInfo = parsedMessage.arguments.hostInfo;
|
||||
if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) {
|
||||
const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match(
|
||||
// The RegExp from https://semver.org/ but without the caret at the start
|
||||
/(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
|
||||
) ?? []).map(Number)
|
||||
|
||||
if (major === 1) {
|
||||
if (minor < 61) {
|
||||
hostInfo += ` <1.61`;
|
||||
} else if (minor < 66) {
|
||||
hostInfo += ` <1.66`;
|
||||
} else if (minor < 68) {
|
||||
hostInfo += ` <1.68`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
|
||||
return typeof value === 'string' ? fromEditorPath(value) : value;
|
||||
});
|
||||
|
||||
return originalOnMessage.call(
|
||||
this,
|
||||
isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON)
|
||||
);
|
||||
},
|
||||
|
||||
send(/** @type {any} */ msg) {
|
||||
return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => {
|
||||
return typeof value === `string` ? toEditorPath(value) : value;
|
||||
})));
|
||||
}
|
||||
});
|
||||
|
||||
return tsserver;
|
||||
};
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require typescript/lib/tsserverlibrary.js
|
||||
require(absPnpApiPath).setup();
|
||||
}
|
||||
}
|
||||
|
||||
// Defer to the real typescript/lib/tsserverlibrary.js your application uses
|
||||
module.exports = moduleWrapper(absRequire(`typescript/lib/tsserverlibrary.js`));
|
20
.yarn/sdks/typescript/lib/typescript.js
vendored
Normal file
20
.yarn/sdks/typescript/lib/typescript.js
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
|
||||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require typescript
|
||||
require(absPnpApiPath).setup();
|
||||
}
|
||||
}
|
||||
|
||||
// Defer to the real typescript your application uses
|
||||
module.exports = absRequire(`typescript`);
|
10
.yarn/sdks/typescript/package.json
vendored
Normal file
10
.yarn/sdks/typescript/package.json
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "typescript",
|
||||
"version": "5.4.5-sdk",
|
||||
"main": "./lib/typescript.js",
|
||||
"type": "commonjs",
|
||||
"bin": {
|
||||
"tsc": "./bin/tsc",
|
||||
"tsserver": "./bin/tsserver"
|
||||
}
|
||||
}
|
5
CHANGELOG.md
Normal file
5
CHANGELOG.md
Normal file
@ -0,0 +1,5 @@
|
||||
# es-toolkit Changelog
|
||||
|
||||
## Version v1.0.0
|
||||
|
||||
Initial release. Released on May 31th, 2024.
|
31
README-ko_kr.md
Normal file
31
README-ko_kr.md
Normal file
@ -0,0 +1,31 @@
|
||||
![](./docs/public/og.png)
|
||||
|
||||
# es-toolkit · [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/toss/slash/blob/main/LICENSE)
|
||||
|
||||
[English](./README.md) | 한국어
|
||||
|
||||
es-toolkit은 높은 성능과 작은 번들 사이즈, 강력한 타입을 자랑하는 현대적인 JavaScript 유틸리티 라이브러리예요.
|
||||
|
||||
- es-toolkit은 매일 사용하는 다양한 유틸리티 함수를 현대적인 구현으로 제공해요. 예를 들어, [debounce](https://es-toolkit.slash.page/reference/function/debounce.html), [delay](https://es-toolkit.slash.page/reference/promise/delay.html), [chunk](https://es-toolkit.slash.page/reference/array/chunk.html), [sum](https://es-toolkit.slash.page/reference/math/sum.html), [pick](https://es-toolkit.slash.page/reference/object/pick.html) 같은 함수들이 있어요.
|
||||
- 설계할 때 퍼포먼스를 중요 원칙으로 두어, es-toolkit은 현대적인 JavaScript 환경에서 [2-3배 빠른 성능](https://es-toolkit.slash.page/ko/performance.html)을 보여요.
|
||||
- es-toolkit은 트리 셰이킹을 기본으로 지원하며, 함수에 따라서는 다른 라이브러리와 비교했을 때 [최대 97% 작은 JavaScript 번들 사이즈](https://es-toolkit.slash.page/ko/bundle-size.html)를 제공해요.
|
||||
- es-toolkit은 TypeScript 타입이 내장되어 있고, 직관적이고 정확한 타입을 추구해요. [isNotNil](https://es-toolkit.slash.page/ko/reference/predicate/isNotNil.html) 같은 사용하기 편리한 유틸리티 함수도 제공해요.
|
||||
- es-toolkit은 100% 테스트 커버리지를 유지하면서, 높은 안정성을 자랑해요.
|
||||
|
||||
|
||||
## 기여하기
|
||||
|
||||
커뮤니티에 있는 모든 분들에게 기여를 환영해요. 아래에 작성되어 있는 기여 가이드를 확인하세요.
|
||||
|
||||
[CONTRIBUTING](./.github/CONTRIBUTING.md)
|
||||
|
||||
## 라이선스
|
||||
|
||||
MIT © Viva Republica, Inc. 자세한 내용은 [LICENSE](./LICENSE)를 참고하세요.
|
||||
|
||||
<a title="Toss" href="https://toss.im">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://static.toss.im/logos/png/4x/logo-toss-reverse.png">
|
||||
<img alt="Toss" src="https://static.toss.im/logos/png/4x/logo-toss.png" width="100">
|
||||
</picture>
|
||||
</a>
|
31
README.md
Normal file
31
README.md
Normal file
@ -0,0 +1,31 @@
|
||||
![](./docs/public/og.png)
|
||||
|
||||
# es-toolkit · [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/toss/slash/blob/main/LICENSE)
|
||||
|
||||
English | [한국어](./README-ko_kr.md)
|
||||
|
||||
es-toolkit is a state-of-the-art, high-performance JavaScript utility library with a small bundle size and strong type annotations.
|
||||
|
||||
- es-toolkit offers a variety of everyday utility functions with modern implementations, such as [debounce](https://es-toolkit.slash.page/reference/function/debounce.html), [delay](https://es-toolkit.slash.page/reference/promise/delay.html), [chunk](https://es-toolkit.slash.page/reference/array/chunk.html), [sum](https://es-toolkit.slash.page/reference/math/sum.html), and [pick](https://es-toolkit.slash.page/reference/object/pick.html).
|
||||
- Designed with performance in mind, es-toolkit achieves [2-3× better performance](https://es-toolkit.slash.page/performance.html) in modern JavaScript environments.
|
||||
- es-toolkit supports tree shaking out of the box, and [reduces JavaScript code by up to 97%](https://es-toolkit.slash.page/bundle-size.html) compared to other libraries.
|
||||
- es-toolkit includes built-in TypeScript support, with straightforward yet robust types. It also provides useful type guards such as [isNotNil](https://es-toolkit.slash.page/reference/predicate/isNotNil.html).
|
||||
- es-toolkit is battle-tested with 100% test coverage, ensuring reliability and robustness.
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome contribution from everyone in the community. Read below for detailed contribution guide.
|
||||
|
||||
[CONTRIBUTING](./.github/CONTRIBUTING.md)
|
||||
|
||||
## License
|
||||
|
||||
MIT © Viva Republica, Inc. See [LICENSE](./LICENSE) for details.
|
||||
|
||||
<a title="Toss" href="https://toss.im">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://static.toss.im/logos/png/4x/logo-toss-reverse.png">
|
||||
<img alt="Toss" src="https://static.toss.im/logos/png/4x/logo-toss.png" width="100">
|
||||
</picture>
|
||||
</a>
|
6
babel.config.js
Normal file
6
babel.config.js
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
require.resolve('@babel/preset-env'),
|
||||
require.resolve('@babel/preset-typescript'),
|
||||
],
|
||||
};
|
13
benchmarks/chunk.bench.ts
Normal file
13
benchmarks/chunk.bench.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { chunk as chunkToolkit } from 'es-toolkit';
|
||||
import { chunk as chunkLodash } from 'lodash';
|
||||
|
||||
describe('chunk', () => {
|
||||
bench('es-toolkit', () => {
|
||||
chunkToolkit([1, 2, 3, 4, 5, 6], 3);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
chunkLodash([1, 2, 3, 4, 5, 6], 3);
|
||||
})
|
||||
});
|
15
benchmarks/clamp.bench.ts
Normal file
15
benchmarks/clamp.bench.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { clamp as clampToolkit } from 'es-toolkit';
|
||||
import { clamp as clampLodash } from 'lodash';
|
||||
|
||||
describe('clamp', () => {
|
||||
bench('es-toolkit', () => {
|
||||
clampToolkit(10, 5, 15)
|
||||
clampToolkit(10, 5)
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
clampLodash(10, 5, 15)
|
||||
clampLodash(10, 5)
|
||||
})
|
||||
});
|
13
benchmarks/difference.bench.ts
Normal file
13
benchmarks/difference.bench.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { difference as differenceToolkit } from 'es-toolkit';
|
||||
import { difference as differenceLodash } from 'lodash';
|
||||
|
||||
describe('difference', () => {
|
||||
bench('es-toolkit', () => {
|
||||
differenceToolkit([1, 2, 3], [2]);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
differenceLodash([1, 2, 3], [2]);
|
||||
})
|
||||
});
|
13
benchmarks/differenceBy.bench.ts
Normal file
13
benchmarks/differenceBy.bench.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { differenceBy as differenceByToolkit } from 'es-toolkit';
|
||||
import { differenceBy as differenceByLodash } from 'lodash';
|
||||
|
||||
describe('differenceBy', () => {
|
||||
bench('es-toolkit', () => {
|
||||
differenceByToolkit([1.2, 2.3, 3.4], [1.2], Math.floor);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
differenceByLodash([1.2, 2.3, 3.4], [1.2], Math.floor);
|
||||
})
|
||||
});
|
13
benchmarks/differenceWith.bench.ts
Normal file
13
benchmarks/differenceWith.bench.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { differenceWith as differenceWithToolkit } from 'es-toolkit';
|
||||
import { differenceWith as differenceWithLodash } from 'lodash';
|
||||
|
||||
describe('differenceWith', () => {
|
||||
bench('es-toolkit', () => {
|
||||
differenceWithToolkit([1.2, 2.3, 3.4], [1.2], (x, y) => Math.floor(x) === Math.floor(y));
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
differenceWithLodash([1.2, 2.3, 3.4], [1.2], (x, y) => Math.floor(x) === Math.floor(y));
|
||||
})
|
||||
});
|
13
benchmarks/drop.bench.ts
Normal file
13
benchmarks/drop.bench.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { drop as dropToolkit } from 'es-toolkit';
|
||||
import { drop as dropLodash } from 'lodash';
|
||||
|
||||
describe('drop', () => {
|
||||
bench('es-toolkit', () => {
|
||||
dropToolkit([1, 2, 3, 4, 5, 6], 3);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
dropLodash([1, 2, 3, 4, 5, 6], 3);
|
||||
})
|
||||
});
|
13
benchmarks/dropRight.bench.ts
Normal file
13
benchmarks/dropRight.bench.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { dropRight as dropRightToolkit } from 'es-toolkit';
|
||||
import { dropRight as dropRightLodash } from 'lodash';
|
||||
|
||||
describe('dropRight', () => {
|
||||
bench('es-toolkit', () => {
|
||||
dropRightToolkit([1, 2, 3, 4, 5, 6], 3);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
dropRightLodash([1, 2, 3, 4, 5, 6], 3);
|
||||
})
|
||||
});
|
13
benchmarks/dropRightWhile.bench.ts
Normal file
13
benchmarks/dropRightWhile.bench.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { dropRightWhile as dropRightWhileToolkit } from 'es-toolkit';
|
||||
import { dropRightWhile as dropRightWhileLodash } from 'lodash';
|
||||
|
||||
describe('dropRightWhile', () => {
|
||||
bench('es-toolkit', () => {
|
||||
dropRightWhileToolkit([1.2, 2.3, 3.4], x => x < 2);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
dropRightWhileLodash([1.2, 2.3, 3.4], x => x < 2);
|
||||
})
|
||||
});
|
13
benchmarks/dropWhile.bench.ts
Normal file
13
benchmarks/dropWhile.bench.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { dropWhile as dropWhileToolkit } from 'es-toolkit';
|
||||
import { dropWhile as dropWhileLodash } from 'lodash';
|
||||
|
||||
describe('dropWhile', () => {
|
||||
bench('es-toolkit', () => {
|
||||
dropWhileToolkit([1.2, 2.3, 3.4], x => x < 2);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
dropWhileLodash([1.2, 2.3, 3.4], x => x < 2);
|
||||
})
|
||||
});
|
29
benchmarks/groupBy.bench.ts
Normal file
29
benchmarks/groupBy.bench.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { groupBy as groupByToolkit } from 'es-toolkit';
|
||||
import { groupBy as groupByLodash } from 'lodash';
|
||||
|
||||
describe('groupBy', () => {
|
||||
bench('es-toolkit', () => {
|
||||
const array = [
|
||||
{ category: 'fruit', name: 'apple' },
|
||||
{ category: 'fruit', name: 'banana' },
|
||||
{ category: 'vegetable', name: 'carrot' },
|
||||
{ category: 'fruit', name: 'pear' },
|
||||
{ category: 'vegetable', name: 'broccoli' }
|
||||
];
|
||||
|
||||
groupByToolkit(array, item => item.category);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
const array = [
|
||||
{ category: 'fruit', name: 'apple' },
|
||||
{ category: 'fruit', name: 'banana' },
|
||||
{ category: 'vegetable', name: 'carrot' },
|
||||
{ category: 'fruit', name: 'pear' },
|
||||
{ category: 'vegetable', name: 'broccoli' }
|
||||
];
|
||||
|
||||
groupByLodash(array, item => item.category);
|
||||
})
|
||||
});
|
13
benchmarks/intersection.bench.ts
Normal file
13
benchmarks/intersection.bench.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { intersection as intersectionToolkit } from 'es-toolkit';
|
||||
import { intersection as intersectionLodash } from 'lodash';
|
||||
|
||||
describe('intersection', () => {
|
||||
bench('es-toolkit', () => {
|
||||
intersectionToolkit([1, 2, 3], [2, 4]);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
intersectionLodash([1, 2, 3], [2, 4]);
|
||||
})
|
||||
});
|
19
benchmarks/intersectionBy.bench.ts
Normal file
19
benchmarks/intersectionBy.bench.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { intersectionBy as intersectionByToolkit } from 'es-toolkit';
|
||||
import { intersectionBy as intersectionByLodash } from 'lodash';
|
||||
|
||||
describe('intersectionBy', () => {
|
||||
bench('es-toolkit', () => {
|
||||
const array1 = [{ id: 1 }, { id: 2 }, { id: 3 }];
|
||||
const array2 = [{ id: 2 }, { id: 4 }];
|
||||
const mapper = item => item.id;
|
||||
intersectionByToolkit(array1, array2, mapper);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
const array1 = [{ id: 1 }, { id: 2 }, { id: 3 }];
|
||||
const array2 = [{ id: 2 }, { id: 4 }];
|
||||
const mapper = item => item.id;
|
||||
intersectionByLodash(array1, array2, mapper);
|
||||
})
|
||||
});
|
19
benchmarks/intersectionWith.bench.ts
Normal file
19
benchmarks/intersectionWith.bench.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { intersectionWith as intersectionWithToolkit } from 'es-toolkit';
|
||||
import { intersectionWith as intersectionWithLodash } from 'lodash';
|
||||
|
||||
describe('intersectionWith', () => {
|
||||
bench('es-toolkit', () => {
|
||||
const array1 = [{ id: 1 }, { id: 2 }, { id: 3 }];
|
||||
const array2 = [{ id: 2 }, { id: 4 }];
|
||||
const areItemsEqual = (a, b) => a.id === b.id;
|
||||
intersectionWithToolkit(array1, array2, areItemsEqual);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
const array1 = [{ id: 1 }, { id: 2 }, { id: 3 }];
|
||||
const array2 = [{ id: 2 }, { id: 4 }];
|
||||
const areItemsEqual = (a, b) => a.id === b.id;
|
||||
intersectionWithLodash(array1, array2, areItemsEqual);
|
||||
})
|
||||
});
|
19
benchmarks/isNil.bench.ts
Normal file
19
benchmarks/isNil.bench.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { isNil as isNilToolkit } from 'es-toolkit';
|
||||
import { isNil as isNilLodash } from 'lodash';
|
||||
|
||||
describe('isNil', () => {
|
||||
bench('es-toolkit', () => {
|
||||
isNilToolkit(null);
|
||||
isNilToolkit(undefined);
|
||||
isNilToolkit(123);
|
||||
isNilToolkit([1, 2, 3]);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
isNilLodash(null);
|
||||
isNilLodash(undefined);
|
||||
isNilLodash(123);
|
||||
isNilLodash([1, 2, 3]);
|
||||
})
|
||||
});
|
13
benchmarks/omit.bench.ts
Normal file
13
benchmarks/omit.bench.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { omit as omitToolkit } from 'es-toolkit';
|
||||
import { omit as omitLodash } from 'lodash';
|
||||
|
||||
describe('omit', () => {
|
||||
bench('es-toolkit', () => {
|
||||
omitToolkit({ foo: 1, bar: 2, baz: 3 }, ['foo', 'bar'])
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
omitLodash({ foo: 1, bar: 2, baz: 3 }, ['foo', 'bar'])
|
||||
})
|
||||
});
|
17
benchmarks/omitBy.bench.ts
Normal file
17
benchmarks/omitBy.bench.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { omitBy as omitByToolkit } from 'es-toolkit';
|
||||
import { omitBy as omitByLodash } from 'lodash';
|
||||
|
||||
describe('omitBy', () => {
|
||||
bench('es-toolkit', () => {
|
||||
const obj = { a: 1, b: 'omit', c: 3 };
|
||||
const shouldOmit = (value: number | string, key: string) => typeof value === 'string';
|
||||
omitByToolkit(obj, shouldOmit);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
const obj = { a: 1, b: 'omit', c: 3 };
|
||||
const shouldOmit = (value: number | string, key: string) => typeof value === 'string';
|
||||
omitByLodash(obj, shouldOmit);
|
||||
})
|
||||
});
|
13
benchmarks/partition.bench.ts
Normal file
13
benchmarks/partition.bench.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { partition as partitionToolkit } from 'es-toolkit';
|
||||
import { partition as partitionLodash } from 'lodash';
|
||||
|
||||
describe('partition', () => {
|
||||
bench('es-toolkit', () => {
|
||||
partitionToolkit([1, 2, 3, 4, 5], x => x < 3);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
partitionLodash([1, 2, 3], x => x < 3);
|
||||
})
|
||||
});
|
13
benchmarks/pick.bench.ts
Normal file
13
benchmarks/pick.bench.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { pick as pickToolkit } from 'es-toolkit';
|
||||
import { pick as pickLodash } from 'lodash';
|
||||
|
||||
describe('pick', () => {
|
||||
bench('es-toolkit', () => {
|
||||
pickToolkit({ foo: 1, bar: 2, baz: 3 }, ['foo', 'bar'])
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
pickLodash({ foo: 1, bar: 2, baz: 3 }, ['foo', 'bar'])
|
||||
})
|
||||
});
|
13
benchmarks/round.bench.ts
Normal file
13
benchmarks/round.bench.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { round as roundToolkit } from 'es-toolkit';
|
||||
import { round as roundLodash } from 'lodash';
|
||||
|
||||
describe('round', () => {
|
||||
bench('es-toolkit', () => {
|
||||
roundToolkit(1.2345, 2);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
roundLodash(1.2345, 2);
|
||||
})
|
||||
});
|
15
benchmarks/sample.bench.ts
Normal file
15
benchmarks/sample.bench.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { sample as sampleToolkit } from 'es-toolkit';
|
||||
import { sample as sampleLodash } from 'lodash';
|
||||
|
||||
describe('sample', () => {
|
||||
bench('es-toolkit', () => {
|
||||
const array = [1, 2, 3, 4, 5];
|
||||
sampleToolkit(array);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
const array = [1, 2, 3, 4, 5];
|
||||
sampleLodash(array);
|
||||
})
|
||||
});
|
15
benchmarks/shuffle.bench.ts
Normal file
15
benchmarks/shuffle.bench.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { shuffle as shuffleToolkit } from 'es-toolkit';
|
||||
import { shuffle as shuffleLodash } from 'lodash';
|
||||
|
||||
describe('shuffle', () => {
|
||||
bench('es-toolkit', () => {
|
||||
const array = [1, 2, 3, 4, 5];
|
||||
shuffleToolkit(array);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
const array = [1, 2, 3, 4, 5];
|
||||
shuffleLodash(array);
|
||||
})
|
||||
});
|
13
benchmarks/sum.bench.ts
Normal file
13
benchmarks/sum.bench.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { sum as sumToolkit } from 'es-toolkit';
|
||||
import { sum as sumLodash } from 'lodash';
|
||||
|
||||
describe('sum', () => {
|
||||
bench('es-toolkit', () => {
|
||||
sumToolkit([1, 2, 3]);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
sumLodash([1, 2, 3]);
|
||||
})
|
||||
});
|
13
benchmarks/take.bench.ts
Normal file
13
benchmarks/take.bench.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { take as takeToolkit } from 'es-toolkit';
|
||||
import { take as takeLodash } from 'lodash';
|
||||
|
||||
describe('take', () => {
|
||||
bench('es-toolkit', () => {
|
||||
takeToolkit([1, 2, 3, 4], 2);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
takeLodash([1, 2, 3, 4], 2);
|
||||
})
|
||||
});
|
13
benchmarks/takeRight.bench.ts
Normal file
13
benchmarks/takeRight.bench.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { takeRight as takeRightToolkit } from 'es-toolkit';
|
||||
import { takeRight as takeRightLodash } from 'lodash';
|
||||
|
||||
describe('takeRight', () => {
|
||||
bench('es-toolkit', () => {
|
||||
takeRightToolkit([1, 2, 3, 4], 2);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
takeRightLodash([1, 2, 3, 4], 2);
|
||||
})
|
||||
});
|
13
benchmarks/takeRightWhile.bench.ts
Normal file
13
benchmarks/takeRightWhile.bench.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { takeRightWhile as takeRightWhileToolkit } from 'es-toolkit';
|
||||
import { takeRightWhile as takeRightWhileLodash } from 'lodash';
|
||||
|
||||
describe('takeRightWhile', () => {
|
||||
bench('es-toolkit', () => {
|
||||
takeRightWhileToolkit([5, 4, 3, 2, 1], n => n < 4);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
takeRightWhileLodash([5, 4, 3, 2, 1], n => n < 4);
|
||||
})
|
||||
});
|
13
benchmarks/takeWhile.bench.ts
Normal file
13
benchmarks/takeWhile.bench.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { takeWhile as takeWhileToolkit } from 'es-toolkit';
|
||||
import { takeWhile as takeWhileLodash } from 'lodash';
|
||||
|
||||
describe('takeWhile', () => {
|
||||
bench('es-toolkit', () => {
|
||||
takeWhileToolkit([5, 4, 3, 2, 1], n => n < 4);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
takeWhileLodash([5, 4, 3, 2, 1], n => n < 4);
|
||||
})
|
||||
});
|
17
benchmarks/union.bench.ts
Normal file
17
benchmarks/union.bench.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { union as unionToolkit } from 'es-toolkit';
|
||||
import { union as unionLodash } from 'lodash';
|
||||
|
||||
describe('union', () => {
|
||||
bench('es-toolkit', () => {
|
||||
const array1 = [1, 2, 3];
|
||||
const array2 = [3, 4, 5];
|
||||
const result = unionToolkit(array1, array2);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
const array1 = [1, 2, 3];
|
||||
const array2 = [3, 4, 5];
|
||||
const result = unionLodash(array1, array2);
|
||||
})
|
||||
});
|
13
benchmarks/unionBy.bench.ts
Normal file
13
benchmarks/unionBy.bench.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { unionBy as unionByToolkit } from 'es-toolkit';
|
||||
import { unionBy as unionByLodash } from 'lodash';
|
||||
|
||||
describe('unionBy', () => {
|
||||
bench('es-toolkit', () => {
|
||||
unionByToolkit([{ id: 1 }, { id: 2 }], [{ id: 2 }, { id: 3 }], x => x.id);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
unionByLodash([{ id: 1 }, { id: 2 }], [{ id: 2 }, { id: 3 }], x => x.id);
|
||||
})
|
||||
});
|
19
benchmarks/unionWith.bench.ts
Normal file
19
benchmarks/unionWith.bench.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { unionWith as unionWithToolkit } from 'es-toolkit';
|
||||
import { unionWith as unionWithLodash } from 'lodash';
|
||||
|
||||
describe('unionWith', () => {
|
||||
bench('es-toolkit', () => {
|
||||
const array1 = [{ id: 1 }, { id: 2 }];
|
||||
const array2 = [{ id: 2 }, { id: 3 }];
|
||||
const areItemsEqual = (a, b) => a.id === b.id;
|
||||
unionWithToolkit(array1, array2, areItemsEqual);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
const array1 = [{ id: 1 }, { id: 2 }];
|
||||
const array2 = [{ id: 2 }, { id: 3 }];
|
||||
const areItemsEqual = (a, b) => a.id === b.id;
|
||||
unionWithLodash(array1, array2, areItemsEqual);
|
||||
})
|
||||
});
|
13
benchmarks/uniq.bench.ts
Normal file
13
benchmarks/uniq.bench.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { uniq as uniqToolkit } from 'es-toolkit';
|
||||
import { uniq as uniqLodash } from 'lodash';
|
||||
|
||||
describe('uniq', () => {
|
||||
bench('es-toolkit', () => {
|
||||
uniqToolkit([11, 2, 3, 44, 11, 2, 3]);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
uniqLodash([11, 2, 3, 44, 11, 2, 3]);
|
||||
})
|
||||
});
|
13
benchmarks/xor.bench.ts
Normal file
13
benchmarks/xor.bench.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { xor as xorToolkit } from 'es-toolkit';
|
||||
import { xor as xorLodash } from 'lodash';
|
||||
|
||||
describe('xor', () => {
|
||||
bench('es-toolkit', () => {
|
||||
xorToolkit([1, 2, 3, 4], [3, 4, 5, 6]);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
xorLodash([1, 2, 3, 4], [3, 4, 5, 6]);
|
||||
})
|
||||
});
|
15
benchmarks/xorBy.bench.ts
Normal file
15
benchmarks/xorBy.bench.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { xorBy as xorByToolkit } from 'es-toolkit';
|
||||
import { xorBy as xorByLodash } from 'lodash';
|
||||
|
||||
describe('xorBy', () => {
|
||||
bench('es-toolkit', () => {
|
||||
const idMapper = obj => obj.id;
|
||||
xorByToolkit([{ id: 1 }, { id: 2 }], [{ id: 2 }, { id: 3 }], idMapper);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
const idMapper = obj => obj.id;
|
||||
xorByLodash([{ id: 1 }, { id: 2 }], [{ id: 2 }, { id: 3 }], idMapper);
|
||||
})
|
||||
});
|
14
benchmarks/xorWith.bench.ts
Normal file
14
benchmarks/xorWith.bench.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { xorWith as xorWithToolkit } from 'es-toolkit';
|
||||
import { xorWith as xorWithLodash } from 'lodash';
|
||||
|
||||
describe('xorWith', () => {
|
||||
bench('es-toolkit', () => {
|
||||
xorWithToolkit([{ id: 1 }, { id: 2 }], [{ id: 2 }, { id: 3 }], (x, y) => x.id === y.id);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
const idMapper = obj => obj.id;
|
||||
xorWithLodash([{ id: 1 }, { id: 2 }], [{ id: 2 }, { id: 3 }], (x, y) => x.id === y.id);
|
||||
})
|
||||
});
|
13
benchmarks/zip.bench.ts
Normal file
13
benchmarks/zip.bench.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { zip as zipToolkit } from 'es-toolkit';
|
||||
import { zip as zipLodash } from 'lodash';
|
||||
|
||||
describe('zip', () => {
|
||||
bench('es-toolkit', () => {
|
||||
zipToolkit([1, 2, 3, 4], [3, 4, 5, 6]);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
zipLodash([1, 2, 3, 4], [3, 4, 5, 6]);
|
||||
})
|
||||
});
|
19
benchmarks/zipWith.bench.ts
Normal file
19
benchmarks/zipWith.bench.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { zipWith as zipWithToolkit } from 'es-toolkit';
|
||||
import { zipWith as zipWithLodash } from 'lodash';
|
||||
|
||||
describe('zipWith', () => {
|
||||
bench('es-toolkit', () => {
|
||||
const arr1 = [1, 2];
|
||||
const arr2 = [3, 4];
|
||||
const arr3 = [5, 6];
|
||||
zipWithToolkit(arr1, arr2, arr3, (a, b, c) => `${a}${b}${c}`);
|
||||
})
|
||||
|
||||
bench('lodash', () => {
|
||||
const arr1 = [1, 2];
|
||||
const arr2 = [3, 4];
|
||||
const arr3 = [5, 6];
|
||||
zipWithLodash(arr1, arr2, arr3, (a, b, c) => `${a}${b}${c}`);
|
||||
})
|
||||
});
|
1
docs/.gitignore
vendored
Normal file
1
docs/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
.vitepress/cache
|
13
docs/.vitepress/config.mts
Normal file
13
docs/.vitepress/config.mts
Normal file
@ -0,0 +1,13 @@
|
||||
import { defineConfig } from 'vitepress';
|
||||
import { en } from './en.mts';
|
||||
import { ko } from './ko.mts';
|
||||
import { shared } from './shared.mts';
|
||||
|
||||
export default defineConfig({
|
||||
...shared,
|
||||
locales: {
|
||||
root: { label: 'English', ...en },
|
||||
ko: { label: '한국어', ...ko }
|
||||
},
|
||||
})
|
||||
|
122
docs/.vitepress/en.mts
Normal file
122
docs/.vitepress/en.mts
Normal file
@ -0,0 +1,122 @@
|
||||
import { defineConfig, type DefaultTheme } from 'vitepress'
|
||||
|
||||
export const en = defineConfig({
|
||||
lang: 'en',
|
||||
description: 'A state-of-the-art, high-performance JavaScript utility library with a small bundle size and strong type annotations.',
|
||||
|
||||
themeConfig: {
|
||||
nav: nav(),
|
||||
|
||||
sidebar: sidebar(),
|
||||
|
||||
editLink: {
|
||||
pattern: 'https://github.com/toss/es-toolkit/edit/main/docs/:path',
|
||||
text: 'Edit this page on GitHub'
|
||||
},
|
||||
|
||||
footer: {
|
||||
message: 'Released under the MIT License.',
|
||||
copyright: `Copyright © ${new Date().getFullYear()} Viva Republica, Inc.`
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function nav(): DefaultTheme.NavItem[] {
|
||||
return [
|
||||
{ text: 'Home', link: '/' },
|
||||
{ text: 'Introduction', link: '/intro' },
|
||||
{ text: 'Reference', link: '/reference/array/chunk' },
|
||||
]
|
||||
}
|
||||
|
||||
function sidebar(): DefaultTheme.Sidebar {
|
||||
return [
|
||||
{
|
||||
text: 'Guide',
|
||||
items: [
|
||||
{ text: 'Introduction', link: '/intro' },
|
||||
{ text: 'Installation', link: '/installation' },
|
||||
{ text: 'Impact on Bundle Size', link: '/bundle-size' },
|
||||
{ text: 'Performance', link: '/performance' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Reference',
|
||||
items: [
|
||||
{
|
||||
text: 'Array Utilities',
|
||||
items: [
|
||||
{ text: 'chunk', link: '/reference/array/chunk' },
|
||||
{ text: 'difference', link: '/reference/array/difference' },
|
||||
{ text: 'differenceBy', link: '/reference/array/differenceBy' },
|
||||
{ text: 'differenceWith', link: '/reference/array/differenceWith' },
|
||||
{ text: 'drop', link: '/reference/array/drop' },
|
||||
{ text: 'dropWhile', link: '/reference/array/dropWhile' },
|
||||
{ text: 'dropRight', link: '/reference/array/dropRight' },
|
||||
{ text: 'dropRightWhile', link: '/reference/array/dropRightWhile' },
|
||||
{ text: 'groupBy', link: '/reference/array/groupBy' },
|
||||
{ text: 'intersection', link: '/reference/array/intersection' },
|
||||
{ text: 'intersectionBy', link: '/reference/array/intersectionBy' },
|
||||
{ text: 'intersectionWith', link: '/reference/array/intersectionWith' },
|
||||
{ text: 'partition', link: '/reference/array/partition' },
|
||||
{ text: 'sample', link: '/reference/array/sample' },
|
||||
{ text: 'shuffle', link: '/reference/array/shuffle' },
|
||||
{ text: 'take', link: '/reference/array/take' },
|
||||
{ text: 'takeWhile', link: '/reference/array/takeWhile' },
|
||||
{ text: 'takeRight', link: '/reference/array/takeRight' },
|
||||
{ text: 'takeRightWhile', link: '/reference/array/takeRightWhile' },
|
||||
{ text: 'union', link: '/reference/array/union' },
|
||||
{ text: 'unionBy', link: '/reference/array/unionBy' },
|
||||
{ text: 'unionWith', link: '/reference/array/unionWith' },
|
||||
{ text: 'uniq', link: '/reference/array/uniq' },
|
||||
{ text: 'xor', link: '/reference/array/xor' },
|
||||
{ text: 'xorBy', link: '/reference/array/xorBy' },
|
||||
{ text: 'xorWith', link: '/reference/array/xorWith' },
|
||||
{ text: 'zip', link: '/reference/array/zip' },
|
||||
{ text: 'zipWith', link: '/reference/array/zipWith' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Function Utilities',
|
||||
items: [
|
||||
{ text: 'debounce', link: '/reference/function/debounce' },
|
||||
{ text: 'throttle', link: '/reference/function/throttle' },
|
||||
{ text: 'once', link: '/reference/function/once' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Math Utilities',
|
||||
items: [
|
||||
{ text: 'clamp', link: '/reference/math/clamp' },
|
||||
{ text: 'round', link: '/reference/math/round' },
|
||||
{ text: 'sum', link: '/reference/math/sum' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Object Utilities',
|
||||
items: [
|
||||
{ text: 'omit', link: '/reference/object/omit' },
|
||||
{ text: 'omitBy', link: '/reference/object/omitBy' },
|
||||
{ text: 'pick', link: '/reference/object/pick' },
|
||||
{ text: 'pickBy', link: '/reference/object/pickBy' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Predicates',
|
||||
items: [
|
||||
{ text: 'isNil', link: '/reference/predicate/isNil' },
|
||||
{ text: 'isNotNil', link: '/reference/predicate/isNotNil' },
|
||||
{ text: 'isNull', link: '/reference/predicate/isNull' },
|
||||
{ text: 'isUndefined', link: '/reference/predicate/isUndefined' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Promise Utilities',
|
||||
items: [
|
||||
{ text: 'delay', link: '/reference/promise/delay' },
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
149
docs/.vitepress/ko.mts
Normal file
149
docs/.vitepress/ko.mts
Normal file
@ -0,0 +1,149 @@
|
||||
import { defineConfig, type DefaultTheme } from 'vitepress'
|
||||
|
||||
export const ko = defineConfig({
|
||||
lang: 'ko',
|
||||
description: '빠른 성능, 작은 번들 사이즈를 가지는 현대적인 JavaScript 유틸리티 라이브러리',
|
||||
|
||||
themeConfig: {
|
||||
nav: nav(),
|
||||
|
||||
sidebar: sidebar(),
|
||||
|
||||
editLink: {
|
||||
pattern: 'https://github.com/toss/es-toolkit/edit/main/docs/:path',
|
||||
text: 'GitHub에서 수정하기'
|
||||
},
|
||||
|
||||
footer: {
|
||||
message: 'MIT 라이선스에 따라 배포됩니다.',
|
||||
copyright: `Copyright © ${new Date().getFullYear()} Viva Republica, Inc.`
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function nav(): DefaultTheme.NavItem[] {
|
||||
return [
|
||||
{ text: '홈', link: '/ko' },
|
||||
{ text: '소개', link: '/ko/intro' },
|
||||
{ text: '레퍼런스', link: '/ko/reference/array/chunk' },
|
||||
]
|
||||
}
|
||||
|
||||
function sidebar(): DefaultTheme.Sidebar {
|
||||
return [
|
||||
{
|
||||
text: '가이드',
|
||||
items: [
|
||||
{ text: '소개', link: '/ko/intro' },
|
||||
{ text: '설치', link: '/ko/installation' },
|
||||
{ text: '번들 사이즈', link: '/ko/bundle-size' },
|
||||
{ text: '성능', link: '/ko/performance' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: '레퍼런스',
|
||||
items: [
|
||||
{
|
||||
text: '배열',
|
||||
items: [
|
||||
{ text: 'chunk', link: '/ko/reference/array/chunk' },
|
||||
{ text: 'difference', link: '/ko/reference/array/difference' },
|
||||
{ text: 'differenceBy', link: '/ko/reference/array/differenceBy' },
|
||||
{ text: 'differenceWith', link: '/ko/reference/array/differenceWith' },
|
||||
{ text: 'drop', link: '/ko/reference/array/drop' },
|
||||
{ text: 'dropRight', link: '/ko/reference/array/dropRight' },
|
||||
{ text: 'dropWhile', link: '/ko/reference/array/dropWhile' },
|
||||
{ text: 'dropRightWhile', link: '/ko/reference/array/dropRightWhile' },
|
||||
{ text: 'groupBy', link: '/ko/reference/array/groupBy' },
|
||||
{ text: 'intersection', link: '/ko/reference/array/intersection' },
|
||||
{ text: 'intersectionBy', link: '/ko/reference/array/intersectionBy' },
|
||||
{ text: 'intersectionWith', link: '/ko/reference/array/intersectionWith' },
|
||||
{ text: 'partition', link: '/ko/reference/array/partition' },
|
||||
{ text: 'sample', link: '/ko/reference/array/sample' },
|
||||
{ text: 'shuffle', link: '/ko/reference/array/shuffle' },
|
||||
{ text: 'take', link: '/ko/reference/array/take' },
|
||||
{ text: 'takeWhile', link: '/ko/reference/array/takeWhile' },
|
||||
{ text: 'takeRight', link: '/ko/reference/array/takeRight' },
|
||||
{ text: 'takeRightWhile', link: '/ko/reference/array/takeRightWhile' },
|
||||
{ text: 'union', link: '/ko/reference/array/union' },
|
||||
{ text: 'unionBy', link: '/ko/reference/array/unionBy' },
|
||||
{ text: 'unionWith', link: '/ko/reference/array/unionWith' },
|
||||
{ text: 'uniq', link: '/ko/reference/array/uniq' },
|
||||
{ text: 'xor', link: '/ko/reference/array/xor' },
|
||||
{ text: 'xorBy', link: '/ko/reference/array/xorBy' },
|
||||
{ text: 'xorWith', link: '/ko/reference/array/xorWith' },
|
||||
{ text: 'zip', link: '/ko/reference/array/zip' },
|
||||
{ text: 'zipWith', link: '/ko/reference/array/zipWith' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: '함수',
|
||||
items: [
|
||||
{ text: 'debounce', link: '/ko/reference/function/debounce' },
|
||||
{ text: 'throttle', link: '/ko/reference/function/throttle' },
|
||||
{ text: 'once', link: '/ko/reference/function/once' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: '숫자',
|
||||
items: [
|
||||
{ text: 'clamp', link: '/ko/reference/math/clamp' },
|
||||
{ text: 'round', link: '/ko/reference/math/round' },
|
||||
{ text: 'sum', link: '/ko/reference/math/sum' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: '객체',
|
||||
items: [
|
||||
{ text: 'omit', link: '/ko/reference/object/omit' },
|
||||
{ text: 'omitBy', link: '/ko/reference/object/omitBy' },
|
||||
{ text: 'pick', link: '/ko/reference/object/pick' },
|
||||
{ text: 'pickBy', link: '/ko/reference/object/pickBy' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: '타입 가드',
|
||||
items: [
|
||||
{ text: 'isNil', link: '/ko/reference/predicate/isNil' },
|
||||
{ text: 'isNotNil', link: '/ko/reference/predicate/isNotNil' },
|
||||
{ text: 'isNull', link: '/ko/reference/predicate/isNull' },
|
||||
{ text: 'isUndefined', link: '/ko/reference/predicate/isUndefined' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Promise',
|
||||
items: [
|
||||
{ text: 'delay', link: '/ko/reference/promise/delay' },
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
export const search: DefaultTheme.LocalSearchOptions["locales"] = {
|
||||
ko: {
|
||||
translations: {
|
||||
button: {
|
||||
buttonText: '검색',
|
||||
buttonAriaLabel: '검색',
|
||||
},
|
||||
modal: {
|
||||
backButtonTitle: '뒤로가기',
|
||||
displayDetails: '더보기',
|
||||
footer: {
|
||||
closeKeyAriaLabel: '닫기',
|
||||
closeText: '닫기',
|
||||
navigateDownKeyAriaLabel: '아래로',
|
||||
navigateText: '이동',
|
||||
navigateUpKeyAriaLabel: '위로',
|
||||
selectKeyAriaLabel: '선택',
|
||||
selectText: '선택',
|
||||
},
|
||||
noResultsText: '검색 결과를 찾지 못했어요.',
|
||||
resetButtonTitle: '모두 지우기',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
82
docs/.vitepress/shared.mts
Normal file
82
docs/.vitepress/shared.mts
Normal file
@ -0,0 +1,82 @@
|
||||
import { createRequire } from 'module';
|
||||
import path from 'path';
|
||||
import { defineConfig } from 'vitepress';
|
||||
import { search as koSearch } from './ko.mts';
|
||||
|
||||
const require = createRequire(import.meta.url)
|
||||
|
||||
export const shared = defineConfig({
|
||||
title: 'es-toolkit',
|
||||
|
||||
lastUpdated: true,
|
||||
metaChunk: true,
|
||||
|
||||
/* prettier-ignore */
|
||||
head: [
|
||||
[
|
||||
"link",
|
||||
{
|
||||
rel: "icon",
|
||||
type: "image/png",
|
||||
sizes: "100x100",
|
||||
href: "/favicon-100x100.png",
|
||||
},
|
||||
],
|
||||
[
|
||||
"link",
|
||||
{
|
||||
rel: "stylesheet",
|
||||
href: "https://static.toss.im/tps/main.css"
|
||||
}
|
||||
],
|
||||
[
|
||||
"link",
|
||||
{
|
||||
rel: "stylesheet",
|
||||
href: "https://static.toss.im/tps/others.css"
|
||||
}
|
||||
],
|
||||
[
|
||||
"meta",
|
||||
{
|
||||
property: "og:image",
|
||||
content: "/og.png",
|
||||
},
|
||||
],
|
||||
],
|
||||
|
||||
themeConfig: {
|
||||
logo: {
|
||||
dark: '/logo_white.png',
|
||||
light: '/logo_black.png',
|
||||
},
|
||||
|
||||
siteTitle: false,
|
||||
|
||||
search: {
|
||||
provider: 'local',
|
||||
options: {
|
||||
locales: {
|
||||
...koSearch,
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
socialLinks: [
|
||||
{ icon: 'github', link: 'https://github.com/toss/es-toolkit' }
|
||||
],
|
||||
},
|
||||
|
||||
vite: {
|
||||
resolve: {
|
||||
alias: {
|
||||
'vue': path.dirname(require.resolve('vue/package.json', {
|
||||
paths: [require.resolve('vitepress')],
|
||||
})),
|
||||
'vue/server-renderer': path.dirname(require.resolve('vue/server-renderer', {
|
||||
paths: [require.resolve('vitepress')],
|
||||
})),
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
8
docs/.vitepress/theme/index.css
Normal file
8
docs/.vitepress/theme/index.css
Normal file
@ -0,0 +1,8 @@
|
||||
:root {
|
||||
--vp-nav-logo-height: 16px;
|
||||
--vp-font-family-base: "Toss Product Sans", ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
}
|
||||
|
||||
:root[lang=ko] {
|
||||
word-break: keep-all;
|
||||
}
|
4
docs/.vitepress/theme/index.js
Normal file
4
docs/.vitepress/theme/index.js
Normal file
@ -0,0 +1,4 @@
|
||||
import DefaultTheme from 'vitepress/theme'
|
||||
import './index.css'
|
||||
|
||||
export default DefaultTheme
|
24
docs/bundle-size.md
Normal file
24
docs/bundle-size.md
Normal file
@ -0,0 +1,24 @@
|
||||
---
|
||||
description: The minimal bundle footprint offered by es-toolkit
|
||||
---
|
||||
Bundle Footprint
|
||||
============
|
||||
|
||||
![Graph showing the difference in bundle size between es-toolkit and lodash. There is a difference up to 97% in bundle size.](/assets/bundle-size.png)
|
||||
|
||||
With its modern implementation, es-toolkit significantly reduces its bundle size, cutting it down by up to 97% compared to other libraries like lodash.
|
||||
|
||||
This makes es-toolkit the most efficient in terms of bundle size, with some utility functions being as small as less than 100 bytes.
|
||||
|
||||
## Bundle Footprint Comparison
|
||||
|
||||
| | es-toolkit@0.0.1 | lodash-es@4.17.21 | Difference |
|
||||
|-----------------------------------------------|------------------|--------------------|------------|
|
||||
| [sample](./reference/array/sample) | 88 bytes | 2000 bytes | -95.6% |
|
||||
| [difference](./reference/array/difference) | 91 bytes | 3190 bytes | -97.2% |
|
||||
| [sum](./reference/math/sum) | 152 bytes | 413 bytes | -63.2% |
|
||||
| [debounce](./reference/function/debounce) | 144 bytes | 1400 bytes | -89.7% |
|
||||
| [throttle](./reference/function/throttle) | 110 bytes | 1460 bytes | -92.5% |
|
||||
| [pick](./reference/object/pick) | 657 bytes | 3860 bytes | -83.0% |
|
||||
| [zip](./reference/array/zip) | 797 bytes | 1790 bytes | -55.5% |
|
||||
|
32
docs/index.md
Normal file
32
docs/index.md
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
# https://vitepress.dev/reference/default-theme-home-page
|
||||
layout: home
|
||||
|
||||
hero:
|
||||
name: "es-toolkit"
|
||||
text: "State-of-the-art JavaScript utility library"
|
||||
# tagline:
|
||||
actions:
|
||||
- theme: brand
|
||||
text: About es-toolkit
|
||||
link: /intro
|
||||
- theme: alt
|
||||
text: Reference
|
||||
link: /reference/array/chunk
|
||||
- theme: alt
|
||||
text: Installation
|
||||
link: /installation
|
||||
|
||||
features:
|
||||
- title: Best performance
|
||||
details: es-toolkit delivers 2-3× better performance in modern JavaScript runtimes compared to other libraries.
|
||||
- title: Small bundle footprint
|
||||
details: es-toolkit ships up to 97% less JavaScript code compared to other alternative libraries.
|
||||
- title: Modern implementation
|
||||
details: es-toolkit fully leverages modern JavaScript APIs for straightforward and error-free implementation.
|
||||
- title: Robust types
|
||||
details: es-toolkit offers simple yet robust types for all functions.
|
||||
- title: Battle-tested
|
||||
details: es-toolkit has 100% test coverage, ensuring maximum robustness.
|
||||
---
|
||||
|
44
docs/installation.md
Normal file
44
docs/installation.md
Normal file
@ -0,0 +1,44 @@
|
||||
---
|
||||
description: How to install es-toolkit
|
||||
prev:
|
||||
text: Introduction to es-toolkit
|
||||
link: ./intro.md
|
||||
next:
|
||||
text: Impact on Bundle Size
|
||||
link: ./bundle-size
|
||||
---
|
||||
Installation
|
||||
============
|
||||
|
||||
es-toolkit is available on [npm](https://npmjs.com/package/es-toolkit) for Node.js, Deno, and Bun.
|
||||
|
||||
|
||||
Node.js
|
||||
---
|
||||
es-toolkit supports Node.js 18 or later. Install es-toolkit with the following command:
|
||||
|
||||
```sh
|
||||
npm install es-toolkit
|
||||
yarn add es-toolkit
|
||||
pnpm install es-toolkit
|
||||
```
|
||||
|
||||
|
||||
Deno
|
||||
----
|
||||
|
||||
es-toolkit is also available on npm for Deno. Use es-toolkit with the `npm:` specifier:
|
||||
|
||||
```typescript
|
||||
import { chunk } from 'npm:es-toolkit@1.0.0';
|
||||
```
|
||||
|
||||
|
||||
Bun
|
||||
---
|
||||
|
||||
es-toolkit is also available on Bun. You can install it via the following command:
|
||||
|
||||
```sh
|
||||
bun add es-toolkit
|
||||
```
|
26
docs/intro.md
Normal file
26
docs/intro.md
Normal file
@ -0,0 +1,26 @@
|
||||
About es-toolkit
|
||||
===============
|
||||
|
||||
es-toolkit is a modern JavaScript utility library that offers a collection of powerful functions for everyday use.
|
||||
|
||||
Compared to alternatives like lodash, es-toolkit provides a [significantly smaller bundle size](./bundle-size.md) (up to 97% less) and [2-3 times faster runtime performance](./performance.md). This is achieved through a modern implementation that leverages the latest JavaScript features.
|
||||
|
||||
es-toolkit comes with built-in TypeScript types and has been rigorously tested, ensuring 100% test coverage for maximum reliability.
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
Here are some of the features es-toolkit offers:
|
||||
|
||||
- **Array**: Utilities for array manipulation, such as [uniq](./reference/array/uniq.md) and [difference](./reference/array/difference.md).
|
||||
- **Function**: Tools for controlling function execution, including [debounce](./reference/function/debounce.md) and [throttle](./reference/function/throttle.md).
|
||||
- **Math**: Numerical utilities like [sum](./reference/math/sum.md) and [round](./reference/math/round.md).
|
||||
- **Object**: Tools for manipulating JavaScript objects, such as [pick](./reference/object/pick.md) and [omit](./reference/object/omit.md).
|
||||
- **Predicate**: Type guard functions like [isNotNil](./reference/predicate/isNotNil.md).
|
||||
- **Promise**: Asynchronous utilities like [delay](./reference/promise/delay.md).
|
||||
|
||||
## Links
|
||||
|
||||
Please refer to the following links for more information about this project.
|
||||
|
||||
- [GitHub](https://github.com/toss/es-toolkit)
|
24
docs/ko/bundle-size.md
Normal file
24
docs/ko/bundle-size.md
Normal file
@ -0,0 +1,24 @@
|
||||
---
|
||||
description: es-toolkit이 가지는 작은 번들 사이즈
|
||||
---
|
||||
번들 사이즈
|
||||
============
|
||||
|
||||
![es-toolkit과 lodash의 번들 사이즈를 비교하는 그래프. es-toolkit이 최대 97% 작은 번들 사이즈를 가진다.](/assets/bundle-size.png)
|
||||
|
||||
es-toolkit은 현대적인 구현을 가지고 있기 때문에, 다른 라이브러리에 비해서 매우 작은 번들 사이즈를 가져요. [lodash](https://lodash.com)와 비교했을 때, 함수에 따라서는 최대 97% 작은 크기를 가져요.
|
||||
|
||||
이런 측면에서, es-toolkit은 번들 사이즈를 줄이는 데에 가장 효율적인 선택이에요. 어떤 유틸리티 함수는 100바이트보다 작은 크기를 가져요.
|
||||
|
||||
## 번들 사이즈 비교
|
||||
|
||||
| | es-toolkit@0.0.1 | lodash-es@4.17.21 | 차이 |
|
||||
|-----------------------------------------------|------------------|--------------------|------------|
|
||||
| [sample](./reference/array/sample.md) | 88 bytes | 2000 bytes | -95.6% |
|
||||
| [difference](./reference/array/difference.md) | 91 bytes | 3190 bytes | -97.2% |
|
||||
| [sum](./reference/math/sum.md) | 152 bytes | 413 bytes | -63.2% |
|
||||
| [debounce](./reference/function/debounce.md) | 144 bytes | 1400 bytes | -89.7% |
|
||||
| [throttle](./reference/function/throttle.md) | 110 bytes | 1460 bytes | -92.5% |
|
||||
| [pick](./reference/object/pick.md) | 657 bytes | 3860 bytes | -83.0% |
|
||||
| [zip](./reference/array/zip.md) | 797 bytes | 1790 bytes | -55.5% |
|
||||
|
32
docs/ko/index.md
Normal file
32
docs/ko/index.md
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
# https://vitepress.dev/reference/default-theme-home-page
|
||||
layout: home
|
||||
|
||||
hero:
|
||||
name: "es-toolkit"
|
||||
text: "현대적인 JavaScript 유틸리티 라이브러리"
|
||||
# tagline:
|
||||
actions:
|
||||
- theme: brand
|
||||
text: es-toolkit 알아보기
|
||||
link: /ko/intro
|
||||
- theme: alt
|
||||
text: 레퍼런스
|
||||
link: /ko/reference/array/chunk
|
||||
- theme: alt
|
||||
text: 설치
|
||||
link: /ko/installation
|
||||
|
||||
features:
|
||||
- title: 빠른 성능
|
||||
details: 같은 기능을 제공하는 다른 라이브러리와 비교했을 때, 평균 2-3배 빠른 런타임 성능을 제공해요.
|
||||
- title: 작은 번들 사이즈
|
||||
details: 같은 기능의 함수들을 기준으로, 최대 97% 작은 JavaScript 크기를 가져요.
|
||||
- title: 현대적인 구현
|
||||
details: 최신 JavaScript API를 사용하여, 구현이 직관적이고 간단해요.
|
||||
- title: 견고한 타입
|
||||
details: 모든 함수에 대해서 간단하지만 견고한 타입을 제공해요.
|
||||
- title: 테스트 커버리지 100%
|
||||
details: 모든 함수와 분기에 대해서 꼼꼼하게 테스트가 작성되어 있어요.
|
||||
---
|
||||
|
44
docs/ko/installation.md
Normal file
44
docs/ko/installation.md
Normal file
@ -0,0 +1,44 @@
|
||||
---
|
||||
description: es-toolkit을 설치하는 방법
|
||||
prev:
|
||||
text: es-toolkit 소개
|
||||
link: ./intro.md
|
||||
next:
|
||||
text: 번들 사이즈에 미치는 영향
|
||||
link: ./bundle-size
|
||||
---
|
||||
설치
|
||||
============
|
||||
|
||||
Node.js나 Bun을 사용하는 경우, [npm](https://npmjs.com/package/es-toolkit)에서 설치할 수 있어요. Deno에서는 [JSR](https://jsr.io/es-toolkit)에서 설치할 수 있어요.
|
||||
|
||||
|
||||
Node.js
|
||||
---
|
||||
es-toolkit은 Node.js 18 또는 이후 버전을 지원해요. es-toolkit을 설치하기 위해서는 아래 명령어를 사용해주세요.
|
||||
|
||||
```sh
|
||||
npm install es-toolkit
|
||||
yarn add es-toolkit
|
||||
pnpm install es-toolkit
|
||||
```
|
||||
|
||||
|
||||
Deno
|
||||
----
|
||||
|
||||
es-toolkit은 Deno도 지원해요. `npm:`을 이용해서 사용하세요.
|
||||
|
||||
```typescript
|
||||
import { chunk } from 'npm:es-toolkit@1.0.0';
|
||||
```
|
||||
|
||||
|
||||
Bun
|
||||
---
|
||||
|
||||
es-toolkit은 Bun에서도 사용할 수 있어요. 아래 명령어를 사용해주세요.
|
||||
|
||||
```sh
|
||||
bun add es-toolkit
|
||||
```
|
27
docs/ko/intro.md
Normal file
27
docs/ko/intro.md
Normal file
@ -0,0 +1,27 @@
|
||||
es-toolkit 소개
|
||||
===============
|
||||
|
||||
es-toolkit은 일상적인 개발에서 사용하는 다양한 함수들을 모은 현대적인 JavaScript 유틸리티 라이브러리예요.
|
||||
|
||||
[lodash](https://lodash.com/)와 같은 다른 라이브러리와 비교했을 때, es-toolkit은 [같은 함수 기준 최대 97% 작은 번들 사이즈](./bundle-size.md)
|
||||
를 제공하며, [2~3배 빠른 속도로](./performance.md) 동작합니다. 최신 JavaScript API를 활용해서 현대적으로 구현한 덕분이죠.
|
||||
|
||||
es-toolkit은 견고한 TypeScript 타입을 내장하여 제공하며, 신뢰성을 높일 수 있도록 100% 테스트 커버리지를 목표로 하고 있습니다.
|
||||
|
||||
|
||||
## 제공하는 기능
|
||||
|
||||
es-toolkit이 제공하는 기능 목록은 다음과 같습니다.
|
||||
|
||||
- **배열**: [uniq](./reference/array/uniq.md)나 [difference](./reference/array/difference.md)와 같이 배열을 다루기 위한 다양한 함수를 제공해요.
|
||||
- **함수**: [debounce](./reference/function/debounce.md)나 [throttle](./reference/function/throttle.md)처럼 함수 호출을 다루는 도구를 제공해요.
|
||||
- **숫자**: [sum](./reference/math/sum.md)이나 [round](./reference/math/round.md) 처럼 숫자를 쉽게 다루는 함수를 제공해요.
|
||||
- **객체**: [pick](./reference/object/pick.md)이나 [omit](./reference/object/omit.md)처럼 JavaScript 객체를 다루는 함수를 제공해요.
|
||||
- **타입 가드**: [isNotNil](./reference/predicate/isNotNil.md)처럼 특정한 객체가 어떤 상태인지 검사하는 타입 가드 함수를 제공해요.
|
||||
- **Promise**: [delay](./reference/promise/delay.md)와 같은 비동기 유틸리티 함수를 제공해요.
|
||||
|
||||
## 링크
|
||||
|
||||
이 프로젝트에 대해서 더 많은 정보를 얻기 위해서는 아래 링크를 참고하세요.
|
||||
|
||||
- [GitHub](https://github.com/toss/es-toolkit)
|
27
docs/ko/performance.md
Normal file
27
docs/ko/performance.md
Normal file
@ -0,0 +1,27 @@
|
||||
---
|
||||
description: es-toolkit과 다른 라이브러리의 성능 차이
|
||||
---
|
||||
성능
|
||||
============
|
||||
|
||||
![es-toolkit과 lodash 사이의 성능 차이를 보여주는 그래프. es-toolkit은 lodash를 쓸 때보다 최대 11배 높은 성능을 보여요.](/assets/performance.png)
|
||||
|
||||
es-toolkit은 설계할 때 성능을 우선적으로 고려하고 있어요. lodash와 같은 다른 라이브러리와 비교했을 때, 평균적으로 2배의 성능 향상을 확인할 수 있었어요. 함수에 따라서는 11배 빠른 성능을 보이기도 했죠.
|
||||
현대적인 JavaScript API을 이용하여 구현했기 때문이에요.
|
||||
|
||||
## 성능 비교
|
||||
|
||||
| | es-toolkit@0.0.1 | lodash-es@4.17.21 | 차이 |
|
||||
|-----------------------------------------------------------|------------------|------------------|------------|
|
||||
| [omit](./reference/object/omit.md) | 4,767,360회 | 403,624회 | 11.8× |
|
||||
| [pick](./reference/object/pick.md) | 9,121,839회 | 2,663,072회 | 3.43× |
|
||||
| [differenceWith](./reference/array/differenceWith.md) | 9,291,897회 | 4,275,222회 | 2.17× |
|
||||
| [difference](./reference/array/difference.md) | 10,436,101회 | 5,155,631회 | 2.02× |
|
||||
| [intersectionWith](./reference/array/intersectionWith.md) | 8,074,722회 | 3,814,479회 | 2.12× |
|
||||
| [intersection](./reference/array/intersection.md) | 9,999,571회 | 4,630,316회 | 2.15× |
|
||||
| [unionBy](./reference/array/unionBy.md) | 6,435,983회 | 3,794,899회 | 1.69× |
|
||||
| [union](./reference/array/union.md) | 5,059,209회 | 4,771,400회 | 1.06× |
|
||||
| [dropRightWhile](./reference/array/dropRightWhile.md) | 7,529,559회 | 5,606,439회 | 1.34× |
|
||||
| [groupBy](./reference/array/groupBy.md) | 5,000,235회 | 5,206,286회 | 0.96× |
|
||||
|
||||
테스트 환경은 MacBook Pro 14인치(M1 Max, 2021)예요. [벤치마크 코드](https://github.com/toss/es-toolkit/tree/main/benchmarks)를 참고하세요.
|
40
docs/ko/reference/array/chunk.md
Normal file
40
docs/ko/reference/array/chunk.md
Normal file
@ -0,0 +1,40 @@
|
||||
# chunk
|
||||
|
||||
배열을 정해진 길이에 맞게 더 작은 배열로 나눠요.
|
||||
|
||||
입력값으로 배열을 받아서, 정해진 길이를 따르는 더 작은 배열 여러 개로 나눠요.
|
||||
입력 배열이 똑같은 길이로 나눠질 수 없다면, 나눠진 마지막 배열이 남은 요소들을 포함하게 돼요.
|
||||
|
||||
|
||||
## 인터페이스
|
||||
|
||||
```typescript
|
||||
function chunk<T>(arr: T[], size: number): T[][];
|
||||
```
|
||||
|
||||
### 파라미터
|
||||
|
||||
- `arr` (`T[]`): 작은 배열들로 나눌 배열
|
||||
- `size` (`number`): 작은 배열들의 길이. 양의 정수여야 해요.
|
||||
|
||||
### 반환 값
|
||||
|
||||
(`T[][]`): 최대 길이 `size`를 가지는 작은 배열들로 구성된 2차원 배열을 반환해요.
|
||||
|
||||
### 에러
|
||||
|
||||
`size`가 양의 정수가 아니면 에러를 던져요.
|
||||
|
||||
## 예시
|
||||
|
||||
```typescript
|
||||
import { chunk } from 'es-toolkit/array';
|
||||
|
||||
// 숫자의 배열을 최대 2의 길이를 가지는 더 작은 배열들로 쪼개요.
|
||||
chunk([1, 2, 3, 4, 5], 2);
|
||||
// Returns: [[1, 2], [3, 4], [5]]
|
||||
|
||||
// 문자열의 배열을 최대 3의 길이를 가지는 더 작은 배열들로 쪼개요.
|
||||
chunk(['a', 'b', 'c', 'd', 'e', 'f', 'g'], 3);
|
||||
// Returns: [['a', 'b', 'c'], ['d', 'e', 'f'], ['g']]
|
||||
```
|
36
docs/ko/reference/array/difference.md
Normal file
36
docs/ko/reference/array/difference.md
Normal file
@ -0,0 +1,36 @@
|
||||
# difference
|
||||
|
||||
두 배열의 차이를 계산해요.
|
||||
|
||||
이 함수는 파라미터로 두 배열을 받아서, 첫 번째 배열에 있지만 두 번째 배열에는 없는 요소들을 포함한 새로운 배열을 반환해요.
|
||||
즉, 첫 번째 배열에서 두 번째 배열에 있는 요소들을 제외한 나머지 요소들로 구성된 배열을 만들어줘요.
|
||||
|
||||
|
||||
## 인터페이스
|
||||
|
||||
```typescript
|
||||
function difference<T>(firstArr: T[], secondArr: T[]): T[];
|
||||
```
|
||||
|
||||
### 파라미터
|
||||
|
||||
- `firstArr` (`T[]`): 차이를 계산할 배열이에요. 이 배열이 주 배열이고, 이 배열의 요소들이 비교되고 필터링돼요.
|
||||
- `secondArr` (`T[]`): 첫 번째 배열에서 제외할 요소들을 포함한 배열이에요. 이 배열의 각 요소는 첫 번째 배열과 비교되며, 일치하는 요소가 있으면 결과에서 제외돼요.
|
||||
|
||||
|
||||
|
||||
### 반환 값
|
||||
|
||||
(`T[]`): 첫 번째 배열에는 있지만 두 번째 배열에는 없는 요소들이 담긴 새로운 배열이에요.
|
||||
|
||||
## 예시
|
||||
|
||||
```typescript
|
||||
import { difference } from 'es-toolkit/array';
|
||||
|
||||
// 사용 예제:
|
||||
const array1 = [1, 2, 3, 4, 5];
|
||||
const array2 = [2, 4];
|
||||
const result = difference(array1, array2);
|
||||
// 2와 4는 두 배열 모두에 있기 때문에 결과에서 제외되고, result 변수에는 [1, 3, 5]가 할당되어요.
|
||||
```
|
33
docs/ko/reference/array/differenceBy.md
Normal file
33
docs/ko/reference/array/differenceBy.md
Normal file
@ -0,0 +1,33 @@
|
||||
# differenceBy
|
||||
|
||||
제공된 함수로 요소들을 매핑한 후 두 배열의 차이를 계산해요.
|
||||
|
||||
이 함수는 두 배열과 매퍼 함수를 받아, 매퍼 함수로 계산된 결과를 기준으로 첫 번째 배열에 있지만 두 번째 배열에는 없는 요소들을 포함한 새로운 배열을 반환해요. 즉, 매핑된 값이 두 번째 배열의 매핑된 값과 일치하는 첫 번째 배열의 요소들을 제외한 나머지 요소들로 구성된 배열을 만들어줘요.
|
||||
|
||||
## 인터페이스
|
||||
|
||||
```typescript
|
||||
function differenceBy<T, U>(firstArr: T[], secondArr: T[], mapper: (value: T) => U): T[]
|
||||
```
|
||||
|
||||
### 파라미터
|
||||
|
||||
- `firstArr` (`T[]`): 차이를 계산할 배열이에요. 이 배열이 주 배열이고, 이 배열의 요소들이 비교되고 필터링돼요.
|
||||
- `secondArr` (`T[]`): 첫 번째 배열에서 제외할 요소들을 포함한 배열이에요.
|
||||
- `mapper` (`(value: T) => U`): 두 배열의 요소들을 매핑할 함수에요. 이 함수는 두 배열의 각 요소에 적용되며, 매핑된 값들을 기준으로 비교를 해요.
|
||||
|
||||
### 반환 값
|
||||
|
||||
(`T[]`): 첫 번째 배열에는 있지만 매핑된 값이 두 번째 배열의 매핑된 값과 일치하지 않는 요소들이 담긴 새로운 배열이에요.
|
||||
|
||||
## 예시
|
||||
|
||||
```typescript
|
||||
import { differenceBy } from 'es-toolkit/array';
|
||||
|
||||
const array1 = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }];
|
||||
const array2 = [{ id: 2 }, { id: 4 }];
|
||||
const mapper = item => item.id;
|
||||
const result = differenceBy(array1, array2, mapper);
|
||||
// result는 [{ id: 1 }, { id: 3 }, { id: 5 }]가 돼요. id가 2인 요소들은 두 배열 모두에 있어서 결과에서 제외돼요.
|
||||
```
|
33
docs/ko/reference/array/differenceWith.md
Normal file
33
docs/ko/reference/array/differenceWith.md
Normal file
@ -0,0 +1,33 @@
|
||||
# differenceWith
|
||||
|
||||
인자로 제공된 비교 함수에 따라 두 배열의 차이를 계산해요.
|
||||
|
||||
이 함수는 두 배열과 비교 함수를 받아요. 이 비교 함수로 요소들이 동일한지 비교해서 첫 번째 배열에 있지만 두 번째 배열에는 없는 요소들을 포함한 새로운 배열을 반환해요.
|
||||
|
||||
## 인터페이스
|
||||
|
||||
```typescript
|
||||
function differenceWith<T>(firstArr: T[], secondArr: T[], areItemsEqual: (x: T, y: T) => boolean): T[]
|
||||
```
|
||||
|
||||
### 파라미터
|
||||
|
||||
- `firstArr` (`T[]`): 차이를 계산할 배열이에요. 이 배열이 주 배열이고, 이 배열의 요소들이 비교되고 필터링돼요.
|
||||
- `secondArr` (`T[]`) : 첫 번째 배열에서 제외할 요소들을 포함한 배열이에요.
|
||||
- `areItemsEqual` (`(x: T, y: T) => boolean`): 두 요소가 동일한지 결정할 함수에요.
|
||||
|
||||
### 반환 값
|
||||
(`T[]`) 비교 함수에 따라 첫 번째 배열에는 있지만 두 번째 배열에는 존재하지 않는다고 결정된 요소들이 담긴 새로운 배열이에요.
|
||||
|
||||
|
||||
## 예시
|
||||
|
||||
```typescript
|
||||
import { differenceWith } from 'es-toolkit/array';
|
||||
|
||||
const array1 = [{ id: 1 }, { id: 2 }, { id: 3 }];
|
||||
const array2 = [{ id: 2 }, { id: 4 }];
|
||||
const areItemsEqual = (a, b) => a.id === b.id;
|
||||
const result = differenceWith(array1, array2, areItemsEqual);
|
||||
// result는 [{ id: 1 }, { id: 3 }]가 돼요. id가 2인 요소들은 동일하다고 간주돼서 결과에서 제외돼요.
|
||||
```
|
28
docs/ko/reference/array/drop.md
Normal file
28
docs/ko/reference/array/drop.md
Normal file
@ -0,0 +1,28 @@
|
||||
# drop
|
||||
|
||||
배열의 시작부터 몇 개의 요소를 제거한 새로운 배열을 반환해요.
|
||||
|
||||
이 함수는 파라미터로 배열과 숫자를 받아요. 배열의 시작부터 숫자만큼의 요소를 제외한 새로운 배열을 반환해요.
|
||||
|
||||
## 인터페이스
|
||||
|
||||
```typescript
|
||||
function drop<T>(arr: T[], itemsCount: number): T[];
|
||||
```
|
||||
|
||||
### 파라미터
|
||||
|
||||
- `arr` (`T[]`): 요소를 제거할 배열.
|
||||
- `itemsCount` (`number`): 배열의 시작부터 제거할 요소의 숫자.
|
||||
|
||||
### 반환 값
|
||||
|
||||
(`T[]`): 배열의 시작부터 숫자만큼의 요소를 제외한 새로운 배열을 반환해요.
|
||||
|
||||
## 예시
|
||||
|
||||
```typescript
|
||||
const array = [1, 2, 3, 4, 5];
|
||||
const result = drop(array, 2);
|
||||
// 첫 두 개 요소가 제거되므로, 결과는 [3, 4, 5]이에요.
|
||||
```
|
28
docs/ko/reference/array/dropRight.md
Normal file
28
docs/ko/reference/array/dropRight.md
Normal file
@ -0,0 +1,28 @@
|
||||
# dropRight
|
||||
|
||||
배열의 마지막부터 몇 개의 요소를 제거한 새로운 배열을 반환해요.
|
||||
|
||||
이 함수는 파라미터로 배열과 숫자를 받아요. 배열의 마지막부터 숫자만큼의 요소를 제외한 새로운 배열을 반환해요.
|
||||
|
||||
## 인터페이스
|
||||
|
||||
```typescript
|
||||
function dropRight<T>(arr: T[], itemsCount: number): T[];
|
||||
```
|
||||
|
||||
### 파라미터
|
||||
|
||||
- `arr` (`T[]`): 요소를 제거할 배열.
|
||||
- `itemsCount` (`number`): 배열의 지막부터 제거할 요소의 숫자.
|
||||
|
||||
### 반환 값
|
||||
|
||||
(`T[]`): 배열의 마지막부터 숫자만큼의 요소를 제외한 새로운 배열을 반환해요.
|
||||
|
||||
## 예시
|
||||
|
||||
```typescript
|
||||
const array = [1, 2, 3, 4, 5];
|
||||
const result = dropRight(array, 2);
|
||||
// 마지막 두 개 요소가 반환되므로, 결괏값은 [1, 2, 3]이 돼요.
|
||||
```
|
29
docs/ko/reference/array/dropRightWhile.md
Normal file
29
docs/ko/reference/array/dropRightWhile.md
Normal file
@ -0,0 +1,29 @@
|
||||
# dropRightWhile
|
||||
|
||||
배열의 끝부터 시작해서, 조건 함수가 `false`를 반환할 때까지 요소들을 제거해요.
|
||||
|
||||
이 함수는 각 배열의 요소를 순회하면서, 배열의 끝부터 조건 함수가 `false`를 반환할 때까지 요소를 제거해요.
|
||||
남은 요소들로 구성된 새로운 배열을 반환해요.
|
||||
|
||||
## 인터페이스
|
||||
|
||||
```typescript
|
||||
function dropRightWhile<T>(arr: T[], canContinueDropping: (item: T) => boolean): T[]
|
||||
```
|
||||
|
||||
### 파라미터
|
||||
|
||||
- `arr` (`T[]`): 요소를 제거할 배열.
|
||||
- `canContinueDropping` (`(item: T) => boolean`): 요소를 제거하는 것을 계속할지 반환하는 조건 함수예요. 각 요소에 대해서 호출되면서, `true`를 반환하는 동안 요소를 제거해요.
|
||||
|
||||
### 반환 값
|
||||
|
||||
(`T[]`): 조건 함수가 `false`를 반환할 때까지 남은 요소들로 이루어진 새로운 배열.
|
||||
|
||||
## Examples
|
||||
|
||||
```typescript
|
||||
const array = [1, 2, 3, 2, 4, 5];
|
||||
const result = dropRightWhile(array, x => x > 3);
|
||||
// 3보다 작거나 같은 요소를 만날 때까지 요소를 제거하므로, 결괏값은 [1, 2, 3, 2]이 되어요.
|
||||
```
|
30
docs/ko/reference/array/dropWhile.md
Normal file
30
docs/ko/reference/array/dropWhile.md
Normal file
@ -0,0 +1,30 @@
|
||||
# dropWhile
|
||||
|
||||
배열의 처음부터 시작해서, 조건 함수가 `false`를 반환할 때까지 요소들을 제거해요.
|
||||
|
||||
이 함수는 각 배열의 요소를 순회하면서, 배열의 시작부터 조건 함수가 `false`를 반환할 때까지 요소를 제거해요.
|
||||
남은 요소들로 구성된 새로운 배열을 반환해요.
|
||||
|
||||
|
||||
## 인터페이스
|
||||
|
||||
```typescript
|
||||
function dropWhile<T>(arr: T[], canContinueDropping: (item: T) => boolean): T[]
|
||||
```
|
||||
|
||||
### 파라미터
|
||||
|
||||
- `arr` (`T[]`): 요소를 제거할 배열.
|
||||
- `canContinueDropping` (`(item: T) => boolean`): 요소를 제거하는 것을 계속할지 반환하는 조건 함수예요. 각 요소에 대해서 호출되면서, `true`를 반환하는 동안 요소를 제거해요.
|
||||
|
||||
### 반환 값
|
||||
|
||||
(`T[]`): 조건 함수가 `false`를 반환할 때까지 남은 요소들로 이루어진 새로운 배열.
|
||||
|
||||
## 예시
|
||||
|
||||
```typescript
|
||||
const array = [1, 2, 3, 2, 4, 5];
|
||||
const result = dropWhile(array, x => x < 3);
|
||||
// 3보다 작은 요소를 발견할 때까지 요소를 제거하므로, 결괏값은 [3, 2, 4, 5]이 되어요.
|
||||
```
|
42
docs/ko/reference/array/groupBy.md
Normal file
42
docs/ko/reference/array/groupBy.md
Normal file
@ -0,0 +1,42 @@
|
||||
# groupBy
|
||||
|
||||
주어진 키 생성 함수에 따라서 배열의 요소를 분류해요.
|
||||
|
||||
이 함수는 파라미터로 배열과 각 요소에서 키를 생성하는 함수를 받아요.
|
||||
키는 함수에서 생성된 키이고, 값은 그 키를 공유하는 요소끼리 묶은 배열인 객체를 반환해요.
|
||||
|
||||
## 인터페이스
|
||||
|
||||
```typescript
|
||||
function groupBy<T, K extends string>(arr: T[], getKeyFromItem: (item: T) => K): Record<K, T[]>;
|
||||
```
|
||||
|
||||
### 파라미터
|
||||
|
||||
- `arr` (`T[]`): 요소를 분류할 배열.
|
||||
- `getKeyFromItem` (`(item: T) => K`): 요소에서 키를 생성하는 함수.
|
||||
|
||||
### 반환 값
|
||||
|
||||
(`Record<K, T[]>`): 키에 따라 요소가 분류된 객체를 반환해요.
|
||||
|
||||
## 예시
|
||||
|
||||
```typescript
|
||||
const array = [
|
||||
{ category: 'fruit', name: 'apple' },
|
||||
{ category: 'fruit', name: 'banana' },
|
||||
{ category: 'vegetable', name: 'carrot' }
|
||||
];
|
||||
const result = groupBy(array, item => item.category);
|
||||
// 결괏값:
|
||||
// {
|
||||
// fruit: [
|
||||
// { category: 'fruit', name: 'apple' },
|
||||
// { category: 'fruit', name: 'banana' }
|
||||
// ],
|
||||
// vegetable: [
|
||||
// { category: 'vegetable', name: 'carrot' }
|
||||
// ]
|
||||
// }
|
||||
```
|
32
docs/ko/reference/array/intersection.md
Normal file
32
docs/ko/reference/array/intersection.md
Normal file
@ -0,0 +1,32 @@
|
||||
# intersection
|
||||
|
||||
두 배열 모두에 포함되어 있는 요소를 반환해요.
|
||||
|
||||
이 함수는 두 개의 배열을 받고, 두 배열 모두에 포함되어 있는 요소로 구성된 새로운 배열을 반환해요.
|
||||
실제로는 첫 번째 배열의 요소들 중에서 두 번째 배열에 포함되어 있지 않은 요소들을 제거해요.
|
||||
|
||||
|
||||
## 인터페이스
|
||||
|
||||
```typescript
|
||||
function intersection<T>(firstArr: T[], secondArr: T[]): T[];
|
||||
```
|
||||
|
||||
### 파라미터
|
||||
|
||||
- `firstArr` (`T[]`): 비교할 첫 번째 배열.
|
||||
- `secondArr` (`T[]`): 비교할 두 번째 배열.
|
||||
|
||||
### 반환 값
|
||||
|
||||
(`T[]`) 두 배열 모두에 포함되어 있는 요소로 구성된 새로운 배열.
|
||||
|
||||
|
||||
## 예시
|
||||
|
||||
```typescript
|
||||
const array1 = [1, 2, 3, 4, 5];
|
||||
const array2 = [3, 4, 5, 6, 7];
|
||||
const result = intersection(array1, array2);
|
||||
// 두 배열에 모두 포함되어 있는 [3, 4, 5]를 반환해요.
|
||||
```
|
36
docs/ko/reference/array/intersectionBy.md
Normal file
36
docs/ko/reference/array/intersectionBy.md
Normal file
@ -0,0 +1,36 @@
|
||||
# intersectionBy
|
||||
|
||||
`mapper` 함수가 반환하는 값을 기준으로, 두 배열의 교집합을 반환해요.
|
||||
|
||||
이 함수는 파라미터로 두 개의 배열과 `mapper` 함수를 받아요.
|
||||
`mapper` 함수로 각 배열의 요소들을 변환했을 때, 두 배열에 모두 포함되는 요소들로 이루어진 새로운 배열을 반환해요.
|
||||
실제 구현을 살펴보면, 첫 번째 배열과 두 번째 배열을 `mapper` 가 반환하는 값을 기준으로 비교하여, 첫 번째 배열의 요소들 중 두 번째 배열에 없는 요소들을 제거해요.
|
||||
|
||||
|
||||
## 인터페이스
|
||||
|
||||
```typescript
|
||||
function intersectionBy<T, U>(firstArr: T[], secondArr: T[], mapper: (item: T) => U): T[];
|
||||
```
|
||||
|
||||
### 파라미터
|
||||
|
||||
|
||||
- `firstArr` (`T[]`): 비교할 첫 번째 배열.
|
||||
- `secondArr` (`T[]`): 비교할 두 번째 배열.
|
||||
- `mapper` (`(item: T) => U`): 비교하기 위해 요소를 새로운 값으로 변환할 함수.
|
||||
|
||||
### 반환 값
|
||||
|
||||
(`T[]`): 첫 번째 배열과 두 번째 배열을 `mapper` 가 반환하는 값을 기준으로 비교하여, 두 배열 모두에 포함되는 요소들만 포함하는 새로운 배열.
|
||||
|
||||
|
||||
## 예시
|
||||
|
||||
```typescript
|
||||
const array1 = [{ id: 1 }, { id: 2 }, { id: 3 }];
|
||||
const array2 = [{ id: 2 }, { id: 4 }];
|
||||
const mapper = item => item.id;
|
||||
const result = intersectionBy(array1, array2, mapper);
|
||||
// `mapper`로 변환했을 때 두 배열 모두에 포함되는 요소로 이루어진 [{ id: 2 }] 값이 반환되어요.
|
||||
```
|
34
docs/ko/reference/array/intersectionWith.md
Normal file
34
docs/ko/reference/array/intersectionWith.md
Normal file
@ -0,0 +1,34 @@
|
||||
# intersectionWith
|
||||
|
||||
두 요소가 일치하는지 여부를 판단하는 커스텀 함수를 기준으로, 두 배열의 교집합을 반환해요.
|
||||
|
||||
이 함수는 파라미터로 두 개의 배열과 커스텀 일치 함수를 받아요.
|
||||
이 함수는 커스텀 일치 함수의 반환 값을 기준으로, 두 배열에 모두 포함된 요소들을 새로운 배열로 반환해요.
|
||||
실제 구현을 살펴보면, 첫 번째 배열의 요소들 중에서 두 번째 배열의 어떤 요소와도 일치 함수를 기준으로 같지 않은 요소들을 제외한 새로운 배열을 반환해요.
|
||||
|
||||
## 인터페이스
|
||||
|
||||
```typescript
|
||||
function intersectionWith<T>(firstArr: T[], secondArr: T[], areItemsEqual: (x: T, y: T) => boolean): T[];
|
||||
```
|
||||
|
||||
### 파라미터
|
||||
|
||||
- `firstArr` (`T[]`): 비교할 첫 번째 배열.
|
||||
- `secondArr` (`T[]`): 비교할 두 번째 배열.
|
||||
- `areItemsEqual` (`(x: T, y: T) => boolean`): 두 요소가 일치하는지 판단하는 일치 함수예요. 두 요소가 일치한다면 `true`를, 일치하지 않는다면 `false`를 반환하게 해주세요.
|
||||
|
||||
### 반환 값
|
||||
|
||||
(`T[]`): 커스텀 일치 함수의 반환 값을 기준으로, 두 배열에 모두 포함된 요소들을 포함하는 새로운 배열.
|
||||
|
||||
|
||||
## 예시
|
||||
|
||||
```typescript
|
||||
const array1 = [{ id: 1 }, { id: 2 }, { id: 3 }];
|
||||
const array2 = [{ id: 2 }, { id: 4 }];
|
||||
const areItemsEqual = (a, b) => a.id === b.id;
|
||||
const result = intersectionWith(array1, array2, areItemsEqual);
|
||||
// `areItemsEqual` 기준으로 array1과 array2에 모두 포함되어 있는 요소들로 이루어진 [{ id: 2 }] 이 반환돼요.
|
||||
```
|
31
docs/ko/reference/array/partition.md
Normal file
31
docs/ko/reference/array/partition.md
Normal file
@ -0,0 +1,31 @@
|
||||
# partition
|
||||
|
||||
배열을 2개로 나누는 데에 쓸 수 있는 함수예요.
|
||||
|
||||
이 함수는 파라미터로 배열과 `true`/`false`를 반환하는 함수를 받아요.
|
||||
이 함수는 두 개의 배열로 이루어진 튜플을 반환하는데요, 첫 번째 배열은 함수가 `true`를 반환하는 요소들로 구성돼요.
|
||||
두 번째 배열은 함수가 `false`를 반환하는 요소들로 구성돼요.
|
||||
|
||||
## 인터페이스
|
||||
|
||||
```typescript
|
||||
function partition<T>(arr: T[], isInTruthy: (value: T) => boolean): [truthy: T[], falsy: T[]];
|
||||
```
|
||||
|
||||
### 파라미터
|
||||
|
||||
- `arr` (`T[]`): 2개로 나눌 배열.
|
||||
- `isInTruthy` (`(value: T) => boolean`): 배열의 요소가 첫 번째 배열에 포함될지, 두 번째 배열에 포함될지 결정하는 함수. `true`를 반환하면 첫 번째 배열에, `false`를 반환하면 두 번째 배열에 포함돼요.
|
||||
|
||||
### 반환 값
|
||||
|
||||
(`[T[], T[]]`): 2개의 배열로 구성된 튜플. 첫 번째 배열은 `isInTruthy`가 `true`를 반환한 요소들로, 두 번째 배열은 `false`를 반환한 요소들로 구성돼요.
|
||||
|
||||
## 예시
|
||||
|
||||
```typescript
|
||||
const array = [1, 2, 3, 4, 5];
|
||||
const is짝수 = x => x % 2 === 0;
|
||||
const [짝수, 홀수] = partition(array, is짝수);
|
||||
// 짝수는 [2, 4], 홀수는 [1, 3, 5]가 되어요.
|
||||
```
|
25
docs/ko/reference/array/sample.md
Normal file
25
docs/ko/reference/array/sample.md
Normal file
@ -0,0 +1,25 @@
|
||||
# sample
|
||||
|
||||
배열을 받아서 그 배열에서 무작위로 선택된 단일 요소를 반환해요.
|
||||
|
||||
## 인터페이스
|
||||
|
||||
```typescript
|
||||
function sample<T>(arr: T[]): T;
|
||||
```
|
||||
|
||||
### 파라미터
|
||||
|
||||
- `arr` (`T[]`): 샘플링할 배열이에요.
|
||||
|
||||
### 반환 값
|
||||
|
||||
(`T`): 배열에서 무작위로 선택된 요소에요.
|
||||
|
||||
## 예시
|
||||
|
||||
```typescript
|
||||
const array = [1, 2, 3, 4, 5];
|
||||
const randomElement = sample(array);
|
||||
// randomElement는 배열에서 무작위로 선택된 요소 중 하나가 될 거예요.
|
||||
```
|
25
docs/ko/reference/array/shuffle.md
Normal file
25
docs/ko/reference/array/shuffle.md
Normal file
@ -0,0 +1,25 @@
|
||||
# shuffle
|
||||
|
||||
배열의 요소 순서를 무작위로 섞어요. Fisher-Yates 알고리즘을 사용해요.
|
||||
|
||||
## 인터페이스
|
||||
|
||||
```typescript
|
||||
function shuffle<T>(arr: T[]): T[];
|
||||
```
|
||||
|
||||
### 파라미터
|
||||
|
||||
- `arr` (`T[]`): 요소를 뒤섞을 배열이에요.
|
||||
|
||||
### 반환 값
|
||||
|
||||
(`T[]`): 요소들이 무작위로 섞인 새로운 배열이에요.
|
||||
|
||||
## 예시
|
||||
|
||||
```typescript
|
||||
const array = [1, 2, 3, 4, 5];
|
||||
const shuffledArray = shuffle(array);
|
||||
// shuffledArray는 배열의 요소들이 무작위로 섞인 새로운 배열인 [3, 1, 4, 5, 2]이 되어요.
|
||||
```
|
34
docs/ko/reference/array/take.md
Normal file
34
docs/ko/reference/array/take.md
Normal file
@ -0,0 +1,34 @@
|
||||
# take
|
||||
|
||||
입력 배열 arr에서 처음 count개의 요소를 포함하는 새로운 배열을 반환해요.
|
||||
|
||||
만약 count가 arr의 길이보다 크면, 전체 배열을 반환해요.
|
||||
|
||||
|
||||
## 인터페이스
|
||||
|
||||
```typescript
|
||||
function take<T>(arr: T[], count: number): T[];
|
||||
```
|
||||
|
||||
### 파라미터
|
||||
|
||||
- `arr` (`T[]`): 요소를 가져올 배열이에요.
|
||||
- `count` (`number`): 가져올 요소의 개수예요.
|
||||
|
||||
### 반환 값
|
||||
|
||||
(T[]): arr에서 처음 `count`개의 요소를 포함하는 새로운 배열이에요.
|
||||
|
||||
## 예시
|
||||
|
||||
```typescript
|
||||
// [1, 2, 3]
|
||||
take([1, 2, 3, 4, 5], 3);
|
||||
|
||||
// ['a', 'b']
|
||||
take(['a', 'b', 'c'], 2);
|
||||
|
||||
// [1, 2, 3]
|
||||
take([1, 2, 3], 5);
|
||||
```
|
35
docs/ko/reference/array/takeRight.md
Normal file
35
docs/ko/reference/array/takeRight.md
Normal file
@ -0,0 +1,35 @@
|
||||
# takeRight
|
||||
|
||||
입력 배열 `arr`에서 마지막 `count`개의 요소를 포함하는 새로운 배열을 반환해요.
|
||||
|
||||
만약 `count`가 `arr`의 길이보다 크면, 전체 배열을 반환해요.
|
||||
|
||||
|
||||
## 인터페이스
|
||||
|
||||
```typescript
|
||||
function takeRight<T>(arr: T[], count: number): T[];
|
||||
```
|
||||
|
||||
### 파라미터
|
||||
|
||||
- `arr` (`T[]`): 요소를 가져올 배열이에요.
|
||||
- `count` (`number`): 가져올 요소의 개수예요.
|
||||
|
||||
### 반환 값
|
||||
|
||||
(`T[]`) `arr` 에서 마지막 `count` 개의 요소를 포함하는 새로운 배열이에요.
|
||||
|
||||
|
||||
## 예시
|
||||
|
||||
```typescript
|
||||
// [4, 5]
|
||||
takeRight([1, 2, 3, 4, 5], 2);
|
||||
|
||||
// ['b', 'c']
|
||||
takeRight(['a', 'b', 'c'], 2);
|
||||
|
||||
// [1, 2, 3]
|
||||
takeRight([1, 2, 3], 5);
|
||||
```
|
30
docs/ko/reference/array/takeRightWhile.md
Normal file
30
docs/ko/reference/array/takeRightWhile.md
Normal file
@ -0,0 +1,30 @@
|
||||
# takeRightWhile
|
||||
|
||||
조건 함수가 `true`를 반환하는 동안 배열의 끝에서부터 요소들을 가져와요.
|
||||
조건을 만족하지 않는 요소가 나오면 멈춰요.
|
||||
|
||||
## 인터페이스
|
||||
|
||||
```typescript
|
||||
function takeRightWhile<T>(arr: T[], shouldContinueTaking: (item: T) => boolean): T[]
|
||||
```
|
||||
|
||||
### 파라미터
|
||||
|
||||
- `arr` (`T[]`): 요소를 가져올 배열이에요.
|
||||
- `shouldContinueTaking` (`(item: T) => boolean`): 각 요소와 함께 호출되는 조건 함수예요. 이 함수가 `true`를 반환하는 동안 요소들이 결과에 포함돼요.
|
||||
|
||||
### 반환 값
|
||||
|
||||
(`T[]`): 조건 함수가 `true`를 반환하는 동안 배열의 끝에서부터 가져온 요소들을 포함하는 새로운 배열이에요.
|
||||
|
||||
|
||||
## 예시
|
||||
|
||||
```typescript
|
||||
// [3, 2, 1]
|
||||
takeRightWhile([5, 4, 3, 2, 1], n => n < 4);
|
||||
|
||||
// []
|
||||
takeRightWhile([1, 2, 3], n => n > 3);
|
||||
```
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user