@soybeanjs/oxc-config 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.en.md +155 -0
- package/README.md +157 -0
- package/dist/import-type-order.js +112 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +187 -0
- package/package.json +75 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SoybeanJS Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.en.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# @soybeanjs/oxc-config
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@soybeanjs/oxc-config)
|
|
4
|
+
[](https://github.com/soybeanjs/oxc-config/blob/main/LICENSE)
|
|
5
|
+
|
|
6
|
+
Shared [oxlint](https://oxc.rs/docs/guide/usage/linter.html) and [oxfmt](https://oxc.rs/docs/guide/usage/formatter.html) configuration for SoybeanJS projects.
|
|
7
|
+
|
|
8
|
+
> [中文](./README.md) | English
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- 🚀 **oxfmt formatter config** — Unified code style with fine-grained import sorting groups
|
|
13
|
+
- 🔍 **oxlint linter config** — Integrated with ESLint / TypeScript / Unicorn / Vue plugins
|
|
14
|
+
- 📦 **Import sorting** — Auto-group and sort imports by dependency layer
|
|
15
|
+
- 🎯 **type-before-value rule** — Custom oxlint JS plugin ensuring `import type` comes after `import` for the same module
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm add -D @soybeanjs/oxc-config oxfmt oxlint
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
### oxfmt
|
|
26
|
+
|
|
27
|
+
Create `oxfmt.config.ts` at project root:
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { fmt } from "@soybeanjs/oxc-config";
|
|
31
|
+
|
|
32
|
+
export default fmt;
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
You can also extend it:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { fmt } from "@soybeanjs/oxc-config";
|
|
39
|
+
|
|
40
|
+
export default {
|
|
41
|
+
...fmt,
|
|
42
|
+
printWidth: 100 // Override defaults
|
|
43
|
+
};
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
#### Import Sort Groups
|
|
47
|
+
|
|
48
|
+
Imports are automatically grouped and sorted by dependency layer:
|
|
49
|
+
|
|
50
|
+
| Order | Group | Description |
|
|
51
|
+
| ----- | ------------------------------------------ | -------------------------------------------------------------------------------------------------- |
|
|
52
|
+
| 1 | `builtin` | Node.js built-in modules (`node:fs`, `node:path`, etc.) |
|
|
53
|
+
| 2 | `external-*` | External deps by layer in `order.json` (build-tools → test → framework → state → UI → CSS → utils) |
|
|
54
|
+
| 3 | `external` | Other unclassified external deps |
|
|
55
|
+
| 4 | `side_effect` / `side_effect_style` | Side-effect and style side-effect imports |
|
|
56
|
+
| 5 | `internal-*` | Project aliases (`@/`) by layer (config → infra → data → state → logic → views) |
|
|
57
|
+
| 6 | `internal` | Other unclassified internal imports |
|
|
58
|
+
| 7 | `subpath` / `parent` / `sibling` / `index` | Relative path imports |
|
|
59
|
+
| 8 | `style` | Stylesheet imports |
|
|
60
|
+
| 9 | `unknown` | Unknown import types |
|
|
61
|
+
|
|
62
|
+
External dependency sort order (`order.json`):
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
Build tools (vite, webpack, esbuild, tsdown...)
|
|
66
|
+
→ Testing (vitest, playwright, cypress...)
|
|
67
|
+
→ Frameworks (vue, nuxt, react, next...)
|
|
68
|
+
→ State management (pinia, zustand, jotai...)
|
|
69
|
+
→ UI libraries (element-plus, ant-design-vue, naive-ui...)
|
|
70
|
+
→ CSS engines (tailwindcss, unocss, postcss...)
|
|
71
|
+
→ Utilities (axios, date-fns, es-toolkit, @tanstack/**...)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Internal alias sort order (`order.json`):
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
Config (config, setting, constants...)
|
|
78
|
+
→ Shared/Utils (shared, utils, lib...)
|
|
79
|
+
→ Plugins/Directives (plugins, directives...)
|
|
80
|
+
→ Middleware (middleware...)
|
|
81
|
+
→ Data layer (api, service...)
|
|
82
|
+
→ i18n (i18n, locales...)
|
|
83
|
+
→ State (store, context...)
|
|
84
|
+
→ Composables/Hooks (composables, hooks...)
|
|
85
|
+
→ Router (router...)
|
|
86
|
+
→ Feature modules (modules...)
|
|
87
|
+
→ Views (components...)
|
|
88
|
+
→ Styles/Assets (styles, assets...)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
> See the full ordering in `node_modules/@soybeanjs/oxc-config/dist/order.json`, or customize by editing `src/order.json` in the source.
|
|
92
|
+
|
|
93
|
+
### oxlint
|
|
94
|
+
|
|
95
|
+
Create `oxlint.config.ts` at project root:
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
import { lint } from "@soybeanjs/oxc-config";
|
|
99
|
+
|
|
100
|
+
export default lint;
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
#### Enabled Plugins
|
|
104
|
+
|
|
105
|
+
- **eslint** — ESLint-compatible rules
|
|
106
|
+
- **typescript** — TypeScript-specific rules
|
|
107
|
+
- **unicorn** — Best practice rules
|
|
108
|
+
- **oxc** — OXC-specific rules
|
|
109
|
+
- **import** — Import/Export rules
|
|
110
|
+
- **vue** — Vue SFC rules
|
|
111
|
+
|
|
112
|
+
#### Custom Rule: import-type-order
|
|
113
|
+
|
|
114
|
+
A custom oxlint JS plugin that ensures `import type` always comes after `import` for the same module:
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
// ✅ Correct
|
|
118
|
+
import { ref } from "vue";
|
|
119
|
+
import type { Ref } from "vue";
|
|
120
|
+
|
|
121
|
+
// ❌ Incorrect
|
|
122
|
+
import type { Ref } from "vue";
|
|
123
|
+
import { ref } from "vue";
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The exported `lint` config already includes this plugin and rule. To override or extend:
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
import { lint } from "@soybeanjs/oxc-config";
|
|
130
|
+
|
|
131
|
+
export default {
|
|
132
|
+
...lint,
|
|
133
|
+
jsPlugins: ["@soybeanjs/oxc-config/import-type-order"],
|
|
134
|
+
rules: {
|
|
135
|
+
"import-type-order/type-after-value": "warn"
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Scripts
|
|
141
|
+
|
|
142
|
+
Add to your `package.json`:
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"scripts": {
|
|
147
|
+
"lint": "oxlint --fix",
|
|
148
|
+
"fmt": "oxfmt"
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## License
|
|
154
|
+
|
|
155
|
+
[MIT](./LICENSE)
|
package/README.md
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# @soybeanjs/oxc-config
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@soybeanjs/oxc-config)
|
|
4
|
+
[](https://github.com/soybeanjs/oxc-config/blob/main/LICENSE)
|
|
5
|
+
|
|
6
|
+
SoybeanJS 的共享 [oxlint](https://oxc.rs/docs/guide/usage/linter.html) 和 [oxfmt](https://oxc.rs/docs/guide/usage/formatter.html) 配置。
|
|
7
|
+
|
|
8
|
+
> 中文 | [English](./README.en.md)
|
|
9
|
+
|
|
10
|
+
## 特性
|
|
11
|
+
|
|
12
|
+
- 🚀 **oxfmt 格式化配置** — 统一代码风格,包含精细的 import 排序分组
|
|
13
|
+
- 🔍 **oxlint 代码检查** — 集成 ESLint / TypeScript / Unicorn / Vue 等插件
|
|
14
|
+
- 📦 **Import 排序** — 按依赖层级自动分组排序 external 和 internal import
|
|
15
|
+
- 🎯 **type-before-value 规则** — 自定义 oxlint JS 插件,确保同模块 `import type` 在 `import` 之后
|
|
16
|
+
|
|
17
|
+
## 安装
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm add -D @soybeanjs/oxc-config oxfmt oxlint
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## 使用
|
|
24
|
+
|
|
25
|
+
### oxfmt 配置
|
|
26
|
+
|
|
27
|
+
在项目根目录创建 `oxfmt.config.ts`:
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { fmt } from "@soybeanjs/oxc-config";
|
|
31
|
+
|
|
32
|
+
export default fmt;
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
也可以在此基础上扩展:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { fmt } from "@soybeanjs/oxc-config";
|
|
39
|
+
|
|
40
|
+
export default {
|
|
41
|
+
...fmt,
|
|
42
|
+
printWidth: 100 // 覆盖默认配置
|
|
43
|
+
};
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
#### Import 排序分组
|
|
47
|
+
|
|
48
|
+
本配置将 import 按依赖层级自动分组排序:
|
|
49
|
+
|
|
50
|
+
| 顺序 | 分组 | 说明 |
|
|
51
|
+
| ---- | ------------------------------------------ | ----------------------------------------------------------------------------------------------- |
|
|
52
|
+
| 1 | `builtin` | Node.js 内置模块 (`node:fs`, `node:path` 等) |
|
|
53
|
+
| 2 | `external-*` | 外部依赖,按 `order.json` 中的层级排列(构建工具 → 测试 → 框架 → 状态管理 → UI → CSS → 工具库) |
|
|
54
|
+
| 3 | `external` | 其他未分类的外部依赖 |
|
|
55
|
+
| 4 | `side_effect` / `side_effect_style` | 副作用导入和样式副作用导入 |
|
|
56
|
+
| 5 | `internal-*` | 项目内部别名(`@/`),按依赖层级排列(配置 → 基础设施 → 数据层 → 状态 → 逻辑 → 视图) |
|
|
57
|
+
| 6 | `internal` | 其他未分类的内部导入 |
|
|
58
|
+
| 7 | `subpath` / `parent` / `sibling` / `index` | 相对路径导入 |
|
|
59
|
+
| 8 | `style` | 样式文件导入 |
|
|
60
|
+
| 9 | `unknown` | 未知类型导入 |
|
|
61
|
+
|
|
62
|
+
External 依赖排序层级(`order.json`):
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
构建工具 (vite, webpack, esbuild, tsdown...)
|
|
66
|
+
→ 测试 (vitest, playwright, cypress...)
|
|
67
|
+
→ 框架 (vue, nuxt, react, next...)
|
|
68
|
+
→ 状态管理 (pinia, zustand, jotai...)
|
|
69
|
+
→ UI 组件库 (element-plus, ant-design-vue, naive-ui...)
|
|
70
|
+
→ CSS 引擎 (tailwindcss, unocss, postcss...)
|
|
71
|
+
→ 工具库 (axios, date-fns, es-toolkit, @tanstack/**...)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Internal 别名排序层级(`order.json`):
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
配置 (config, setting, constants...)
|
|
78
|
+
→ 共享/工具 (shared, utils, lib...)
|
|
79
|
+
→ 插件/指令 (plugins, directives...)
|
|
80
|
+
→ 中间件 (middleware...)
|
|
81
|
+
→ 数据层 (api, service...)
|
|
82
|
+
→ 国际化 (i18n, locales...)
|
|
83
|
+
→ 状态 (store, context...)
|
|
84
|
+
→ 逻辑复用 (composables, hooks...)
|
|
85
|
+
→ 路由 (router...)
|
|
86
|
+
→ 功能模块 (modules...)
|
|
87
|
+
→ 视图 (components...)
|
|
88
|
+
→ 样式/资源 (styles, assets...)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
> 你可以在 `node_modules/@soybeanjs/oxc-config/dist/order.json` 中查看完整排序,或直接修改源码中的 `src/order.json` 来自定义。
|
|
92
|
+
|
|
93
|
+
### oxlint 配置
|
|
94
|
+
|
|
95
|
+
在项目根目录创建 `oxlint.config.ts`:
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
import { lint } from "@soybeanjs/oxc-config";
|
|
99
|
+
|
|
100
|
+
export default lint;
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
#### 启用的插件
|
|
104
|
+
|
|
105
|
+
- **eslint** — ESLint 兼容规则
|
|
106
|
+
- **typescript** — TypeScript 专用规则
|
|
107
|
+
- **unicorn** — 最佳实践规则
|
|
108
|
+
- **oxc** — OXC 特有规则
|
|
109
|
+
- **import** — Import/Export 规则
|
|
110
|
+
- **vue** — Vue SFC 规则
|
|
111
|
+
|
|
112
|
+
#### 自定义规则:import-type-order
|
|
113
|
+
|
|
114
|
+
本配置附带一个 oxlint JS 插件,确保同一模块的 `import type` 始终在 `import` 之后:
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
// ✅ 正确
|
|
118
|
+
import { ref } from "vue";
|
|
119
|
+
import type { Ref } from "vue";
|
|
120
|
+
|
|
121
|
+
// ❌ 错误
|
|
122
|
+
import type { Ref } from "vue";
|
|
123
|
+
import { ref } from "vue";
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
在 `oxlint.config.ts` 中启用:
|
|
127
|
+
|
|
128
|
+
(导出的lint默认已经包含了插件和规则,这里仅展示如何覆盖或添加规则)
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
import { lint } from "@soybeanjs/oxc-config";
|
|
132
|
+
|
|
133
|
+
export default {
|
|
134
|
+
...lint,
|
|
135
|
+
jsPlugins: ["@soybeanjs/oxc-config/import-type-order"],
|
|
136
|
+
rules: {
|
|
137
|
+
"import-type-order/type-after-value": "warn"
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## 脚本
|
|
143
|
+
|
|
144
|
+
在 `package.json` 中添加:
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"scripts": {
|
|
149
|
+
"lint": "oxlint --fix",
|
|
150
|
+
"fmt": "oxfmt"
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## 许可证
|
|
156
|
+
|
|
157
|
+
[MIT](./LICENSE)
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
//#region src/import-type-order.js
|
|
2
|
+
/**
|
|
3
|
+
* oxlint JS plugin: import-type-order
|
|
4
|
+
*
|
|
5
|
+
* 确保同一模块的 `import type` 始终在 `import` (value import) 之后。
|
|
6
|
+
* 与 oxfmt 的 sortImports 配合使用:oxfmt 负责分组排序,此插件负责同模块 value-before-type。
|
|
7
|
+
*
|
|
8
|
+
* 基于 eslint-plugin-simple-import-sort 的核心思路实现。
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* 判断 import 是否为 type-only import(`import type { X } from '...'`)
|
|
12
|
+
* 也兼容 `import typeof`(Flow 语法)。
|
|
13
|
+
*/
|
|
14
|
+
function isTypeImport(node) {
|
|
15
|
+
return node.importKind === "type" || node.importKind === "typeof";
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* 获取 import 声明前附着的注释的起始位置。
|
|
19
|
+
* 如果没有前导注释,返回节点自身的起始位置。
|
|
20
|
+
*/
|
|
21
|
+
function getStartWithComments(node, sourceCode) {
|
|
22
|
+
const comments = sourceCode.getCommentsBefore(node);
|
|
23
|
+
if (comments.length > 0) return comments[0].range[0];
|
|
24
|
+
return node.range[0];
|
|
25
|
+
}
|
|
26
|
+
const plugin = {
|
|
27
|
+
meta: { name: "import-type-order" },
|
|
28
|
+
rules: { "type-after-value": {
|
|
29
|
+
meta: {
|
|
30
|
+
type: "layout",
|
|
31
|
+
fixable: "code",
|
|
32
|
+
docs: {
|
|
33
|
+
description: "Ensure value imports come before type imports for the same module source.",
|
|
34
|
+
url: "https://github.com/soybeanjs/oxfmt-import-order"
|
|
35
|
+
},
|
|
36
|
+
messages: { typeBeforeValue: "Type import from \"{{source}}\" must be placed after its value import." },
|
|
37
|
+
schema: []
|
|
38
|
+
},
|
|
39
|
+
create(context) {
|
|
40
|
+
const sourceCode = context.sourceCode;
|
|
41
|
+
return { "Program:exit"() {
|
|
42
|
+
const body = sourceCode.ast.body;
|
|
43
|
+
const allImports = [];
|
|
44
|
+
for (let i = 0; i < body.length; i++) if (body[i].type === "ImportDeclaration") allImports.push({
|
|
45
|
+
node: body[i],
|
|
46
|
+
bodyIndex: i
|
|
47
|
+
});
|
|
48
|
+
if (allImports.length < 2) return;
|
|
49
|
+
const groups = [];
|
|
50
|
+
let currentGroup = [allImports[0]];
|
|
51
|
+
for (let i = 1; i < allImports.length; i++) {
|
|
52
|
+
const prev = allImports[i - 1];
|
|
53
|
+
const curr = allImports[i];
|
|
54
|
+
const linesBetween = curr.node.loc.start.line - prev.node.loc.end.line;
|
|
55
|
+
if (prev.node.source.value === curr.node.source.value && linesBetween <= 1) currentGroup.push(curr);
|
|
56
|
+
else {
|
|
57
|
+
groups.push(currentGroup);
|
|
58
|
+
currentGroup = [curr];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
groups.push(currentGroup);
|
|
62
|
+
for (const group of groups) {
|
|
63
|
+
if (group.length < 2) continue;
|
|
64
|
+
if (!group.some((item, i) => {
|
|
65
|
+
if (!isTypeImport(item.node)) return false;
|
|
66
|
+
for (let j = i + 1; j < group.length; j++) if (!isTypeImport(group[j].node)) return true;
|
|
67
|
+
return false;
|
|
68
|
+
})) continue;
|
|
69
|
+
const sorted = [...group].sort((a, b) => {
|
|
70
|
+
const aIsType = isTypeImport(a.node);
|
|
71
|
+
if (aIsType === isTypeImport(b.node)) return 0;
|
|
72
|
+
return aIsType ? 1 : -1;
|
|
73
|
+
});
|
|
74
|
+
const firstNode = group[0].node;
|
|
75
|
+
const lastNode = group[group.length - 1].node;
|
|
76
|
+
const source = firstNode.source.value;
|
|
77
|
+
context.report({
|
|
78
|
+
node: firstNode,
|
|
79
|
+
messageId: "typeBeforeValue",
|
|
80
|
+
data: { source },
|
|
81
|
+
fix(fixer) {
|
|
82
|
+
const parts = [];
|
|
83
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
84
|
+
const item = sorted[i];
|
|
85
|
+
const prevItem = i > 0 ? sorted[i - 1] : null;
|
|
86
|
+
const start = getStartWithComments(item.node, sourceCode);
|
|
87
|
+
const text = sourceCode.text.slice(start, item.node.range[1]);
|
|
88
|
+
if (i > 0) {
|
|
89
|
+
const prevOriginalIndex = group.findIndex((g) => g === prevItem);
|
|
90
|
+
const currOriginalIndex = group.findIndex((g) => g === item);
|
|
91
|
+
if (Math.abs(currOriginalIndex - prevOriginalIndex) === 1) {
|
|
92
|
+
const earlier = group[Math.min(prevOriginalIndex, currOriginalIndex)];
|
|
93
|
+
const later = group[Math.max(prevOriginalIndex, currOriginalIndex)];
|
|
94
|
+
const sep = sourceCode.text.slice(earlier.node.range[1], getStartWithComments(later.node, sourceCode));
|
|
95
|
+
parts.push(sep);
|
|
96
|
+
} else parts.push("\n");
|
|
97
|
+
}
|
|
98
|
+
parts.push(text);
|
|
99
|
+
}
|
|
100
|
+
const rangeStart = getStartWithComments(firstNode, sourceCode);
|
|
101
|
+
const rangeEnd = lastNode.range[1];
|
|
102
|
+
return fixer.replaceTextRange([rangeStart, rangeEnd], parts.join(""));
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
} };
|
|
107
|
+
}
|
|
108
|
+
} }
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
//#endregion
|
|
112
|
+
export { plugin as default };
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
//#region src/order.json
|
|
2
|
+
var external = [
|
|
3
|
+
"vite",
|
|
4
|
+
"@vitejs/**",
|
|
5
|
+
"vite-plugin-*",
|
|
6
|
+
"tsdown",
|
|
7
|
+
"unplugin-*",
|
|
8
|
+
"vitest",
|
|
9
|
+
"@vitest/**",
|
|
10
|
+
"playwright",
|
|
11
|
+
"cypress",
|
|
12
|
+
"vue",
|
|
13
|
+
"@vue/**",
|
|
14
|
+
"vue-router",
|
|
15
|
+
"@vueuse/**",
|
|
16
|
+
"nuxt",
|
|
17
|
+
"@nuxt/**",
|
|
18
|
+
"react",
|
|
19
|
+
"react-dom",
|
|
20
|
+
"@react/**",
|
|
21
|
+
"next",
|
|
22
|
+
"@next/**",
|
|
23
|
+
"pinia",
|
|
24
|
+
"pinia-colada",
|
|
25
|
+
"zustand",
|
|
26
|
+
"jotai",
|
|
27
|
+
"@soybeanjs/**",
|
|
28
|
+
"nuxt-ui",
|
|
29
|
+
"element-plus",
|
|
30
|
+
"ant-design-vue",
|
|
31
|
+
"antd-next",
|
|
32
|
+
"naive-ui",
|
|
33
|
+
"@arco-design/**",
|
|
34
|
+
"@iconify/**",
|
|
35
|
+
"tailwindcss",
|
|
36
|
+
"@tailwindcss/**",
|
|
37
|
+
"unocss",
|
|
38
|
+
"@unocss/**",
|
|
39
|
+
"postcss",
|
|
40
|
+
"@postcss/**",
|
|
41
|
+
"axios",
|
|
42
|
+
"date-fns",
|
|
43
|
+
"dayjs",
|
|
44
|
+
"es-toolkit",
|
|
45
|
+
"defu",
|
|
46
|
+
"ohash",
|
|
47
|
+
"@tanstack/**"
|
|
48
|
+
];
|
|
49
|
+
var internal = [
|
|
50
|
+
"@/config",
|
|
51
|
+
"@/config/**",
|
|
52
|
+
"@/configs",
|
|
53
|
+
"@/configs/**",
|
|
54
|
+
"@/constant",
|
|
55
|
+
"@/constant/**",
|
|
56
|
+
"@/constants",
|
|
57
|
+
"@/constants/**",
|
|
58
|
+
"@/setting",
|
|
59
|
+
"@/setting/**",
|
|
60
|
+
"@/settings",
|
|
61
|
+
"@/settings/**",
|
|
62
|
+
"@/shared",
|
|
63
|
+
"@/shared/**",
|
|
64
|
+
"@/utils",
|
|
65
|
+
"@/utils/**",
|
|
66
|
+
"@/lib",
|
|
67
|
+
"@/lib/**",
|
|
68
|
+
"@/plugin",
|
|
69
|
+
"@/plugin/**",
|
|
70
|
+
"@/plugins",
|
|
71
|
+
"@/plugins/**",
|
|
72
|
+
"@/directives",
|
|
73
|
+
"@/directives/**",
|
|
74
|
+
"@/middleware",
|
|
75
|
+
"@/middleware/**",
|
|
76
|
+
"@/api",
|
|
77
|
+
"@/api/**",
|
|
78
|
+
"@/service",
|
|
79
|
+
"@/service/**",
|
|
80
|
+
"@/services",
|
|
81
|
+
"@/services/**",
|
|
82
|
+
"@/i18n",
|
|
83
|
+
"@/i18n/**",
|
|
84
|
+
"@/locales",
|
|
85
|
+
"@/locales/**",
|
|
86
|
+
"@/store",
|
|
87
|
+
"@/store/**",
|
|
88
|
+
"@/context",
|
|
89
|
+
"@/context/**",
|
|
90
|
+
"@/composables",
|
|
91
|
+
"@/composables/**",
|
|
92
|
+
"@/hooks",
|
|
93
|
+
"@/hooks/**",
|
|
94
|
+
"@/router",
|
|
95
|
+
"@/modules",
|
|
96
|
+
"@/modules/**",
|
|
97
|
+
"@/components",
|
|
98
|
+
"@/styles",
|
|
99
|
+
"@/assets",
|
|
100
|
+
"@/assets/**",
|
|
101
|
+
"@/**",
|
|
102
|
+
"@/types",
|
|
103
|
+
"@/types/**"
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
//#endregion
|
|
107
|
+
//#region src/oxfmt.ts
|
|
108
|
+
const customGroups = [];
|
|
109
|
+
const externalGroupNames = [];
|
|
110
|
+
const internalGroupNames = [];
|
|
111
|
+
external.forEach((item, index) => {
|
|
112
|
+
const groupName = `external-${index}`;
|
|
113
|
+
externalGroupNames.push(groupName);
|
|
114
|
+
customGroups.push({
|
|
115
|
+
groupName,
|
|
116
|
+
elementNamePattern: [item],
|
|
117
|
+
selector: "external"
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
internal.forEach((item, index) => {
|
|
121
|
+
const groupName = `internal-${index}`;
|
|
122
|
+
internalGroupNames.push(groupName);
|
|
123
|
+
customGroups.push({
|
|
124
|
+
groupName,
|
|
125
|
+
elementNamePattern: [item],
|
|
126
|
+
selector: "internal"
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
const fmt = {
|
|
130
|
+
printWidth: 120,
|
|
131
|
+
singleQuote: true,
|
|
132
|
+
trailingComma: "none",
|
|
133
|
+
arrowParens: "avoid",
|
|
134
|
+
htmlWhitespaceSensitivity: "ignore",
|
|
135
|
+
experimentalSortPackageJson: { sortScripts: true },
|
|
136
|
+
sortImports: {
|
|
137
|
+
newlinesBetween: false,
|
|
138
|
+
customGroups,
|
|
139
|
+
groups: [
|
|
140
|
+
"builtin",
|
|
141
|
+
...externalGroupNames,
|
|
142
|
+
"external",
|
|
143
|
+
"side_effect",
|
|
144
|
+
"side_effect_style",
|
|
145
|
+
...internalGroupNames,
|
|
146
|
+
"internal",
|
|
147
|
+
"subpath",
|
|
148
|
+
"parent",
|
|
149
|
+
"sibling",
|
|
150
|
+
"index",
|
|
151
|
+
"style",
|
|
152
|
+
"unknown"
|
|
153
|
+
]
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
//#endregion
|
|
158
|
+
//#region src/oxlint.ts
|
|
159
|
+
const lint = {
|
|
160
|
+
categories: {
|
|
161
|
+
correctness: "error",
|
|
162
|
+
suspicious: "error"
|
|
163
|
+
},
|
|
164
|
+
plugins: [
|
|
165
|
+
"eslint",
|
|
166
|
+
"typescript",
|
|
167
|
+
"unicorn",
|
|
168
|
+
"oxc",
|
|
169
|
+
"import",
|
|
170
|
+
"vue"
|
|
171
|
+
],
|
|
172
|
+
jsPlugins: ["@soybeanjs/oxc-config/import-type-order"],
|
|
173
|
+
rules: {
|
|
174
|
+
"import/no-unassigned-import": "off",
|
|
175
|
+
"import-type-order/type-after-value": "warn",
|
|
176
|
+
"no-unused-vars": "off",
|
|
177
|
+
"unicorn/consistent-function-scoping": "off",
|
|
178
|
+
"unicorn/no-array-reverse": "off",
|
|
179
|
+
"unicorn/no-array-sort": "off",
|
|
180
|
+
"unicorn/no-empty-file": "off",
|
|
181
|
+
"unicorn/require-module-specifiers": "off",
|
|
182
|
+
"vue/prefer-import-from-vue": "off"
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
//#endregion
|
|
187
|
+
export { fmt, lint };
|
package/package.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@soybeanjs/oxc-config",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "SoybeanJS's oxlint and oxfmt config",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"eslint",
|
|
7
|
+
"oxfmt",
|
|
8
|
+
"oxlint",
|
|
9
|
+
"prettier",
|
|
10
|
+
"soybeanjs"
|
|
11
|
+
],
|
|
12
|
+
"homepage": "https://github.com/soybeanjs/oxc-config",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/soybeanjs/oxc-config/issues"
|
|
15
|
+
},
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"author": {
|
|
18
|
+
"name": "Soybean",
|
|
19
|
+
"email": "soybeanjs@outlook.com",
|
|
20
|
+
"url": "https://github.com/soybeanjs"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"url": "https://github.com/soybeanjs/oxc-config.git"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist"
|
|
27
|
+
],
|
|
28
|
+
"type": "module",
|
|
29
|
+
"main": "./dist/index.js",
|
|
30
|
+
"module": "./dist/index.js",
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"import": "./dist/index.js",
|
|
36
|
+
"require": "./dist/index.js"
|
|
37
|
+
},
|
|
38
|
+
"./import-type-order": {
|
|
39
|
+
"import": "./dist/import-type-order.js",
|
|
40
|
+
"require": "./dist/import-type-order.js"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"registry": "https://registry.npmjs.org/"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@soybeanjs/cli": "^1.7.2",
|
|
48
|
+
"@soybeanjs/oxc-config": "link:dist",
|
|
49
|
+
"@types/node": "^25.9.0",
|
|
50
|
+
"lint-staged": "^17.0.5",
|
|
51
|
+
"oxfmt": "^0.51.0",
|
|
52
|
+
"oxlint": "^1.66.0",
|
|
53
|
+
"simple-git-hooks": "^2.13.1",
|
|
54
|
+
"tsdown": "^0.22.0",
|
|
55
|
+
"tsx": "^4.22.3",
|
|
56
|
+
"typescript": "^6.0.3"
|
|
57
|
+
},
|
|
58
|
+
"simple-git-hooks": {
|
|
59
|
+
"commit-msg": "pnpm soy git-commit-verify",
|
|
60
|
+
"pre-commit": "pnpm typecheck && pnpm lint-staged"
|
|
61
|
+
},
|
|
62
|
+
"lint-staged": {
|
|
63
|
+
"*": "oxlint . --fix && oxfmt"
|
|
64
|
+
},
|
|
65
|
+
"scripts": {
|
|
66
|
+
"build": "tsdown",
|
|
67
|
+
"commit": "soy git-commit",
|
|
68
|
+
"lint": "oxlint --fix",
|
|
69
|
+
"fmt": "oxfmt",
|
|
70
|
+
"publish-pkg": "pnpm publish --access public",
|
|
71
|
+
"release": "soy release",
|
|
72
|
+
"typecheck": "tsc --noEmit --skipLibCheck",
|
|
73
|
+
"upkg": "soy ncu"
|
|
74
|
+
}
|
|
75
|
+
}
|