├── .changeset
├── README.md
└── config.json
├── .github
└── workflows
│ ├── ci.yml
│ └── deploy.yml
├── .gitignore
├── .husky
├── .gitignore
└── pre-commit
├── .prettierignore
├── .prettierrc
├── CHANGELOG.md
├── CONTRIBUTING.md
├── CONTRIBUTING_CN.md
├── README.md
├── README_CN.md
├── commitlint.config.js
├── package.json
├── packages
├── auto-polyfills-webpack-plugin
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── index.ts
│ ├── package.json
│ └── tsconfig.json
├── babel-preset-ko-app
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── index.js
│ └── package.json
├── create-ko
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── package.json
│ ├── src
│ │ └── index.ts
│ ├── template
│ │ ├── .eslintrc.js
│ │ ├── .gitignore
│ │ ├── .prettierrc.js
│ │ ├── .stylelintrc.js
│ │ ├── ko.config.js
│ │ ├── package.json
│ │ ├── src
│ │ │ ├── App.tsx
│ │ │ ├── main.tsx
│ │ │ ├── public
│ │ │ │ ├── assets
│ │ │ │ │ ├── KO.svg
│ │ │ │ │ └── react.svg
│ │ │ │ ├── favicon.ico
│ │ │ │ └── index.html
│ │ │ └── styles
│ │ │ │ ├── App.css
│ │ │ │ └── index.css
│ │ └── tsconfig.json
│ └── tsconfig.json
├── dynamic-resolve-webpack-plugin
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── index.ts
│ ├── package.json
│ └── tsconfig.json
├── eslint-plugin-dt-react
│ ├── index.js
│ ├── package.json
│ ├── rules
│ │ ├── jsx-closing-bracket-location.js
│ │ ├── jsx-tag-spacing.js
│ │ ├── jsx-wrap-multilines.js
│ │ └── self-closing-comp.js
│ └── utils
│ │ ├── ast.js
│ │ ├── getTokenBeforeClosingBracket.js
│ │ ├── isCreateElement.js
│ │ ├── isDestructuredFromPragmaImport.js
│ │ ├── jsx.js
│ │ ├── pragma.js
│ │ ├── report.js
│ │ └── variable.js
├── ko-lint-config
│ ├── .eslintrc.js
│ ├── .prettierrc.js
│ ├── .stylelintrc.js
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── README_CN.md
│ ├── index.d.ts
│ ├── index.js
│ ├── package.json
│ └── test
│ │ ├── basic.js
│ │ └── validate-config.js
├── ko-lints
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── index.d.ts
│ ├── package.json
│ ├── src
│ │ ├── eslint
│ │ │ ├── index.ts
│ │ │ └── parser.ts
│ │ ├── factory
│ │ │ ├── parser.ts
│ │ │ └── runner.ts
│ │ ├── index.ts
│ │ ├── interfaces.ts
│ │ ├── prettier
│ │ │ ├── index.ts
│ │ │ └── parser.ts
│ │ ├── stylelint
│ │ │ ├── index.ts
│ │ │ └── parser.ts
│ │ └── threads
│ │ │ ├── Pool.ts
│ │ │ ├── Worker.ts
│ │ │ └── index.ts
│ └── tsconfig.json
└── ko
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── README_CN.md
│ ├── index.d.ts
│ ├── jest.config.js
│ ├── package.json
│ ├── src
│ ├── actions
│ │ ├── build.ts
│ │ ├── dev.ts
│ │ ├── factory.ts
│ │ └── lints.ts
│ ├── cli.ts
│ ├── core
│ │ ├── commander.ts
│ │ ├── config.ts
│ │ ├── hooks.ts
│ │ └── service.ts
│ ├── types.ts
│ ├── utils
│ │ └── index.ts
│ └── webpack
│ │ ├── custom-plugins
│ │ └── purge-cache-webpack-plugin
│ │ │ └── index.ts
│ │ ├── index.ts
│ │ ├── loaders
│ │ ├── asset.ts
│ │ ├── babel
│ │ │ └── index.ts
│ │ ├── index.ts
│ │ ├── script.ts
│ │ └── style.ts
│ │ └── plugins.ts
│ └── tsconfig.json
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
└── website
├── .gitignore
├── README.md
├── babel.config.js
├── docs
├── FAQ.md
├── advanced
│ ├── _category_.json
│ ├── architecture.md
│ └── plugins.md
├── cli.md
├── configuration.md
├── getting-started.md
└── introduction.md
├── docusaurus.config.js
├── i18n
└── zh-CN
│ ├── code.json
│ ├── docusaurus-plugin-content-docs
│ ├── current.json
│ ├── current
│ │ ├── FAQ.md
│ │ ├── advanced
│ │ │ ├── _category_.json
│ │ │ ├── architecture.md
│ │ │ └── plugins.md
│ │ ├── cli.md
│ │ ├── configuration.md
│ │ ├── getting-started.md
│ │ └── introduction.md
│ ├── version-5.x.json
│ └── version-5.x
│ │ ├── FAQ.md
│ │ ├── advanced
│ │ ├── _category_.json
│ │ ├── architecture.md
│ │ └── migration.md
│ │ ├── cli
│ │ ├── _category_.json
│ │ ├── ko-build.md
│ │ ├── ko-dev.md
│ │ ├── ko-eslint.md
│ │ ├── ko-lint-config.md
│ │ ├── ko-prettier.md
│ │ └── ko-stylelint.md
│ │ ├── getting-started.md
│ │ └── introduction.md
│ └── docusaurus-theme-classic
│ ├── footer.json
│ └── navbar.json
├── package.json
├── scripts
└── replace.js
├── sidebars.js
├── src
├── components
│ └── HomepageFeatures
│ │ ├── index.tsx
│ │ └── styles.module.css
├── css
│ └── custom.css
└── pages
│ ├── index.module.css
│ ├── index.tsx
│ └── markdown-page.md
├── static
├── .nojekyll
└── img
│ ├── architecture.svg
│ └── favicon.ico
├── tsconfig.json
├── versioned_docs
└── version-5.x
│ ├── FAQ.md
│ ├── advanced
│ ├── _category_.json
│ ├── architecture.md
│ └── migration.md
│ ├── cli
│ ├── _category_.json
│ ├── ko-build.md
│ ├── ko-dev.md
│ ├── ko-eslint.md
│ ├── ko-lint-config.md
│ ├── ko-prettier.md
│ └── ko-stylelint.md
│ ├── getting-started.md
│ └── introduction.md
├── versioned_sidebars
├── version-5.x-sidebars.json
└── version-6.x-sidebars.json
└── versions.json
/.changeset/README.md:
--------------------------------------------------------------------------------
1 | # Changesets
2 |
3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4 | with multi-package repos, or single-package repos to help you version and publish your code. You can
5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets)
6 |
7 | We have a quick list of common questions to get you started engaging with this project in
8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
9 |
--------------------------------------------------------------------------------
/.changeset/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://unpkg.com/@changesets/config@1.7.0/schema.json",
3 | "changelog": "@changesets/cli/changelog",
4 | "commit": true,
5 | "fixed": [],
6 | "linked": [],
7 | "access": "public",
8 | "baseBranch": "master",
9 | "updateInternalDependencies": "patch",
10 | "ignore": []
11 | }
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on: push
3 | jobs:
4 | lint:
5 | runs-on: ubuntu-latest
6 | steps:
7 | - uses: actions/checkout@v2
8 | - name: Install pnpm
9 | uses: pnpm/action-setup@v2.2.1
10 | with:
11 | version: 6.32.2
12 | - uses: actions/setup-node@v2
13 | with:
14 | node-version: 14.x
15 | cache: pnpm
16 | - name: pnpm install
17 | run: pnpm install
18 | - name: check
19 | run: pnpm check
20 |
21 | # on: push
22 | # jobs:
23 | # # install dependencies
24 | # setup:
25 | # name: setup
26 | # runs-on: ubuntu-latest
27 | # steps:
28 | # - uses: actions/checkout@v2
29 | # - name: eslint
30 | # uses: actions/setup-node@v1
31 | # with:
32 | # node-version: '12.x'
33 | # # cache node_modules
34 | # # spped up the procedure of installing packages
35 | # - uses: actions/cache@v2
36 | # with:
37 | # path: '**/node_modules'
38 | # key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
39 |
40 | # - name: install packages
41 | # run: yarn
42 |
43 | # # static code check
44 | # # eslint and prettier
45 | # static-check:
46 | # name: static check
47 | # runs-on: ubuntu-latest
48 | # needs: [setup]
49 | # steps:
50 | # - uses: actions/checkout@v2
51 | # - name: Use Node.js
52 | # uses: actions/setup-node@v1
53 | # with:
54 | # node-version: '12.x'
55 | # - uses: actions/cache@v2
56 | # with:
57 | # path: '**/node_modules'
58 | # key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
59 | # - name: eslint
60 | # run: node -v && yarn eslint
61 | # - name: prettier
62 | # run: yarn prettier
63 |
64 | # # run unit test
65 | # unit-test:
66 | # name: unit test
67 | # runs-on: ubuntu-latest
68 | # needs: [setup, static-check]
69 | # steps:
70 | # - uses: actions/checkout@v2
71 | # - name: Use Node.js
72 | # uses: actions/setup-node@v1
73 | # with:
74 | # node-version: '12.x'
75 | # - uses: actions/cache@v2
76 | # with:
77 | # path: '**/node_modules'
78 | # key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
79 | # - name: unit-test
80 | # run: node -v && yarn test
81 |
--------------------------------------------------------------------------------
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | name: Deploy to GitHub Pages
2 |
3 | on:
4 | push:
5 | branches: [master, feat_github_workflow]
6 | # paths: [website/**]
7 |
8 | jobs:
9 | deploy:
10 | name: Deploy to GitHub Pages
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/checkout@v2
14 | - name: Install pnpm
15 | uses: pnpm/action-setup@v2.2.1
16 | with:
17 | version: 6.32.2
18 | - uses: actions/setup-node@v2
19 | with:
20 | node-version: 14.x
21 | cache: pnpm
22 | - name: Build website
23 | working-directory: website
24 | run: |
25 | pnpm install
26 | pnpm build
27 |
28 | # Popular action to deploy to GitHub Pages:
29 | # Docs: https://github.com/peaceiris/actions-gh-pages#%EF%B8%8F-docusaurus
30 | - name: Deploy to GitHub Pages
31 | uses: peaceiris/actions-gh-pages@v3
32 | with:
33 | github_token: ${{ secrets.GITHUB_TOKEN }}
34 | # Build output to publish to the `gh-pages` branch:
35 | publish_dir: website/build
36 | # Assign commit authorship to the official GH-Actions bot for deploys to `gh-pages` branch:
37 | # https://github.com/actions/checkout/issues/13#issuecomment-724415212
38 | # The GH actions bot is used by default if you didn't specify the two fields.
39 | # You can swap them out with your own user credentials.
40 | user_name: github-actions[bot]
41 | user_email: 41898282+github-actions[bot]@users.noreply.github.com
42 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.DS_Store
2 | *.idea
3 | node_modules*
4 | npm-debug.log
5 | dist/*
6 | idea/
7 | /.vscode/
8 | compiler_ts/*
9 | .history/
10 | true?{\"compact\":false}/
11 | lib
12 | .yalc
13 | yalc.lock
--------------------------------------------------------------------------------
/.husky/.gitignore:
--------------------------------------------------------------------------------
1 | _
2 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | pnpm commitlint -c --edit $1
5 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | /.vscode/
2 | *.md
3 | *.json
4 | /template/
5 | /.github/
6 | pnpm-lock.yaml
7 | **/build
8 | **/lib
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/prettierrc",
3 | "bracketSpacing": true,
4 | "singleQuote": true,
5 | "bracketSameLine": false,
6 | "trailingComma": "es5",
7 | "arrowParens": "avoid",
8 | "printWidth": 80,
9 | "tabWidth": 2
10 | }
11 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## We use [Semantic Versioning](https://semver.org/) to manage package version
4 |
5 | Given a version number MAJOR.MINOR.PATCH, increment the:
6 |
7 | * MAJOR version when you make incompatible API changes,
8 | * MINOR version when you add functionality in a backwards compatible manner, and
9 | * PATCH version when you make backwards compatible bug fixes.
10 | Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.
11 |
12 | **For more details, please refer to Changelog.md in subfolder**
13 |
14 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to ko
2 |
3 | We use **pnpm workspace** to manage our packages. so make sure you use **pnpm** as package manager than **npm** or **yarn**.
4 |
5 | To getting started with this repo:
6 |
7 | ``` bash
8 | pnpm install
9 | ```
10 |
11 | ## Code Structure
12 |
13 | as a **monorepo**, ko now maintain 5 packages in packages directory:
14 |
15 | * **ko**: main package
16 | * **ko-lints**: code format cli, include **eslint**, **prettier** and **stylelint**, can be integrated in ko or use individually
17 | * **ko-config**: default config used by **ko-lints**
18 | * **ko-lint-config**: code format configs, include **eslint**, **prettier** and **stylelint**
19 | * **babel-preset-ko-app**: babel preset used by ko
20 | ### Debug
21 |
22 | use `pnpm debug` to debug local packages
23 |
24 | ### Local Testing
25 |
26 | use **pnpm link** to link `ko` into local packages for testing
27 |
28 | ## Submitting a Pull Request (PR)
29 |
30 | Before you submit your Pull Request (PR) consider the following guidelines:
31 | - Run `pnpm changeset` in the root of the repository and describe your changes. The resulting files should be committed as they will be used during release.
32 | - Run the full test suite and ensure that all tests pass.
33 | - Push your branch to GitHub:
34 |
35 | ```shell
36 | git push origin my-fix-branch
37 | ```
38 |
39 | - In GitHub, send a pull request.
40 | - If we suggest changes then:
41 |
42 | - Make the required updates.
43 | - Re-run the test suites to ensure tests are still passing.
44 | - Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
45 |
46 | ```shell
47 | git rebase main -i
48 | git push -f
49 | ```
50 |
51 | That's it! Thank you for your contribution!
52 |
--------------------------------------------------------------------------------
/CONTRIBUTING_CN.md:
--------------------------------------------------------------------------------
1 | # 贡献到 ko
2 |
3 | We use **pnpm workspace** to manage our packages. so make sure you use **pnpm** as package manager than **npm** or **yarn**.
4 | 我们使用 **pnpm workspace** 来管理我们的包,请确保您使用 **pnpm** 作为包管理器,而不是 **npm** 或 **yarn**。
5 |
6 | 在使用此仓库之前:
7 | ``` bash
8 | pnpm install
9 | ```
10 |
11 | ## 代码结构
12 |
13 | 作为一个 monorepo,ko 现在在 packages 目录中维护了 5 个包:
14 |
15 | * **ko**: 主要包
16 | * **ko-lints**: 代码格式化 cli, 包 **eslint**, **prettier** 和 **stylelint**, 可以集成到 ko 中或单独使用
17 | * **ko-config**: **ko-lints** 使用的默认配置
18 | * **ko-lint-config**: 代码格式化配置,包括 **eslint**, **prettier** 和 **stylelint**
19 | * **babel-preset-ko-app**: ko 使用的 babel 预设
20 |
21 | ### 调试
22 |
23 | 使用 `pnpm debug` 调试本地包
24 |
25 | ### 本地测试
26 |
27 | 使用 **pnpm link** 将 `ko` 链接到本地包中进行测试
28 |
29 | ## 提交 Pull Request (PR)
30 |
31 | 在提交 Pull Request (PR) 之前,请考虑以下准则:
32 | - 在存储库的根目录中运行 `pnpm changeset`,并描述您的更改。生成的文件应该被提交,因为它们将在发布时使用。
33 | - 运行完整的测试套件,并确保所有测试都通过。
34 | - 推送您的分支到 GitHub:
35 |
36 | ```shell
37 | git push origin my-fix-branch
38 | ```
39 |
40 | - 在 GitHub 上发送一个 pull request。
41 | - 如果我们建议更改,则:
42 |
43 | - Make the required updates.
44 | - Re-run the test suites to ensure tests are still passing.
45 | - Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
46 | - 进行所需的更新。
47 |
48 | - 重新运行测试套件,以确保测试仍然通过。
49 |
50 | - 将您的分支 rebase 并强制推送到您的 GitHub 存储库(这将更新您的 Pull Request):
51 |
52 | ```shell
53 | git rebase main -i
54 | git push -f
55 | ```
56 |
57 | 感谢您的贡献!
58 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
KO
5 |
Simple, yet powerful, tool for managing your react applications
6 |
7 |
8 |
9 |
10 |
11 | English | [简体中文](./README_CN.md)
12 | ## Features
13 |
14 | * Support building applications on top of **webpack v5** and **esbuild**
15 | * Customize ko to work exactly the way you need it for your applications
16 | * Built-in popular linting tools to lint your source code
17 | * Built-in support typescript
18 |
19 | ## Installation
20 |
21 | You can install ko using npm, yarn or pnpm:
22 | ``` bash
23 | npm install ko --save-dev
24 | # or
25 | yarn add ko --dev
26 | # or
27 | pnpm add ko --save-dev
28 | ```
29 |
30 | ## Documents
31 | * [Introduction](https://dtstack.github.io/ko/zh-CN/docs/current/introduction)
32 | * [Getting Started](https://dtstack.github.io/ko/zh-CN/docs/current/getting-started)
33 | * [FAQ](https://dtstack.github.io/ko/zh-CN/docs/current/FAQ)
34 |
35 | ## Contributing
36 |
37 | We'd love to have your helping hand on `ko`! See [CONTRIBUTING](./CONTRIBUTING.md) for more information on how to get started.
38 |
39 | ## License
40 |
41 | Copyright © DTStack. All rights reserved.
42 |
43 | Licensed under the MIT license.
44 |
--------------------------------------------------------------------------------
/README_CN.md:
--------------------------------------------------------------------------------
1 | # ko
2 |
3 | ## 一个简单而强大的工具,用于管理您的 React 应用程序。
4 |
5 |
6 |
7 | ## 特点
8 |
9 | * 支持在 **webpack v5** 和 **esbuild** 上构建应用程序
10 | * 定制 ko,使其完全按照您的应用程序需求工作
11 | * 内置流行的 lint 工具,用于对源代码进行 lint
12 | * 内置支持 TypeScript
13 |
14 | ## 安装
15 |
16 | 您可以使用 npm、yarn 或 pnpm 安装 ko:
17 | ``` bash
18 | npm install ko --save-dev
19 | # 或者
20 | yarn add ko --dev
21 | # 或者
22 | pnpm add ko --save-dev
23 | ```
24 |
25 | ## 文档
26 | * [介绍](https://dtstack.github.io/ko/docs/current/introduction)
27 | * [入门指南](https://dtstack.github.io/ko/docs/current/getting-started)
28 | * [常见问题](https://dtstack.github.io/ko/docs/current/FAQ)
29 |
30 | ## Contributing
31 |
32 | 我们很乐意在 `ko` 上得到您的帮助!有关如何入手的更多信息,请参见 [CONTRIBUTING](./CONTRIBUTING_CN.md)。
33 |
34 | ## License
35 |
36 | 版权所有 © DTStack。保留所有权利。
37 |
38 | 根据 MIT 许可证获得许可。
39 |
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['@commitlint/config-conventional'],
3 | rules: {
4 | 'type-case': [2, 'always', 'lower-case'],
5 | 'scope-case': [0, 'always'],
6 | },
7 | ignores: [message => message.includes('Releases:')],
8 | };
9 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "workspaces": [
4 | "packages/*"
5 | ],
6 | "scripts": {
7 | "prepare": "husky install",
8 | "prettier:check": "prettier --config .prettierrc --ignore-path .gitignore --ignore-path .prettierignore --check .",
9 | "prettier:write": "prettier --config .prettierrc --ignore-path .gitignore --ignore-path .prettierignore --write .",
10 | "check": "pnpm prettier:check",
11 | "test": "pnpm test",
12 | "debug:ko": "pnpm --filter ./packages/ko debug",
13 | "debug:ko-lints": "pnpm --filter ./packages/ko-lints debug",
14 | "debug:plugins": "pnpm --filter ./packages/auto-polyfills-webpack-plugin debug & pnpm --filter ./packages/dynamic-resolve-webpack-plugin debug",
15 | "debug:all": "pnpm debug:ko & pnpm debug:ko-lints & pnpm debug:plugins",
16 | "docs:start": "cd website && pnpm start",
17 | "changeset": "pnpm run prettier:write && changeset",
18 | "bump": "changeset version",
19 | "release": "changeset publish"
20 | },
21 | "config": {
22 | "commitizen": {
23 | "path": "cz-conventional-changelog"
24 | }
25 | },
26 | "devDependencies": {
27 | "@changesets/cli": "^2.26.0",
28 | "@commitlint/cli": "^17.4.4",
29 | "@commitlint/config-conventional": "^17.4.4",
30 | "@tsconfig/node14": "^1.0.3",
31 | "@types/node": "^17.0.45",
32 | "commitizen": "^4.3.0",
33 | "cz-conventional-changelog": "^3.3.0",
34 | "husky": "^8.0.3",
35 | "prettier": "^2.8.4"
36 | },
37 | "packageManager": "pnpm@6.32.12"
38 | }
39 |
--------------------------------------------------------------------------------
/packages/auto-polyfills-webpack-plugin/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # auto-polyfills-webpack-plugin
2 |
3 | ## 2.0.0
4 |
5 | ### Major Changes
6 |
7 | - ded1b6ee5: add new scope for packages
8 |
9 | ## 1.1.1
10 |
11 | ### Patch Changes
12 |
13 | - 4e63e269: support Windows
14 |
15 | ## 1.1.0
16 |
17 | ### Minor Changes
18 |
19 | - fba9a04c: support new option
20 | - auto-polyfills-webpack-plugin: support longTermCache option to decide whether or not to store cache polyfills.
21 |
22 | ## 1.0.2
23 |
24 | ### Patch Changes
25 |
26 | - 55aa11c9: fix bug
27 | - auto polyfills webpack plugin can't read browserslist correctly
28 |
29 | ## 1.0.1
30 |
31 | ### Patch Changes
32 |
33 | - 3508d49b: fixed bugs of can't send correct core-js-builder options
34 |
35 | ## 1.0.0
36 |
37 | ### Major Changes
38 |
39 | - 403d780e: release auto-polyfills-webpack-plugin, and support it in ko
40 |
41 | 1. release auto-polyfills-webpack-plugin, find more in it's README
42 | 2. add auto-polyfills-webpack-plugin & dynamic-resolve-webpack-plugin into ko, and support change these plugins via config options:
43 |
44 | ```js
45 | export type IOptions = {
46 | dynamicResolve?: (request: T) => T;
47 | autoPolyfills: boolean | AutoPolyfillsWebpackPluginOptions;
48 | }
49 | ```
50 |
--------------------------------------------------------------------------------
/packages/auto-polyfills-webpack-plugin/README.md:
--------------------------------------------------------------------------------
1 | A webpack plugin for auto import polyfills using core-js custom build, you can combine it with esbuild-loader because esbuild-loader don't do auto polyfills
2 |
3 | ## Getting Started
4 | 1. Install as devDependencies:
5 | ``` bash
6 | pnpm install auto-polyfills-webpack-plugin -D
7 | ```
8 |
9 | 2. then add it into webpack plugins config:
10 |
11 | ```js
12 | config.plugins.push(
13 | new AutoPolyfillsWebpackPlugin();
14 | );
15 | ```
16 |
17 | and a minified file will be generated in project root (or custom with option cwd), then you should commit it for reused.
18 |
19 | ## Options
20 |
21 | ```ts
22 | type IOpts = {
23 | cwd?: string; // cwd, default value is `process.cwd()`
24 | browserslistPath?: string; // default value is .browserslistrc in root directory
25 | hashType?: string; // crypto type, default value is md5
26 | customPrefix?: string; //custom polyfill prefix, default value is 'dt'
27 | excludeCoreJsModules?: string[]; //exclude core-js modules.
28 | };
29 | ```
--------------------------------------------------------------------------------
/packages/auto-polyfills-webpack-plugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@dtinsight/auto-polyfills-webpack-plugin",
3 | "version": "2.0.0",
4 | "description": "a webpack plugin for auto generate polyfills",
5 | "main": "lib/index.js",
6 | "typings": "lib/index.d.ts",
7 | "scripts": {
8 | "prepublishOnly": "rm -rf lib && tsc",
9 | "build": "rm -rf lib && tsc",
10 | "debug": "rm -rf lib && tsc --sourcemap -w"
11 | },
12 | "peerDependencies": {
13 | "core-js": "^3",
14 | "html-webpack-plugin": "^5.5.0",
15 | "webpack": "^5.72.1"
16 | },
17 | "devDependencies": {
18 | "html-webpack-plugin": "^5.5.0",
19 | "webpack": "^5.72.1"
20 | },
21 | "author": "xbrave",
22 | "license": "MIT",
23 | "dependencies": {
24 | "core-js-builder": "^3.24.1",
25 | "terser": "^5.15.0"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/packages/auto-polyfills-webpack-plugin/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@tsconfig/node14/tsconfig.json",
3 | "include": ["**/*.ts", "index.d.ts"],
4 | "compilerOptions": {
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "esModuleInterop": true,
8 | "strict": true,
9 | "strictPropertyInitialization": false,
10 | "outDir": "lib",
11 | "declaration": true
12 | },
13 | }
--------------------------------------------------------------------------------
/packages/babel-preset-ko-app/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # babel-preset-ko-app
2 |
3 | ## 1.0.0
4 |
5 | ### Minor Changes
6 |
7 | - support typescript preset
8 |
--------------------------------------------------------------------------------
/packages/babel-preset-ko-app/README.md:
--------------------------------------------------------------------------------
1 | # babel-preset-ko-app
2 |
3 | This package includes the Babel preset used by [ko](https://github.com/DTStack/ko)
4 |
5 | ## Usage Outside of ko
6 |
7 | please checkout how to [Using a Preset](https://babeljs.io/docs/en/presets#using-a-preset)
8 |
9 | ```json
10 | {
11 | "presets": ["ko-app"]
12 | }
13 | ```
14 |
15 | ## Output targets
16 |
17 | We assume that you know Babel Config Option [Output targets](https://babeljs.io/docs/en/options#output-targets).And it's great to use [`browserslist`](https://github.com/browserslist/browserslist) to manage babel output targets.
18 |
--------------------------------------------------------------------------------
/packages/babel-preset-ko-app/index.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | module.exports = function (api, opts = {}) {
4 | let absoluteRuntimePath = false;
5 | if (opts.useAbsoluteRuntime) {
6 | absoluteRuntimePath = path.dirname(
7 | require.resolve('@babel/runtime/package.json')
8 | );
9 | }
10 | const env = process.env.BABEL_ENV || process.env.NODE_ENV;
11 | const isProd = env === 'production';
12 | return {
13 | assumptions: {
14 | //use assignment rather than using Object.defineProperty
15 | setPublicClassFields: true,
16 | },
17 | presets: [
18 | [
19 | require('@babel/preset-env').default,
20 | {
21 | useBuiltIns: 'entry',
22 | corejs: 3,
23 | // Exclude transforms that make all code slower
24 | exclude: ['transform-typeof-symbol'],
25 | },
26 | ],
27 | [
28 | require('@babel/preset-react').default,
29 | {
30 | development: !isProd,
31 | },
32 | ],
33 | [require('@babel/preset-typescript').default],
34 | ],
35 | plugins: [
36 | //support proposal decorators
37 | //NOTE: https://babeljs.io/docs/en/babel-plugin-proposal-decorators#note-compatibility-with-babelplugin-proposal-class-properties
38 | [require('@babel/plugin-proposal-decorators').default, { legacy: true }],
39 | [
40 | require('@babel/plugin-transform-runtime').default,
41 | {
42 | corejs: false,
43 | version: require('@babel/runtime/package.json').version,
44 | regenerator: true,
45 | absoluteRuntime: absoluteRuntimePath,
46 | },
47 | ],
48 | ...(opts.customizePlugins || []),
49 | ],
50 | };
51 | };
52 |
--------------------------------------------------------------------------------
/packages/babel-preset-ko-app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "babel-preset-ko-app",
3 | "version": "1.0.0",
4 | "description": "Babel preset used by ko",
5 | "keywords": [
6 | "ko",
7 | "ko-script",
8 | "babel",
9 | "babel-presets",
10 | "ko-app"
11 | ],
12 | "bugs": {
13 | "url": "https://github.com/DTStack/ko/issues"
14 | },
15 | "repository": {
16 | "type": "git",
17 | "url": "https://github.com/DTStack/ko",
18 | "directory": "packages/babel-preset-ko-app"
19 | },
20 | "license": "MIT",
21 | "main": "index.js",
22 | "dependencies": {
23 | "@babel/core": "^7.18.0",
24 | "@babel/plugin-proposal-decorators": "^7.17.12",
25 | "@babel/plugin-transform-runtime": "^7.18.0",
26 | "@babel/preset-env": "^7.18.0",
27 | "@babel/preset-react": "^7.17.12",
28 | "@babel/preset-typescript": "^7.17.12",
29 | "@babel/runtime": "^7.18.0"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/packages/create-ko/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # create-ko
2 |
3 | ## 1.0.2
4 |
5 | ### Patch Changes
6 |
7 | - dd8e687d7: update jsdoc for create-ko template
8 |
9 | ## 1.0.1
10 |
11 | ### Patch Changes
12 |
13 | - ce2d5bc7d: add init project
14 |
--------------------------------------------------------------------------------
/packages/create-ko/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
ko
5 |
Simple, yet powerful, tool for managing your react applications
6 |
7 |
8 |
9 | # create-ko
10 |
11 | This package is the global command for creating [ko](https://github.com/DTStack/ko) application.
12 |
13 |
14 |
15 | Please refer to ko's document:
16 |
17 | * [Introduction](https://dtstack.github.io/ko/docs/current/introduction)
18 | * [Getting Started](https://dtstack.github.io/ko/docs/current/getting-started)
19 | * [FAQ](https://dtstack.github.io/ko/docs/current/FAQ)
--------------------------------------------------------------------------------
/packages/create-ko/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "create-ko",
3 | "version": "1.0.2",
4 | "description": "create react project with ko",
5 | "repository": {
6 | "type": "git",
7 | "url": "https://github.com/DTStack/ko",
8 | "directory": "packages/create-ko"
9 | },
10 | "main": "./src/index.ts",
11 | "bin": {
12 | "create-ko": "./lib/index.js"
13 | },
14 | "files": [
15 | "lib/*",
16 | "template"
17 | ],
18 | "scripts": {
19 | "build": "tsc"
20 | },
21 | "author": "",
22 | "license": "ISC",
23 | "dependencies": {
24 | "commander": "^9.2.0",
25 | "inquirer": "^8.2.2"
26 | },
27 | "devDependencies": {
28 | "@types/inquirer": "^8.2.2"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/packages/create-ko/template/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: [require.resolve('ko-lint-config/.eslintrc')],
3 | };
4 |
--------------------------------------------------------------------------------
/packages/create-ko/template/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | *.log
3 | npm-debug.log*
4 | yarn-debug.log*
5 | yarn-error.log*
6 |
7 | # Runtime data
8 | *.pid
9 | *.seed
10 | *.pid.lock
11 |
12 | # Directory for instrumented libs generated by jscoverage/JSCover
13 | lib-cov
14 |
15 | # Coverage directory used by tools like istanbul
16 | coverage
17 |
18 | # nyc test coverage
19 | .nyc_output
20 |
21 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
22 | .grunt
23 |
24 | # Bower dependency directory (https://bower.io/)
25 | bower_components
26 |
27 | # node-waf configuration
28 | .lock-wscript
29 |
30 | # Compiled binary addons (https://nodejs.org/api/addons.html)
31 | build/Release
32 |
33 | # Dependency directories
34 | **/node_modules
35 | jspm_packages/
36 |
37 | # Optional npm cache directory
38 | .npm
39 |
40 | # Optional eslint cache
41 | .eslintcache
42 |
43 | # Optional REPL history
44 | .node_repl_history
45 |
46 | # Output of 'npm pack'
47 | *.tgz
48 |
49 | # Yarn Integrity file
50 | .yarn-integrity
51 |
52 | # dotenv environment variables file
53 | .env
54 |
55 | # next.js build output
56 | .next
57 |
58 | # OS X temporary files
59 | .DS_Store
60 |
61 | # Heft
62 | .heft
63 |
64 | # 打包后的产物
65 | build/**
66 |
67 | **/dist
68 | **/website
69 |
70 | # Misc
71 | .turbo
72 | *.csv
73 | dist
74 | .vscode
75 | .idea
76 | config.json
77 | !schema/**
78 | !benchmark.log
79 |
--------------------------------------------------------------------------------
/packages/create-ko/template/.prettierrc.js:
--------------------------------------------------------------------------------
1 | const prettier = require('ko-lint-config/.prettierrc');
2 |
3 | module.exports = {
4 | ...prettier,
5 | };
6 |
--------------------------------------------------------------------------------
/packages/create-ko/template/.stylelintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['ko-lint-config/.stylelintrc'],
3 | };
4 |
--------------------------------------------------------------------------------
/packages/create-ko/template/ko.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | const finalKoConfig = (function () {
4 | const ROOT_PATH = process.cwd();
5 | const APP_PATH = path.resolve(ROOT_PATH, 'src');
6 | const BUILD_PATH = path.resolve(ROOT_PATH, `dist`);
7 | const WEB_PUBLIC = path.resolve(APP_PATH, 'public');
8 | /**
9 | * @type {import("ko/lib/types").IOptions}
10 | */
11 | const baseKoConfig = {
12 | entry: path.join(APP_PATH, './main.tsx'),
13 | outputPath: BUILD_PATH,
14 | staticPath: APP_PATH,
15 | htmlTemplate: path.join(APP_PATH, './public/index.html'),
16 | alias: {
17 | '@': path.resolve('src'),
18 | public: path.resolve('src/public/'),
19 | styles: path.resolve('src/styles/'),
20 | },
21 | serve: {
22 | staticPath: path.join(process.cwd(), './src/public'),
23 | },
24 | copy: [
25 | {
26 | from: path.resolve(WEB_PUBLIC),
27 | to: path.resolve(BUILD_PATH, 'public'),
28 | globOptions: {
29 | dot: true,
30 | gitignore: true,
31 | ignore: ['**/index.html'],
32 | },
33 | },
34 | ],
35 | // more config can find in https://dtstack.github.io/ko/docs/current/configuration
36 | };
37 | // You can add extra ko config here
38 | const extraConfig = {};
39 | // You can add extra plugins config here
40 | const plugins = [];
41 | const config = { ...baseKoConfig, ...extraConfig, plugins };
42 | return config;
43 | })();
44 |
45 | module.exports = finalKoConfig;
46 |
--------------------------------------------------------------------------------
/packages/create-ko/template/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ko-project",
3 | "private": true,
4 | "version": "1.0.0",
5 | "scripts": {
6 | "dev": "ko dev",
7 | "build": "ko build",
8 | "prettier": "ko prettier ./**/*.{ts,tsx,js,jsx} --concurrency",
9 | "prettier:fix": "ko prettier ./**/*.{ts,tsx,js,jsx} --write --concurrency",
10 | "eslint": "ko eslint ./**/*.{ts,tsx,js,jsx} --concurrency",
11 | "eslint:fix": "ko eslint ./**/*.{ts,tsx,js,jsx} --write --concurrency",
12 | "stylelint": "ko stylelint ./**/*.{css,sass,scss,less} --concurrency",
13 | "stylelint:fix": "ko stylelint ./**/*.{css,sass,scss,less} --write --concurrency"
14 | },
15 | "dependencies": {
16 | "react": "^18.2.0",
17 | "react-dom": "^18.2.0"
18 | },
19 | "devDependencies": {
20 | "@types/react": "^18.0.37",
21 | "@types/react-dom": "^18.0.11",
22 | "typescript": "^5.0.2",
23 | "ko": "^6.5.2",
24 | "ko-lint-config": "^2.2.19"
25 | }
26 | }
--------------------------------------------------------------------------------
/packages/create-ko/template/src/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import '@/styles/App.css';
3 |
4 | function App() {
5 | return (
6 | <>
7 |
23 | KO + React
24 |
25 |
26 | Edit src/App.tsx
and save to test HMR
27 |
28 |
29 |
30 | Click on the KO and React logos to learn more
31 |
32 | >
33 | );
34 | }
35 |
36 | export default App;
37 |
--------------------------------------------------------------------------------
/packages/create-ko/template/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import App from './App';
4 | import '@/styles/index.css';
5 |
6 | ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
7 |
8 |
9 |
10 | );
11 |
--------------------------------------------------------------------------------
/packages/create-ko/template/src/public/assets/KO.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 | 画板
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/packages/create-ko/template/src/public/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/create-ko/template/src/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DTStack/ko/ac25ced47831ef98ba6c360c591373bded72786d/packages/create-ko/template/src/public/favicon.ico
--------------------------------------------------------------------------------
/packages/create-ko/template/src/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | KO + React + TS
5 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/packages/create-ko/template/src/styles/App.css:
--------------------------------------------------------------------------------
1 | #root {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | will-change: filter;
12 | transition: filter 300ms;
13 | }
14 |
15 | .logo:hover {
16 | filter: drop-shadow(0 0 2em #646cffaa);
17 | }
18 |
19 | .logo.react:hover {
20 | filter: drop-shadow(0 0 2em #61dafbaa);
21 | }
22 |
23 | @keyframes logo-spin {
24 | from {
25 | transform: rotate(0deg);
26 | }
27 | to {
28 | transform: rotate(360deg);
29 | }
30 | }
31 |
32 | @media (prefers-reduced-motion: no-preference) {
33 | a:nth-of-type(2) .logo {
34 | animation: logo-spin infinite 20s linear;
35 | }
36 | }
37 |
38 | .card {
39 | padding: 2em;
40 | }
41 |
42 | .read-the-docs {
43 | color: #888;
44 | }
45 |
--------------------------------------------------------------------------------
/packages/create-ko/template/src/styles/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3 | line-height: 1.5;
4 | font-weight: 400;
5 | color-scheme: light dark;
6 | color: rgba(255, 255, 255, 0.87);
7 | background-color: #242424;
8 | font-synthesis: none;
9 | text-rendering: optimizelegibility;
10 | -webkit-font-smoothing: antialiased;
11 | -moz-osx-font-smoothing: grayscale;
12 | -webkit-text-size-adjust: 100%;
13 | }
14 |
15 | a {
16 | font-weight: 500;
17 | color: #646cff;
18 | text-decoration: inherit;
19 | }
20 |
21 | a:hover {
22 | color: #535bf2;
23 | }
24 |
25 | body {
26 | margin: 0;
27 | display: flex;
28 | place-items: center;
29 | min-width: 320px;
30 | min-height: 100vh;
31 | }
32 |
33 | h1 {
34 | font-size: 3.2em;
35 | line-height: 1.1;
36 | }
37 |
38 | button {
39 | border-radius: 8px;
40 | border: 1px solid transparent;
41 | padding: 0.6em 1.2em;
42 | font-size: 1em;
43 | font-weight: 500;
44 | font-family: inherit;
45 | background-color: #1a1a1a;
46 | cursor: pointer;
47 | transition: border-color 0.25s;
48 | }
49 |
50 | button:hover {
51 | border-color: #646cff;
52 | }
53 |
54 | button:focus,
55 | button:focus-visible {
56 | outline: 4px auto -webkit-focus-ring-color;
57 | }
58 |
59 | @media (prefers-color-scheme: light) {
60 | :root {
61 | color: #213547;
62 | background-color: #fff;
63 | }
64 | a:hover {
65 | color: #747bff;
66 | }
67 | button {
68 | background-color: #f9f9f9;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/packages/create-ko/template/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "noEmit": true, // Don't emit; allow Babel to transform files.
4 | "outDir": "./dist/",
5 | "baseUrl": ".",
6 | "experimentalDecorators": true,
7 | "noImplicitAny": false,
8 | "esModuleInterop": true,
9 | "allowJs": true,
10 | "skipLibCheck": true,
11 | "module": "commonjs",
12 | "target": "es5",
13 | "lib": ["es6", "es2018", "dom"],
14 | "jsx": "react",
15 | "allowSyntheticDefaultImports": true,
16 | "downlevelIteration": true,
17 | "paths": {
18 | "@/*": ["./src/*"],
19 | "styles/*": ["./src/styles/*"]
20 | },
21 | "typeRoots": ["node", "node_modules/@types", "./typings"]
22 | },
23 | "exclude": ["node_modules", "dist", "src/public/**/*"],
24 | "include": ["./**/*.ts", "./**/*.tsx", "src/**/*"]
25 | }
26 |
--------------------------------------------------------------------------------
/packages/create-ko/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@tsconfig/node14/tsconfig.json",
3 | "include": ["src/**/*.ts", "index.d.ts"],
4 | "exclude": ["src/**/*.test.ts"],
5 | "compilerOptions": {
6 | "allowJs": true,
7 | "skipLibCheck": true,
8 | "esModuleInterop": true,
9 | "strict": true,
10 | "strictPropertyInitialization": false,
11 | "outDir": "lib",
12 | },
13 | }
--------------------------------------------------------------------------------
/packages/dynamic-resolve-webpack-plugin/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # dynamic-resolve-webpack-plugin
2 |
3 | ## 2.0.0
4 |
5 | ### Major Changes
6 |
7 | - cb8af539: init dynamic-resolve-webpack-plugin
8 |
--------------------------------------------------------------------------------
/packages/dynamic-resolve-webpack-plugin/README.md:
--------------------------------------------------------------------------------
1 | A webpack plugin for dynamic resolve paths, you can use it to resolve paths dynamically.
2 |
3 | ## Getting Started
4 | 1. Install as devDependencies:
5 | ``` bash
6 | pnpm install dynamic-resolve-webpack-plugin -D
7 | ```
8 |
9 | 2. custom dynamic resolve function:
10 | ```js
11 | const targetDir = path.resolve('./custom-icon');
12 | const baseDir = require
13 | .resolve('@ant-design/icons-svg')
14 | .replace(/lib\/index\.js/, 'es/asn/');
15 | const scopeList = list.map((file) => path.join(baseDir, file));
16 |
17 | function dynamic(request) {
18 | const innerPath = request.request || request.path;
19 | if (scopeList.includes(innerPath)) {
20 | request.path = path.join(targetDir, innerPath.split(baseDir)[1]);
21 | return request;
22 | }
23 | return request;
24 | }
25 |
26 | ```
27 | 3. then add it to webpack resolve plugin config:
28 |
29 | ```js
30 | config.resolve.plugins.push(
31 | new DynamicResolvePlugin({
32 | dynamic,
33 | })
34 | );
35 | ```
36 | **Ensure This Plugin is used in [webpack resolve plugins](https://webpack.js.org/configuration/resolve/#resolveplugins)**
37 |
38 | ## Options
39 |
40 | ```ts
41 | type IOptions = {
42 | source: string; // enhanced-resolve register hook, default value is `file`
43 | target: string; // next hooks to call, default value is `final-file`
44 | dynamic: (request: T) => T; //dynamic function, you can do whatever you want with callback parameter request, and you should return it back after modified.
45 | };
46 | ```
--------------------------------------------------------------------------------
/packages/dynamic-resolve-webpack-plugin/index.ts:
--------------------------------------------------------------------------------
1 | import { ResolvePluginInstance, Resolver } from 'webpack';
2 |
3 | export type IOptions = {
4 | source?: string;
5 | target?: string;
6 | dynamic: (request: T) => T;
7 | };
8 |
9 | class DynamicResolveWebpackPlugin implements ResolvePluginInstance {
10 | private opts: IOptions;
11 | constructor(opts: IOptions) {
12 | this.opts = opts;
13 | if (!this.opts.dynamic) {
14 | throw new SyntaxError('dynamic callback function is noop');
15 | }
16 | }
17 |
18 | apply(resolver: Resolver) {
19 | const { source = 'file', target = 'final-file', dynamic } = this.opts;
20 | resolver.ensureHook(source);
21 | resolver.ensureHook(target);
22 | resolver
23 | .getHook(source)
24 | .tapAsync(DynamicResolveWebpackPlugin.name, (request, ctx, callback) => {
25 | const newResolve = dynamic(request);
26 | return resolver.doResolve(
27 | target,
28 | newResolve,
29 | `${DynamicResolveWebpackPlugin.name}: ${request.path}`,
30 | ctx,
31 | (err: Error, result: any) => {
32 | if (err) return callback(err);
33 | if (result) return callback(null, result);
34 | return callback();
35 | }
36 | );
37 | });
38 | }
39 | }
40 |
41 | export default DynamicResolveWebpackPlugin;
42 |
--------------------------------------------------------------------------------
/packages/dynamic-resolve-webpack-plugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "dynamic-resolve-webpack-plugin",
3 | "version": "2.0.0",
4 | "description": "a webpack plugin for dynamic resolve paths",
5 | "main": "lib/index.js",
6 | "typings": "lib/index.d.ts",
7 | "scripts": {
8 | "prepublishOnly": "rm -rf lib && tsc",
9 | "build": "rm -rf lib && tsc",
10 | "debug": "rm -rf lib && tsc --sourcemap -w"
11 | },
12 | "peerDependencies": {
13 | "webpack": "^5 || ^4"
14 | },
15 | "devDependencies": {
16 | "webpack": "^5.72.1"
17 | },
18 | "author": "xbrave",
19 | "license": "MIT"
20 | }
21 |
--------------------------------------------------------------------------------
/packages/dynamic-resolve-webpack-plugin/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@tsconfig/node14/tsconfig.json",
3 | "include": ["**/*.ts", "index.d.ts"],
4 | "compilerOptions": {
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "esModuleInterop": true,
8 | "strict": true,
9 | "strictPropertyInitialization": false,
10 | "outDir": "lib",
11 | "declaration": true
12 | },
13 | }
--------------------------------------------------------------------------------
/packages/eslint-plugin-dt-react/index.js:
--------------------------------------------------------------------------------
1 | const rules = {
2 | 'jsx-closing-bracket-location': require('./rules/jsx-closing-bracket-location'),
3 | 'jsx-tag-spacing': require('./rules/jsx-tag-spacing'),
4 | 'jsx-wrap-multilines': require('./rules/jsx-wrap-multilines'),
5 | 'self-closing-comp': require('./rules/self-closing-comp'),
6 | };
7 |
8 | module.exports = {
9 | rules,
10 | configs: {
11 | all: {
12 | plugins: ['dt-react'],
13 | rules,
14 | },
15 | },
16 | };
17 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-dt-react/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "eslint-plugin-dt-react",
3 | "version": "0.0.6",
4 | "description": "",
5 | "main": "index.js",
6 | "author": "",
7 | "license": "MIT",
8 | "dependencies": {
9 | "eslint": "^8.16.0",
10 | "object.hasown": "^1.1.1",
11 | "semver": "^7.3.7"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-dt-react/rules/self-closing-comp.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview Prevent extra closing tags for components without children
3 | * @author Yannick Croissant
4 | */
5 |
6 | 'use strict';
7 |
8 | const jsxUtil = require('../utils/jsx');
9 | const report = require('../utils/report');
10 |
11 | // ------------------------------------------------------------------------------
12 | // Rule Definition
13 | // ------------------------------------------------------------------------------
14 |
15 | const optionDefaults = { component: true, html: true };
16 |
17 | const messages = {
18 | notSelfClosing: 'Empty components are self-closing',
19 | };
20 |
21 | module.exports = {
22 | meta: {
23 | docs: {
24 | description: 'Prevent extra closing tags for components without children',
25 | category: 'Stylistic Issues',
26 | recommended: false,
27 | url: 'https://github.com/DTStack/Code-Style-Guide/blob/master/react/README.md#tags',
28 | },
29 | fixable: 'code',
30 |
31 | messages,
32 |
33 | schema: [
34 | {
35 | type: 'object',
36 | properties: {
37 | component: {
38 | default: optionDefaults.component,
39 | type: 'boolean',
40 | },
41 | html: {
42 | default: optionDefaults.html,
43 | type: 'boolean',
44 | },
45 | },
46 | additionalProperties: false,
47 | },
48 | ],
49 | },
50 |
51 | create(context) {
52 | function isComponent(node) {
53 | return (
54 | node.name &&
55 | (node.name.type === 'JSXIdentifier' ||
56 | node.name.type === 'JSXMemberExpression') &&
57 | !jsxUtil.isDOMComponent(node)
58 | );
59 | }
60 |
61 | function childrenIsEmpty(node) {
62 | return node.parent.children.length === 0;
63 | }
64 |
65 | function childrenIsMultilineSpaces(node) {
66 | const childrens = node.parent.children;
67 |
68 | return (
69 | childrens.length === 1 &&
70 | (childrens[0].type === 'Literal' || childrens[0].type === 'JSXText') &&
71 | childrens[0].value.indexOf('\n') !== -1 &&
72 | childrens[0].value.replace(/(?!\xA0)\s/g, '') === ''
73 | );
74 | }
75 |
76 | function isShouldBeSelfClosed(node) {
77 | const configuration = Object.assign(
78 | {},
79 | optionDefaults,
80 | context.options[0]
81 | );
82 | return (
83 | ((configuration.component && isComponent(node)) ||
84 | (configuration.html && jsxUtil.isDOMComponent(node))) &&
85 | !node.selfClosing &&
86 | (childrenIsEmpty(node) || childrenIsMultilineSpaces(node))
87 | );
88 | }
89 |
90 | return {
91 | JSXOpeningElement(node) {
92 | if (!isShouldBeSelfClosed(node)) {
93 | return;
94 | }
95 | report(context, messages.notSelfClosing, 'notSelfClosing', {
96 | node,
97 | fix(fixer) {
98 | // Represents the last character of the JSXOpeningElement, the '>' character
99 | const openingElementEnding = node.range[1] - 1;
100 | // Represents the last character of the JSXClosingElement, the '>' character
101 | const closingElementEnding = node.parent.closingElement.range[1];
102 |
103 | // Replace />.*<\/.*>/ with '/>'
104 | const range = [openingElementEnding, closingElementEnding];
105 | return fixer.replaceTextRange(range, ' />');
106 | },
107 | });
108 | },
109 | };
110 | },
111 | };
112 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-dt-react/utils/getTokenBeforeClosingBracket.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Find the token before the closing bracket.
5 | * @param {ASTNode} node - The JSX element node.
6 | * @returns {Token} The token before the closing bracket.
7 | */
8 | function getTokenBeforeClosingBracket(node) {
9 | const attributes = node.attributes;
10 | if (!attributes || attributes.length === 0) {
11 | return node.name;
12 | }
13 | return attributes[attributes.length - 1];
14 | }
15 |
16 | module.exports = getTokenBeforeClosingBracket;
17 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-dt-react/utils/isCreateElement.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const pragmaUtil = require('./pragma');
4 | const isDestructuredFromPragmaImport = require('./isDestructuredFromPragmaImport');
5 |
6 | /**
7 | * Checks if the node is a createElement call
8 | * @param {ASTNode} node - The AST node being checked.
9 | * @param {Context} context - The AST node being checked.
10 | * @returns {Boolean} - True if node is a createElement call object literal, False if not.
11 | */
12 | module.exports = function isCreateElement(node, context) {
13 | const pragma = pragmaUtil.getFromContext(context);
14 | if (
15 | node.callee &&
16 | node.callee.type === 'MemberExpression' &&
17 | node.callee.property.name === 'createElement' &&
18 | node.callee.object &&
19 | node.callee.object.name === pragma
20 | ) {
21 | return true;
22 | }
23 |
24 | if (
25 | node &&
26 | node.callee &&
27 | node.callee.name === 'createElement' &&
28 | isDestructuredFromPragmaImport('createElement', context)
29 | ) {
30 | return true;
31 | }
32 |
33 | return false;
34 | };
35 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-dt-react/utils/isDestructuredFromPragmaImport.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const pragmaUtil = require('./pragma');
4 | const variableUtil = require('./variable');
5 |
6 | /**
7 | * Check if variable is destructured from pragma import
8 | *
9 | * @param {string} variable The variable name to check
10 | * @param {Context} context eslint context
11 | * @returns {Boolean} True if createElement is destructured from the pragma
12 | */
13 | module.exports = function isDestructuredFromPragmaImport(variable, context) {
14 | const pragma = pragmaUtil.getFromContext(context);
15 | const variables = variableUtil.variablesInScope(context);
16 | const variableInScope = variableUtil.getVariable(variables, variable);
17 | if (variableInScope) {
18 | const latestDef = variableUtil.getLatestVariableDefinition(variableInScope);
19 | if (latestDef) {
20 | // check if latest definition is a variable declaration: 'variable = value'
21 | if (latestDef.node.type === 'VariableDeclarator' && latestDef.node.init) {
22 | // check for: 'variable = pragma.variable'
23 | if (
24 | latestDef.node.init.type === 'MemberExpression' &&
25 | latestDef.node.init.object.type === 'Identifier' &&
26 | latestDef.node.init.object.name === pragma
27 | ) {
28 | return true;
29 | }
30 | // check for: '{variable} = pragma'
31 | if (
32 | latestDef.node.init.type === 'Identifier' &&
33 | latestDef.node.init.name === pragma
34 | ) {
35 | return true;
36 | }
37 |
38 | // "require('react')"
39 | let requireExpression = null;
40 |
41 | // get "require('react')" from: "{variable} = require('react')"
42 | if (latestDef.node.init.type === 'CallExpression') {
43 | requireExpression = latestDef.node.init;
44 | }
45 | // get "require('react')" from: "variable = require('react').variable"
46 | if (
47 | !requireExpression &&
48 | latestDef.node.init.type === 'MemberExpression' &&
49 | latestDef.node.init.object.type === 'CallExpression'
50 | ) {
51 | requireExpression = latestDef.node.init.object;
52 | }
53 |
54 | // check proper require.
55 | if (
56 | requireExpression &&
57 | requireExpression.callee &&
58 | requireExpression.callee.name === 'require' &&
59 | requireExpression.arguments[0] &&
60 | requireExpression.arguments[0].value === pragma.toLocaleLowerCase()
61 | ) {
62 | return true;
63 | }
64 |
65 | return false;
66 | }
67 |
68 | // latest definition is an import declaration: import {} from 'react'
69 | if (
70 | latestDef.parent &&
71 | latestDef.parent.type === 'ImportDeclaration' &&
72 | latestDef.parent.source.value === pragma.toLocaleLowerCase()
73 | ) {
74 | return true;
75 | }
76 | }
77 | }
78 | return false;
79 | };
80 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-dt-react/utils/pragma.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview Utility functions for React pragma configuration
3 | * @author Yannick Croissant
4 | */
5 |
6 | 'use strict';
7 |
8 | const JSX_ANNOTATION_REGEX = /@jsx\s+([^\s]+)/;
9 | // Does not check for reserved keywords or unicode characters
10 | const JS_IDENTIFIER_REGEX = /^[_$a-zA-Z][_$a-zA-Z0-9]*$/;
11 |
12 | /**
13 | * @param {Context} context
14 | * @returns {string}
15 | */
16 | function getCreateClassFromContext(context) {
17 | let pragma = 'createReactClass';
18 | // .eslintrc shared settings (https://eslint.org/docs/user-guide/configuring#adding-shared-settings)
19 | if (context.settings.react && context.settings.react.createClass) {
20 | pragma = context.settings.react.createClass;
21 | }
22 | if (!JS_IDENTIFIER_REGEX.test(pragma)) {
23 | throw new Error(
24 | `createClass pragma ${pragma} is not a valid function name`
25 | );
26 | }
27 | return pragma;
28 | }
29 |
30 | /**
31 | * @param {Context} context
32 | * @returns {string}
33 | */
34 | function getFragmentFromContext(context) {
35 | let pragma = 'Fragment';
36 | // .eslintrc shared settings (https://eslint.org/docs/user-guide/configuring#adding-shared-settings)
37 | if (context.settings.react && context.settings.react.fragment) {
38 | pragma = context.settings.react.fragment;
39 | }
40 | if (!JS_IDENTIFIER_REGEX.test(pragma)) {
41 | throw new Error(`Fragment pragma ${pragma} is not a valid identifier`);
42 | }
43 | return pragma;
44 | }
45 |
46 | /**
47 | * @param {Context} context
48 | * @returns {string}
49 | */
50 | function getFromContext(context) {
51 | let pragma = 'React';
52 |
53 | const sourceCode = context.getSourceCode();
54 | const pragmaNode = sourceCode
55 | .getAllComments()
56 | .find(node => JSX_ANNOTATION_REGEX.test(node.value));
57 |
58 | if (pragmaNode) {
59 | const matches = JSX_ANNOTATION_REGEX.exec(pragmaNode.value);
60 | pragma = matches[1].split('.')[0];
61 | // .eslintrc shared settings (https://eslint.org/docs/user-guide/configuring#adding-shared-settings)
62 | } else if (context.settings.react && context.settings.react.pragma) {
63 | pragma = context.settings.react.pragma;
64 | }
65 |
66 | if (!JS_IDENTIFIER_REGEX.test(pragma)) {
67 | throw new Error(`React pragma ${pragma} is not a valid identifier`);
68 | }
69 | return pragma;
70 | }
71 |
72 | module.exports = {
73 | getCreateClassFromContext,
74 | getFragmentFromContext,
75 | getFromContext,
76 | };
77 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-dt-react/utils/report.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const semver = require('semver');
4 | const eslintPkg = require('eslint/package.json');
5 |
6 | module.exports = function report(context, message, messageId, data) {
7 | context.report(
8 | Object.assign(
9 | messageId && semver.satisfies(eslintPkg.version, '>= 4.15')
10 | ? { messageId }
11 | : { message },
12 | data
13 | )
14 | );
15 | };
16 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-dt-react/utils/variable.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview Utility functions for React components detection
3 | * @author Yannick Croissant
4 | */
5 |
6 | 'use strict';
7 |
8 | /**
9 | * Search a particular variable in a list
10 | * @param {Array} variables The variables list.
11 | * @param {string} name The name of the variable to search.
12 | * @returns {Boolean} True if the variable was found, false if not.
13 | */
14 | function findVariable(variables, name) {
15 | return variables.some(variable => variable.name === name);
16 | }
17 |
18 | /**
19 | * Find and return a particular variable in a list
20 | * @param {Array} variables The variables list.
21 | * @param {string} name The name of the variable to search.
22 | * @returns {Object} Variable if the variable was found, null if not.
23 | */
24 | function getVariable(variables, name) {
25 | return variables.find(variable => variable.name === name);
26 | }
27 |
28 | /**
29 | * List all variable in a given scope
30 | *
31 | * Contain a patch for babel-eslint to avoid https://github.com/babel/babel-eslint/issues/21
32 | *
33 | * @param {Object} context The current rule context.
34 | * @returns {Array} The variables list
35 | */
36 | function variablesInScope(context) {
37 | let scope = context.getScope();
38 | let variables = scope.variables;
39 |
40 | while (scope.type !== 'global') {
41 | scope = scope.upper;
42 | variables = scope.variables.concat(variables);
43 | }
44 | if (scope.childScopes.length) {
45 | variables = scope.childScopes[0].variables.concat(variables);
46 | if (scope.childScopes[0].childScopes.length) {
47 | variables =
48 | scope.childScopes[0].childScopes[0].variables.concat(variables);
49 | }
50 | }
51 | variables.reverse();
52 |
53 | return variables;
54 | }
55 |
56 | /**
57 | * Find a variable by name in the current scope.
58 | * @param {Object} context The current rule context.
59 | * @param {string} name Name of the variable to look for.
60 | * @returns {ASTNode|null} Return null if the variable could not be found, ASTNode otherwise.
61 | */
62 | function findVariableByName(context, name) {
63 | const variable = getVariable(variablesInScope(context), name);
64 |
65 | if (!variable || !variable.defs[0] || !variable.defs[0].node) {
66 | return null;
67 | }
68 |
69 | if (variable.defs[0].node.type === 'TypeAlias') {
70 | return variable.defs[0].node.right;
71 | }
72 |
73 | if (variable.defs[0].type === 'ImportBinding') {
74 | return variable.defs[0].node;
75 | }
76 |
77 | return variable.defs[0].node.init;
78 | }
79 |
80 | /**
81 | * Returns the latest definition of the variable.
82 | * @param {Object} variable
83 | * @returns {Object | undefined} The latest variable definition or undefined.
84 | */
85 | function getLatestVariableDefinition(variable) {
86 | return variable.defs[variable.defs.length - 1];
87 | }
88 |
89 | module.exports = {
90 | findVariable,
91 | findVariableByName,
92 | getVariable,
93 | variablesInScope,
94 | getLatestVariableDefinition,
95 | };
96 |
--------------------------------------------------------------------------------
/packages/ko-lint-config/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | semi: true, // 行末添加分号
3 | tabWidth: 4, // tab 缩进,默认 2
4 | printWidth: 100, // 换行列数,默认 80
5 | singleQuote: true, // 单引号
6 | useTabs: false, // 使用 tab 缩进,默认 false 使用空格
7 | bracketSpacing: true, // 对象中打印空格 默认 true
8 | arrowParens: 'always', // 箭头函数参数括号 可选 avoid(一个参数时省略) | always
9 | trailingComma: 'es5', // 尾逗号 可选 none | es5 | all
10 | };
11 |
--------------------------------------------------------------------------------
/packages/ko-lint-config/.stylelintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | files: ['**/*.css', '**/*.scss'],
3 | customSyntax: require.resolve('postcss-scss'),
4 | extends: 'stylelint-config-standard',
5 | plugins: ['stylelint-order', 'stylelint-scss'],
6 | rules: {
7 | // null 为关闭规则
8 | indentation: 4, // 缩进4格
9 | 'at-rule-no-unknown': null, // 允许未知规则
10 | 'declaration-empty-line-before': 'never', // 第一条属性声明前不允许有空行
11 | 'selector-class-pattern': '[a-zA-Z]+', // className 的大小写
12 | // 规则之前的空行
13 | 'rule-empty-line-before': [
14 | 'always',
15 | {
16 | except: ['inside-block', 'first-nested', 'after-single-line-comment'],
17 | },
18 | ],
19 | 'alpha-value-notation': 'number', // 小数显示数字(number)或百分数(percentage)
20 | 'color-function-notation': 'legacy', // 颜色 rgba 等使用传统逗号隔开
21 | 'color-hex-case': 'upper', // 颜色十六进制字符大写
22 | 'selector-list-comma-newline-after': 'always-multi-line',
23 | 'max-line-length': [
24 | 300,
25 | {
26 | ignore: ['non-comments'],
27 | },
28 | ],
29 | 'font-family-no-missing-generic-family-keyword': null, // 是否必须包含通用字体
30 | 'no-descending-specificity': null, // 选择器顺序
31 | 'keyframes-name-pattern': null, // keyframes 推荐小写+连字符命名
32 | 'no-empty-source': null, // 空文件
33 | 'block-no-empty': null, // 空规则
34 | 'function-url-quotes': null, // url 不需要引号
35 | 'function-no-unknown': null, // 未知方法名
36 | 'selector-id-pattern': null, // id 使用连字符和小写字母
37 | 'selector-pseudo-class-no-unknown': [
38 | true,
39 | {
40 | ignorePseudoClasses: ['global'],
41 | },
42 | ],
43 | 'selector-no-vendor-prefix': [
44 | true,
45 | {
46 | ignoreSelectors: ['::-webkit-input-placeholder'],
47 | },
48 | ],
49 | 'at-rule-name-case': null, // less 中变量名的大小写
50 | 'selector-no-vendor-prefix': null, // 兼容写法
51 | 'property-no-vendor-prefix': null, // 兼容写法
52 | 'selector-pseudo-class-no-unknown': null, // 兼容写法
53 | 'selector-type-no-unknown': null, // 兼容写法
54 | 'number-max-precision': 10, // 数字中允许的小数位数
55 | 'value-no-vendor-prefix': null,
56 | },
57 | };
58 |
--------------------------------------------------------------------------------
/packages/ko-lint-config/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # ko-lint-config
2 |
3 | ## 2.2.21
4 |
5 | ### Patch Changes
6 |
7 | - 7f809f46: eslint ts-ignore warning
8 |
9 | ## 2.2.20
10 |
11 | ### Patch Changes
12 |
13 | - 4d4b037c: eslint import sort
14 |
15 | ## 2.2.19
16 |
17 | ### Patch Changes
18 |
19 | - abcf6b77: react hooks eslint rule
20 |
21 | ## 2.2.18
22 |
23 | ### Patch Changes
24 |
25 | - 2f66429b: space-before-function-paren
26 |
27 | ## 2.2.17
28 |
29 | ### Patch Changes
30 |
31 | - 7a0c20ff: space-before-function-paren anonymous
32 |
33 | ## 2.2.16
34 |
35 | ### Patch Changes
36 |
37 | - ab8fd720: some rules
38 |
39 | ## 2.2.15
40 |
41 | ### Patch Changes
42 |
43 | - 0b1a315c: postcss-less
44 |
45 | ## 2.2.14
46 |
47 | ### Patch Changes
48 |
49 | - ec113a5e: add theme rules
50 |
51 | ## 2.2.13
52 |
53 | ### Patch Changes
54 |
55 | - 456fd274: lint config
56 |
57 | ## 2.2.12
58 |
59 | ### Patch Changes
60 |
61 | - 8d8d981f: lock dependencies version
62 |
63 | ## 2.2.11
64 |
65 | ### Patch Changes
66 |
67 | - 830b3280: ko lint tsc
68 |
69 | ## 2.2.10
70 |
71 | ### Patch Changes
72 |
73 | - 9554156e: stylelint version
74 |
75 | ## 2.2.9
76 |
77 | ### Patch Changes
78 |
79 | - 205b0044: lint config
80 |
81 | ## 2.2.8
82 |
83 | ### Patch Changes
84 |
85 | - 40884a3c: lint config
86 |
87 | ## 2.2.7
88 |
89 | ### Patch Changes
90 |
91 | - edb4ae7e: change prettier config
92 |
93 | ## 2.2.6
94 |
95 | ### Patch Changes
96 |
97 | - 5f645514: update stylelint rules
98 |
99 | ## 2.2.5
100 |
101 | ### Patch Changes
102 |
103 | - 472d7e0c: update eslint rules
104 |
105 | ## 2.2.4
106 |
107 | ### Patch Changes
108 |
109 | - 25de5d7e: update eslint rules
110 |
111 | ## 2.2.3
112 |
113 | ### Patch Changes
114 |
115 | - 35a552d2: update eslint semi and stylelint config
116 |
117 | ## 2.2.2
118 |
119 | ### Patch Changes
120 |
121 | - b82bab70: update eslint config
122 |
123 | ## 2.2.1
124 |
125 | ### Patch Changes
126 |
127 | - dea5d69b: update eslint comma-dangle
128 |
129 | ## 2.2.0
130 |
131 | ### Minor Changes
132 |
133 | - 67325569: update lint config
134 |
135 | ## 2.1.0
136 |
137 | ### Minor Changes
138 |
139 | - 98ec512a: prettier printWidth
140 | - 1721dfa0: Support Lints & Format with concurrency mode, Add Config & Plugin of Prettier in Eslint
141 |
142 | - `ko-lint-config`:
143 |
144 | Add Config & Plugin of Prettier in Eslint Config
145 |
146 | - `ko-lints`:
147 |
148 | - Support concurrency mode with multithreading to do lint or format tasks,you can enable concurrency mode via `--concurrency` cli flag
149 | - Default threads Count is `require('os').cpus().length`, you can specify it via `--concurrentNumber` like `--concurrentNumber=4`
150 |
151 | - `ko`:
152 | - Support `ko prettier`,`ko eslint`,`ko stylelint` commands with concurrency mode, you can also specify this mode with `ko.config.js`
153 |
154 | ## 2.0.1
155 |
156 | ### Patch Changes
157 |
158 | - acb01e3e: update package.json config to include config files
159 |
160 | ## 2.0.0
161 |
162 | ### Major Changes
163 |
164 | - e854ccd8: 1. add new plugin:eslint-plugin-dt-react 2. update eslint & prettier configs
165 |
166 | ## 1.0.1
167 |
168 | ### Patch Changes
169 |
170 | - 8a65b00b: add eslint-config-prettier
171 |
172 | ## 1.0.0
173 |
174 | ### Major Changes
175 |
176 | - 84adca00: publish ko v6.0 and it's related packages
177 |
--------------------------------------------------------------------------------
/packages/ko-lint-config/README.md:
--------------------------------------------------------------------------------
1 | # [ko-lint-config] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url]
2 |
3 | [npm-image]: https://img.shields.io/npm/v/ko-lint-config.svg
4 | [npm-url]: https://npmjs.org/package/ko-lint-config
5 | [downloads-image]: https://img.shields.io/npm/dm/ko-lint-config.svg
6 | [downloads-url]: https://npmjs.org/package/ko-lint-config
7 |
8 |
9 | English | 简体中文 (Simplified Chinese)
10 |
11 |
12 | This module saves time in three ways for you:
13 |
14 | - **No configuration** - The easier way to enforce code quality in your
15 | project. No configuration rules. It just works.
16 | - **Automatically format code** - Just run `pnpm lint-fix` and say goodbye to
17 | messy or inconsistent code.
18 | - **Catch style issues & programmer errors early** - Reduce manual review in the code review process, and leave simple things to tools to save time.
19 |
20 | No hesitation. No more maintenance `.eslintrc`. Give it a try right now!
21 |
22 | ## Detailed rules
23 | - **four spaces are required** – indent
24 | - **single quotation marks are required for string** – except where escape is need
25 | - **require keyword followed by space** - ` if (condition) {...}`
26 | - **requires no spaces after the function name** - ` function name (arg) {...}` except anonymous functions and async ` function (arg) {...} `` async () { ... }`
27 | - **semicolons are not mandatory**
28 | - **not mandatory = = =** - the field type returned by the backend cannot be guaranteed
29 | - **do not force ternary operators to wrap**
30 | - **allow but do not require trailing commas** - when the last element or attribute is on a different line from the end or attribute
31 | - **function content is allowed to be empty**
32 | - **allow this alias** - alias optional `self` `_this` `that', cannot be deconstructed from this
33 | - **no debugger required**
34 | - **no console is recommended**
35 |
36 | ## Install
37 |
38 | ``` bash
39 | pnpm add ko-lint-config -D
40 | ```
41 |
42 | ## Usage
43 |
44 | How to get Code Style Guide: 如何引入 Code Style Guide
45 |
46 | 1、Then, add this to your `.eslintrc.js`、`.prettierrc.js`、`.stylelintrc.js` file:
47 |
48 | ``` js
49 | module.exports = {
50 | extends: [require.resolve('ko-lint-config')],
51 | }
52 | ```
53 | ``` js
54 | const prettier = require('ko-lint-config/.prettierrc')
55 |
56 | module.exports = {
57 | ...prettier,
58 | }
59 | ```
60 | ``` js
61 | module.exports = {
62 | extends: [require.resolve('ko-lint-config/.stylelintrc')],
63 | }
64 | ```
65 |
66 | You should not override settings. Because this is a Code Style Guide for group.
67 |
68 | 2、Add script to `package.json`:
69 |
70 | ``` json
71 | "scripts": {
72 | "lint": "npx eslint './src/**/*.ts' './src/**/*.tsx'",
73 | "lint-fix": "npx eslint './src/**/*.ts' './src/**/*.tsx' --fix",
74 | "lint-css": "npx stylelint './src/**/*.scss' './src/**/*.css'",
75 | "lint-css-fix": "npx stylelint './src/**/*.scss' './src/**/*.css' --fix"
76 | },
77 | ```
78 |
79 | You can use `pnpm lint-fix` to correct most code style problems.
80 |
81 | ## How do I disable a eslint rule?
82 |
83 | In rare cases, you'll need to break a rule and hide the error generated by `Code Style Guide`.
84 |
85 | `ko-lint-config` uses [ESLint](http://eslint.org/) under-the-hood and
86 | you can hide errors as you normally would if you used ESLint directly. stylelint is same to eslint.
87 |
88 | Disable **all rules** on a specific line:
89 |
90 | ```js
91 | file = 'I know what I am doing' // eslint-disable-line
92 | ```
93 |
94 | Or, disable **only** the `"no-use-before-define"` rule:
95 |
96 | ```js
97 | file = 'I know what I am doing' // eslint-disable-line no-use-before-define
98 | ```
99 |
100 | Or, disable the `"no-use-before-define"` rule for **multiple lines**:
101 |
102 | ```js
103 | /* eslint-disable no-use-before-define */
104 | console.log('offending code goes here...')
105 | console.log('offending code goes here...')
106 | console.log('offending code goes here...')
107 | /* eslint-enable no-use-before-define */
108 | ```
109 |
110 | ### Looking for something easier than this?
111 |
112 | You can add to your `pnpm lint` script and install eslint plugin for vscode.
113 |
114 |
115 | ## Learn more
116 |
117 | [Code-Style-Guide](https://github.com/DTStack/Code-Style-Guide)
118 |
119 | ## License
120 |
121 | MIT. Copyright (c) 2022 dt-insight
122 |
--------------------------------------------------------------------------------
/packages/ko-lint-config/README_CN.md:
--------------------------------------------------------------------------------
1 | # [ko-lint-config] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url]
2 |
3 | [npm-image]: https://img.shields.io/npm/v/ko-lint-config.svg
4 | [npm-url]: https://npmjs.org/package/ko-lint-config
5 | [downloads-image]: https://img.shields.io/npm/dm/ko-lint-config.svg
6 | [downloads-url]: https://npmjs.org/package/ko-lint-config
7 |
8 |
9 | 简体中文 | English
10 |
11 |
12 | 通过以下方式为你的项目节省时间:
13 |
14 | - **无须配置规则** - 统一的代码风格,无须配置规则,轻松拥有。
15 | - **自动代码格式化** - 只需运行 `pnpm lint-fix` 从此和脏乱差的代码说再见。
16 | - **提前发现风格及程序问题** - 减少 Code Review 过程中的人工审查,简单的事情交给工具做,节约时间。
17 |
18 | 无须犹豫。再也不用维护 `.eslintrc` 了,开箱即用。
19 |
20 | ## 细则
21 |
22 | - **要求使用四个空格** – 进行缩进
23 | - **要求字符串使用单引号** – 需要转义的地方除外
24 | - **要求关键字后加空格** - `if (condition) { ... }`
25 | - **要求函数名后不加空格** - `function name(arg) { ... }` 匿名函数、async 除外 `function (arg) { ... }` `async () { ... }`
26 | - **不强制要求有无分号**
27 | - **不强制使用 ===** - 后端返回的字段类型不敢保证
28 | - **不强制三元运算符换行**
29 | - **允许但不要求尾随逗号** - 当最后一个元素或属性与结束或属性位于不同的行时
30 | - **允许函数内容为空**
31 | - **允许 this 别名** - 别名可选 `self` `_this` `that`,不可以从 this 解构
32 | - **要求无 debugger**
33 | - **建议无 console**
34 |
35 | ## 安装
36 |
37 | ``` bash
38 | pnpm add ko-lint-config@lastest -D
39 | ```
40 |
41 | ## 使用
42 |
43 | 如何引入 Code Style Guide
44 |
45 | 1、在 `.eslintrc.js`、`.prettierrc.js`、`.stylelintrc.js` 文件中:
46 |
47 | ``` js
48 | module.exports = {
49 | extends: [require.resolve('ko-lint-config')],
50 | }
51 | ```
52 | ``` js
53 | const prettier = require('ko-lint-config/.prettierrc')
54 |
55 | module.exports = {
56 | ...prettier,
57 | }
58 | ```
59 | ``` js
60 | module.exports = {
61 | extends: [require.resolve('ko-lint-config/.stylelintrc')],
62 | }
63 | ```
64 |
65 | 因为这是统一代码风格,所以 `ko-lint-config` 不应该被自定义规则覆盖。
66 |
67 | 2、在 `package.json` 文件中添加 script:
68 |
69 | ``` json
70 | "scripts": {
71 | "lint": "npx eslint './src/**/*.ts' './src/**/*.tsx'",
72 | "lint-fix": "npx eslint './src/**/*.ts' './src/**/*.tsx' --fix",
73 | "lint-css": "npx stylelint './src/**/*.scss' './src/**/*.css'",
74 | "lint-css-fix": "npx stylelint './src/**/*.scss' './src/**/*.css' --fix"
75 | },
76 | ```
77 |
78 | 你可以使用 `pnpm lint-fix` 来纠正大部分的代码风格问题。
79 |
80 | ## 如何隐藏某类警告?
81 |
82 | 很少的情况下你需要绕开 `Code Style Guide` 以隐藏某些警告信息。
83 |
84 | `ko-lint-config` 代码规范底层使用的是 [ESLint](http://eslint.org/)。所以如果你想隐藏某些警告,方法和使用 ESLint 时一样,stylelint 同理。
85 |
86 | 对某一行禁用**所有规则**:
87 | ```js
88 | file = 'I know what I am doing' // eslint-disable-line
89 | ```
90 |
91 | 或者,**只禁**用 `"no-use-before-define"` 这条规则:
92 | ```js
93 | file = 'I know what I am doing' // eslint-disable-line no-use-before-define
94 | ```
95 |
96 | 或者,对**多行**禁用 `"no-use-before-define"` 这一规则:
97 | ```js
98 | /* eslint-disable no-use-before-define */
99 | console.log('offending code goes here...')
100 | console.log('offending code goes here...')
101 | console.log('offending code goes here...')
102 | /* eslint-enable no-use-before-define */
103 | ```
104 |
105 | ### 使用技巧
106 |
107 | 可以将 ESLint 的检查放到 `pnpm lint` 命令中,vscode 安装 eslint 插件。
108 |
109 |
110 | ## 了解更多
111 |
112 | [Code-Style-Guide](https://github.com/DTStack/Code-Style-Guide)
113 |
114 | ## License
115 |
116 | MIT. Copyright (c) 2022 dt-insight
117 |
--------------------------------------------------------------------------------
/packages/ko-lint-config/index.d.ts:
--------------------------------------------------------------------------------
1 | export * as prettier from 'prettier';
2 | export * as eslint from 'eslint';
3 | export * as stylelint from 'stylelint';
4 |
--------------------------------------------------------------------------------
/packages/ko-lint-config/index.js:
--------------------------------------------------------------------------------
1 | const prettier = require('prettier');
2 | const eslint = require('eslint');
3 | const stylelint = require('stylelint');
4 |
5 | module.exports = {
6 | prettier,
7 | eslint,
8 | stylelint,
9 | };
10 |
--------------------------------------------------------------------------------
/packages/ko-lint-config/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ko-lint-config",
3 | "version": "2.2.21",
4 | "description": "lint configs about eslint stylelint and prettier",
5 | "main": "index.js",
6 | "files": [
7 | "**/*",
8 | "!test/**/*"
9 | ],
10 | "typings": "index.d.ts",
11 | "scripts": {
12 | "lint": "eslint .",
13 | "test": "tape test/*.js"
14 | },
15 | "keywords": [
16 | "code style",
17 | "eslint",
18 | "eslint config",
19 | "prettier",
20 | "stylelint",
21 | "lint"
22 | ],
23 | "bugs": {
24 | "url": "https://github.com/DTStack/ko/issues"
25 | },
26 | "repository": {
27 | "type": "git",
28 | "url": "https://github.com/DTStack/ko",
29 | "directory": "packages/ko-lint-config"
30 | },
31 | "homepage": "https://github.com/DTStack/ko",
32 | "author": "DTStack",
33 | "license": "MIT",
34 | "dependencies": {
35 | "@typescript-eslint/eslint-plugin": "5.30.0",
36 | "@typescript-eslint/parser": "5.30.0",
37 | "eslint": "8.22.0",
38 | "eslint-config-prettier": "8.5.0",
39 | "eslint-config-standard": "17.0.0",
40 | "eslint-plugin-dt-react": "0.0.6",
41 | "eslint-plugin-import": "2.26.0",
42 | "eslint-plugin-jest": "26.5.3",
43 | "eslint-plugin-jsx-a11y": "6.6.0",
44 | "eslint-plugin-n": "15.2.3",
45 | "eslint-plugin-prettier": "4.2.1",
46 | "eslint-plugin-promise": "6.0.0",
47 | "eslint-plugin-react": "7.30.1",
48 | "eslint-plugin-react-hooks": "4.6.0",
49 | "eslint-plugin-simple-import-sort": "^10.0.0",
50 | "eslint-plugin-sort-requires": "2.1.0",
51 | "postcss": "8.4.14",
52 | "postcss-less": "6.0.0",
53 | "postcss-scss": "4.0.4",
54 | "prettier": "2.7.1",
55 | "stylelint": "14.11.0",
56 | "stylelint-config-standard": "25.0.0",
57 | "stylelint-order": "5.0.0",
58 | "stylelint-scss": "4.3.0"
59 | },
60 | "devDependencies": {
61 | "tape": "^5.5.2",
62 | "typescript": "4.7.4"
63 | },
64 | "engines": {
65 | "node": ">=14"
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/packages/ko-lint-config/test/basic.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable import/no-extraneous-dependencies */
2 | const config = require('../');
3 | const test = require('tape');
4 |
5 | test('test basic properties of config', function (t) {
6 | t.ok(isObject(config.parserOptions));
7 | t.ok(isObject(config.env));
8 | t.ok(isObject(config.globals));
9 | t.ok(isObject(config.rules));
10 | t.end();
11 | });
12 |
13 | function isObject(obj) {
14 | return typeof obj === 'object' && obj !== null;
15 | }
16 |
--------------------------------------------------------------------------------
/packages/ko-lint-config/test/validate-config.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable import/no-extraneous-dependencies */
2 | const { ESLint } = require('eslint');
3 | const test = require('tape');
4 |
5 | test('load config in eslint to validate all rule syntax is correct', async function (t) {
6 | const eslint = new ESLint();
7 | const code = 'const foo = 1\nconst bar = (val) => val + 1\nbar(foo)\n';
8 | const [lintResult] = await eslint.lintText(code);
9 | t.equal(lintResult.errorCount, 0);
10 | t.end();
11 | });
12 |
13 | test('ensure we allow top level await', async function (t) {
14 | const eslint = new ESLint();
15 | const code =
16 | 'const foo = await 1\nconst bar = (val) => val + 2\nawait bar(foo)\n';
17 | const [lintResult] = await eslint.lintText(code);
18 | t.equal(lintResult.errorCount, 0);
19 | t.end();
20 | });
21 |
--------------------------------------------------------------------------------
/packages/ko-lints/README.md:
--------------------------------------------------------------------------------
1 | # ko-lint
2 |
3 | This package is used by [ko](https://github.com/DTStack/ko)
4 |
--------------------------------------------------------------------------------
/packages/ko-lints/index.d.ts:
--------------------------------------------------------------------------------
1 | import { Pattern } from 'fast-glob';
2 |
3 | export type IOpts = {
4 | write: boolean;
5 | configPath: string;
6 | patterns: Pattern[];
7 | concurrency?: boolean;
8 | concurrentNumber?: number;
9 | };
10 |
11 | export type IKeys = 'eslint' | 'prettier' | 'stylelint';
12 |
13 | declare class Lints {
14 | private runner;
15 | private opts;
16 | state: 0 | 1;
17 | constructor(opts: IOpts);
18 | run(key: IKeys): Promise;
19 | }
20 |
21 | export default Lints;
22 |
--------------------------------------------------------------------------------
/packages/ko-lints/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ko-lints",
3 | "version": "4.0.21",
4 | "description": "lint tools used by ko",
5 | "keywords": [
6 | "ko",
7 | "ko-script",
8 | "eslint",
9 | "prettier",
10 | "lint",
11 | "lint tools"
12 | ],
13 | "bugs": {
14 | "url": "https://github.com/DTStack/ko/issues"
15 | },
16 | "repository": {
17 | "type": "git",
18 | "url": "https://github.com/DTStack/ko",
19 | "directory": "packages/ko-lints"
20 | },
21 | "license": "MIT",
22 | "typings": "index.d.ts",
23 | "main": "lib/index.js",
24 | "files": [
25 | "lib/*",
26 | "index.d.ts"
27 | ],
28 | "scripts": {
29 | "prepublishOnly": "rm -rf lib && tsc",
30 | "build": "tsc",
31 | "debug": "rm -rf lib && tsc --sourcemap -w"
32 | },
33 | "dependencies": {
34 | "fast-glob": "^3.2.11"
35 | },
36 | "peerDependencies": {
37 | "ko-lint-config": "workspace:*"
38 | },
39 | "devDependencies": {
40 | "typescript": "^4.6.4",
41 | "ko-lint-config": "workspace:*"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/packages/ko-lints/src/eslint/index.ts:
--------------------------------------------------------------------------------
1 | import ESLintParser from './parser';
2 | import LintRunnerFactory from '../factory/runner';
3 | import { IOpts, IChildOpts } from '../interfaces';
4 |
5 | class ESLintRunner extends LintRunnerFactory {
6 | static readonly IGNORE_FILES = ['.eslintignore'];
7 | static readonly NAME = 'eslint';
8 |
9 | constructor(opts: IOpts) {
10 | const { configPath, write } = opts;
11 | const parser = new ESLintParser({
12 | configPath,
13 | write,
14 | name: ESLintRunner.NAME,
15 | });
16 | const childOpts: IChildOpts = {
17 | parser,
18 | name: ESLintRunner.NAME,
19 | ignoreFiles: ESLintRunner.IGNORE_FILES,
20 | };
21 | super(opts, childOpts);
22 | }
23 | }
24 |
25 | export default ESLintRunner;
26 |
--------------------------------------------------------------------------------
/packages/ko-lints/src/eslint/parser.ts:
--------------------------------------------------------------------------------
1 | import { eslint } from 'ko-lint-config';
2 | import LintParserFactory from '../factory/parser';
3 | import { IParserOpts } from '../interfaces';
4 |
5 | class ESLintParser extends LintParserFactory {
6 | static readonly EXTENSIONS = ['ts', 'tsx', 'js', 'jsx'];
7 | private eslintInstance: eslint.ESLint;
8 | private opts: IParserOpts;
9 | private config: Record;
10 |
11 | constructor(opts: IParserOpts) {
12 | super();
13 | this.opts = opts;
14 | this.generateConfig();
15 | this.initInstance();
16 | }
17 |
18 | private initInstance() {
19 | const { write } = this.opts;
20 | this.eslintInstance = new eslint.ESLint({
21 | fix: write,
22 | overrideConfig: this.config,
23 | useEslintrc: false,
24 | extensions: ESLintParser.EXTENSIONS,
25 | });
26 | }
27 |
28 | public async format(file: string): Promise {
29 | const formatter = await this.eslintInstance.loadFormatter();
30 | let resultText = '';
31 | try {
32 | const result = await this.eslintInstance.lintFiles(file);
33 | if (this.opts.write) {
34 | await eslint.ESLint.outputFixes(result);
35 | }
36 | if (result[0].errorCount) {
37 | resultText = formatter.format(result) as string;
38 | }
39 | return resultText;
40 | } catch (ex) {
41 | console.log(ex);
42 | process.exit(1);
43 | }
44 | }
45 |
46 | public generateConfig() {
47 | if (this.opts.configPath) {
48 | this.config = this.getConfigFromFile(this.opts.configPath);
49 | } else {
50 | const localConfigPath = this.detectLocalRunnerConfig(this.opts.name);
51 | if (localConfigPath) {
52 | this.config = this.getConfigFromFile(localConfigPath);
53 | }
54 | }
55 | }
56 | }
57 |
58 | export default ESLintParser;
59 |
--------------------------------------------------------------------------------
/packages/ko-lints/src/factory/parser.ts:
--------------------------------------------------------------------------------
1 | import { isAbsolute, join } from 'path';
2 | import { readdirSync, statSync } from 'fs';
3 | import assert from 'assert';
4 |
5 | abstract class LintParserFactory {
6 | public abstract format(file: string): Promise;
7 | protected abstract generateConfig(): any;
8 | private cwd = process.cwd();
9 |
10 | protected getConfigFromFile(filepath: string): Promise> {
11 | assert(isAbsolute(filepath), 'only accept absolute config filepath');
12 | return require(filepath);
13 | }
14 |
15 | protected detectLocalRunnerConfig(name: string): string {
16 | const files = readdirSync(this.cwd).filter(
17 | path => !statSync(path).isDirectory()
18 | );
19 | let ret: string = '';
20 | for (let file of files) {
21 | if (file.includes(name) && !file.includes('ignore')) {
22 | ret = file;
23 | break;
24 | }
25 | }
26 | return ret ? join(this.cwd, ret) : ret;
27 | }
28 | }
29 |
30 | export default LintParserFactory;
31 |
--------------------------------------------------------------------------------
/packages/ko-lints/src/factory/runner.ts:
--------------------------------------------------------------------------------
1 | import { join } from 'path';
2 | import { existsSync, readFileSync } from 'fs';
3 | import { cpus } from 'os';
4 | import { performance } from 'perf_hooks';
5 | import fg, { Pattern } from 'fast-glob';
6 | import MultiThreading from '../threads';
7 | import Parser from '../factory/parser';
8 | import { IChildOpts, IOpts } from '../interfaces';
9 |
10 | abstract class LintRunnerFactory {
11 | private opts: IOpts;
12 | private childOpts: IChildOpts;
13 | private parser: Parser;
14 | private cwd = process.cwd();
15 | constructor(opts: IOpts, childOpts: IChildOpts) {
16 | this.opts = opts;
17 | this.childOpts = childOpts;
18 | this.parser = childOpts.parser;
19 | }
20 |
21 | protected async getEntries(
22 | patterns: Pattern[],
23 | ignoreFiles: string[]
24 | ): Promise {
25 | return fg(patterns, {
26 | dot: true,
27 | ignore: this.getIgnorePatterns(...ignoreFiles),
28 | });
29 | }
30 |
31 | private getIgnorePatterns(...ignoreFiles: string[]) {
32 | return ['.gitignore', ...ignoreFiles]
33 | .map(fileName => {
34 | const filePath = join(this.cwd, fileName);
35 | if (existsSync(filePath)) {
36 | return readFileSync(filePath, 'utf-8')
37 | .split('\n')
38 | .filter(str => str && !str.startsWith('#'));
39 | }
40 | return [];
41 | })
42 | .reduce((acc, current) => {
43 | current.forEach(p => {
44 | if (!acc.includes(p)) {
45 | acc.push(p);
46 | }
47 | });
48 | return acc;
49 | }, []);
50 | }
51 |
52 | protected getConcurrentNumber(entriesCount: number, num?: number) {
53 | const initNumber = num ? num : cpus().length;
54 | return initNumber < entriesCount ? initNumber : entriesCount;
55 | }
56 |
57 | private async run(entries: string[]) {
58 | let ret: string[];
59 | const { concurrency } = this.opts;
60 | if (concurrency) {
61 | ret = await this.runInConcurrencyMode(entries);
62 | } else {
63 | ret = await this.runInNormalMode(entries);
64 | }
65 | return ret;
66 | }
67 |
68 | private async runInConcurrencyMode(entries: string[]) {
69 | const { concurrentNumber, write, configPath } = this.opts;
70 | const threads = new MultiThreading({
71 | entries,
72 | concurrentNumber: this.getConcurrentNumber(
73 | entries.length,
74 | concurrentNumber
75 | ),
76 | write,
77 | configPath,
78 | name: this.childOpts.name,
79 | });
80 | return threads.batch();
81 | }
82 |
83 | private async runInNormalMode(entries: string[]) {
84 | const pList = entries.map(async file => await this.parser.format(file));
85 | const result = await Promise.all(pList);
86 | return result.filter(Boolean);
87 | }
88 |
89 | public async start() {
90 | const { patterns } = this.opts;
91 | const { ignoreFiles, name } = this.childOpts;
92 | const entries = await this.getEntries(patterns, ignoreFiles);
93 | const totalCount = entries.length;
94 | if (entries.length === 0) {
95 | console.log(`No files matched with pattern:${patterns} via ${name}`);
96 | process.exit(0);
97 | }
98 | const startTime = performance.now();
99 | const ret = await this.run(entries);
100 | const endTime = performance.now();
101 | console.log(
102 | `exec ${name} with ${totalCount} files cost ${(
103 | (endTime - startTime) /
104 | 1000
105 | ).toFixed(2)}s`
106 | );
107 | return ret;
108 | }
109 | }
110 |
111 | export default LintRunnerFactory;
112 |
--------------------------------------------------------------------------------
/packages/ko-lints/src/index.ts:
--------------------------------------------------------------------------------
1 | import LintRunnerFactory from './factory/runner';
2 | import ESlintRunner from './eslint';
3 | import PrettierRunner from './prettier';
4 | import StyleLintRunner from './stylelint';
5 |
6 | import { IOpts, IKeys } from './interfaces';
7 |
8 | class Lints {
9 | private runner: LintRunnerFactory;
10 | private opts: IOpts;
11 | constructor(opts: IOpts) {
12 | this.opts = opts;
13 | }
14 |
15 | async run(key: IKeys) {
16 | switch (key) {
17 | case 'eslint':
18 | this.runner = new ESlintRunner(this.opts);
19 | break;
20 | case 'prettier':
21 | this.runner = new PrettierRunner(this.opts);
22 | break;
23 | case 'stylelint':
24 | this.runner = new StyleLintRunner(this.opts);
25 | break;
26 | }
27 | const result = await this.runner.start();
28 | return result;
29 | }
30 | }
31 |
32 | export default Lints;
33 |
--------------------------------------------------------------------------------
/packages/ko-lints/src/interfaces.ts:
--------------------------------------------------------------------------------
1 | import { Pattern } from 'fast-glob';
2 | import Parser from './factory/parser';
3 |
4 | export type IOpts = {
5 | write: boolean;
6 | configPath: string;
7 | patterns: Pattern[];
8 | concurrency?: boolean;
9 | concurrentNumber?: number;
10 | };
11 |
12 | export type IKeys = 'eslint' | 'prettier' | 'stylelint';
13 |
14 | export type IParserOpts = Pick & {
15 | name: IKeys;
16 | };
17 |
18 | export type IThreadOpts = IParserOpts & {
19 | entries: string[];
20 | concurrentNumber: NonNullable;
21 | };
22 |
23 | export type IChildOpts = {
24 | parser: Parser;
25 | ignoreFiles: string[];
26 | name: IKeys;
27 | };
28 |
--------------------------------------------------------------------------------
/packages/ko-lints/src/prettier/index.ts:
--------------------------------------------------------------------------------
1 | import LintRunnerFactory from '../factory/runner';
2 | import PrettierParser from './parser';
3 | import { IOpts, IChildOpts } from '../interfaces';
4 |
5 | class PrettierRunner extends LintRunnerFactory {
6 | static readonly IGNORE_FILES = ['.prettierignore'];
7 | static readonly NAME = 'prettier';
8 |
9 | constructor(opts: IOpts) {
10 | const { configPath, write } = opts;
11 | const parser = new PrettierParser({
12 | configPath,
13 | write,
14 | name: PrettierRunner.NAME,
15 | });
16 | const childOpts: IChildOpts = {
17 | parser,
18 | name: PrettierRunner.NAME,
19 | ignoreFiles: PrettierRunner.IGNORE_FILES,
20 | };
21 | super(opts, childOpts);
22 | }
23 | }
24 |
25 | export default PrettierRunner;
26 |
--------------------------------------------------------------------------------
/packages/ko-lints/src/prettier/parser.ts:
--------------------------------------------------------------------------------
1 | import { readFile, writeFile } from 'fs/promises';
2 | import { prettier } from 'ko-lint-config';
3 | import LintParserFactory from '../factory/parser';
4 | import { IParserOpts } from '../interfaces';
5 |
6 | const { format, check } = prettier;
7 |
8 | class PrettierParser extends LintParserFactory {
9 | private opts: IParserOpts;
10 | private config: Record;
11 | constructor(opts: IParserOpts) {
12 | super();
13 | this.opts = opts;
14 | this.generateConfig();
15 | }
16 |
17 | public generateConfig() {
18 | if (this.opts.configPath) {
19 | this.config = this.getConfigFromFile(this.opts.configPath);
20 | } else {
21 | const localConfigPath = this.detectLocalRunnerConfig(this.opts.name);
22 | if (localConfigPath) {
23 | this.config = this.getConfigFromFile(localConfigPath);
24 | }
25 | }
26 | }
27 |
28 | public async format(file: string): Promise {
29 | const opts = { ...this.config, filepath: file };
30 | let resultText = '';
31 | try {
32 | const source = await readFile(file, 'utf-8');
33 | if (this.opts.write) {
34 | const formatContent = format(source, opts);
35 | await writeFile(file, formatContent, 'utf-8');
36 | } else {
37 | if (!check(source, opts)) {
38 | resultText = `file ${opts.filepath} doesn't match ${this.opts.name} config`;
39 | }
40 | }
41 | return resultText;
42 | } catch (ex) {
43 | console.log(ex);
44 | process.exit(1);
45 | }
46 | }
47 | }
48 |
49 | export default PrettierParser;
50 |
--------------------------------------------------------------------------------
/packages/ko-lints/src/stylelint/index.ts:
--------------------------------------------------------------------------------
1 | import StyleLintParser from './parser';
2 | import LintRunnerFactory from '../factory/runner';
3 | import { IOpts, IChildOpts } from '../interfaces';
4 |
5 | class StyleLintRunner extends LintRunnerFactory {
6 | static readonly IGNORE_FILES = ['.stylelintignore'];
7 | static readonly NAME = 'stylelint';
8 | constructor(opts: IOpts) {
9 | const { configPath, write } = opts;
10 | const parser = new StyleLintParser({
11 | configPath,
12 | write,
13 | name: StyleLintRunner.NAME,
14 | });
15 | const childOpts: IChildOpts = {
16 | parser,
17 | name: StyleLintRunner.NAME,
18 | ignoreFiles: StyleLintRunner.IGNORE_FILES,
19 | };
20 | super(opts, childOpts);
21 | }
22 | }
23 |
24 | export default StyleLintRunner;
25 |
--------------------------------------------------------------------------------
/packages/ko-lints/src/stylelint/parser.ts:
--------------------------------------------------------------------------------
1 | import { stylelint } from 'ko-lint-config';
2 | import LintParserFactory from '../factory/parser';
3 | import { IParserOpts } from '../interfaces';
4 |
5 | const { lint, formatters } = stylelint;
6 |
7 | class StyleLintParser extends LintParserFactory {
8 | private opts: IParserOpts;
9 | private config: Record;
10 | constructor(opts: IParserOpts) {
11 | super();
12 | this.opts = opts;
13 | this.generateConfig();
14 | }
15 |
16 | public generateConfig() {
17 | if (this.opts.configPath) {
18 | this.config = this.getConfigFromFile(this.opts.configPath);
19 | } else {
20 | const localConfigPath = this.detectLocalRunnerConfig(this.opts.name);
21 | if (localConfigPath) {
22 | this.config = this.getConfigFromFile(localConfigPath);
23 | }
24 | }
25 | }
26 |
27 | public async format(file: string): Promise {
28 | const { write } = this.opts;
29 | let resultText = '';
30 | try {
31 | const result = await lint({
32 | fix: write,
33 | config: this.config,
34 | files: file,
35 | });
36 | if (result.errored) {
37 | resultText = formatters.string(result.results, result);
38 | }
39 | return resultText;
40 | } catch (ex) {
41 | console.error(ex);
42 | process.exit(1);
43 | }
44 | }
45 | }
46 |
47 | export default StyleLintParser;
48 |
--------------------------------------------------------------------------------
/packages/ko-lints/src/threads/Pool.ts:
--------------------------------------------------------------------------------
1 | import { join } from 'path';
2 | import { Worker } from 'worker_threads';
3 | import { IThreadOpts, IParserOpts } from '../interfaces';
4 |
5 | class ThreadPool {
6 | private readonly workers: Worker[] = [];
7 | private readonly workerPList: Promise[] = [];
8 | private readonly opts: IThreadOpts;
9 | private queue: string[];
10 | private stdout: string[] = [];
11 |
12 | constructor(opts: IThreadOpts) {
13 | console.log(
14 | `Using concurrent mode with ${opts.concurrentNumber} threads...`
15 | );
16 | this.opts = opts;
17 | this.queue = this.opts.entries;
18 | this.format();
19 | }
20 |
21 | format() {
22 | const { concurrentNumber, configPath, write, name } = this.opts;
23 | if (this.workers.length < concurrentNumber) {
24 | this.workerPList.push(
25 | this.createWorker({
26 | configPath,
27 | write,
28 | name,
29 | })
30 | );
31 | this.format();
32 | }
33 | }
34 |
35 | createWorker(opts: IParserOpts): Promise {
36 | const worker = new Worker(join(__dirname, './Worker.js'), {
37 | workerData: {
38 | opts,
39 | },
40 | });
41 | return new Promise(resolve => {
42 | worker.postMessage(this.queue.shift());
43 | worker.on('message', (result: string) => {
44 | this.stdout.push(result);
45 | if (this.queue.length === 0) {
46 | resolve(true);
47 | } else {
48 | const next = this.queue.shift();
49 | worker.postMessage(next);
50 | }
51 | });
52 | worker.on('error', err => {
53 | console.log(err);
54 | process.exit(1);
55 | });
56 | this.workers.push(worker);
57 | });
58 | }
59 |
60 | async exec(): Promise {
61 | return Promise.all(this.workerPList).then(() => {
62 | return this.stdout;
63 | });
64 | }
65 | }
66 |
67 | export default ThreadPool;
68 |
--------------------------------------------------------------------------------
/packages/ko-lints/src/threads/Worker.ts:
--------------------------------------------------------------------------------
1 | import { workerData, parentPort } from 'worker_threads';
2 | import Parser from '../factory/parser';
3 | import { IParserOpts } from '../interfaces';
4 |
5 | let parser: Parser;
6 |
7 | switch ((workerData.opts as IParserOpts).name) {
8 | case 'eslint':
9 | const ESLintParser = require('../eslint/parser').default;
10 | parser = new ESLintParser(workerData.opts);
11 | break;
12 | case 'prettier':
13 | const PrettierParser = require('../prettier/parser').default;
14 | parser = new PrettierParser(workerData.opts);
15 | break;
16 | case 'stylelint':
17 | const StyleParser = require('../stylelint/parser').default;
18 | parser = new StyleParser(workerData.opts);
19 | break;
20 | }
21 |
22 | parentPort?.on('message', async (file: string) => {
23 | const result = await parser.format(file);
24 | parentPort?.postMessage(result);
25 | });
26 |
--------------------------------------------------------------------------------
/packages/ko-lints/src/threads/index.ts:
--------------------------------------------------------------------------------
1 | import ThreadPool from './Pool';
2 | import { IThreadOpts } from '../interfaces';
3 |
4 | class MultiThreading {
5 | private opts: IThreadOpts;
6 | constructor(opts: IThreadOpts) {
7 | this.opts = opts;
8 | }
9 |
10 | public async batch() {
11 | const pool = new ThreadPool(this.opts);
12 | return await pool.exec();
13 | }
14 | }
15 |
16 | export default MultiThreading;
17 |
--------------------------------------------------------------------------------
/packages/ko-lints/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@tsconfig/node14/tsconfig.json",
3 | "include": ["src/**/*.ts", "index.d.ts"],
4 | "exclude": ["src/**/*.test.ts"],
5 | "compilerOptions": {
6 | "allowJs": true,
7 | "skipLibCheck": true,
8 | "esModuleInterop": true,
9 | "strict": true,
10 | "strictPropertyInitialization": false,
11 | "outDir": "lib",
12 | },
13 | }
--------------------------------------------------------------------------------
/packages/ko/README.md:
--------------------------------------------------------------------------------
1 | # ko
2 | English | [简体中文](./README_CN.md)
3 | ## Simple, yet powerful, tool for managing your react applications.
4 |
5 |
6 |
7 | ## Features
8 |
9 | * Support building applications on top of **webpack v5** and **esbuild**
10 | * Customize ko to work exactly the way you need it for your applications
11 | * Built-in popular linting tools to lint your source code
12 | * Built-in support typescript
13 |
14 | ## Installation
15 |
16 | You can install ko using npm, yarn or pnpm:
17 | ``` bash
18 | npm install ko --save-dev
19 | # or
20 | yarn add ko --dev
21 | # or
22 | pnpm add ko --save-dev
23 | ```
24 |
25 | ## Documents
26 | * [Introduction](https://dtstack.github.io/ko/zh-CN/docs/current/introduction)
27 | * [Getting Started](https://dtstack.github.io/ko/zh-CN/docs/current/getting-started)
28 | * [FAQ](https://dtstack.github.io/ko/zh-CN/docs/current/FAQ)
29 |
30 | ## Contributing
31 |
32 | We'd love to have your helping hand on `ko`! See [CONTRIBUTING](../../CONTRIBUTING.md) for more information on how to get started.
33 |
34 | ## License
35 |
36 | Copyright © DTStack. All rights reserved.
37 |
38 | Licensed under the MIT license.
39 |
--------------------------------------------------------------------------------
/packages/ko/README_CN.md:
--------------------------------------------------------------------------------
1 | # ko
2 |
3 | ## 一个简单而强大的工具,用于管理您的 React 应用程序。
4 |
5 |
6 |
7 | ## 特点
8 |
9 | * 支持在 **webpack v5** 和 **esbuild** 上构建应用程序
10 | * 定制 ko,使其完全按照您的应用程序需求工作
11 | * 内置流行的 lint 工具,用于对源代码进行 lint
12 | * 内置支持 TypeScript
13 |
14 | ## 安装
15 |
16 | 您可以使用 npm、yarn 或 pnpm 安装 ko:
17 | ``` bash
18 | npm install ko --save-dev
19 | # 或者
20 | yarn add ko --dev
21 | # 或者
22 | pnpm add ko --save-dev
23 | ```
24 |
25 | ## 文档
26 | * [介绍](https://dtstack.github.io/ko/docs/current/introduction)
27 | * [入门指南](https://dtstack.github.io/ko/docs/current/getting-started)
28 | * [常见问题](https://dtstack.github.io/ko/docs/current/FAQ)
29 |
30 | ## Contributing
31 |
32 | 我们很乐意在 `ko` 上得到您的帮助!有关如何入手的更多信息,请参见 [CONTRIBUTING](../../CONTRIBUTING_CN.md)。
33 |
34 | ## License
35 |
36 | 版权所有 © DTStack。保留所有权利。
37 |
38 | 根据 MIT 许可证获得许可。
39 |
--------------------------------------------------------------------------------
/packages/ko/index.d.ts:
--------------------------------------------------------------------------------
1 | declare module '@nuxt/friendly-errors-webpack-plugin';
2 | declare module 'error-overlay-webpack-plugin';
3 |
--------------------------------------------------------------------------------
/packages/ko/jest.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
2 | module.exports = {
3 | preset: 'ts-jest',
4 | testEnvironment: 'node',
5 | };
6 |
--------------------------------------------------------------------------------
/packages/ko/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ko",
3 | "version": "6.6.4",
4 | "description": "build & lint library",
5 | "keywords": [
6 | "ko",
7 | "react",
8 | "typescript",
9 | "babel",
10 | "sass",
11 | "scss",
12 | "webpack",
13 | "webpack v5",
14 | "server",
15 | "dtstack",
16 | "cli",
17 | "build",
18 | "script"
19 | ],
20 | "bugs": {
21 | "url": "https://github.com/DTStack/ko/issues"
22 | },
23 | "typings": "index.d.ts",
24 | "repository": {
25 | "type": "git",
26 | "url": "https://github.com/DTStack/ko",
27 | "directory": "packages/ko"
28 | },
29 | "license": "MIT",
30 | "author": "DTStack",
31 | "bin": {
32 | "ko": "./lib/cli.js"
33 | },
34 | "files": [
35 | "lib/*"
36 | ],
37 | "scripts": {
38 | "prepublishOnly": "rm -rf lib && tsc",
39 | "debug": "tsc -w --sourceMap",
40 | "test": "jest",
41 | "build": "tsc"
42 | },
43 | "dependencies": {
44 | "@babel/core": "^7.18.0",
45 | "@dtinsight/auto-polyfills-webpack-plugin": "workspace:2.0.0",
46 | "@nuxt/friendly-errors-webpack-plugin": "^2.5.2",
47 | "@parcel/css": "^1.12.2",
48 | "@pmmmwh/react-refresh-webpack-plugin": "^0.5.7",
49 | "autoprefixer": "^10.4.7",
50 | "babel-loader": "^8.2.5",
51 | "babel-plugin-treasure": "^0.9.0",
52 | "babel-preset-ko-app": "workspace:^1.0.0",
53 | "buffer": "^6.0.3",
54 | "case-sensitive-paths-webpack-plugin": "^2.4.0",
55 | "chalk": "^4.1.2",
56 | "clean-webpack-plugin": "^4.0.0",
57 | "commander": "^9.2.0",
58 | "copy-webpack-plugin": "^11.0.0",
59 | "crypto-browserify": "^3.12.0",
60 | "css-loader": "^6.7.1",
61 | "css-minimizer-webpack-plugin": "^4.0.0",
62 | "detect-port": "^2.0.0",
63 | "dynamic-resolve-webpack-plugin": "workspace:^2.0.0",
64 | "esbuild-loader": "^2.19.0",
65 | "html-webpack-plugin": "^5.5.0",
66 | "inquirer": "^8.2.2",
67 | "ko-lints": "workspace:^4.0.0",
68 | "less": "^3.13.1",
69 | "less-loader": "^9.1.0",
70 | "lodash": "^4.17.21",
71 | "mini-css-extract-plugin": "^2.6.0",
72 | "os-browserify": "^0.3.0",
73 | "postcss": "^8.4.14",
74 | "postcss-loader": "^7.0.0",
75 | "postcss-url": "^10.1.3",
76 | "querystring-es3": "^0.2.1",
77 | "react-refresh": "^0.13.0",
78 | "sass": "^1.52.1",
79 | "sass-loader": "^13.0.0",
80 | "stream-browserify": "^3.0.0",
81 | "string_decoder": "^1.3.0",
82 | "style-loader": "^3.3.1",
83 | "tapable": "^2.2.1",
84 | "terser-webpack-plugin": "^5.3.6",
85 | "thread-loader": "^3.0.4",
86 | "webpack": "^5.72.1",
87 | "webpack-bundle-analyzer": "^4.5.0",
88 | "webpack-dev-server": "4.14.0",
89 | "webpackbar": "^5.0.2",
90 | "worker-loader": "^3.0.8"
91 | },
92 | "devDependencies": {
93 | "@types/case-sensitive-paths-webpack-plugin": "^2.1.6",
94 | "@types/detect-port": "^1.3.2",
95 | "@types/inquirer": "^8.2.2",
96 | "@types/jest": "^27.5.1",
97 | "@types/lodash": "^4.14.182",
98 | "@types/webpack-bundle-analyzer": "^4.4.1",
99 | "jest": "^28.1.0",
100 | "ts-jest": "^28.0.3",
101 | "typescript": "^4.6.4"
102 | },
103 | "engines": {
104 | "node": ">=14"
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/packages/ko/src/actions/build.ts:
--------------------------------------------------------------------------------
1 | import webpack, { Configuration } from 'webpack';
2 | import Service from '../core/service';
3 | import WebpackConfig from '../webpack';
4 | import { ActionFactory } from './factory';
5 | import TerserWebpackPlugin from 'terser-webpack-plugin';
6 |
7 | import { ESBuildMinifyPlugin } from 'esbuild-loader';
8 | import { ICliOptions } from '../types';
9 |
10 | class Build extends ActionFactory {
11 | private webpackConfig: WebpackConfig;
12 | constructor(service: Service) {
13 | super(service);
14 | }
15 |
16 | protected async generateConfig() {
17 | this.webpackConfig = new WebpackConfig(this.service);
18 | const extraConfig = {
19 | optimization: {
20 | minimize: true,
21 | minimizer: [
22 | new TerserWebpackPlugin({
23 | terserOptions: {
24 | compress: {
25 | ...this.service.config.experiment?.compress,
26 | },
27 | },
28 | }),
29 | ...(this.service.config.experiment?.minimizer
30 | ? [
31 | new ESBuildMinifyPlugin({
32 | target: 'es2015',
33 | css: true,
34 | }),
35 | ]
36 | : ['...']),
37 | ],
38 | },
39 | } as Configuration;
40 | const ret = this.webpackConfig.merge(extraConfig);
41 | const plugins: any = await this.service.apply({
42 | key: this.service.hookKeySet.WEBPACK_PLUGIN,
43 | context: ret.plugins,
44 | });
45 | ret.plugins = plugins;
46 | await this.service.apply({
47 | key: this.service.hookKeySet.MODIFY_WEBPACK,
48 | context: ret,
49 | });
50 | return ret;
51 | }
52 |
53 | public registerCommand(): void {
54 | const cmdName = 'build';
55 | this.service.commander.registerCommand({
56 | name: cmdName,
57 | description: 'build project',
58 | options: [
59 | {
60 | flags: '--hash',
61 | description: 'output file name with hash',
62 | },
63 | ],
64 | });
65 | this.service.commander.bindAction(cmdName, this.action.bind(this));
66 | }
67 |
68 | protected async action(cliOpts: ICliOptions) {
69 | process.title = 'ko-build';
70 | process.env.NODE_ENV = 'production';
71 | this.service.freezeCliOptsWith(cliOpts);
72 | const config = await this.generateConfig();
73 | webpack(config, (error, stats: any) => {
74 | if (stats && stats.hasErrors()) {
75 | throw stats.toString({
76 | logging: 'error',
77 | colors: true,
78 | });
79 | }
80 | if (error) {
81 | throw error;
82 | }
83 | this.successStdout('ko build completed!');
84 | });
85 | }
86 | }
87 |
88 | export default Build;
89 |
--------------------------------------------------------------------------------
/packages/ko/src/actions/factory.ts:
--------------------------------------------------------------------------------
1 | import chalk from 'chalk';
2 | import Service from '../core/service';
3 |
4 | export abstract class ActionFactory {
5 | protected service: Service;
6 | protected abstract generateConfig(opts: any): any;
7 | protected abstract registerCommand(): void;
8 | protected abstract action(...args: any[]): void;
9 |
10 | protected constructor(service: Service) {
11 | this.service = service;
12 | }
13 |
14 | protected successStdout(...logs: string[]) {
15 | console.log(...logs.map(log => chalk.green(log)));
16 | }
17 |
18 | protected warningStdout(...logs: string[]) {
19 | console.log(...logs.map(log => chalk.green(log)));
20 | }
21 |
22 | protected errorStdout(...logs: string[]) {
23 | console.log(...logs.map(log => chalk.green(log)));
24 | }
25 | }
26 |
27 | export default ActionFactory;
28 |
--------------------------------------------------------------------------------
/packages/ko/src/actions/lints.ts:
--------------------------------------------------------------------------------
1 | import { ActionFactory } from './factory';
2 | import Lints, { IKeys, IOpts as ILintOpts } from 'ko-lints';
3 | import Service from '../core/service';
4 | import { assert } from '../utils';
5 |
6 | class LintFactory extends ActionFactory {
7 | private name: IKeys;
8 | constructor(service: Service, name: IKeys) {
9 | super(service);
10 | this.name = name;
11 | this.generateConfig();
12 | }
13 |
14 | public generateConfig() {
15 | const opts = this.service.config?.lints?.[this.name];
16 | return opts || {};
17 | }
18 |
19 | public registerCommand(): void {
20 | const name = this.name;
21 | this.service.commander.registerCommand({
22 | name,
23 | description: `lint your codes via ${name}`,
24 | args: [
25 | {
26 | flags: '',
27 | description: ` Specify ${name} lint patterns(via glob)`,
28 | },
29 | ],
30 | options: [
31 | {
32 | flags: '-w, --write',
33 | description: 'try to fix problems automatically',
34 | },
35 | {
36 | flags: '-c, --configPath ',
37 | description: `Specify ${name} config path`,
38 | },
39 | {
40 | flags: '--concurrency',
41 | description: 'Enable concurrency mode',
42 | },
43 | {
44 | flags: '--concurrentNumber ',
45 | description: 'Specify max worker count',
46 | },
47 | ],
48 | });
49 | this.service.commander.bindAction(name, this.action.bind(this));
50 | }
51 |
52 | protected async action(patterns: string | string[], cliOpts: ILintOpts) {
53 | const config = this.generateConfig();
54 | const finalOpts = Object.freeze({
55 | name: this.name,
56 | ...config,
57 | ...cliOpts,
58 | patterns: Array.isArray(patterns) ? patterns : [patterns],
59 | });
60 | const { name, ...opts } = finalOpts;
61 | assert(
62 | opts.patterns,
63 | `patterns config of ${name} should be specified(via glob)`
64 | );
65 | process.title = finalOpts.name;
66 | const lintRunner = new Lints(opts);
67 | const result = (await lintRunner.run(name)).filter(Boolean);
68 | if (result.length === 0) {
69 | this.successStdout('[success]', `lint via ${name}`);
70 | process.exit(0);
71 | } else {
72 | this.warningStdout(`lint via ${name} failed:`);
73 | result.forEach(str => {
74 | str && this.warningStdout('[failed]', str);
75 | });
76 | process.exit(1);
77 | }
78 | }
79 | }
80 |
81 | export default LintFactory;
82 |
--------------------------------------------------------------------------------
/packages/ko/src/cli.ts:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node --max_old_space_size=4096
2 | 'use strict';
3 | import Service from './core/service';
4 | import Dev from './actions/dev';
5 | import Build from './actions/build';
6 | import LintFactory from './actions/lints';
7 | import { IKeys } from 'ko-lints';
8 |
9 | function exec() {
10 | const service = new Service();
11 | // register commands
12 | const dev = new Dev(service);
13 | dev.registerCommand();
14 | const build = new Build(service);
15 | build.registerCommand();
16 | (['eslint', 'prettier', 'stylelint'] as IKeys[]).forEach(name => {
17 | const runner = new LintFactory(service, name);
18 | runner.registerCommand();
19 | });
20 | service.run();
21 | }
22 |
23 | exec();
24 |
--------------------------------------------------------------------------------
/packages/ko/src/core/commander.ts:
--------------------------------------------------------------------------------
1 | import { program, Command } from 'commander';
2 | import { assert } from '../utils';
3 |
4 | type RegisterOptions = {
5 | flags: string;
6 | description: string;
7 | defaultValue?: string | boolean;
8 | };
9 |
10 | type CMDProperties = {
11 | description: string;
12 | options?: RegisterOptions[];
13 | args?: {
14 | flags: string;
15 | description: string;
16 | }[];
17 | action?: ActionFn;
18 | };
19 |
20 | type ActionFn = Parameters[0];
21 |
22 | enum STATE {
23 | INIT,
24 | PARSE,
25 | DONE,
26 | }
27 |
28 | class Commander {
29 | private STATE: STATE;
30 | public program: Command;
31 | private pkg: Record;
32 | private cmdSet: Record;
33 | constructor() {
34 | this.program = program;
35 | this.STATE = STATE.INIT;
36 | this.cmdSet = {} as Record;
37 | this.pkg = require('../../package.json');
38 | }
39 |
40 | registerCommand({
41 | name,
42 | description,
43 | args,
44 | options,
45 | }: CMDProperties & { name: string }) {
46 | assert(
47 | this.STATE === STATE.INIT,
48 | `register command should be called in INIT state`
49 | );
50 | assert(!this.cmdSet[name], `command ${name} has been registered`);
51 | assert(description, `command ${name} must have a description`);
52 | this.cmdSet[name] = {
53 | description,
54 | options,
55 | args,
56 | };
57 | }
58 |
59 | bindAction(name: string, fn: ActionFn) {
60 | assert(
61 | this.STATE === STATE.INIT,
62 | `bind command action should be called in INIT state`
63 | );
64 | assert(this.cmdSet[name], `command ${name} hasn't been registered`);
65 | assert(
66 | !this.cmdSet[name].action,
67 | `command ${name} action has been registered`
68 | );
69 | this.cmdSet[name].action = fn;
70 | }
71 |
72 | parse() {
73 | this.STATE = STATE.PARSE;
74 | this.program
75 | .description('Project Toolkit for React Applications')
76 | .version(this.pkg!.version, '-v, --version')
77 | .usage(' [options]');
78 | Object.keys(this.cmdSet).forEach(name => {
79 | const cmd = this.cmdSet[name];
80 | const command = this.program.command(name);
81 | command.description(cmd.description);
82 | if (cmd.args) {
83 | cmd.args.forEach(argv => {
84 | command.argument(argv.flags, argv.description);
85 | });
86 | }
87 | if (cmd.options) {
88 | cmd.options.forEach(option => {
89 | command.option(option.flags, option.description, option.defaultValue);
90 | });
91 | }
92 | if (cmd.action) {
93 | command.action(cmd.action);
94 | } else {
95 | throw new Error(`command ${name} action hasn't been bind`);
96 | }
97 | });
98 | this.program.parse();
99 | this.STATE = STATE.DONE;
100 | }
101 | }
102 |
103 | export default Commander;
104 |
--------------------------------------------------------------------------------
/packages/ko/src/core/config.ts:
--------------------------------------------------------------------------------
1 | import { join } from 'path';
2 | import { existsSync } from 'fs';
3 | import { merge, cloneDeep } from 'lodash';
4 | import { assert } from '../utils';
5 | import { IOptions, ICliOptions } from '../types';
6 |
7 | class Config {
8 | private cwd: string;
9 | private origin: Record;
10 | private current: Record;
11 | private path: string;
12 | public cliOpts: Partial;
13 | constructor() {
14 | this.cwd = process.cwd();
15 | this.path = this.getConfigPath('ko.config.js');
16 | this.generate();
17 | }
18 |
19 | private get isDevOrBuildCommand() {
20 | const flag = process.argv.find(arg => arg === 'dev' || arg === 'build');
21 | return !!flag;
22 | }
23 |
24 | private getConfigPath(path: string) {
25 | const absolutePath = join(process.cwd(), path);
26 | this.isDevOrBuildCommand &&
27 | assert(
28 | existsSync(absolutePath),
29 | 'ko.config.js file not exist, please check if it exist'
30 | );
31 | return absolutePath;
32 | }
33 |
34 | public generate() {
35 | this.origin = {};
36 | if (this.isDevOrBuildCommand) {
37 | this.origin = require(this.path);
38 | }
39 | this.current = merge(this.default, cloneDeep(this.origin));
40 | return Object.freeze(this.current) as IOptions;
41 | }
42 |
43 | public freezeWithOpts(cliOpts: Partial) {
44 | this.cliOpts = cliOpts;
45 | return Object.freeze(merge(this.current, this.cliOpts));
46 | }
47 |
48 | get default(): Partial {
49 | return {
50 | cwd: this.cwd,
51 | serve: {
52 | host: '127.0.0.1',
53 | port: 8080,
54 | },
55 | hash: true,
56 | analyzer: false,
57 | lessOptions: {
58 | javascriptEnabled: true,
59 | },
60 | publicPath: '/',
61 | experiment: {
62 | speedUp: true,
63 | minimizer: true,
64 | enableCssModule: true,
65 | disableLazyImports: false,
66 | },
67 | autoPolyfills: false,
68 | };
69 | }
70 | }
71 |
72 | export default Config;
73 |
--------------------------------------------------------------------------------
/packages/ko/src/core/hooks.ts:
--------------------------------------------------------------------------------
1 | import { AsyncSeriesWaterfallHook } from 'tapable';
2 | import { HookItem, ACTION, HOOK_KEY_SET, HookOptions } from '../types';
3 | import webpack from 'webpack';
4 |
5 | class Hooks {
6 | private hooks: Record>;
7 | public hookKeySet = HOOK_KEY_SET;
8 | constructor() {
9 | this.hooks = {};
10 | }
11 |
12 | public register({ key, action, opts }: HookOptions) {
13 | this.hooks[key] ||= {
14 | [ACTION.ADD]: [],
15 | [ACTION.UPDATE]: [],
16 | };
17 | this.hooks[key][action].push(opts);
18 | }
19 |
20 | public apply(opts: { key: string; context?: any }) {
21 | const hooks = this.hooks[opts.key];
22 | if (!hooks) return Promise.resolve(opts.context);
23 | const tapInstance = new AsyncSeriesWaterfallHook(['ctx']);
24 | hooks[ACTION.ADD].forEach(hook => {
25 | tapInstance.tapPromise(
26 | { name: hook.name, stage: hook.stage, before: hook.before },
27 | async (ctx: any) => {
28 | const result = await hook.fn(ctx, webpack);
29 | return ctx.concat(result);
30 | }
31 | );
32 | });
33 | hooks[ACTION.UPDATE].forEach(hook => {
34 | tapInstance.tapPromise(
35 | { name: hook.name, stage: hook.stage, before: hook.before },
36 | async ctx => {
37 | const result = await hook.fn(ctx, webpack);
38 | return result;
39 | }
40 | );
41 | });
42 | return tapInstance.promise(opts.context);
43 | }
44 | }
45 |
46 | export default Hooks;
47 |
--------------------------------------------------------------------------------
/packages/ko/src/core/service.ts:
--------------------------------------------------------------------------------
1 | import Commander from './commander';
2 | import Hooks from './hooks';
3 | import Config from './config';
4 | import { IOptions, ICliOptions, HOOK_KEY_SET, ACTION } from '../types';
5 |
6 | class Service extends Hooks {
7 | public config: IOptions;
8 | public cliOpts: Partial;
9 | public commander: Commander;
10 |
11 | constructor() {
12 | super();
13 | this.commander = new Commander();
14 | this.config = new Config().generate();
15 | this.config.plugins &&
16 | this.config.plugins.forEach(p => {
17 | // MODIFY_WEBPACK only support UPDATE
18 | if (p.key === HOOK_KEY_SET.MODIFY_WEBPACK) {
19 | p.action = ACTION.UPDATE;
20 | }
21 | this.register(p);
22 | });
23 | }
24 |
25 | freezeCliOptsWith(cliOpts: Partial) {
26 | this.cliOpts = Object.freeze(cliOpts);
27 | }
28 |
29 | run() {
30 | this.commander.parse();
31 | }
32 | }
33 |
34 | export default Service;
35 |
--------------------------------------------------------------------------------
/packages/ko/src/types.ts:
--------------------------------------------------------------------------------
1 | import { Pattern } from 'copy-webpack-plugin';
2 | import { Plugin } from 'postcss';
3 | import { IKeys, IOpts } from 'ko-lints';
4 | import { IOpts as AutoPolyfillsWebpackPluginOptions } from '@dtinsight/auto-polyfills-webpack-plugin';
5 | import { ClientConfiguration, Configuration as WebpackDevServerConfiguration } from 'webpack-dev-server';
6 |
7 | export interface IServeConfig extends WebpackDevServerConfiguration {
8 | proxy?: Record;
9 | host: string;
10 | port: number;
11 | staticPath?: string;
12 | client?: boolean | ClientConfiguration | undefined;
13 | historyApiFallback?: any;
14 | compilationSuccessInfo?: { messages: string[]; notes?: string[] };
15 | }
16 |
17 | export type IOptions = {
18 | //common configs
19 | /**
20 | * The current working directory.
21 | * @param {string}
22 | */
23 | cwd: string;
24 | /**
25 | * An object mapping module names to file paths or directories.
26 | * @param {Record}
27 | */
28 | alias?: Record;
29 | /**
30 | * An array of patterns specifying files to copy to the output directory.
31 | * @param {Pattern[]}
32 | */
33 | copy?: Pattern[];
34 | /**
35 | * The entry point of the application.
36 | * @param {string}
37 | */
38 | entry?: string;
39 | /**
40 | * The path to the output directory.
41 | * @param {string}
42 | */
43 | outputPath?: string;
44 | /**
45 | * The public path of the application.
46 | * @param {string}
47 | */
48 | publicPath?: string;
49 | /**
50 | * Whether to append a hash to the output file name for cache busting.
51 | * @param {boolean}
52 | */
53 | hash?: boolean;
54 | /**
55 | * An object mapping module names to global variables.
56 | * @param {Record}
57 | */
58 | externals?: Record;
59 | /**
60 | * An array of plugin configurations.
61 | * @param {HookOptions[]}
62 | */
63 | plugins?: HookOptions[];
64 | /**
65 | * The path to the HTML template to use for the application.
66 | * @param {string}
67 | */
68 | htmlTemplate?: string;
69 | htmlChunks?: 'all' | string[];
70 | // style configs
71 | /**
72 | * Whether to enable the bundle analyzer plugin.
73 | * @param {boolean}
74 | */
75 | analyzer?: boolean;
76 | /**
77 | * An array of additional PostCSS plugins to use.
78 | * @param {Plugin[]}
79 | */
80 | extraPostCSSPlugins?: Plugin[];
81 | /**
82 | * Options to pass to the Less compiler.
83 | * @param {*}
84 | */
85 | lessOptions?: any;
86 | // integrated plugins options
87 | /**
88 | * A function to dynamically resolve module requests.
89 | * @param {Function}
90 | */
91 | dynamicResolve?: (request: T) => T;
92 | /**
93 | * Whether to enable the auto-polyfills plugin, or an options object for the plugin.
94 | * @param {string}
95 | */
96 | autoPolyfills: boolean | AutoPolyfillsWebpackPluginOptions;
97 | // dev, or serve configs
98 | /**
99 | * Options for the development server.
100 | * Docs url: https://webpack.js.org/configuration/dev-server/
101 | * @param {IServeConfig}
102 | */
103 | serve: IServeConfig;
104 | // experimental features
105 | /**
106 | * Experimental features to enable.
107 | * @param {{speedUp?: boolean, minimizer?: boolean, disableLazyImports?: boolean, enableCssModule?: boolean, compress?: any}}
108 | */
109 | experiment?: {
110 | speedUp?: boolean;
111 | minimizer?: boolean;
112 | disableLazyImports?: boolean;
113 | enableCssModule?: boolean;
114 | compress?: any;
115 | };
116 | //misc
117 | /**
118 | * Options for the linter plugins.
119 | * @param {Record>}
120 | */
121 | lints?: Record>;
122 | };
123 |
124 | export type ICliOptions = {
125 | hash?: boolean;
126 | analyzer?: boolean;
127 | };
128 |
129 | export type IWebpackOptions = IOptions & {
130 | isProd: boolean;
131 | } & ICliOptions;
132 |
133 | export type HookItem = {
134 | name: string;
135 | fn: Function;
136 | stage?: number;
137 | before?: string;
138 | };
139 |
140 | export enum ACTION {
141 | ADD = 'add',
142 | UPDATE = 'update',
143 | }
144 |
145 | export enum HOOK_KEY_SET {
146 | WEBPACK_PLUGIN = 'WebpackPlugin',
147 | MODIFY_WEBPACK = 'ModifyWebpack',
148 | }
149 |
150 | export type HookOptions = {
151 | key: string;
152 | action: ACTION;
153 | opts: HookItem;
154 | };
155 |
--------------------------------------------------------------------------------
/packages/ko/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | export function getCacheIdentifier(env: string, pkgs: string[]): string {
2 | let cacheIdentifier = env || '';
3 | Object.values(pkgs).forEach(pkgName => {
4 | cacheIdentifier += `:${pkgName}@`;
5 | cacheIdentifier += require(`${pkgName}/package.json`).version || '';
6 | });
7 | return cacheIdentifier;
8 | }
9 |
10 | export function getResolvePath(name: string) {
11 | const resolvePath = require.resolve(name);
12 | return resolvePath;
13 | }
14 |
15 | export { default as assert } from 'assert';
16 |
--------------------------------------------------------------------------------
/packages/ko/src/webpack/custom-plugins/purge-cache-webpack-plugin/index.ts:
--------------------------------------------------------------------------------
1 | import { Compiler } from 'webpack';
2 | import fs from 'fs/promises';
3 | import path from 'path';
4 |
5 | class PurgeCacheWebpackPlugin {
6 | WEBPACK_PLUGIN_NAME = 'PurgeCacheWebpackPlugin';
7 |
8 | purgeCacheFiles(
9 | directory: string,
10 | maxAge: number,
11 | callback: (errors?: Error[]) => void
12 | ) {
13 | fs.readdir(directory)
14 | .then(files => {
15 | const expiredPacks = [];
16 | if (files.length === 0) return callback();
17 |
18 | for (const file of files) {
19 | const pack = new Promise((resolve, reject) => {
20 | const filePath = path.join(directory, file);
21 | fs.stat(filePath)
22 | .then(stats => {
23 | if (stats.mtime.getTime() + maxAge < Date.now()) {
24 | fs.unlink(filePath)
25 | .then(() => {
26 | resolve(true);
27 | })
28 | .catch(err => reject(err));
29 | } else {
30 | resolve(true);
31 | }
32 | })
33 | .catch(err => reject(err));
34 | });
35 |
36 | expiredPacks.push(pack);
37 | }
38 |
39 | Promise.allSettled(expiredPacks).then(results => {
40 | const errors = results
41 | .filter(result => result.status === 'rejected')
42 | .map((result: any) => result.reason);
43 | callback(errors);
44 | });
45 | })
46 | .catch(err => {
47 | callback([err]);
48 | });
49 | }
50 |
51 | apply(compiler: Compiler) {
52 | compiler.hooks.done.tapAsync(
53 | { name: this.WEBPACK_PLUGIN_NAME },
54 | (_, callback) => {
55 | const { type, maxAge, cacheLocation } = compiler.options.cache as any;
56 | if (type === 'filesystem') {
57 | const logger = compiler.getInfrastructureLogger(
58 | this.WEBPACK_PLUGIN_NAME
59 | );
60 | this.purgeCacheFiles(cacheLocation, maxAge, errors => {
61 | if (errors?.length) {
62 | errors.forEach(err => logger.warn(err.message));
63 | } else {
64 | logger.info(`purge expired cache files completed`);
65 | }
66 | callback();
67 | });
68 | } else {
69 | callback();
70 | }
71 | }
72 | );
73 | }
74 | }
75 |
76 | export default PurgeCacheWebpackPlugin;
77 |
--------------------------------------------------------------------------------
/packages/ko/src/webpack/index.ts:
--------------------------------------------------------------------------------
1 | import { join } from 'path';
2 | import { existsSync } from 'fs';
3 | import { Configuration, FileCacheOptions } from 'webpack';
4 | import DynamicResolveWebpackPlugin from 'dynamic-resolve-webpack-plugin';
5 | import { merge } from 'lodash';
6 | import loaders from './loaders';
7 | import getPlugins from './plugins';
8 | import { assert } from '../utils';
9 | import Service from '../core/service';
10 | import { IOptions } from '../types';
11 |
12 | class WebpackConfig {
13 | private extensions = [
14 | '.ts',
15 | '.tsx',
16 | '.js',
17 | '.jsx',
18 | '.css',
19 | '.scss',
20 | '.sass',
21 | '.less',
22 | '.json',
23 | '.html',
24 | ];
25 | private opts: IOptions;
26 | private env: 'production' | 'development';
27 | constructor(service: Service) {
28 | this.opts = { ...service.config, ...service.cliOpts };
29 | this.env =
30 | process.env.NODE_ENV === 'production' ? 'production' : 'development';
31 | }
32 |
33 | public merge(...opts: Configuration[]): Configuration {
34 | return merge(this.base, ...opts);
35 | }
36 |
37 | get cache(): FileCacheOptions {
38 | const { experiment } = this.opts;
39 | const type = experiment?.speedUp
40 | ? 'filesystem'
41 | : this.isProd
42 | ? 'filesystem'
43 | : 'memory';
44 | const cache: Exclude, boolean> = {
45 | type,
46 | };
47 | if (type === 'filesystem') {
48 | (cache as FileCacheOptions).version = this.projectVersion;
49 | (cache as FileCacheOptions).maxAge = 7 * 24 * 3600000;
50 | } else {
51 | (
52 | cache as Exclude<
53 | NonNullable,
54 | boolean | FileCacheOptions
55 | >
56 | ).maxGenerations = 1;
57 | }
58 | return cache as FileCacheOptions;
59 | }
60 |
61 | get projectVersion(): string {
62 | const pkgPath = join(this.opts.cwd, 'package.json');
63 | assert(existsSync(pkgPath), 'project package.json file not found');
64 | return require(pkgPath).version;
65 | }
66 |
67 | get base() {
68 | const { cwd, publicPath, entry, outputPath, alias, hash, analyzer } =
69 | this.opts;
70 |
71 | const webpackBaseConf = {
72 | mode: this.env,
73 | target: 'web',
74 | context: cwd,
75 | entry,
76 | output: {
77 | path: outputPath,
78 | filename: `js/[name].${hash ? '[contenthash].' : ''}js`,
79 | publicPath,
80 | },
81 | module: {
82 | rules: loaders({
83 | isProd: this.isProd,
84 | ...this.opts,
85 | }),
86 | },
87 | plugins: getPlugins({
88 | isProd: this.isProd,
89 | analyzer,
90 | ...this.opts,
91 | }),
92 | resolve: {
93 | plugins: [
94 | this.opts.dynamicResolve &&
95 | new DynamicResolveWebpackPlugin({
96 | dynamic: this.opts.dynamicResolve,
97 | }),
98 | ].filter(Boolean),
99 | extensions: this.extensions,
100 | alias,
101 | fallback: {
102 | fs: false,
103 | path: false,
104 | events: false,
105 | os: require.resolve('os-browserify/browser'),
106 | crypto: require.resolve('crypto-browserify'),
107 | stream: require.resolve('stream-browserify'),
108 | buffer: require.resolve('buffer/'),
109 | string_decoder: require.resolve('string_decoder/'),
110 | querystring: require.resolve('querystring-es3'),
111 | },
112 | },
113 | performance: {
114 | hints: false,
115 | },
116 | cache: this.cache,
117 | stats: 'none',
118 | infrastructureLogging: {
119 | level: 'error',
120 | },
121 | };
122 | return webpackBaseConf as Configuration;
123 | }
124 |
125 | get isProd() {
126 | return this.env === 'production';
127 | }
128 | }
129 |
130 | export default WebpackConfig;
131 |
--------------------------------------------------------------------------------
/packages/ko/src/webpack/loaders/asset.ts:
--------------------------------------------------------------------------------
1 | const assetModules = [
2 | {
3 | test: /\.(woff|woff2|ttf|eot)$/,
4 | type: 'asset/resource',
5 | generator: {
6 | filename: 'fonts/[hash][ext][query]',
7 | },
8 | },
9 | {
10 | test: /\.(png|jpg|jpeg|gif|webp|svg|ico)$/i,
11 | type: 'asset/resource',
12 | generator: {
13 | filename: 'images/[hash][ext][query]',
14 | },
15 | },
16 | ];
17 |
18 | export default assetModules;
19 |
--------------------------------------------------------------------------------
/packages/ko/src/webpack/loaders/babel/index.ts:
--------------------------------------------------------------------------------
1 | import { getCacheIdentifier, getResolvePath } from '../../../utils';
2 | import { IWebpackOptions } from '../../../types';
3 |
4 | class BabelLoader {
5 | private BABEL_LOADER: string;
6 | private opts: IWebpackOptions;
7 | private speedUp: boolean;
8 | constructor(opts: IWebpackOptions) {
9 | this.BABEL_LOADER = getResolvePath('babel-loader');
10 | this.opts = opts;
11 | }
12 |
13 | get config() {
14 | return {
15 | loader: this.BABEL_LOADER,
16 | options: {
17 | presets: [
18 | [
19 | getResolvePath('babel-preset-ko-app'),
20 | {
21 | useAbsoluteRuntime: true,
22 | },
23 | ],
24 | ],
25 | plugins: this.plugins,
26 | babelrc: false,
27 | configFile: false,
28 | cacheIdentifier: this.cacheIdentifier,
29 | cacheDirectory: !this.speedUp,
30 | cacheCompression: false,
31 | compact: this.opts.isProd,
32 | },
33 | };
34 | }
35 |
36 | get treasurePluginConfig() {
37 | const babelPluginTreasurePath = getResolvePath('babel-plugin-treasure');
38 | return [
39 | [
40 | babelPluginTreasurePath,
41 | {
42 | libraryName: 'antd',
43 | libraryDirectory: 'lib',
44 | style: 'css',
45 | },
46 | 'antd',
47 | ],
48 | [
49 | babelPluginTreasurePath,
50 | {
51 | libraryName: 'dt-react-component',
52 | libraryDirectory: '/src/components/',
53 | camel2DashComponentName: 'lower',
54 | },
55 | 'drc',
56 | ],
57 | //TODO: check lodash tree shaking in webpack 5
58 | // [
59 | // babelPluginTreasurePath,
60 | // {
61 | // libraryName: 'lodash',
62 | // libraryDirectory: '/',
63 | // camel2DashComponentName: false,
64 | // },
65 | // 'lodash',
66 | // ],
67 | ];
68 | }
69 |
70 | get plugins() {
71 | return [...this.treasurePluginConfig].filter(Boolean);
72 | }
73 |
74 | get cacheIdentifier() {
75 | return getCacheIdentifier(this.opts.isProd ? 'production' : '', [
76 | 'ko',
77 | 'babel-preset-ko-app',
78 | 'babel-plugin-treasure',
79 | ]);
80 | }
81 | }
82 |
83 | export default BabelLoader;
84 |
--------------------------------------------------------------------------------
/packages/ko/src/webpack/loaders/index.ts:
--------------------------------------------------------------------------------
1 | import Style from './style';
2 | import asset from './asset';
3 | import Script from './script';
4 | import { IWebpackOptions } from '../../types';
5 |
6 | const loaders = (opts: IWebpackOptions) => {
7 | const scripts = new Script(opts);
8 | const style = new Style(opts);
9 | return [...asset, ...style.config, ...scripts.config];
10 | };
11 |
12 | export default loaders;
13 |
--------------------------------------------------------------------------------
/packages/ko/src/webpack/loaders/script.ts:
--------------------------------------------------------------------------------
1 | import BabelLoader from './babel';
2 | import { IWebpackOptions } from '../../types';
3 | class Script {
4 | private THREAD_LOADER = require.resolve('thread-loader');
5 | private WORKER_LOADER = require.resolve('worker-loader');
6 | private ESBUILD_LOADER = require.resolve('esbuild-loader');
7 | private BABEL_LOADER: BabelLoader;
8 | private opts: IWebpackOptions;
9 | constructor(opts: IWebpackOptions) {
10 | this.opts = opts;
11 | this.BABEL_LOADER = new BabelLoader(opts);
12 | }
13 |
14 | get config() {
15 | const scriptLoader = [
16 | {
17 | test: /\.worker.[jt]s$/,
18 | loader: this.WORKER_LOADER,
19 | include: (input: string) =>
20 | /dt-react-monaco-editor[\\/]lib[\\/]languages/.test(input),
21 | options: {
22 | inline: 'fallback',
23 | },
24 | },
25 | {
26 | test: /\.m?(t|j)sx?$/,
27 | include: (input: string) => {
28 | // internal modules dt-common compatible
29 | if (/node_modules[\\/]dt-common[\\/]src[\\/]/.test(input)) {
30 | return true;
31 | } else if (input.includes('antlr4-c3')) {
32 | return true;
33 | } else if (input.includes('antlr4ng')) {
34 | return true;
35 | } else if (input.includes('node_modules')) {
36 | return false;
37 | } else {
38 | return true;
39 | }
40 | },
41 | use: [
42 | {
43 | loader: this.THREAD_LOADER,
44 | options: {
45 | name: 'ko-js-pool',
46 | },
47 | },
48 | this.opts.experiment?.speedUp
49 | ? {
50 | loader: this.ESBUILD_LOADER,
51 | options: {
52 | loader: 'tsx',
53 | target: 'es2015',
54 | },
55 | }
56 | : this.BABEL_LOADER.config,
57 | ].filter(Boolean),
58 | },
59 | ];
60 | return scriptLoader;
61 | }
62 | }
63 |
64 | export default Script;
65 |
--------------------------------------------------------------------------------
/packages/ko/src/webpack/loaders/style.ts:
--------------------------------------------------------------------------------
1 | import { join } from 'path';
2 | import { realpathSync, existsSync } from 'fs';
3 | import { loader as MiniCssExtractPluginLoader } from 'mini-css-extract-plugin';
4 | import autoprefixer from 'autoprefixer';
5 | const postCssUrl = require('postcss-url');
6 | import { getResolvePath } from '../../utils';
7 | import { IWebpackOptions } from '../../types';
8 |
9 | class Style {
10 | private STYLE_LOADER = getResolvePath('style-loader');
11 | private CSS_LOADER = getResolvePath('css-loader');
12 | private SASS_LOADER = getResolvePath('sass-loader');
13 | private LESS_LOADER = getResolvePath('less-loader');
14 | private POSTCSS_LOADER = getResolvePath('postcss-loader');
15 | private CSS_MODULE_FILE_SUFFIX_REGEX = /\.module.s[ac]ss$/;
16 | private opts: IWebpackOptions;
17 | constructor(opts: IWebpackOptions) {
18 | this.opts = opts;
19 | }
20 |
21 | get config() {
22 | const enableCssModule = this.opts?.experiment?.enableCssModule;
23 | return [
24 | {
25 | test: /\.css$/,
26 | use: [this.styleLoader, this.cssLoader, this.postCSSLoader],
27 | },
28 | {
29 | test: /\.s[ac]ss$/,
30 | exclude: (input: string) => {
31 | if (enableCssModule) {
32 | return this.CSS_MODULE_FILE_SUFFIX_REGEX.test(input);
33 | } else {
34 | return false;
35 | }
36 | },
37 | use: [
38 | this.styleLoader,
39 | this.cssLoader,
40 | this.postCSSLoader,
41 | this.sassLoader,
42 | ],
43 | },
44 | enableCssModule && this.sassCssModuleConfig,
45 | {
46 | test: /\.less$/,
47 | use: [
48 | this.styleLoader,
49 | this.cssLoader,
50 | this.postCSSLoader,
51 | this.lessLoader,
52 | ],
53 | },
54 | ];
55 | }
56 |
57 | get sassCssModuleConfig() {
58 | return {
59 | test: /\.module.s[ac]ss$/,
60 | use: [
61 | this.styleLoader,
62 | {
63 | loader: this.CSS_LOADER,
64 | options: {
65 | esModule: true,
66 | modules: {
67 | namedExport: true,
68 | localIdentName: this.opts.isProd
69 | ? '[path][name]__[local]'
70 | : '[local]_[hash:base64]',
71 | },
72 | },
73 | },
74 | this.postCSSLoader,
75 | this.sassLoader,
76 | ],
77 | };
78 | }
79 |
80 | get styleLoader() {
81 | return {
82 | loader: this.opts.isProd ? MiniCssExtractPluginLoader : this.STYLE_LOADER,
83 | };
84 | }
85 |
86 | get cssLoader() {
87 | return {
88 | loader: this.CSS_LOADER,
89 | options: {
90 | sourceMap: true,
91 | },
92 | };
93 | }
94 |
95 | get sassLoader() {
96 | return {
97 | loader: this.SASS_LOADER,
98 | options: {
99 | sourceMap: true,
100 | },
101 | };
102 | }
103 |
104 | get lessLoader() {
105 | const { lessOptions = {} } = this.opts;
106 | return {
107 | loader: this.LESS_LOADER,
108 | options: {
109 | sourceMap: true,
110 | lessOptions,
111 | },
112 | };
113 | }
114 |
115 | get postCSSLoader() {
116 | return {
117 | loader: this.POSTCSS_LOADER,
118 | options: {
119 | sourceMap: true,
120 | postcssOptions: {
121 | plugins: this.postCSSPlugins,
122 | },
123 | },
124 | };
125 | }
126 |
127 | get postCSSPlugins() {
128 | const extraPostCSSPlugins = this.opts.extraPostCSSPlugins || [];
129 | return [
130 | autoprefixer(),
131 | postCssUrl([
132 | {
133 | filter: '**/src/public/img/**/*',
134 | url: (args: any) => {
135 | const originUrl = args?.originUrl;
136 | return originUrl
137 | ? join(this.opts.cwd, originUrl)
138 | : args.absolutePath;
139 | },
140 | basePath: '/',
141 | },
142 | {
143 | filter: '**/src/public/font/**/*',
144 | url: (args: any) => {
145 | const originUrl = args?.originUrl;
146 | return originUrl
147 | ? join(this.opts.cwd, originUrl)
148 | : args.absolutePath;
149 | },
150 | basePath: '/',
151 | },
152 | ]),
153 | ...extraPostCSSPlugins,
154 | ].filter(Boolean);
155 | }
156 | }
157 |
158 | export default Style;
159 |
--------------------------------------------------------------------------------
/packages/ko/src/webpack/plugins.ts:
--------------------------------------------------------------------------------
1 | import { IgnorePlugin, optimize } from 'webpack';
2 | import MiniCssExtractPlugin from 'mini-css-extract-plugin';
3 | import CaseSensitivePathsPlugin from 'case-sensitive-paths-webpack-plugin';
4 | import ReactRefreshPlugin from '@pmmmwh/react-refresh-webpack-plugin';
5 | import WebpackBar from 'webpackbar';
6 | import { CleanWebpackPlugin } from 'clean-webpack-plugin';
7 | import CopyWebpackPlugin from 'copy-webpack-plugin';
8 | import HtmlWebpackPlugin from 'html-webpack-plugin';
9 | import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
10 | import AutoPolyfillsWebpackPlugin from '@dtinsight/auto-polyfills-webpack-plugin';
11 | import FriendlyErrorsWebpackPlugin from '@nuxt/friendly-errors-webpack-plugin';
12 | import PurgeCacheWebpackPlugin from './custom-plugins/purge-cache-webpack-plugin';
13 | import { IWebpackOptions } from '../types';
14 |
15 | function getPlugins(opts: IWebpackOptions) {
16 | const {
17 | isProd,
18 | htmlTemplate,
19 | htmlChunks,
20 | copy,
21 | analyzer,
22 | autoPolyfills,
23 | serve: { host, port, compilationSuccessInfo },
24 | } = opts;
25 | const htmlOptions: HtmlWebpackPlugin.Options = {
26 | template: htmlTemplate,
27 | };
28 | if (htmlChunks) {
29 | htmlOptions.chunks = htmlChunks;
30 | }
31 | return [
32 | new IgnorePlugin({
33 | resourceRegExp: /^\.\/locale$/,
34 | contextRegExp: /moment$/,
35 | }),
36 | isProd &&
37 | new optimize.SplitChunksPlugin({
38 | chunks: 'all',
39 | minSize: 30000,
40 | maxSize: 600000,
41 | minChunks: 1,
42 | automaticNameDelimiter: '_',
43 | cacheGroups: {
44 | baseCommon: {
45 | test: new RegExp(
46 | `[\\/]node_modules[\\/](${[
47 | 'react',
48 | 'react-router',
49 | 'react-dom',
50 | 'react-redux',
51 | 'redux',
52 | 'react-router-redux',
53 | ].join('|')})`
54 | ),
55 | priority: 1,
56 | },
57 | antd: {
58 | name: 'antd',
59 | test: /[\\/]node_modules[\\/]antd[\\/]/,
60 | chunks: 'initial',
61 | },
62 | lodash: {
63 | name: 'lodash',
64 | test: /[\\/]node_modules[\\/]lodash[\\/]/,
65 | chunks: 'initial',
66 | priority: -10,
67 | },
68 | default: {
69 | minChunks: 2,
70 | priority: -20,
71 | reuseExistingChunk: true,
72 | },
73 | },
74 | }),
75 | isProd &&
76 | new MiniCssExtractPlugin({
77 | filename: 'css/[name].[contenthash].css',
78 | chunkFilename: 'css/[id].[contenthash].css',
79 | }),
80 | new CaseSensitivePathsPlugin(),
81 | new HtmlWebpackPlugin(htmlOptions),
82 | copy &&
83 | new CopyWebpackPlugin({
84 | patterns: copy,
85 | }),
86 | new WebpackBar(),
87 | new CleanWebpackPlugin({
88 | verbose: false,
89 | dry: false,
90 | }),
91 | new ReactRefreshPlugin({
92 | overlay: false,
93 | }),
94 | analyzer && new BundleAnalyzerPlugin(),
95 | !isProd &&
96 | new FriendlyErrorsWebpackPlugin({
97 | compilationSuccessInfo: compilationSuccessInfo ?? {
98 | messages: [`Your application is running at http://${host}:${port}`],
99 | notes: [],
100 | },
101 | }),
102 | !isProd && new PurgeCacheWebpackPlugin(),
103 | isProd &&
104 | autoPolyfills &&
105 | (typeof autoPolyfills === 'boolean'
106 | ? new AutoPolyfillsWebpackPlugin()
107 | : new AutoPolyfillsWebpackPlugin(autoPolyfills)),
108 | ].filter(Boolean);
109 | }
110 |
111 | export default getPlugins;
112 |
--------------------------------------------------------------------------------
/packages/ko/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@tsconfig/node14/tsconfig.json",
3 | "include": ["src/**/*.ts", "index.d.ts"],
4 | "exclude": ["src/**/*.test.ts"],
5 | "compilerOptions": {
6 | "allowJs": true,
7 | "skipLibCheck": true,
8 | "esModuleInterop": true,
9 | "strict": true,
10 | "strictPropertyInitialization": false,
11 | "outDir": "lib",
12 | "declaration": true,
13 | },
14 | }
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - 'packages/**'
3 | - 'website'
4 | - '!packages/create-ko/template'
5 |
--------------------------------------------------------------------------------
/website/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependencies
2 | /node_modules
3 |
4 | # Production
5 | **/build
6 |
7 | # Generated files
8 | .docusaurus
9 | .cache-loader
10 |
11 | # Misc
12 | .DS_Store
13 | .env.local
14 | .env.development.local
15 | .env.test.local
16 | .env.production.local
17 |
18 | npm-debug.log*
19 | yarn-debug.log*
20 | yarn-error.log*
21 |
--------------------------------------------------------------------------------
/website/README.md:
--------------------------------------------------------------------------------
1 | # Website
2 |
3 | This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.
4 |
5 | ### Installation
6 |
7 | ```
8 | $ yarn
9 | ```
10 |
11 | ### Local Development
12 |
13 | ```
14 | $ yarn start
15 | ```
16 |
17 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
18 |
19 | ### Build
20 |
21 | ```
22 | $ yarn build
23 | ```
24 |
25 | This command generates static content into the `build` directory and can be served using any static contents hosting service.
26 |
27 | ### Deployment
28 |
29 | Using SSH:
30 |
31 | ```
32 | $ USE_SSH=true yarn deploy
33 | ```
34 |
35 | Not using SSH:
36 |
37 | ```
38 | $ GIT_USER= yarn deploy
39 | ```
40 |
41 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
42 |
--------------------------------------------------------------------------------
/website/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
3 | };
4 |
--------------------------------------------------------------------------------
/website/docs/FAQ.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 5
3 | title: FAQ
4 | ---
5 |
6 | ## How to polyfill Node.js core modules
7 |
8 | Webpack 5 no longer polyfills Node.js core modules automatically which means if you use them in your code running in browsers or alike, you will have to install compatible modules from npm and include them yourself. And if your target environment is browser, just install some packages and add **resolve.fallback** into **ko.config.js**.
9 | :::tip
10 | From v5.3.4, ko polyfill these core modules internally, so you don't have to install below packages and add configs.
11 | :::
12 |
13 | ```js
14 | {
15 | resolve: {
16 | fallback: {
17 | fs: false,
18 | path: false,
19 | events: false,
20 | os: require.resolve('os-browserify/browser'),
21 | crypto: require.resolve('crypto-browserify'),
22 | stream: require.resolve('stream-browserify'),
23 | buffer: require.resolve('buffer/'),
24 | string_decoder: require.resolve('string_decoder/'),
25 | },
26 | }
27 | }
28 | ```
29 |
30 | ### Environment variables process.env.node_env
31 |
32 | * To custom plugins in your ko.config.js between development and production builds you may use environment variables.
33 | * ko dev vs build inject process.env.node_env as developement and production
34 |
35 | ```js
36 | plugins: [
37 | new CopyWebpackPlugin(yourOwnCopyConfig),
38 | process.env.NODE_ENV === 'production' ? new VersionPlugin() : null
39 | ].filter(Boolean)
40 |
41 | ```
42 |
43 | ## How to use web workers
44 |
45 | :::caution
46 | For compatible reason we use `work-loader` internally. So you can migrate into ko without considering update your import Worker code.But using worker like below examples is recommended.
47 | :::
48 |
49 | You can use [Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) without [worker-loader](https://github.com/webpack-contrib/worker-loader) in ko, just like this:
50 |
51 | ```js
52 | new Worker(new URL('./worker.js', import.meta.url));
53 | ```
54 |
55 | And you should update your project **tsconfig.json** into these configs:
56 |
57 | ```json
58 | "compilerOptions": {
59 | "module": "esnext",
60 | "moduleResolution": "Node"
61 | }
62 | ```
63 |
--------------------------------------------------------------------------------
/website/docs/advanced/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Advanced",
3 | "position": 5
4 | }
--------------------------------------------------------------------------------
/website/docs/advanced/architecture.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 1
3 | title: Architecture
4 | ---
5 |
6 | 
7 |
8 | This diagram shows how ko works to build your applications and lint your source code. we maintain 4 packages and get them together into package **ko**.
9 |
10 | * **babel-preset-ko-app**: babel preset used by ko
11 | * **ko-lint-config**: our config files of eslint, prettier and stylelint, used by ko-lints as default configs
12 | * **ko-lints**: cli for lint source code
13 | * **ko**: main entrance, getting webpack instance and ko-lints together.
14 |
--------------------------------------------------------------------------------
/website/docs/advanced/plugins.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 2
3 | title: How to Write Plugins
4 | ---
5 |
6 | Ko support use plugin to modify internal configs and behaviors.Here is an example:
7 |
8 | ```js
9 | const VersionWebpackPlugin = require('./version-webpack-plugin');
10 | module.exports = {
11 | plugins: [
12 | {
13 | key: 'WebpackPlugin',
14 | action: 'add',
15 | opts: {
16 | name: 'VersionWebpackPlugin',
17 | fn: () => new VersionWebpackPlugin(),
18 | },
19 | },
20 | ],
21 | }
22 | ```
23 |
24 | As you can see, you can register your own ko plugin in via add plugins config in **ko.config.js**, and you should specify `key`, `action` and `opts` values:
25 |
26 | * key: supported hook keys, only `WebpackPlugin` & `ModifyWebpack` are supported currently.
27 | * action: supported actions, you can use `add` when add configs or use `update` when you want fully control current configs
28 | * opts: all opts passed will use internally via `tapable`, supported types:
29 |
30 | ```typescript
31 | export type HookItem = {
32 | name: string;
33 | fn: Function;
34 | stage?: number;
35 | before?: string;
36 | };
37 | ```
38 |
--------------------------------------------------------------------------------
/website/docs/cli.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 3
3 | title: Command Line Interface
4 | ---
5 |
6 | ## ko dev
7 |
8 | start a development server that provides live reloading.
9 |
10 | Optional arguments:
11 |
12 | * `-h --hash`: output filename with it's contenthash
13 | * `-a,--analyzer`: show output files with an interactive zoomable treemap in **http://127.0.0.1:8888**
14 |
15 | ## ko build
16 |
17 | Use internal webpack instance to bundle files, compiled files will be write to **dist** directory by default.
18 |
19 | Optional arguments:
20 |
21 | * `--hash`: output filename with it's contenthash
22 |
23 | ## ko lint
24 |
25 | Lint your code via prettier, eslint or stylelint, You can use `pnpm` or `npx` to run lint on the command like this:
26 |
27 | ``` bash
28 | # Run lint via prettier on files:
29 | pnpm exec ko prettier file1.js file2.ts
30 | # Run lint via prettier on multiple files via glob syntax and try to fix problems
31 | pnpm exec ko prettier "src/**" --write
32 | # Run lint via eslint on files:
33 | pnpm exec ko eslint file1.js file2.ts
34 | # Run lint via eslint on multiple files via glob syntax on concurrency mode
35 | pnpm exec ko eslint "src/**" --concurrency
36 | # Run lint via stylelint on files:
37 | pnpm exec ko stylelint file1.css file2.less
38 | # Run lint via stylelint on multiple files via glob syntax with custom config
39 | pnpm exec ko stylelint "src/**" --configPath="/path/to/custom/config"
40 | ```
41 |
42 | Optional arguments:
43 |
44 | * `-w, --write`: try to fix problems automatically
45 | * `-c, --configPath `: overriding default config path, and use this configuration
46 | * `--concurrency`: use multithreading to lint files
47 | * `--concurrentNumber `: specify threads number, default is `require('os').cpus().length`
48 |
49 | You can add ignore patterns in `.gitignore` file and `.prettierignore` file via prettier, `.eslintignore` file via eslint, `.stylelint` file via stylelint,
50 | all of these patterns matched files will be ignored when lint running.
51 |
--------------------------------------------------------------------------------
/website/docs/configuration.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 4
3 | title: Configuration
4 | ---
5 |
6 | You can custom ko's action via **ko.config.js**, below are supported configurations:
7 |
8 | ``` typescript
9 | import { ClientConfiguration } from 'webpack-dev-server';
10 |
11 | export type IOptions = {
12 | //common configs
13 | cwd: string; //current working directory
14 | alias?: Record; // Create aliases to import or require certain modules more easily
15 | copy?: Pattern[]; // copy files patterns
16 | entry?: string; // all start from here
17 | outputPath?: string; // The output directory as an absolute path
18 | publicPath?: string; // specify the base path for all the assets within your application
19 | hash?: boolean; // output files with it's content hash
20 | externals?: Record; //excluding dependencies from the output bundles
21 | plugins?: any[]; // ko internal plugins, you can define your own plugin of ko.
22 | htmlTemplate?: string; //output html file template
23 | htmlChunks?: 'all' | string[]; // add only some chunks to html
24 | // style configs
25 | analyzer?: boolean; // show output files with an interactive zoomable treemap
26 | extraPostCSSPlugins?: Plugin[]; // extra post css plugins
27 | lessOptions?: any; // custom less options
28 | // integrated plugins options
29 | dynamicResolve?: (request: T) => T; // dynamic resolve function
30 | autoPolyfills: boolean | AutoPolyfillsWebpackPluginOptions; // auto polyfills plugin options
31 | // dev, or serve configs
32 | serve: {
33 | proxy?: Record; // proxy of dev server
34 | host: string; // host of dev server
35 | port: number; // port of dev server
36 | staticPath?: string; // static path that will be watch of dev server
37 | client?: boolean | ClientConfiguration | undefined; // client of dev server
38 | compilationSuccessInfo?: { messages: string[]; notes?: string[] }; // log after successful compilation, as same as friendly-errors-webpack-plugin
39 | // other all webpack-dev-server supported configs
40 | };
41 | // experimental features
42 | experiment?: {
43 | speedUp?: boolean; // enable speed up configs of dev & build actions
44 | minimizer?: boolean; // enable minimizer via esbuild in build action
45 | enableCssModule?: boolean; //enable css module
46 | disableLazyImports?: boolean; // disable lazy compilation of imports
47 | };
48 | lints?: Record>; // lint configs
49 | };
50 | ```
51 |
52 | For more details, please see [link](https://github.com/DTStack/ko/blob/master/packages/ko/src/types.ts)
53 |
--------------------------------------------------------------------------------
/website/docs/getting-started.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 2
3 | title: Getting Started
4 | ---
5 |
6 | ## Prerequisites
7 |
8 | * Node.js version: Node.js 14+
9 |
10 | ## Create a React Project in One Line
11 | Your can use CLI to create a React Project with TypeScript.
12 | ``` bash
13 | pnpm create ko
14 | # or
15 | npm create ko
16 | # or
17 | yarn create ko
18 | ```
19 | After waiting a second, you could see `Creating project in...` in terminal.
20 |
21 | And then just going into the folder and install dependencies.
22 |
23 | ## Install ko
24 |
25 | You can install ko using npm, yarn or pnpm:
26 |
27 | ``` bash
28 | pnpm add ko --save-dev
29 | # or
30 | npm install ko --save-dev
31 | # or
32 | yarn add ko --dev
33 | ```
34 |
35 | Polyfills are needed for IE browsers. We recommended [core-js](https://github.com/zloirock/core-js) and [regenerator-runtime](https://www.npmjs.com/package/regenerator-runtime) for it. And you should install them as dependencies:
36 |
37 | ``` bash
38 | pnpm add core-js regenerator-runtime
39 | ```
40 |
41 | ## Configuration
42 |
43 | After install ko,you can create an configuration file named **ko.config.js** for customize ko. And you can specify your own **entry** and **output** configurations, for more configuration, please see [Configuration](./configuration) ko will help you merge these configs and use them in internal webpack instance. A real world showcase:
44 |
45 | ``` js
46 | module.exports = {
47 | entry: './src/app.tsx',
48 | outputPath: './dist' //Your own output path
49 | serve: {
50 | proxy: PROXY_CONFIG, // Your own proxy config
51 | host: '0.0.0.0',
52 | port: 8084,
53 | },
54 | };
55 | ```
56 |
57 | ## Everyday Commands
58 |
59 | Your daily workflow only needs a few ko commands:
60 |
61 | ### ko dev
62 |
63 | start a development server that provides live reloading. You can change development server default behaviors via **serve** configurations.
64 |
65 | ### ko build
66 |
67 | bundle files with internal webpack instance, with some built-in loaders and plugins that can speed up build process.
68 |
--------------------------------------------------------------------------------
/website/docs/introduction.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 1
3 | title: Introduction
4 | ---
5 |
6 | **ko** is a simple, yet powerful, tool for managing your react applications.
7 |
8 | ## Features
9 |
10 | * Support building applications on top of **webpack v5** and **esbuild**
11 | * Customize ko to work exactly the way you need it for your applications
12 | * Built-in popular linting tools to lint your source code
13 | * Built-in support typescript
14 |
15 | ## Installation
16 |
17 | You can install ko using npm, yarn or pnpm:
18 | ``` bash
19 | npm install ko --save-dev
20 | # or
21 | yarn add ko --dev
22 | # or
23 | pnpm add ko --save-dev
24 | ```
25 |
26 | ## Contributing
27 |
28 | We'd love to have your helping hand on `ko`! See [CONTRIBUTING](https://github.com/DTStack/ko/blob/master/CONTRIBUTING.md) for more information on how to get started.
29 |
30 | ## License
31 |
32 | Copyright © DTStack. All rights reserved.
33 |
34 | Licensed under the MIT license.
--------------------------------------------------------------------------------
/website/docusaurus.config.js:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | // Note: type annotations allow type checking and IDEs autocompletion
3 |
4 | const lightCodeTheme = require('prism-react-renderer/themes/github');
5 | const darkCodeTheme = require('prism-react-renderer/themes/dracula');
6 |
7 | /** @type {import('@docusaurus/types').Config} */
8 | const config = {
9 | title: 'ko',
10 | tagline: 'Project toolkit for React Applications',
11 | url: 'https://dtstack.github.io',
12 | baseUrl: '/ko/',
13 | onBrokenLinks: 'throw',
14 | onBrokenMarkdownLinks: 'warn',
15 | favicon: 'img/favicon.ico',
16 | organizationName: 'DTStack', // Usually your GitHub org/user name.
17 | projectName: 'ko', // Usually your repo name.
18 | presets: [
19 | [
20 | 'classic',
21 | /** @type {import('@docusaurus/preset-classic').Options} */
22 | ({
23 | docs: {
24 | sidebarPath: require.resolve('./sidebars.js'),
25 | // Please change this to your repo.
26 | editUrl: 'https://github.com/DTStack/ko/website/',
27 | lastVersion: 'current',
28 | versions: {
29 | current: {
30 | label: '6.x',
31 | path: 'current',
32 | },
33 | },
34 | },
35 | // blog: {
36 | // showReadingTime: true,
37 | // // Please change this to your repo.
38 | // editUrl:
39 | // 'https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/',
40 | // },
41 | theme: {
42 | customCss: require.resolve('./src/css/custom.css'),
43 | },
44 | }),
45 | ],
46 | ],
47 | i18n: {
48 | defaultLocale: 'en',
49 | locales: ['en', 'zh-CN'],
50 | localeConfigs: {
51 | en: {
52 | htmlLang: 'en-GB',
53 | },
54 | // You can omit a locale (e.g. fr) if you don't need to override the defaults
55 | 'zh-CN': {
56 | htmlLang: 'zh-CN',
57 | },
58 | },
59 | },
60 | themeConfig:
61 | /** @type {import('@docusaurus/preset-classic').ThemeConfig} */
62 | ({
63 | navbar: {
64 | title: 'KO',
65 | items: [
66 | {
67 | type: 'doc',
68 | docId: 'introduction',
69 | position: 'left',
70 | label: 'Docs',
71 | },
72 | {
73 | type: 'localeDropdown',
74 | position: 'right',
75 | },
76 | {
77 | type: 'docsVersionDropdown',
78 | position: 'right',
79 | dropdownActiveClassDisabled: true,
80 | },
81 | {
82 | href: 'https://github.com/DTStack/ko',
83 | label: 'GitHub',
84 | position: 'right',
85 | },
86 | ],
87 | },
88 | footer: {
89 | style: 'dark',
90 | links: [
91 | {
92 | title: 'Docs',
93 | items: [
94 | {
95 | label: 'Introduction',
96 | to: '/docs/current/introduction',
97 | },
98 | {
99 | label: 'Getting Started',
100 | to: '/docs/current/getting-started',
101 | },
102 | {
103 | label: 'FAQ',
104 | to: '/docs/current/FAQ',
105 | },
106 | ],
107 | },
108 | {
109 | title: 'Community',
110 | items: [
111 | {
112 | label: 'GitHub',
113 | href: 'https://github.com/ko',
114 | },
115 | ],
116 | },
117 | ],
118 | copyright: `Copyright © ${new Date().getFullYear()} DTStack, Inc. 数栈 UED 团队`,
119 | },
120 | prism: {
121 | theme: lightCodeTheme,
122 | darkTheme: darkCodeTheme,
123 | },
124 | }),
125 | };
126 |
127 | module.exports = config;
128 |
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-plugin-content-docs/current.json:
--------------------------------------------------------------------------------
1 | {
2 | "version.label": {
3 | "message": "6.x",
4 | "description": "The label for version current"
5 | },
6 | "sidebar.tutorialSidebar.category.Advanced": {
7 | "message": "高级选项",
8 | "description": "The label for category Advanced in sidebar tutorialSidebar"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-plugin-content-docs/current/FAQ.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 5
3 | title: 常见问题
4 | ---
5 |
6 | ## 如何 polyfill Node.js 核心模块
7 |
8 | Webpack 5 不再自动 polyfill Node.js 核心模块,这意味着如果您在浏览器或类似环境中使用它们,您必须从 npm 安装兼容的模块并引用它们。如果您的目标环境是浏览器,只需安装一些包并将 **resolve.fallback** 添加到 **ko.config.js** 中即可。
9 | :::tip
10 | 从 v5.3.4 开始,ko 在内部 polyfill 这些核心模块,因此您不必再安装以下包并配置。
11 | :::
12 |
13 | ```js
14 | {
15 | resolve: {
16 | fallback: {
17 | fs: false,
18 | path: false,
19 | events: false,
20 | os: require.resolve('os-browserify/browser'),
21 | crypto: require.resolve('crypto-browserify'),
22 | stream: require.resolve('stream-browserify'),
23 | buffer: require.resolve('buffer/'),
24 | string_decoder: require.resolve('string_decoder/'),
25 | },
26 | }
27 | }
28 | ```
29 |
30 |
31 | ### 环境变量 process.env.node_env
32 |
33 | * 您可以使用环境变量在开发和生产构建之间自定义 ko.config.js 中的插件。
34 | * ko dev vs build 将 process.env.node_env 注入为 developement 和 production
35 |
36 |
37 | ```js
38 | plugins: [
39 | new CopyWebpackPlugin(yourOwnCopyConfig),
40 | process.env.NODE_ENV === 'production' ? new VersionPlugin() : null
41 | ].filter(Boolean)
42 |
43 | ```
44 | ## 如何使用 Web Workers
45 |
46 | :::caution
47 | 为了保证兼容性,我们在 ko 中内部使用了 `worker-loader`。因此,您可以在不更新导入 Worker 代码的情况下迁移到 ko。但是,建议使用以下示例中的方式使用 worker。
48 | :::
49 |
50 | 您可以在 ko 中不引入 [worker-loader](https://github.com/webpack-contrib/worker-loader) 而使用 [Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers),就像这样:
51 |
52 |
53 |
54 | ```js
55 | new Worker(new URL('./worker.js', import.meta.url));
56 | ```
57 |
58 | 您需要修改项目中 **tsconfig.json** 的如下配置:
59 |
60 | ```json
61 | "compilerOptions": {
62 | "module": "esnext",
63 | "moduleResolution": "Node"
64 | }
65 | ```
66 |
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-plugin-content-docs/current/advanced/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "进阶",
3 | "position": 5
4 | }
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-plugin-content-docs/current/advanced/architecture.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 1
3 | title: 架构
4 | ---
5 |
6 | 
7 |
8 | 这张图展示了 ko 如何构建您的应用程序并对源代码进行 lint。我们维护 4 个包并将它们组合成 **ko** 包。
9 |
10 | * **babel-preset-ko-app**:ko 使用的 babel 预设
11 | * **ko-lint-config**:我们的 eslint、prettier 和 stylelint 配置文件,作为 ko-lints 的默认配置
12 | * **ko-lints**:用于 lint 源代码的 CLI
13 | * **ko**:主入口,将 webpack 实例和 ko-lints 结合在一起。
14 |
15 |
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-plugin-content-docs/current/advanced/plugins.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 2
3 | title: 如何编写插件
4 | ---
5 |
6 | Ko 支持使用插件来修改内部配置和行为。以下是一个示例:
7 |
8 | ```js
9 | const VersionWebpackPlugin = require('./version-webpack-plugin');
10 | module.exports = {
11 | plugins: [
12 | {
13 | key: 'WebpackPlugin',
14 | action: 'add',
15 | opts: {
16 | name: 'VersionWebpackPlugin',
17 | fn: () => new VersionWebpackPlugin(),
18 | },
19 | },
20 | ],
21 | }
22 | ```
23 |
24 | 如您所见,您可以通过在 **ko.config.js** 中添加插件配置来注册自己的 ko 插件,并且您需要指定 `key`、`action` 和 `opts` 值:
25 |
26 | * key:钩子主键,目前仅支持 `WebpackPlugin` 和 `ModifyWebpack`。
27 | * action:支持的操作,当您添加配置时,可以使用 `add`,当您想要完全控制当前配置时,可以使用 `update`。
28 | * opts:所有传递的 opts 将通过 `tapable` 在内部使用,支持的类型:
29 |
30 | ```typescript
31 | export type HookItem = {
32 | name: string;
33 | fn: Function;
34 | stage?: number;
35 | before?: string;
36 | };
37 | ```
38 |
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-plugin-content-docs/current/cli.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 3
3 | title: 命令行界面
4 | ---
5 |
6 | ## ko dev
7 |
8 | 启动开发服务器。
9 |
10 | 可选参数:
11 |
12 | * `-h --hash`:输出带有内容哈希的文件名
13 | * `-a,--analyzer`:在 **http://127.0.0.1:8888** 中显示文件的可视化bundle报告
14 |
15 | ## ko build
16 |
17 | 使用内部 webpack 实例打包文件,默认情况下编译文件将写入 **dist** 目录。
18 |
19 | 可选参数:
20 |
21 | * `--hash`:输出带有内容哈希的文件名
22 |
23 | ## ko lint
24 |
25 | 通过 prettier、eslint 或 stylelint 对代码进行 lint,您可以使用 `pnpm` 或 `npx` 在命令行上运行 lint,如下所示:
26 |
27 | ``` bash
28 | # 在文件上通过 prettier 运行 lint:
29 | pnpm exec ko prettier file1.js file2.ts
30 | # 通过 glob 语法在多个文件上通过 prettier 运行 lint 并尝试修复问题
31 | pnpm exec ko prettier "src/**" --write
32 | # 在文件上通过 eslint 运行 lint:
33 | pnpm exec ko eslint file1.js file2.ts
34 | # 通过 glob 语法在多个文件上通过 eslint 运行 lint 并发模式
35 | pnpm exec ko eslint "src/**" --concurrency
36 | # 在文件上通过 stylelint 运行 lint:
37 | pnpm exec ko stylelint file1.css file2.less
38 | # 通过 glob 语法在多个文件上通过 stylelint 运行 lint 并使用自定义配置
39 | pnpm exec ko stylelint "src/**" --configPath="/path/to/custom/config"
40 | ```
41 |
42 | Optional arguments:
43 |
44 | * `-w, --write`: 尝试自动修复问题
45 | * `-c, --configPath `: 覆盖默认配置路径,并使用此配置
46 | * `--concurrency`: 使用多线程对文件进行 lint
47 | * `--concurrentNumber `: 指定线程数,默认为 `require('os').cpus().length`
48 |
49 | 您可以通过在 `.gitignore` , `.prettierignore` , `.eslintignore` , `.stylelint` 文件中添加需要忽略的文件,所有这些匹配到的文件在 lint 运行时都将被忽略。
50 |
51 |
52 |
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-plugin-content-docs/current/configuration.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 4
3 | title: 配置
4 | ---
5 |
6 | 你可以通过 **ko.config.js** 自定义 ko 的配置,以下是支持的配置项:
7 |
8 | ``` typescript
9 | export type IOptions = {
10 | // 通用配置
11 | cwd: string; // 当前工作目录
12 | alias?: Record; // 创建别名以更轻松地导入或引入某些模块
13 | copy?: Pattern[]; // 使用拷贝文件模式
14 | entry?: string; // 入口文件路径
15 | outputPath?: string; // 输出目录的绝对路径
16 | publicPath?: string; // 指定应用程序中所有资源文件的目录
17 | hash?: boolean; // 使用内容哈希输出文件
18 | externals?: Record; // 从输出的Bundle中需要排除的依赖
19 | plugins?: any[]; // ko 内部插件,您可以定义自己的 ko 插件。
20 | htmlTemplate?: string; // 输出 HTML 文件模板
21 | htmlChunks?: 'all' | string[]; // 添加到 HTML 中的 chunk
22 | // 样式配置
23 | analyzer?: boolean; // 显示带有可缩放的交互式树状图的输出文件
24 | extraPostCSSPlugins?: Plugin[]; // 额外的 postcss 插件
25 | lessOptions?: any; // 自定义 less 选项
26 | // 集成插件选项
27 | dynamicResolve?: (request: T) => T; // 动态解析函数
28 | autoPolyfills: boolean | AutoPolyfillsWebpackPluginOptions; // 自动 polyfills 插件选项
29 | // 开发配置
30 | serve: {
31 | proxy?: Record; // 开发服务器的代理配置
32 | host: string; // 开发服务器的主机名
33 | port: number; // 开发服务器的端口
34 | staticPath?: string; // 监视的资源路径
35 | client?: boolean | ClientConfiguration | undefined; // 日志、错误捕获等配置项
36 | compilationSuccessInfo?: { messages: string[]; notes?: string[] }; // 成功编译后的日志,与 friendly-errors-webpack-plugin 相同
37 | // 其他所有 webpack-dev-server 支持的配置项
38 | };
39 | // 实验性功能
40 | experiment?: {
41 | speedUp?: boolean; // 启用 dev 和 build 时的加速选项
42 | minimizer?: boolean; // 在 build 时中通过 esbuild 启用压缩处理器
43 | enableCssModule?: boolean; // 启用 css 模块化
44 | disableLazyImports?: boolean; // 是否禁用导入懒编译
45 | };
46 | lints?: Record>; // lint 配置
47 | };
48 |
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-plugin-content-docs/current/getting-started.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 2
3 | title: 入门指南
4 | ---
5 |
6 | ## 环境要求
7 |
8 | * Node.js 版本: Node.js 14+
9 |
10 | ## 命令行创建 React 项目
11 | 您可以使用 CLI 通过 TypeScript 创建 React 项目。
12 | ``` bash
13 | pnpm create ko
14 | # 或者
15 | npm create ko
16 | # 或者
17 | yarn create ko
18 | ```
19 |
20 | 稍等片刻后,您可以在终端中看到“Creating project in...”。
21 |
22 | 然后进入文件夹并安装依赖项。
23 |
24 | ## 安装 ko
25 |
26 | 你可以使用 npm、yarn 或 pnpm 来安装 ko:
27 |
28 | ``` bash
29 | pnpm add ko --save-dev
30 | # 或者
31 | npm install ko --save-dev
32 | # 或者
33 | yarn add ko --dev
34 | ```
35 |
36 | IE 浏览器需要使用 polyfills。我们推荐使用 [core-js](https://github.com/zloirock/core-js) 和 [regenerator-runtime](https://www.npmjs.com/package/regenerator-runtime)。你需要将它们安装为依赖项:
37 |
38 | ``` bash
39 | pnpm add core-js regenerator-runtime
40 | ```
41 |
42 | ## 配置
43 |
44 | 安装 ko 后,你可以创建一个名为 **ko.config.js** 的配置文件来自定义 ko。你可以指定自己的 **entry** 和 **output** 配置。更多配置信息请参见 [配置](./configuration)。ko 将帮助你合并这些配置并在内部 webpack 实例中使用它们。以下是一个真实的案例:
45 |
46 | ``` js
47 | module.exports = {
48 | entry: './src/app.tsx',
49 | outputPath: './dist' // 你自己的输出路径
50 | serve: {
51 | proxy: PROXY_CONFIG, // 你自己的代理配置
52 | host: '0.0.0.0',
53 | port: 8084,
54 | },
55 | };
56 |
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-plugin-content-docs/current/introduction.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 1
3 | title: 介绍
4 | ---
5 |
6 | **ko** 是一个简单而强大的工具,用于管理您的 React 应用程序。
7 |
8 | ## 特点
9 |
10 | * 支持在 **webpack v5** 和 **esbuild** 上构建应用程序
11 | * 定制 ko,使其完全按照您的应用程序需求工作
12 | * 内置流行的 lint 工具,用于对源代码进行 lint
13 | * 内置支持 TypeScript
14 |
15 | ## 安装
16 |
17 | 您可以使用 npm、yarn 或 pnpm 安装 ko:
18 | ``` bash
19 | npm install ko --save-dev
20 | # 或者
21 | yarn add ko --dev
22 | # 或者
23 | pnpm add ko --save-dev
24 | ```
25 |
26 | ## 贡献
27 |
28 | 我们很乐意在 `ko` 上得到您的帮助!有关如何入手的更多信息,请参见 [CONTRIBUTING](https://github.com/DTStack/ko/blob/master/CONTRIBUTING.md)。
29 |
30 | ## 许可证
31 |
32 | 版权所有 © DTStack。保留所有权利。
33 |
34 | 根据 MIT 许可证获得许可。
35 |
36 |
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-plugin-content-docs/version-5.x.json:
--------------------------------------------------------------------------------
1 | {
2 | "version.label": {
3 | "message": "5.x",
4 | "description": "The label for version 5.x"
5 | },
6 | "sidebar.tutorialSidebar.category.Command Line Interface": {
7 | "message": "命令行界面",
8 | "description": "The label for category Command Line Interface in sidebar tutorialSidebar"
9 | },
10 | "sidebar.tutorialSidebar.category.Advanced": {
11 | "message": "高级选项",
12 | "description": "The label for category Advanced in sidebar tutorialSidebar"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-plugin-content-docs/version-5.x/FAQ.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 4
3 | title: 常见问题
4 | ---
5 |
6 | ## 如何覆盖 webpack 配置
7 | 您可以通过 **ko.config.js** 覆盖 webpack 配置,如果需要,我们建议您覆盖 [copy-webpack-plugin](https://github.com/webpack-contrib/copy-webpack-plugin) 和 [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin)。您可以像这样覆盖:
8 |
9 |
10 |
11 | ``` js
12 | const CopyWebpackPlugin = require('copy-webpack-plugin');
13 |
14 | const copyConfig = [
15 | { from: path.resolve(__dirname, 'public/config'), to: 'config' },
16 | { from: path.resolve(__dirname, 'public/assets'), to: 'assets' },
17 | ]
18 |
19 | module.exports = {
20 | ... //other webpack configs
21 | plugins: [
22 | new CopyWebpackPlugin(copyConfig),
23 | ],
24 | };
25 |
26 | ```
27 |
28 | ## 如何 polyfill Node.js 核心模块:
29 |
30 | Webpack 5 不再自动 polyfill Node.js 核心模块,这意味着如果您在浏览器或类似环境中使用它们,您必须从 npm 安装兼容的模块并引用它们。如果您的目标环境是浏览器,则只需安装一些包并将 **resolve.fallback** 添加到 **ko.config.js** 中。
31 | :::tip
32 | 从 v5.3.4 开始,ko 在内部 polyfill 这些核心模块,因此您不必再安装以下包并配置。
33 | :::
34 |
35 | ### 安装 browserify 包:
36 | ```bash
37 | pnpm add os-browserify crypto-browserify stream-browserify buffer string_decoder -D
38 | ```
39 |
40 | ### 将以下配置添加到 **ko.config.js** 中:
41 |
42 |
43 | ```js
44 | module.exports = {
45 | ... //other webpack configs
46 | resolve: {
47 | fallback: {
48 | fs: false,
49 | path: false,
50 | events: false,
51 | os: require.resolve('os-browserify/browser'),
52 | crypto: require.resolve('crypto-browserify'),
53 | stream: require.resolve('stream-browserify'),
54 | buffer: require.resolve('buffer/'),
55 | string_decoder: require.resolve('string_decoder/'),
56 | },
57 | }
58 | };
59 | ```
60 | ### 环境变量 process.env.node_env
61 |
62 | * 在你的 ko.config.js 中,你可以使用环境变量来自定义开发和生产构建中的插件。
63 | * ko dev 和 build 会注入 process.env.node_env 作为 development 和 production。
64 |
65 |
66 | ```js
67 | plugins: [
68 | new CopyWebpackPlugin(yourOwnCopyConfig),
69 | process.env.NODE_ENV === 'production' ? new VersionPlugin() : null
70 | ].filter(Boolean)
71 |
72 | ```
73 | ## 如何使用 Web Workers
74 |
75 | :::caution
76 | 为了保证兼容性,我们在 ko 中内部使用了 `worker-loader`。因此,您可以在不更新导入 Worker 代码的情况下迁移到 ko。但是,建议使用以下示例中的方式使用 worker。
77 | :::
78 |
79 | 您可以在 ko 中不使用 [worker-loader](https://github.com/webpack-contrib/worker-loader) 使用 [Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers),就像这样:
80 |
81 |
82 | ```js
83 | new Worker(new URL('./worker.js', import.meta.url));
84 | ```
85 | 您需要修改项目中 **tsconfig.json** 的如下配置:
86 | ```json
87 | "compilerOptions": {
88 | "module": "esnext",
89 | "moduleResolution": "Node"
90 | }
91 | ```
92 |
93 | ## 为什么我的插件不起作用
94 | 您的一些插件可能太旧,无法适应 webpack(v5) 的最新版本,因此您应该将插件更新到最新版本。一些常用的插件例如:
95 | * [copy-webpack-plugin](https://github.com/webpack-contrib/copy-webpack-plugin#patterns)
96 | * [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin)
97 |
98 | 并确保在迁移到 ko 时具有正确的插件配置。
99 |
100 | ## 为什么我的插件不起作用
101 | 您的一些插件可能太旧,无法适应 webpack(v5) 的最新版本,因此您应该将插件更新到最新版本。例如:
102 | * [copy-webpack-plugin](https://github.com/webpack-contrib/copy-webpack-plugin#patterns)
103 | * [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin)
104 |
105 | 并确保在迁移到 ko 时具有正确的插件配置。
106 |
107 |
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-plugin-content-docs/version-5.x/advanced/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Advanced",
3 | "position": 5
4 | }
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-plugin-content-docs/version-5.x/advanced/architecture.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 1
3 | title: 架构
4 | ---
5 |
6 | 
7 |
8 | 这张图展示了 ko 如何构建你的应用并对你的源代码进行 lint。我们维护了 4 个包并将它们合并到了 **ko** 包中。
9 | * **babel-preset-ko-app**: ko 使用的 babel preset
10 | * **ko-config**: 我们的 eslint、prettier 和 stylelint 配置文件,作为 ko-lints 的默认配置
11 | * **ko-lints**: 用于 lint 源代码的 CLI
12 | * **ko**: 主入口,将 webpack 实例和 ko-lints 结合在一起。
13 |
14 |
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-plugin-content-docs/version-5.x/advanced/migration.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 2
3 | title: 迁移
4 | ---
5 |
6 | ko是基于webpack构建的,因此从webpack迁移很容易。
7 |
8 | :::caution
9 | ko在内部使用webpack v5,因此如果您使用的是webpack v4或更早的版本,请参考[webpack迁移](https://webpack.js.org/migrate/5)
10 | :::
11 |
12 | ## 删除重复的loader和plugin
13 | ko中有一些内置的webpack loader和plugin,如下所示:
14 | ### Loaders
15 | * babel-loader和babel依赖项
16 | * css-loader
17 | * esbuild-loader
18 | * less-loader及其依赖项
19 | * postcss-loader
20 | * sass-loader及其依赖项
21 | * thread-loader
22 | * worker-loader
23 |
24 |
25 | ### plugins
26 | * @pmmmwh/react-refresh-webpack-plugin
27 | * case-sensitive-paths-webpack-plugin
28 | * css-minimizer-webpack-plugin
29 | * tsconfig-paths-webpack-plugin
30 |
31 | 你应该从你的 **package.json** 中删除它们。
32 |
33 | ## 创建 **ko.config.js**
34 | **ko.config.js** 允许您自定义自己的配置,并且所有自定义的配置都将合并到内部的webpack实例中。如果需要,我们建议您覆盖 [copy-webpack-plugin](https://github.com/webpack-contrib/copy-webpack-plugin) 和 [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin)。您可以在 [FAQ](/docs/5.x/FAQ) 中获取更多详细信息。
35 |
36 | ## 按您的意愿运行命令
37 | 您可以运行 `pnpm ko -h`,然后您可以找到所有的ko命令,选择一个您喜欢的并使用它。
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-plugin-content-docs/version-5.x/cli/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Command Line Interface",
3 | "position": 3
4 |
5 | }
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-plugin-content-docs/version-5.x/cli/ko-build.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 1
3 | title: ko build
4 | ---
5 |
6 | 使用内部的 webpack 实例来构建打包,默认情况下编译后的文件将被写入 **dist** 目录。您可以通过 **ko.config.js** 更改此行为。
7 |
8 | 可选参数:
9 |
10 | * `--hash`:使用内容哈希输出文件名
11 | * `-t,--ts,--typescript`:是否支持 TypeScript,ko 默认支持 TypeScript
12 | * `-e,--esbuild`:启用 esbuild(现在只支持 esbuild 压缩)
13 |
14 |
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-plugin-content-docs/version-5.x/cli/ko-dev.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 2
3 | title: ko dev
4 | ---
5 |
6 | 启动一个提供实时热重载的开发服务器。您可以通过 **ko.config.js** 中的 **devServer** 值更改开发服务器的默认行为,或使用 cli 参数。
7 |
8 | 可选参数:
9 | * `-p, --port `: 服务器启动的端口号
10 | * `--host `: 服务器启动的主机,您可以指定像 **0.0.0.0** 这样的 IP
11 | * `-t, --ts`: 是否支持 TypeScript,ko 默认支持 TypeScript
12 | * `-h --hash`: 输出带有内容哈希的文件名
13 | * `-a,--analyzer`: 在 **http://127.0.0.1:8888** 中显示文件的可视化bundle报告
14 |
15 |
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-plugin-content-docs/version-5.x/cli/ko-eslint.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 3
3 | title: ko eslint
4 | ---
5 |
6 | :::tip
7 | `ko eslint`已经移动到`ko-lints`包中,如果您想使用此功能,请在终端中运行`pnpm add ko-lints -D`
8 | :::
9 |
10 | 别名`ko el`
11 |
12 | **请注意,`ko eslint`是实验性的**
13 |
14 | 使用**eslint**格式化您的代码,我们整理了一个[eslint配置](https://github.com/DTStack/ko/blob/master/packages/ko-config/eslint.js)并将其用作默认的eslint配置,您可以通过cli参数覆盖它。
15 |
16 | ## 如何使用
17 | 您可以使用`pnpm`或`npx`在命令行上运行`ko eslint`,如下所示:
18 |
19 | ``` bash
20 | # lint指定文件
21 | npx eslint file1.js
22 | # 通过glob语法lint多个文件
23 | npx ko eslint "src/**"
24 | ```
25 |
26 | ## 可选参数:
27 |
28 | * `-f, --fix`: 自动修复问题
29 | * `-c, --config `: 覆盖默认的eslint配置路径,并使用此配置
30 | * `--ignore-path `: 指定忽略文件的路径
31 |
32 |
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-plugin-content-docs/version-5.x/cli/ko-lint-config.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 6
3 | title: ko-lint-config
4 | ---
5 |
6 | `ko-lint-config` 为您节省时间的三种方式:
7 |
8 | - **无需配置** - 让您更容易的在项目中强制使用代码检查。无需进行额外的配置就可以运行。
9 | - **自动格式化代码** - 只需运行 `pnpm lint-fix`,就可以告别混乱或不一致的代码。
10 | - **发现样式问题和程序错误** - 减少代码审查过程中的手动审核,并将简单的事情留给工具来节省时间。
11 |
12 | 别犹豫了,别再维护 `.eslintrc`。现在就试试吧!
13 |
14 | ## 详细规则
15 | - **需要四个空格** – 缩进
16 | - **字符串需要单引号** – 除了需要转义的地方
17 | - **需要关键字后跟空格** - ` if (condition) {...}`
18 | - **函数名后不需要空格** - ` function name (arg) {...}` 除了匿名函数和异步 ` function (arg) {...} `` async () { ... }`
19 | - **分号不是必需的**
20 | - **不强制 = = =** - 后端返回的字段类型无法保证
21 | - **不强制三元运算符换行**
22 | - **允许但不要求尾随逗号** - 当最后一个元素或属性在不同行时,与结尾或属性不同行
23 | - **函数内容允许为空**
24 | - **允许使用 this 别名** - 别名可选 `self` `_this` `that',不能从中解构出来
25 | - **不允许debugger**
26 | - **不允许使用控制台打印**
27 |
28 |
29 | ## 安装
30 |
31 | ``` bash
32 | pnpm add ko-lint-config -D
33 | ```
34 |
35 | ## 使用
36 |
37 | 如何引入 Code Style Guide
38 |
39 |
40 | 1、Then, add this to your `.eslintrc.js`、`.prettierrc.js`、`.stylelintrc.js` file:
41 |
42 | ``` js
43 | module.exports = {
44 | extends: [require.resolve('ko-lint-config')],
45 | }
46 | ```
47 | ``` js
48 | const prettier = require('ko-lint-config/.prettierrc')
49 |
50 | module.exports = {
51 | ...prettier,
52 | }
53 | ```
54 | ``` js
55 | module.exports = {
56 | extends: [require.resolve('ko-lint-config/.stylelintrc')],
57 | }
58 | ```
59 |
60 | 你不应该覆盖这些配置,因为统一代码规范是属于团队的
61 |
62 | 2、在`package.json`中添加如下脚本:
63 |
64 | ``` json
65 | "scripts": {
66 | "lint": "npx eslint './src/**/*.ts' './src/**/*.tsx'",
67 | "lint-fix": "npx eslint './src/**/*.ts' './src/**/*.tsx' --fix",
68 | "lint-css": "npx stylelint './src/**/*.scss' './src/**/*.css'",
69 | "lint-css-fix": "npx stylelint './src/**/*.scss' './src/**/*.css' --fix"
70 | },
71 | ```
72 |
73 | 你可以使用 `pnpm lint-fix` 来修复大多数代码风格问题。
74 |
75 | ## 如何禁用 eslint 规则?
76 |
77 | 在极少数情况下,您需要打破规则并隐藏由 `Code Style Guide` 生成的错误。
78 |
79 | `ko-lint-config` 底层使用 [ESLint](http://eslint.org/),您可以像直接使用 ESLint 一样正常隐藏错误。stylelint 与 eslint 相同。
80 |
81 | 在特定行上禁用 **所有规则**:
82 |
83 | ```js
84 | file = 'I know what I am doing' // eslint-disable-line
85 | ```
86 |
87 | 或者, 禁用 **指定** 规则 `"no-use-before-define"`:
88 |
89 | ```js
90 | file = 'I know what I am doing' // eslint-disable-line no-use-before-define
91 | ```
92 |
93 | 或者, 对**多行**禁用 `"no-use-before-define"` 规则:
94 |
95 | ```js
96 | /* eslint-disable no-use-before-define */
97 | console.log('offending code goes here...')
98 | console.log('offending code goes here...')
99 | console.log('offending code goes here...')
100 | /* eslint-enable no-use-before-define */
101 | ```
102 |
103 | ### 想找比这更简单的东西吗?
104 |
105 | 您可以添加到“pnpm lint”脚本中,并为vscode安装eslint插件。
106 |
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-plugin-content-docs/version-5.x/cli/ko-prettier.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 4
3 | title: ko prettier
4 | ---
5 |
6 | :::tip
7 | `ko prettier`已经被移动到`ko-lints`包中,如果您想使用此功能,请在终端中运行`pnpm add ko-lints -D`
8 | :::
9 |
10 | 别名`ko pr`
11 |
12 | **请注意,`ko prettier`是实验性的**
13 |
14 | 使用**prettier**格式化您的代码,我们整理了一个[prettier配置](https://github.com/DTStack/ko/blob/master/packages/ko-config/prettier.js)并将其用作默认的prettier配置,您可以通过cli参数覆盖它。
15 |
16 | ## 如何使用
17 | 您可以使用`pnpm`或`npx`在命令行上运行`ko prettier`,如下所示:
18 |
19 | ``` bash
20 | # 指定prettier文件
21 | npx prettier file1.js
22 | # 通过glob语法prettier多个文件
23 | npx ko prettier "src/**"
24 | ```
25 |
26 | ## 可选参数:
27 |
28 | * `-w, --write`: 原地修改文件。
29 | * `-c, --config `: 覆盖默认的prettier配置路径,并使用此配置
30 | * `--ignore-path `: 指定忽略文件的路径
31 |
32 |
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-plugin-content-docs/version-5.x/cli/ko-stylelint.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 5
3 | title: ko stylelint
4 | ---
5 |
6 | :::tip
7 | `ko stylelint`已经被移动到`ko-lints`包中,如果您想使用此功能,请在终端中运行`pnpm add ko-lints -D`
8 | :::
9 |
10 | 别名`ko sl`
11 |
12 | **请注意,`ko stylelint`是实验性的**
13 |
14 | 使用**stylelint**格式化您的代码,我们整理了一个[stylelint配置](https://github.com/DTStack/ko/blob/master/packages/ko-config/stylelint.js)并将其用作默认的stylelint配置,您可以通过cli参数覆盖它。
15 |
16 | ## 如何使用
17 | 您可以使用`pnpm`或`npx`在命令行上运行`ko stylelint`,如下所示:
18 |
19 | ``` bash
20 | # 指定lint文件
21 | npx stylelint file1.js
22 | # 通过glob语法prettier多个文件
23 | npx ko stylelint "src/**"
24 | ```
25 |
26 | ## 可选参数:
27 |
28 | * `-f, --fix`: 自动修复问题
29 | * `-c, --config `: 覆盖默认的eslint配置路径,并使用此配置
30 | * `--ignore-path `: 指定忽略文件的路径
31 |
32 |
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-plugin-content-docs/version-5.x/getting-started.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 2
3 | title: 入门指南
4 | ---
5 |
6 | ## 环境要求
7 |
8 | * Node.js 版本: Node.js 10.13.0 +
9 |
10 | ## 安装 ko
11 |
12 | 您可以使用 npm、yarn 或 pnpm 安装 ko:
13 | ``` bash
14 | pnpm add ko --save-dev
15 | # 或者
16 | npm install ko --save-dev
17 | # 或者
18 | yarn add ko --dev
19 | ```
20 | IE 浏览器需要使用 polyfills。我们推荐使用 [core-js](https://github.com/zloirock/core-js) 和 [regenerator-runtime](https://www.npmjs.com/package/regenerator-runtime)。您应该将它们安装为依赖项:
21 | ``` bash
22 | pnpm add core-js regenerator-runtime
23 | ```
24 |
25 | ## 配置
26 |
27 | 安装 ko 后,您可以创建一个名为 **ko.config.js** 的配置文件来自定义 ko。您可以指定自己的 **entry** 和 **output** 配置,使用与 webpack 配置相同的插件和加载器,ko 将帮助您合并这些配置并在内部 webpack 实例中使用它们。一个真实的案例:
28 | ``` js
29 | module.exports = {
30 | entry: './src/app.tsx',
31 | output: {
32 | publicPath: '/',
33 | },
34 | plugins: [
35 | new CopyWebpackPlugin(yourOwnCopyConfig),
36 | ],
37 | devServer: {
38 | proxy: PROXY_CONFIG, // 您自己的代理配置
39 | host: '0.0.0.0',
40 | port: 8084,
41 | },
42 | };
43 | ```
44 |
45 | ## 日常命令
46 |
47 | 您的日常工作中只需要几个ko命令:
48 |
49 | ### ko dev
50 | 启动提供实时热重载的开发服务器。 您可以通过**devServer**配置更改开发服务器的默认行为。
51 |
52 | ### ko build
53 | 使用内部webpack实例进行构建打包,并使用一些内置的加载器和插件可以加速构建过程。
54 |
55 |
56 |
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-plugin-content-docs/version-5.x/introduction.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 1
3 | title: 简介
4 | ---
5 |
6 | **ko** 是一个简单而强大的工具,用于管理您的 React 应用程序。
7 |
8 | ## 特点
9 |
10 | * 支持在 **webpack v5** 和 **esbuild** 上构建应用程序
11 | * 自定义 ko,使其完全按照您的应用程序需求工作
12 | * 内置流行的 lint 工具,用于对源代码进行 lint
13 | * 内置支持 TypeScript
14 |
15 | ## 安装
16 |
17 | 您可以使用 npm、yarn 或 pnpm 安装 ko:
18 | ``` bash
19 | npm install ko --save-dev
20 | # 或者
21 | yarn add ko --dev
22 | # 或者
23 | pnpm add ko --save-dev
24 | ```
25 |
26 | ## 贡献
27 |
28 | 我们很乐意在 `ko` 上得到您的帮助!有关如何入手的更多信息,请参见 [CONTRIBUTING](https://github.com/DTStack/ko/blob/master/CONTRIBUTING.md)。
29 |
30 | ## 许可证
31 |
32 | 版权所有 © DTStack。保留所有权利。
33 |
34 | 根据 MIT 许可证获得许可。
35 |
36 |
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-theme-classic/footer.json:
--------------------------------------------------------------------------------
1 | {
2 | "link.title.Docs": {
3 | "message": "文档",
4 | "description": "The title of the footer links column with title=Docs in the footer"
5 | },
6 | "link.title.Community": {
7 | "message": "社区",
8 | "description": "The title of the footer links column with title=Community in the footer"
9 | },
10 | "link.item.label.Introduction": {
11 | "message": "介绍",
12 | "description": "The label of footer link with label=Introduction linking to /docs/current/introduction"
13 | },
14 | "link.item.label.Getting Started": {
15 | "message": "入门指南",
16 | "description": "The label of footer link with label=Getting Started linking to /docs/current/getting-started"
17 | },
18 | "link.item.label.FAQ": {
19 | "message": "常见问题",
20 | "description": "The label of footer link with label=FAQ linking to /docs/current/FAQ"
21 | },
22 | "link.item.label.GitHub": {
23 | "message": "GitHub",
24 | "description": "The label of footer link with label=GitHub linking to https://github.com/ko"
25 | },
26 | "copyright": {
27 | "message": "Copyright © 2023 DTStack, Inc. 数栈 UED 团队",
28 | "description": "The footer copyright"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/website/i18n/zh-CN/docusaurus-theme-classic/navbar.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": {
3 | "message": "KO",
4 | "description": "The title in the navbar"
5 | },
6 | "item.label.Docs": {
7 | "message": "文档",
8 | "description": "Navbar item with label Docs"
9 | },
10 | "item.label.GitHub": {
11 | "message": "GitHub",
12 | "description": "Navbar item with label GitHub"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/website/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "website",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "docusaurus": "docusaurus",
7 | "start": "docusaurus start",
8 | "build": "docusaurus build",
9 | "swizzle": "docusaurus swizzle",
10 | "deploy": "docusaurus deploy",
11 | "clear": "docusaurus clear",
12 | "serve": "docusaurus serve",
13 | "write-translations": "docusaurus write-translations",
14 | "write-heading-ids": "docusaurus write-heading-ids",
15 | "typecheck": "tsc"
16 | },
17 | "dependencies": {
18 | "@algolia/client-search": "^4.12.1",
19 | "@docusaurus/core": "2.0.0-beta.16",
20 | "@docusaurus/preset-classic": "2.0.0-beta.16",
21 | "@mdx-js/react": "^1.6.22",
22 | "clsx": "^1.1.1",
23 | "prism-react-renderer": "^1.2.1",
24 | "react": "^17.0.1",
25 | "react-dom": "^17.0.1"
26 | },
27 | "devDependencies": {
28 | "@docusaurus/module-type-aliases": "2.0.0-beta.16",
29 | "@tsconfig/docusaurus": "^1.0.4",
30 | "@types/react": "^17.0.39",
31 | "typescript": "^4.5.2"
32 | },
33 | "browserslist": {
34 | "production": [
35 | ">0.5%",
36 | "not dead",
37 | "not op_mini all"
38 | ],
39 | "development": [
40 | "last 1 chrome version",
41 | "last 1 firefox version",
42 | "last 1 safari version"
43 | ]
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/website/scripts/replace.js:
--------------------------------------------------------------------------------
1 | const { join } = require('path');
2 | const { readFileSync, writeFileSync } = require('fs');
3 |
4 | const filepath = join(__dirname, '../docs/advanced/migration.md');
5 |
6 | function main() {
7 | try {
8 | const { plugins, loaders } = getPluginsAndLoaders();
9 | const replacedContent = replaceContent(plugins, loaders);
10 | writeFileSync(filepath, replacedContent);
11 | } catch (ex) {
12 | console.error(ex);
13 | }
14 | }
15 |
16 | function getPluginsAndLoaders() {
17 | const pkg = require('../../packages/ko/package.json');
18 | const plugins = [],
19 | loaders = [];
20 | Object.keys(pkg.dependencies).map(key => {
21 | if (/webpack-plugin$/.test(key)) {
22 | plugins.push(key);
23 | }
24 | if (/loader$/.test(key)) {
25 | loaders.push(key);
26 | }
27 | });
28 | return { plugins, loaders };
29 | }
30 |
31 | function replaceContent(plugins, loaders) {
32 | const content = readFileSync(filepath, 'utf8');
33 | return content
34 | .replace('loaderList', loaders.map(i => `* ${i}`).join('\n'))
35 | .replace('pluginList', plugins.map(i => `* ${i}`).join('\n'));
36 | }
37 |
38 | main();
39 |
--------------------------------------------------------------------------------
/website/sidebars.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Creating a sidebar enables you to:
3 | - create an ordered group of docs
4 | - render a sidebar for each doc of that group
5 | - provide next/previous navigation
6 |
7 | The sidebars can be generated from the filesystem, or explicitly defined here.
8 |
9 | Create as many sidebars as you want.
10 | */
11 |
12 | // @ts-check
13 |
14 | /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
15 | const sidebars = {
16 | // By default, Docusaurus generates a sidebar from the docs folder structure
17 | tutorialSidebar: [{ type: 'autogenerated', dirName: '.' }],
18 |
19 | // But you can create a sidebar manually
20 | /*
21 | tutorialSidebar: [
22 | {
23 | type: 'category',
24 | label: 'Tutorial',
25 | items: ['hello'],
26 | },
27 | ],
28 | */
29 | };
30 |
31 | module.exports = sidebars;
32 |
--------------------------------------------------------------------------------
/website/src/components/HomepageFeatures/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import clsx from 'clsx';
3 | import styles from './styles.module.css';
4 | import Translate from '@docusaurus/Translate';
5 |
6 | type FeatureItem = {
7 | title: JSX.Element;
8 | description: JSX.Element;
9 | };
10 |
11 | const FeatureList: FeatureItem[] = [
12 | {
13 | title: Easy to Use ,
14 | description: (
15 |
16 | ko is a simple, yet powerful, tool for managing your react applications
17 |
18 | ),
19 | },
20 | {
21 | title: Flexible ,
22 | description: (
23 |
24 | You can use ko to build your own applications with default
25 | configuration, or customize it to fit your needs
26 |
27 | ),
28 | },
29 | {
30 | title: Faster ,
31 | description: (
32 |
33 | ko is built on top of Webpack v5 and esbuild, so it is blazing fast
34 |
35 | ),
36 | },
37 | ];
38 |
39 | function Feature({ title, description }: FeatureItem) {
40 | return (
41 |
42 |
43 |
{title}
44 |
{description}
45 |
46 |
47 | );
48 | }
49 |
50 | export default function HomepageFeatures(): JSX.Element {
51 | return (
52 |
53 |
54 |
55 | {FeatureList.map((props, idx) => (
56 |
57 | ))}
58 |
59 |
60 |
61 | );
62 | }
63 |
--------------------------------------------------------------------------------
/website/src/components/HomepageFeatures/styles.module.css:
--------------------------------------------------------------------------------
1 | .features {
2 | display: flex;
3 | align-items: center;
4 | padding: 2rem 0;
5 | width: 100%;
6 | }
7 |
8 | .featureSvg {
9 | height: 200px;
10 | width: 200px;
11 | }
12 |
--------------------------------------------------------------------------------
/website/src/css/custom.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Any CSS included here will be global. The classic template
3 | * bundles Infima by default. Infima is a CSS framework designed to
4 | * work well for content-centric websites.
5 | */
6 |
7 | /* You can override the default Infima variables here. */
8 | :root {
9 | --ifm-color-primary: #006ef6;
10 | --ifm-color-primary-dark: #29784c;
11 | --ifm-color-primary-darker: #277148;
12 | --ifm-color-primary-darkest: #205d3b;
13 | --ifm-color-primary-light: #33925d;
14 | --ifm-color-primary-lighter: #359962;
15 | --ifm-color-primary-lightest: #3cad6e;
16 | --ifm-code-font-size: 95%;
17 | }
18 |
19 | /* For readability concerns, you should choose a lighter palette in dark mode. */
20 | [data-theme='dark'] {
21 | --ifm-heading-color: #fff;
22 | --ifm-font-color-base-inverse: #fff;
23 | }
24 |
25 | .docusaurus-highlight-code-line {
26 | background-color: rgba(0, 0, 0, 0.1);
27 | display: block;
28 | margin: 0 calc(-1 * var(--ifm-pre-padding));
29 | padding: 0 var(--ifm-pre-padding);
30 | }
31 |
32 | [data-theme='dark'] .docusaurus-highlight-code-line {
33 | background-color: rgba(0, 0, 0, 0.3);
34 | }
35 |
--------------------------------------------------------------------------------
/website/src/pages/index.module.css:
--------------------------------------------------------------------------------
1 | /**
2 | * CSS files with the .module.css suffix will be treated as CSS modules
3 | * and scoped locally.
4 | */
5 |
6 | .heroBanner {
7 | padding: 4rem 0;
8 | text-align: center;
9 | position: relative;
10 | overflow: hidden;
11 | }
12 |
13 | @media screen and (max-width: 966px) {
14 | .heroBanner {
15 | padding: 2rem;
16 | }
17 | }
18 |
19 | .buttons {
20 | display: flex;
21 | align-items: center;
22 | justify-content: center;
23 | }
24 |
--------------------------------------------------------------------------------
/website/src/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import clsx from 'clsx';
3 | import Layout from '@theme/Layout';
4 | import Link from '@docusaurus/Link';
5 | import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
6 | import styles from './index.module.css';
7 | import HomepageFeatures from '@site/src/components/HomepageFeatures';
8 | import Translate, { translate } from '@docusaurus/Translate';
9 |
10 | function HomepageHeader() {
11 | const { siteConfig } = useDocusaurusContext();
12 | return (
13 |
14 |
15 |
{siteConfig.title}
16 |
17 |
20 |
21 |
22 |
26 |
29 |
30 |
31 |
32 |
33 | );
34 | }
35 |
36 | export default function Home(): JSX.Element {
37 | const { siteConfig } = useDocusaurusContext();
38 | return (
39 |
46 |
47 |
48 |
49 |
50 |
51 | );
52 | }
53 |
--------------------------------------------------------------------------------
/website/src/pages/markdown-page.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Markdown page example
3 | ---
4 |
5 | # Markdown page example
6 |
7 | You don't need React to write simple standalone pages.
8 |
--------------------------------------------------------------------------------
/website/static/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DTStack/ko/ac25ced47831ef98ba6c360c591373bded72786d/website/static/.nojekyll
--------------------------------------------------------------------------------
/website/static/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DTStack/ko/ac25ced47831ef98ba6c360c591373bded72786d/website/static/img/favicon.ico
--------------------------------------------------------------------------------
/website/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | // This file is not used in compilation. It is here just for a nice editor experience.
3 | "extends": "@tsconfig/docusaurus/tsconfig.json",
4 | "compilerOptions": {
5 | "baseUrl": "."
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/website/versioned_docs/version-5.x/FAQ.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 4
3 | title: FAQ
4 | ---
5 |
6 | ## How to override webpack configs
7 | You can override webpack configs via **ko.config.js**, and we recommend you override [copy-webpack-plugin](https://github.com/webpack-contrib/copy-webpack-plugin),[html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin) if needed. You can override like this:
8 |
9 | ``` js
10 | const CopyWebpackPlugin = require('copy-webpack-plugin');
11 |
12 | const copyConfig = [
13 | { from: path.resolve(__dirname, 'public/config'), to: 'config' },
14 | { from: path.resolve(__dirname, 'public/assets'), to: 'assets' },
15 | ]
16 |
17 | module.exports = {
18 | ... //other webpack configs
19 | plugins: [
20 | new CopyWebpackPlugin(copyConfig),
21 | ],
22 | };
23 |
24 | ```
25 |
26 | ## How to polyfill Node.js core modules:
27 |
28 | Webpack 5 no longer polyfills Node.js core modules automatically which means if you use them in your code running in browsers or alike, you will have to install compatible modules from npm and include them yourself. And if your target environment is browser, just install some packages and add **resolve.fallback** into **ko.config.js**.
29 | :::tip
30 | From v5.3.4, ko polyfill these core modules internally, so you don't have to install below packages and add configs.
31 | :::
32 |
33 | ### Install browserify packages:
34 | ```bash
35 | pnpm add os-browserify crypto-browserify stream-browserify buffer string_decoder -D
36 | ```
37 |
38 | ### Add configs into **ko.config.js**:
39 |
40 | ```js
41 | module.exports = {
42 | ... //other webpack configs
43 | resolve: {
44 | fallback: {
45 | fs: false,
46 | path: false,
47 | events: false,
48 | os: require.resolve('os-browserify/browser'),
49 | crypto: require.resolve('crypto-browserify'),
50 | stream: require.resolve('stream-browserify'),
51 | buffer: require.resolve('buffer/'),
52 | string_decoder: require.resolve('string_decoder/'),
53 | },
54 | }
55 | };
56 | ```
57 | ### Environment variables process.env.node_env
58 |
59 | * To custom plugins in your ko.config.js between development and production builds you may use environment variables.
60 | * ko dev vs build inject process.env.node_env as developement and production
61 |
62 | ```js
63 | plugins: [
64 | new CopyWebpackPlugin(yourOwnCopyConfig),
65 | process.env.NODE_ENV === 'production' ? new VersionPlugin() : null
66 | ].filter(Boolean)
67 |
68 | ```
69 | ## How to use web workers
70 |
71 | :::caution
72 | For compatible reason we use `work-loader` internally. So you can migrate into ko without considering update your import Worker code.But using worker like below examples is recommended.
73 | :::
74 |
75 | You can use [Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) without [worker-loader](https://github.com/webpack-contrib/worker-loader) in ko, just like this:
76 | ```js
77 | new Worker(new URL('./worker.js', import.meta.url));
78 | ```
79 | And you should update your project **tsconfig.json** into these configs:
80 | ```json
81 | "compilerOptions": {
82 | "module": "esnext",
83 | "moduleResolution": "Node"
84 | }
85 | ```
86 |
87 | ## Why my devSever config not working
88 | :::caution
89 | **webpack-dev-server** has some troubles in ko, we downgrade **webpack-dev-server** temporarily to v3 in ko v5.3.4
90 | :::
91 |
92 | ko use **webpack-dev-server** v4 internally. So if you find out that your old **devServer** configs not working,please refer to [webpack-dev-server migration v4](https://github.com/webpack/webpack-dev-server/blob/master/migration-v4.md) and update your **devServer** configs.
93 |
94 | ## Why my plugin not working
95 | some of your plugins may be too old to suit latest version of webpack(v5), so you should update your plugins to the latest version.Some of plugins are normally been used in your projects, like:
96 | * [copy-webpack-plugin](https://github.com/webpack-contrib/copy-webpack-plugin#patterns)
97 | * [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin)
98 |
99 | And make sure you have the right configs of your plugins when you migrate into ko.
--------------------------------------------------------------------------------
/website/versioned_docs/version-5.x/advanced/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Advanced",
3 | "position": 5
4 | }
--------------------------------------------------------------------------------
/website/versioned_docs/version-5.x/advanced/architecture.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 1
3 | title: Architecture
4 | ---
5 |
6 | 
7 |
8 | This diagram shows how ko works to build your applications and lint your source code. we maintain 4 packages and get them together into package **ko**.
9 | * **babel-preset-ko-app**: babel preset used by ko
10 | * **ko-config**: our config files of eslint, prettier and stylelint, used by ko-lints as default configs
11 | * **ko-lints**: cli for lint source code
12 | * **ko**: main entrance, getting webpack instance and ko-lints together.
13 |
14 |
--------------------------------------------------------------------------------
/website/versioned_docs/version-5.x/advanced/migration.md:
--------------------------------------------------------------------------------
1 | -->
2 | ---
3 | sidebar_position: 2
4 | title: Migration
5 | ---
6 |
7 | ko is built on top of webpack so it's easy to migrate from webpack.
8 |
9 | :::caution
10 | ko use webpack v5 internally, so if you use webpack v4 or earlier webpack version before, please refer to [webpack migrate](https://webpack.js.org/migrate/5)
11 | :::
12 |
13 | ## Remove duplicated loaders & plugins
14 | There are some built-in webpack loaders & plugins in ko as shown below:
15 | ### Loaders
16 | * babel-loader and babel dependencies
17 | * css-loader
18 | * esbuild-loader
19 | * less-loader and it's dependencies
20 | * postcss-loader
21 | * sass-loader and it's dependencies
22 | * thread-loader
23 | * worker-loader
24 |
25 | ### plugins
26 | * @pmmmwh/react-refresh-webpack-plugin
27 | * case-sensitive-paths-webpack-plugin
28 | * css-minimizer-webpack-plugin
29 | * tsconfig-paths-webpack-plugin
30 |
31 | You should remove them from your **package.json** if you have used them.
32 |
33 | ## Create **ko.config.js**
34 | **ko.config.js** let you customize your own configs, and all your customized configs will be merged into internal webpack instance.we recommend you override [copy-webpack-plugin](https://github.com/webpack-contrib/copy-webpack-plugin),[html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin) if needed. you can get more details in [FAQ](/docs/5.x/FAQ)
35 |
36 | ## Run commands as you'd like
37 | You can run `pnpm ko -h` then you can find all ko commands, choose one you'd like and use it.
38 |
39 |
--------------------------------------------------------------------------------
/website/versioned_docs/version-5.x/cli/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Command Line Interface",
3 | "position": 3
4 | }
--------------------------------------------------------------------------------
/website/versioned_docs/version-5.x/cli/ko-build.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 1
3 | title: ko build
4 | ---
5 |
6 | Use internal webpack instance to bundle files, compiled files will be write to **dist** directory by default. You can change this behavior via **ko.config.js**.
7 |
8 | Optional arguments:
9 |
10 | * `--hash`: output filename with it's contenthash
11 | * `-t,--ts,--typescript`: support typescript or not, ko support typescript by default
12 | * `-e,--esbuild`: enable esbuild (now only esbuild minification is supported)
--------------------------------------------------------------------------------
/website/versioned_docs/version-5.x/cli/ko-dev.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 2
3 | title: ko dev
4 | ---
5 |
6 | start a development server that provides live reloading. You can change development server default behaviors via **devServer** values in **ko.config.js**, or use cli arguments.
7 |
8 | Optional arguments:
9 | * `-p, --port `: server start on which port, a number value is accepted
10 | * `--host `: server start on which host, you can specify an ip like **0.0.0.0**
11 | * `-t, --ts`: support typescript or not, ko support typescript by default
12 | * `-h --hash`: output filename with it's contenthash
13 | * `-a,--analyzer`: show output files with an interactive zoomable treemap in **http://127.0.0.1:8888**
14 |
--------------------------------------------------------------------------------
/website/versioned_docs/version-5.x/cli/ko-eslint.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 3
3 | title: ko eslint
4 | ---
5 |
6 | :::tip
7 | `ko eslint` has been moved into package `ko-lints`, so if you want use this feature, please run `pnpm add ko-lints -D` in your terminal
8 | :::
9 |
10 | Alias `ko el`
11 |
12 | **Please note that `ko eslint` is experimental**
13 |
14 | use **eslint** to format your codes, we collate an [eslint configuration](https://github.com/DTStack/ko/blob/master/packages/ko-config/eslint.js) and use it as default eslint configuration, you can override it via cli arguments.
15 |
16 | ## How to Use
17 | You can use `pnpm` or `npx` to run `ko eslint` on the command like this:
18 |
19 | ``` bash
20 | # Run on files:
21 | npx eslint file1.js
22 | # Run on multiple files via glob syntax
23 | npx ko eslint "src/**"
24 | ```
25 |
26 | ## Optional arguments:
27 |
28 | * `-f, --fix`: Fix problems automatically
29 | * `-c, --config `: overriding default eslint config path, and use this configuration
30 | * `--ignore-path `: Specify path of ignore file
--------------------------------------------------------------------------------
/website/versioned_docs/version-5.x/cli/ko-lint-config.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 6
3 | title: ko-lint-config
4 | ---
5 |
6 | `ko-lint-config` saves time in three ways for you:
7 |
8 | - **No configuration** - The easier way to enforce code quality in your
9 | project. No configuration rules. It just works.
10 | - **Automatically format code** - Just run `pnpm lint-fix` and say goodbye to
11 | messy or inconsistent code.
12 | - **Catch style issues & programmer errors early** - Reduce manual review in the code review process, and leave simple things to tools to save time.
13 |
14 | No hesitation. No more maintenance `.eslintrc`. Give it a try right now!
15 |
16 | ## Detailed rules
17 | - **four spaces are required** – indent
18 | - **single quotation marks are required for string** – except where escape is need
19 | - **require keyword followed by space** - ` if (condition) {...}`
20 | - **requires no spaces after the function name** - ` function name (arg) {...}` except anonymous functions and async ` function (arg) {...} `` async () { ... }`
21 | - **semicolons are not mandatory**
22 | - **not mandatory = = =** - the field type returned by the backend cannot be guaranteed
23 | - **do not force ternary operators to wrap**
24 | - **allow but do not require trailing commas** - when the last element or attribute is on a different line from the end or attribute
25 | - **function content is allowed to be empty**
26 | - **allow this alias** - alias optional `self` `_this` `that', cannot be deconstructed from this
27 | - **no debugger required**
28 | - **no console is recommended**
29 |
30 | ## Install
31 |
32 | ``` bash
33 | pnpm add ko-lint-config -D
34 | ```
35 |
36 | ## Usage
37 |
38 | How to get Code Style Guide: 如何引入 Code Style Guide
39 |
40 | 1、Then, add this to your `.eslintrc.js`、`.prettierrc.js`、`.stylelintrc.js` file:
41 |
42 | ``` js
43 | module.exports = {
44 | extends: [require.resolve('ko-lint-config')],
45 | }
46 | ```
47 | ``` js
48 | const prettier = require('ko-lint-config/.prettierrc')
49 |
50 | module.exports = {
51 | ...prettier,
52 | }
53 | ```
54 | ``` js
55 | module.exports = {
56 | extends: [require.resolve('ko-lint-config/.stylelintrc')],
57 | }
58 | ```
59 |
60 | You should not override settings. Because this is a Code Style Guide for group.
61 |
62 | 2、Add script to `package.json`:
63 |
64 | ``` json
65 | "scripts": {
66 | "lint": "npx eslint './src/**/*.ts' './src/**/*.tsx'",
67 | "lint-fix": "npx eslint './src/**/*.ts' './src/**/*.tsx' --fix",
68 | "lint-css": "npx stylelint './src/**/*.scss' './src/**/*.css'",
69 | "lint-css-fix": "npx stylelint './src/**/*.scss' './src/**/*.css' --fix"
70 | },
71 | ```
72 |
73 | You can use `pnpm lint-fix` to correct most code style problems.
74 |
75 | ## How do I disable a eslint rule?
76 |
77 | In rare cases, you'll need to break a rule and hide the error generated by `Code Style Guide`.
78 |
79 | `ko-lint-config` uses [ESLint](http://eslint.org/) under-the-hood and
80 | you can hide errors as you normally would if you used ESLint directly. stylelint is same to eslint.
81 |
82 | Disable **all rules** on a specific line:
83 |
84 | ```js
85 | file = 'I know what I am doing' // eslint-disable-line
86 | ```
87 |
88 | Or, disable **only** the `"no-use-before-define"` rule:
89 |
90 | ```js
91 | file = 'I know what I am doing' // eslint-disable-line no-use-before-define
92 | ```
93 |
94 | Or, disable the `"no-use-before-define"` rule for **multiple lines**:
95 |
96 | ```js
97 | /* eslint-disable no-use-before-define */
98 | console.log('offending code goes here...')
99 | console.log('offending code goes here...')
100 | console.log('offending code goes here...')
101 | /* eslint-enable no-use-before-define */
102 | ```
103 |
104 | ### Looking for something easier than this?
105 |
106 | You can add to your `pnpm lint` script and install eslint plugin for vscode.
107 |
--------------------------------------------------------------------------------
/website/versioned_docs/version-5.x/cli/ko-prettier.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 4
3 | title: ko prettier
4 | ---
5 |
6 | :::tip
7 | `ko prettier` has been moved into package `ko-lints`, so if you want use this feature, please run `pnpm add ko-lints -D` in your terminal
8 | :::
9 |
10 | Alias `ko pr`
11 |
12 | **Please note that `ko prettier` is experimental**
13 |
14 | use **prettier** to format your codes, we collate an [prettier configuration](https://github.com/DTStack/ko/blob/master/packages/ko-config/prettier.js) and use it as default prettier configuration, you can override it via cli arguments.
15 |
16 | ## How to Use
17 | You can use `pnpm` or `npx` to run `ko prettier` on the command like this:
18 |
19 | ``` bash
20 | # Run on files:
21 | npx prettier file1.js
22 | # Run on multiple files via glob syntax
23 | npx ko prettier "src/**"
24 | ```
25 |
26 | ## Optional arguments:
27 |
28 | * `-w, --write`: Edit files in-place.
29 | * `-c, --config `: overriding default prettier config path, and use this configuration
30 | * `--ignore-path `: Specify path of ignore file
--------------------------------------------------------------------------------
/website/versioned_docs/version-5.x/cli/ko-stylelint.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 5
3 | title: ko stylelint
4 | ---
5 |
6 | :::tip
7 | `ko stylelint` has been moved into package `ko-lints`, so if you want use this feature, please run `pnpm add ko-lints -D` in your terminal
8 | :::
9 |
10 | Alias `ko sl`
11 |
12 | **Please note that `ko stylelint` is experimental**
13 |
14 | use **stylelint** to format your codes, we collate an [stylelint configuration](https://github.com/DTStack/ko/blob/master/packages/ko-config/stylelint.js) and use it as default stylelint configuration, you can override it via cli arguments.
15 |
16 | ## How to Use
17 | You can use `pnpm` or `npx` to run `ko stylelint` on the command like this:
18 |
19 | ``` bash
20 | # Run on files:
21 | npx stylelint file1.js
22 | # Run on multiple files via glob syntax
23 | npx ko stylelint "src/**"
24 | ```
25 |
26 | ## Optional arguments:
27 |
28 | * `-f, --fix`: Fix problems automatically
29 | * `-c, --config `: overriding default eslint config path, and use this configuration
30 | * `--ignore-path `: Specify path of ignore file
--------------------------------------------------------------------------------
/website/versioned_docs/version-5.x/getting-started.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 2
3 | title: Getting Started
4 | ---
5 |
6 | ## Prerequisites
7 |
8 | * Node.js version: Node.js 10.13.0 +
9 |
10 | ## Install ko
11 |
12 | You can install ko using npm, yarn or pnpm:
13 | ``` bash
14 | pnpm add ko --save-dev
15 | # or
16 | npm install ko --save-dev
17 | # or
18 | yarn add ko --dev
19 | ```
20 | Polyfills are needed for IE browsers. We recommended [core-js](https://github.com/zloirock/core-js) and [regenerator-runtime](https://www.npmjs.com/package/regenerator-runtime) for it. And you should install them as dependencies:
21 | ``` bash
22 | pnpm add core-js regenerator-runtime
23 | ```
24 |
25 | ## Configuration
26 |
27 | After install ko,you can create an configuration file named **ko.config.js** for customize ko. And you can specify your own **entry** and **output** configurations, use plugins and loaders as same in webpack configurations, ko will help you merge these configs and use them in internal webpack instance. A real world showcase:
28 | ``` js
29 | module.exports = {
30 | entry: './src/app.tsx',
31 | output: {
32 | publicPath: '/',
33 | },
34 | plugins: [
35 | new CopyWebpackPlugin(yourOwnCopyConfig),
36 | ],
37 | devServer: {
38 | proxy: PROXY_CONFIG, // Your own proxy config
39 | host: '0.0.0.0',
40 | port: 8084,
41 | },
42 | };
43 | ```
44 |
45 | ## Everyday Commands
46 |
47 | Your daily workflow only needs a few ko commands:
48 |
49 | ### ko dev
50 | start a development server that provides live reloading. You can change development server default behaviors via **devServer** configurations.
51 |
52 | ### ko build
53 | bundle files with internal webpack instance, with some built-in loaders and plugins that can speed up build process.
54 |
55 |
56 |
--------------------------------------------------------------------------------
/website/versioned_docs/version-5.x/introduction.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 1
3 | title: Introduction
4 | ---
5 |
6 | **ko** is a simple, yet powerful, tool for managing your react applications.
7 |
8 | ## Features
9 |
10 | * Support building applications on top of **webpack v5** and **esbuild**
11 | * Customize ko to work exactly the way you need it for your applications
12 | * Built-in popular linting tools to lint your source code
13 | * Built-in support typescript
14 |
15 | ## Installation
16 |
17 | You can install ko using npm, yarn or pnpm:
18 | ``` bash
19 | npm install ko --save-dev
20 | # or
21 | yarn add ko --dev
22 | # or
23 | pnpm add ko --save-dev
24 | ```
25 |
26 | ## Contributing
27 |
28 | We'd love to have your helping hand on `ko`! See [CONTRIBUTING](https://github.com/DTStack/ko/blob/master/CONTRIBUTING.md) for more information on how to get started.
29 |
30 | ## License
31 |
32 | Copyright © DTStack. All rights reserved.
33 |
34 | Licensed under the MIT license.
--------------------------------------------------------------------------------
/website/versioned_sidebars/version-5.x-sidebars.json:
--------------------------------------------------------------------------------
1 | {
2 | "tutorialSidebar": [
3 | {
4 | "type": "autogenerated",
5 | "dirName": "."
6 | }
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/website/versioned_sidebars/version-6.x-sidebars.json:
--------------------------------------------------------------------------------
1 | {
2 | "tutorialSidebar": [
3 | {
4 | "type": "autogenerated",
5 | "dirName": "."
6 | }
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/website/versions.json:
--------------------------------------------------------------------------------
1 | [
2 | "5.x"
3 | ]
4 |
--------------------------------------------------------------------------------