diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..e83bfca --- /dev/null +++ b/.eslintignore @@ -0,0 +1,12 @@ +*.sh +node_modules +*.md +*.woff +*.ttf +.vscode +.idea +dist +/public +/docs +.husky +.local \ No newline at end of file diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..fb9b6fa --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,66 @@ +// @see: http://eslint.cn + +module.exports = { + root: true, + env: { + browser: true, + node: true, + es6: true + }, + // 指定如何解析语法 + parser: 'vue-eslint-parser', + // 优先级低于 parse 的语法解析配置 + parserOptions: { + parser: '@typescript-eslint/parser', + ecmaVersion: 2020, + sourceType: 'module', + jsxPragma: 'React', + ecmaFeatures: { + jsx: true + } + }, + // 继承某些已有的规则 + extends: [ + 'plugin:vue/vue3-recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended' + ], + /** + * "off" 或 0 ==> 关闭规则 + * "warn" 或 1 ==> 打开的规则作为警告(不影响代码执行) + * "error" 或 2 ==> 规则作为一个错误(代码不能执行,界面报错) + */ + rules: { + // eslint (http://eslint.cn/docs/rules) + 'no-var': 'error', // 要求使用 let 或 const 而不是 var + 'no-multiple-empty-lines': ['error', { max: 1 }], // 不允许多个空行 + 'prefer-const': 'off', // 使用 let 关键字声明但在初始分配后从未重新分配的变量,要求使用 const + 'no-use-before-define': 'off', // 禁止在 函数/类/变量 定义之前使用它们 + + // typeScript (https://typescript-eslint.io/rules) + '@typescript-eslint/no-unused-vars': 'error', // 禁止定义未使用的变量 + '@typescript-eslint/no-empty-function': 'error', // 禁止空函数 + '@typescript-eslint/prefer-ts-expect-error': 'error', // 禁止使用 @ts-ignore + '@typescript-eslint/ban-ts-comment': 'error', // 禁止 @ts- 使用注释或要求在指令后进行描述 + '@typescript-eslint/no-inferrable-types': 'off', // 可以轻松推断的显式类型可能会增加不必要的冗长 + '@typescript-eslint/no-namespace': 'off', // 禁止使用自定义 TypeScript 模块和命名空间 + '@typescript-eslint/no-explicit-any': 'off', // 禁止使用 any 类型 + '@typescript-eslint/ban-types': 'off', // 禁止使用特定类型 + '@typescript-eslint/no-var-requires': 'off', // 允许使用 require() 函数导入模块 + '@typescript-eslint/no-non-null-assertion': 'off', // 不允许使用后缀运算符的非空断言(!) + + // vue (https://eslint.vuejs.org/rules) + 'vue/script-setup-uses-vars': 'error', // 防止 \ No newline at end of file +@import './style.scss'; + diff --git a/packages/components/Alert/index.ts b/packages/components/Alert/index.ts index 67411ea..0897dad 100644 --- a/packages/components/Alert/index.ts +++ b/packages/components/Alert/index.ts @@ -1,6 +1,6 @@ -import Alert from "./Alert.vue"; -import { withInstall } from "@breeze-ui/utils"; +import Alert from './Alert.vue' +import { withInstall } from '@breeze-ui/utils' -export const BreAlert = withInstall(Alert); +export const BreAlert = withInstall(Alert) -export * from "./interface.ts"; \ No newline at end of file +export * from './interface.ts' diff --git a/packages/components/Alert/interface.ts b/packages/components/Alert/interface.ts index 47f6066..344f869 100644 --- a/packages/components/Alert/interface.ts +++ b/packages/components/Alert/interface.ts @@ -1,20 +1,20 @@ -export type AlertType = "success" | "info" | "warning" | "danger"; +export type AlertType = 'success' | 'info' | 'warning' | 'danger' export interface AlertProps { - title?: string; - type?: AlertType; - description?: string; - effect?: "light" | "dark"; - closable?: boolean; - center?: boolean; - showIcon?: boolean; + title?: string + type?: AlertType + description?: string + effect?: 'light' | 'dark' + closable?: boolean + center?: boolean + showIcon?: boolean } export interface AlertEmits { - (e: "close"): void; + (e: 'close'): void } export interface AlertInstance { - open(): void; - close(): void; -} \ No newline at end of file + open(): void + close(): void +} diff --git a/packages/components/Alert/style.scss b/packages/components/Alert/style.scss index 6f63d5b..b174d60 100644 --- a/packages/components/Alert/style.scss +++ b/packages/components/Alert/style.scss @@ -76,7 +76,8 @@ &.text-center { justify-content: center; - span, p { + span, + p { text-align: center; } } diff --git a/packages/components/Avatar/Avatar.vue b/packages/components/Avatar/Avatar.vue index 89b1f33..c05ed82 100644 --- a/packages/components/Avatar/Avatar.vue +++ b/packages/components/Avatar/Avatar.vue @@ -1,11 +1,5 @@ - - + - - - \ No newline at end of file + diff --git a/packages/components/Button/Button.test.tsx b/packages/components/Button/Button.test.tsx index cc6495b..c333c3e 100644 --- a/packages/components/Button/Button.test.tsx +++ b/packages/components/Button/Button.test.tsx @@ -1,91 +1,88 @@ -import { describe, it, expect, vi } from "vitest"; -import { mount } from "@vue/test-utils"; +import { describe, it, expect, vi } from 'vitest' +import { mount } from '@vue/test-utils' // import type { ButtonType, ButtonSize } from "./types"; -import Button from "./Button.vue"; -describe("Button.vue", () => { - // Props: type - it("should has the correct type class when type prop is set", () => { - const types = ["primary", "success", "warning", "danger", "info"]; - types.forEach((type) => { - const wrapper = mount(Button, { - props: { type: type as any }, - }); - expect(wrapper.classes()).toContain(`bre-button--${type}`); - }); - }); +import Button from './Button.vue' +describe('Button.vue', () => { + // Props: type + it('should has the correct type class when type prop is set', () => { + const types = ['primary', 'success', 'warning', 'danger', 'info'] + types.forEach((type) => { + const wrapper = mount(Button, { + props: { type: type as any } + }) + expect(wrapper.classes()).toContain(`bre-button--${type}`) + }) + }) - // Props: size - it("should has the correct size class when size prop is set", () => { - const sizes = ["large", "default", "small"]; - sizes.forEach((size) => { - const wrapper = mount(Button, { - props: { size: size as any }, - }); - expect(wrapper.classes()).toContain(`bre-button--${size}`); - }); - }); + // Props: size + it('should has the correct size class when size prop is set', () => { + const sizes = ['large', 'default', 'small'] + sizes.forEach((size) => { + const wrapper = mount(Button, { + props: { size: size as any } + }) + expect(wrapper.classes()).toContain(`bre-button--${size}`) + }) + }) - // Props: plain, round, circle - it.each([ - ["plain", "is-plain"], - ["round", "is-round"], - ["circle", "is-circle"], - ["disabled", "is-disabled"], - ["loading", "is-loading"], - ])( - "should has the correct class when prop %s is set to true", - (prop, className) => { - const wrapper = mount(Button, { - props: { [prop]: true }, - global: { - stubs: ["ErIcon"], - }, - }); - expect(wrapper.classes()).toContain(className); - } - ); + // Props: plain, round, circle + it.each([ + ['plain', 'is-plain'], + ['round', 'is-round'], + ['circle', 'is-circle'], + ['disabled', 'is-disabled'], + ['loading', 'is-loading'] + ])('should has the correct class when prop %s is set to true', (prop, className) => { + const wrapper = mount(Button, { + props: { [prop]: true }, + global: { + stubs: ['ErIcon'] + } + }) + expect(wrapper.classes()).toContain(className) + }) - it("should has the correct native type attribute when native-type prop is set", () => { - const wrapper = mount(Button, { - props: { nativeType: "submit" }, - }); - expect(wrapper.element.tagName).toBe("BUTTON"); - expect((wrapper.element as any).type).toBe("submit"); - }); + it('should has the correct native type attribute when native-type prop is set', () => { + const wrapper = mount(Button, { + props: { nativeType: 'submit' } + }) + expect(wrapper.element.tagName).toBe('BUTTON') + expect((wrapper.element as any).type).toBe('submit') + }) - // Test the click event with and without throttle - it.each([ - ["withoutThrottle", false], - ["withThrottle", true], - ])("emits click event %s", async (_, useThrottle) => { - const clickSpy = vi.fn(); - const wrapper = mount(() => ( -