Skip to content

Commit 44f230c

Browse files
authored
chore: migrate from eslint to oxc (#128)
1 parent 0c95dbb commit 44f230c

15 files changed

Lines changed: 865 additions & 3700 deletions

.oxfmtrc.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"$schema": "./node_modules/oxfmt/configuration_schema.json",
3+
"semi": false,
4+
"singleQuote": true,
5+
"jsxSingleQuote": true,
6+
"trailingComma": "all",
7+
"printWidth": 100,
8+
"tabWidth": 2,
9+
"insertFinalNewline": true,
10+
"sortPackageJson": false,
11+
"ignorePatterns": [
12+
"coverage/**",
13+
"dist/**",
14+
"node_modules/**",
15+
"pnpm-lock.yaml",
16+
"packages/icons/ts/**"
17+
]
18+
}

.oxlintrc.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"$schema": "./node_modules/oxlint/configuration_schema.json",
3+
"plugins": ["eslint", "oxc", "typescript", "unicorn", "react", "import"],
4+
"categories": {
5+
"correctness": "error",
6+
"suspicious": "error"
7+
},
8+
"ignorePatterns": ["dist/**", "coverage/**", "node_modules/**"],
9+
"options": {
10+
"reportUnusedDisableDirectives": "error"
11+
},
12+
"overrides": [
13+
{
14+
"files": ["packages/icons/scripts/**/*.ts", "packages/svg/scripts/**/*.ts"],
15+
"env": {
16+
"node": true
17+
}
18+
},
19+
{
20+
"files": ["packages/icons/ts/**/*.ts", "packages/icons/ts/**/*.tsx"],
21+
"env": {
22+
"browser": true
23+
}
24+
}
25+
]
26+
}

.vscode/extensions.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"recommendations": ["oxc.oxc-vscode"]
3+
}

.vscode/settings.json

Lines changed: 37 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,44 @@
11
{
2-
// Disable the default formatter, use eslint instead
2+
// Use Oxc for formatting on supported files
33
"prettier.enable": false,
44
"editor.formatOnSave": false,
55

6-
// Auto fix
7-
"editor.codeActionsOnSave": {
8-
"source.fixAll.eslint": "explicit",
9-
"source.organizeImports": "never"
6+
"[javascript]": {
7+
"editor.defaultFormatter": "oxc.oxc-vscode",
8+
"editor.formatOnSave": true
9+
},
10+
"[javascriptreact]": {
11+
"editor.defaultFormatter": "oxc.oxc-vscode",
12+
"editor.formatOnSave": true
13+
},
14+
"[typescript]": {
15+
"editor.defaultFormatter": "oxc.oxc-vscode",
16+
"editor.formatOnSave": true
17+
},
18+
"[typescriptreact]": {
19+
"editor.defaultFormatter": "oxc.oxc-vscode",
20+
"editor.formatOnSave": true
21+
},
22+
"[json]": {
23+
"editor.defaultFormatter": "oxc.oxc-vscode",
24+
"editor.formatOnSave": true
25+
},
26+
"[jsonc]": {
27+
"editor.defaultFormatter": "oxc.oxc-vscode",
28+
"editor.formatOnSave": true
29+
},
30+
"[markdown]": {
31+
"editor.defaultFormatter": "oxc.oxc-vscode",
32+
"editor.formatOnSave": true
33+
},
34+
"[yaml]": {
35+
"editor.defaultFormatter": "oxc.oxc-vscode",
36+
"editor.formatOnSave": true
1037
},
1138

12-
// Silent the stylistic rules in you IDE, but still auto fix them
13-
"eslint.rules.customizations": [
14-
{ "rule": "style/*", "severity": "off", "fixable": true },
15-
{ "rule": "format/*", "severity": "off", "fixable": true },
16-
{ "rule": "*-indent", "severity": "off", "fixable": true },
17-
{ "rule": "*-spacing", "severity": "off", "fixable": true },
18-
{ "rule": "*-spaces", "severity": "off", "fixable": true },
19-
{ "rule": "*-order", "severity": "off", "fixable": true },
20-
{ "rule": "*-dangle", "severity": "off", "fixable": true },
21-
{ "rule": "*-newline", "severity": "off", "fixable": true },
22-
{ "rule": "*quotes", "severity": "off", "fixable": true },
23-
{ "rule": "*semi", "severity": "off", "fixable": true }
24-
],
25-
26-
// Enable eslint for all supported languages
27-
"eslint.validate": [
28-
"javascript",
29-
"javascriptreact",
30-
"typescript",
31-
"typescriptreact",
32-
"vue",
33-
"html",
34-
"markdown",
35-
"json",
36-
"jsonc",
37-
"yaml",
38-
"toml",
39-
"xml",
40-
"gql",
41-
"graphql",
42-
"astro",
43-
"svelte",
44-
"css",
45-
"less",
46-
"scss",
47-
"pcss",
48-
"postcss"
49-
]
39+
// Auto fix lint issues on save
40+
"editor.codeActionsOnSave": {
41+
"source.fixAll.oxc": "always",
42+
"source.organizeImports": "never"
43+
}
5044
}

eslint.config.mjs

Lines changed: 0 additions & 8 deletions
This file was deleted.

package.json

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,50 @@
22
"name": "@univerjs/icons-workspace",
33
"version": "1.1.1",
44
"private": true,
5-
"packageManager": "pnpm@10.26.0",
5+
"packageManager": "pnpm@10.32.1",
66
"description": "Icons used by Univer",
77
"author": "DreamNum Co., Ltd. <developer@univer.ai>",
88
"license": "MIT",
99
"repository": "https://github.com/dream-num/univer-icons.git",
1010
"sideEffects": false,
1111
"main": "index.js",
12-
"engines": {
13-
"node": ">=22",
14-
"pnpm": ">=10"
12+
"devEngines": {
13+
"runtime": [
14+
{
15+
"name": "node",
16+
"range": ">=22.18"
17+
},
18+
{
19+
"name": "pnpm",
20+
"range": ">=10.1"
21+
}
22+
]
1523
},
1624
"scripts": {
1725
"build": "pnpm --filter ./packages/icons run build",
18-
"lint": "eslint"
19-
},
20-
"dependencies": {
21-
"tsx": "^4.21.0"
26+
"format": "oxfmt .",
27+
"format:check": "oxfmt --check .",
28+
"lint": "oxlint .",
29+
"lint:fix": "oxlint --fix .",
30+
"lint:staged": "lint-staged",
31+
"prepare": "simple-git-hooks"
2232
},
33+
"dependencies": {},
2334
"devDependencies": {
24-
"@antfu/eslint-config": "^6.7.3",
25-
"@eslint-react/eslint-plugin": "^2.4.0",
26-
"@types/node": "^25.0.3",
27-
"@types/react": "^19.2.7",
35+
"@types/node": "^25.5.0",
36+
"@types/react": "^19.2.14",
2837
"@types/react-dom": "^19.2.3",
29-
"eslint": "^9.39.2",
30-
"eslint-plugin-react-hooks": "^7.0.1",
31-
"eslint-plugin-react-refresh": "^0.4.26",
38+
"lint-staged": "^16.4.0",
39+
"oxfmt": "^0.40.0",
40+
"oxlint": "^1.55.0",
41+
"simple-git-hooks": "^2.13.1",
3242
"typescript": "^5.9.3"
43+
},
44+
"simple-git-hooks": {
45+
"pre-commit": "pnpm lint:staged"
46+
},
47+
"lint-staged": {
48+
"*.{js,jsx,ts,tsx,cjs,cts,mjs,mts}": "oxlint",
49+
"*.{md,markdown,yml,yaml}": "oxfmt --check ."
3350
}
3451
}

packages/icons/package.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
"univer"
2121
],
2222
"sideEffects": false,
23+
"imports": {
24+
"#build/*": "./scripts/build/*.ts"
25+
},
2326
"exports": {
2427
".": {
2528
"import": "./dist/esm/index.js",
@@ -31,7 +34,7 @@
3134
"dist"
3235
],
3336
"scripts": {
34-
"build": "tsx ./scripts/build/index.ts && tsc"
37+
"build": "node --experimental-strip-types ./scripts/build/index.ts && tsc"
3538
},
3639
"peerDependencies": {
3740
"react": "*",
@@ -40,9 +43,9 @@
4043
"devDependencies": {
4144
"@types/svg-parser": "^2.0.6",
4245
"@univerjs/icons-svg": "workspace:*",
43-
"rolldown": "1.0.0-beta.57",
46+
"rolldown": "1.0.0-rc.9",
4447
"svg-parser": "^2.0.4",
45-
"svgo": "^4.0.0",
48+
"svgo": "^4.0.1",
4649
"typescript": "^5.9.3"
4750
}
4851
}

packages/icons/scripts/build/index.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import type { IconNode } from './normalize-ast'
1+
import type { IconNode } from '#build/normalize-ast'
22
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
33
import { resolve } from 'node:path'
44
import { fileURLToPath } from 'node:url'
5-
import manifest from '@univerjs/icons-svg/manifest'
5+
import manifest from '@univerjs/icons-svg/manifest' with { type: 'json' }
66
import { rolldown } from 'rolldown'
7-
import { normalizeAST } from './normalize-ast'
8-
import { parseSvg } from './parse-svg'
9-
import { getIconComponent } from './templates'
7+
import { normalizeAST } from '#build/normalize-ast'
8+
import { parseSvg } from '#build/parse-svg'
9+
import { getIconComponent } from '#build/templates'
1010

1111
const __dirname = fileURLToPath(new URL('.', import.meta.url))
1212

@@ -45,10 +45,7 @@ async function compileTsFile() {
4545
for (const icon of [{ name: 'base' }, ...Object.values(manifest).flat(), { name: 'index' }]) {
4646
const bundle = await rolldown({
4747
input: `ts/${icon.name}.tsx`,
48-
external: [
49-
/^react/,
50-
/^.\//,
51-
],
48+
external: [/^react/, /^.\//],
5249
})
5350

5451
await bundle.write({

packages/icons/scripts/build/normalize-ast.ts

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { camelCase } from './camel-case'
1+
import { camelCase } from '#build/camel-case'
22

33
interface Attrs {
44
style: object | string
@@ -26,10 +26,7 @@ interface NormalizationContext {
2626
idReplacementSet: Set<string>
2727
}
2828

29-
function normalizeDefinitions(
30-
node: IconElement,
31-
context: NormalizationContext,
32-
) {
29+
function normalizeDefinitions(node: IconElement, context: NormalizationContext) {
3330
if (node.tag === 'defs') {
3431
node.children?.forEach((def) => {
3532
if (typeof def.attrs.id === 'string') {
@@ -63,12 +60,9 @@ function createNormalizationContext(): NormalizationContext {
6360
/**
6461
* map svg-parser ast to React element, so it would be convenient to render
6562
*/
66-
function doNormalize(
67-
roots: IconNode[],
68-
context: NormalizationContext,
69-
): IconElement[] {
63+
function doNormalize(roots: IconNode[], context: NormalizationContext): IconElement[] {
7064
return roots
71-
.map(node => ({
65+
.map((node) => ({
7266
tag: node.tagName,
7367
attrs: node.properties,
7468
children: doNormalize(node.children, context),
@@ -95,17 +89,13 @@ function normalizeChildren(node: IconElement) {
9589

9690
function addDefIds(root: IconElement, context: NormalizationContext) {
9791
const defIds = Array.from(context.idReplacementSet)
98-
if (defIds.length === 0)
99-
return
92+
if (defIds.length === 0) return
10093
root.defIds = defIds
10194
}
10295

10396
function replaceIds(name: string, str: string, set: Set<string>): string {
10497
return Array.from(set.keys()).reduce((parsed, currentToReplace) => {
105-
return parsed.replace(
106-
new RegExp(currentToReplace, 'g'),
107-
`${name}_${currentToReplace}`,
108-
)
98+
return parsed.replace(new RegExp(currentToReplace, 'g'), `${name}_${currentToReplace}`)
10999
}, str)
110100
}
111101

@@ -133,10 +123,7 @@ function normalizeClassName(node: IconElement) {
133123
}
134124
}
135125

136-
export function normalizeAST(
137-
name: string,
138-
roots: IconNode[],
139-
): string[] {
126+
export function normalizeAST(name: string, roots: IconNode[]): string[] {
140127
const context = createNormalizationContext()
141128
const normalizedRoots = doNormalize(roots, context)
142129

@@ -148,7 +135,7 @@ export function normalizeAST(
148135
normalizeWidthAndHeight(root)
149136
})
150137

151-
return normalizedRoots.map(root =>
138+
return normalizedRoots.map((root) =>
152139
replaceIds(name, JSON.stringify(root), context.idReplacementSet),
153140
)
154141
}

packages/icons/scripts/build/templates.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,22 @@ export function getIconComponent({
77
name: string
88
componentName: string
99
}) {
10-
return `/* eslint-disable */
11-
import { createElement, forwardRef } from 'react';
12-
import type { IconProps } from './base';
13-
import { IconBase } from './base';
14-
const element = ${element};
10+
return `import { createElement, forwardRef } from 'react'
11+
import type { IconProps } from './base'
12+
import { IconBase } from './base'
13+
14+
const element = ${element}
15+
1516
export const ${componentName} = forwardRef<SVGElement, IconProps>(function ${componentName}(props, ref) {
1617
return createElement(IconBase, Object.assign({}, props, {
1718
id: '${name}',
18-
ref: ref,
19+
ref,
1920
icon: element,
20-
}));
21-
});
22-
${componentName}.displayName = '${componentName}';
23-
export default ${componentName};
21+
}))
22+
})
23+
24+
${componentName}.displayName = '${componentName}'
25+
26+
export default ${componentName}
2427
`
2528
}

0 commit comments

Comments
 (0)