vitepress-theme-element-plus 0.0.1 → 0.0.3

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.
Files changed (50) hide show
  1. package/client/components/A11yTag.vue +29 -0
  2. package/client/components/ApiTyping.vue +54 -0
  3. package/client/components/Backdrop.vue +41 -0
  4. package/client/components/Bili.vue +94 -0
  5. package/client/components/Content.vue +150 -0
  6. package/client/components/DeprecatedTag.vue +19 -0
  7. package/client/components/Doc.vue +181 -0
  8. package/client/components/DocAside.vue +46 -0
  9. package/client/components/DocAsideOutline.vue +82 -0
  10. package/client/components/DocFooter.vue +159 -0
  11. package/client/components/Footer.vue +77 -0
  12. package/client/components/FooterCopyright.vue +27 -0
  13. package/client/components/Layout.vue +156 -0
  14. package/client/components/Link.vue +41 -0
  15. package/client/components/LocalNav.vue +160 -0
  16. package/client/components/Nav.vue +69 -0
  17. package/client/components/NavBar.vue +203 -0
  18. package/client/components/NavBarTitle.vue +75 -0
  19. package/client/components/Sidebar.vue +129 -0
  20. package/client/components/SidebarGroup.vue +51 -0
  21. package/client/components/SidebarItem.vue +302 -0
  22. package/client/components/Tag.vue +25 -0
  23. package/client/components/VPNavBarSearch.vue +23 -0
  24. package/client/components/VersionTag.vue +18 -0
  25. package/client/hooks/useBackTop.ts +74 -0
  26. package/client/hooks/useLangs.ts +50 -0
  27. package/client/hooks/useSidebar.ts +105 -0
  28. package/client/hooks/useSidebarControl.ts +78 -0
  29. package/client/hooks/useSize.ts +69 -0
  30. package/client/utils/client/common.ts +49 -0
  31. package/client/utils/client/outline.ts +113 -0
  32. package/client/utils/common.ts +90 -0
  33. package/client/utils/throttle.ts +46 -0
  34. package/dist/index.d.mts +5 -0
  35. package/dist/index.mjs +6 -0
  36. package/dist/markdown/plugins/external-link-icon.d.mts +6 -0
  37. package/dist/markdown/plugins/external-link-icon.mjs +26 -0
  38. package/dist/markdown/plugins/table-wrapper.d.mts +6 -0
  39. package/dist/markdown/plugins/table-wrapper.mjs +8 -0
  40. package/dist/markdown/plugins/tag.d.mts +6 -0
  41. package/dist/markdown/plugins/tag.mjs +25 -0
  42. package/dist/markdown/plugins/tooltip.d.mts +6 -0
  43. package/dist/markdown/plugins/tooltip.mjs +24 -0
  44. package/package.json +8 -7
  45. package/shared/constants.ts +3 -0
  46. package/styles/base.scss +37 -0
  47. package/styles/code.scss +283 -0
  48. package/styles/doc-content.scss +161 -0
  49. package/styles/index.scss +69 -0
  50. package/styles/tag-content.scss +30 -0
@@ -0,0 +1,69 @@
1
+ import type { MaybeRef } from '@vueuse/core'
2
+ import type { Ref, ShallowRef } from 'vue'
3
+ import { useEventListener } from '@vueuse/core'
4
+ import { computed, isRef, onMounted, ref, shallowRef, unref, watch } from 'vue'
5
+ import { isString } from '../utils/common'
6
+
7
+ function getValue(value: string | number): string {
8
+ return isString(value) ? value : `${value}px`
9
+ }
10
+
11
+ export interface SizeOptions {
12
+ width: string | number | undefined
13
+ height: string | number | undefined
14
+ ratio: string | number | undefined
15
+ }
16
+
17
+ export interface SizeInfo<E extends HTMLElement> {
18
+ el: ShallowRef<E | undefined>
19
+ width: Ref<string>
20
+ height: Ref<string>
21
+ resize: () => void
22
+ }
23
+
24
+ export function useSize<E extends HTMLElement>(options: SizeOptions, extraHeight: MaybeRef<number> = 0): SizeInfo<E> {
25
+ const el = shallowRef<E>()
26
+ const width = computed(() => getValue(unref(options.width) ?? '100%'))
27
+ const height = ref('auto')
28
+
29
+ const getRadio = (ratio: number | string | undefined): number => {
30
+ if (isString(ratio)) {
31
+ const [width, height] = ratio.split(':')
32
+ const parsedRadio = Number(width) / Number(height)
33
+
34
+ if (!Number.isNaN(parsedRadio))
35
+ return parsedRadio
36
+ }
37
+
38
+ return typeof ratio === 'number' ? ratio : 16 / 9
39
+ }
40
+
41
+ const getHeight = (width: number): string => {
42
+ const height = unref(options.height)
43
+ const ratio = getRadio(unref(options.ratio))
44
+
45
+ return height
46
+ ? getValue(height)
47
+ : `${Number(width) / ratio + unref(extraHeight)}px`
48
+ }
49
+
50
+ const updateHeight = (): void => {
51
+ if (el.value)
52
+ height.value = getHeight(el.value.clientWidth)
53
+ }
54
+
55
+ onMounted(() => {
56
+ updateHeight()
57
+ if (isRef(extraHeight))
58
+ watch(extraHeight, updateHeight)
59
+ useEventListener('orientationchange', updateHeight)
60
+ useEventListener('resize', updateHeight)
61
+ })
62
+
63
+ return {
64
+ el,
65
+ width,
66
+ height,
67
+ resize: updateHeight,
68
+ }
69
+ }
@@ -0,0 +1,49 @@
1
+ import type { DefaultTheme } from 'vitepress'
2
+ import { isActive } from '../common'
3
+
4
+ export interface SidebarLink {
5
+ text: string
6
+ link: string
7
+ docFooterText?: string
8
+ }
9
+ export function getFlatSideBarLinks(sidebar: DefaultTheme.SidebarItem[]): SidebarLink[] {
10
+ const links: SidebarLink[] = []
11
+
12
+ function recursivelyExtractLinks(items: DefaultTheme.SidebarItem[]) {
13
+ for (const item of items) {
14
+ if (item.text && item.link) {
15
+ links.push({
16
+ text: item.text,
17
+ link: item.link,
18
+ docFooterText: item.docFooterText,
19
+ })
20
+ }
21
+
22
+ if (item.items) {
23
+ recursivelyExtractLinks(item.items)
24
+ }
25
+ }
26
+ }
27
+
28
+ recursivelyExtractLinks(sidebar)
29
+
30
+ return links
31
+ }
32
+
33
+ /**
34
+ * Check if the given sidebar item contains any active link.
35
+ */
36
+ export function hasActiveLink(
37
+ path: string,
38
+ items: DefaultTheme.SidebarItem | DefaultTheme.SidebarItem[],
39
+ ): boolean {
40
+ if (Array.isArray(items)) {
41
+ return items.some(item => hasActiveLink(path, item))
42
+ }
43
+
44
+ return isActive(path, items.link)
45
+ ? true
46
+ : items.items
47
+ ? hasActiveLink(path, items.items)
48
+ : false
49
+ }
@@ -0,0 +1,113 @@
1
+ import type { Header } from 'vitepress'
2
+ import type { DefaultTheme } from 'vitepress/theme'
3
+
4
+ const ignoreRE = /\b(?:VPBadge|header-anchor|footnote-ref|ignore-header)\b/
5
+
6
+ // cached list of anchor elements from resolveHeaders
7
+ const resolvedHeaders: { element: HTMLHeadElement, link: string }[] = []
8
+
9
+ export type MenuItem = Omit<Header, 'slug' | 'children'> & {
10
+ element: HTMLHeadElement
11
+ children?: MenuItem[]
12
+ }
13
+
14
+ export function resolveTitle(theme: DefaultTheme.Config): string {
15
+ return (
16
+ (typeof theme.outline === 'object'
17
+ && !Array.isArray(theme.outline)
18
+ && theme.outline.label)
19
+ || theme.outlineTitle
20
+ || 'On this page'
21
+ )
22
+ }
23
+
24
+ export function getHeaders(range: DefaultTheme.Config['outline']): MenuItem[] {
25
+ const headers = Array.from(document.querySelectorAll('.VPDoc :where(h1,h2,h3,h4,h5,h6)'))
26
+ .filter(el => el.id && el.hasChildNodes())
27
+ .map((el) => {
28
+ const level = Number(el.tagName[1])
29
+ return {
30
+ element: el as HTMLHeadElement,
31
+ title: serializeHeader(el),
32
+ link: `#${el.id}`,
33
+ level,
34
+ }
35
+ })
36
+
37
+ return resolveHeaders(headers, range)
38
+ }
39
+
40
+ function serializeHeader(h: Element): string {
41
+ let ret = ''
42
+ for (const node of Array.from(h.childNodes)) {
43
+ if (node.nodeType === 1) {
44
+ if (ignoreRE.test((node as Element).className))
45
+ continue
46
+ ret += node.textContent
47
+ }
48
+ else if (node.nodeType === 3) {
49
+ ret += node.textContent
50
+ }
51
+ }
52
+ return ret.trim()
53
+ }
54
+
55
+ export function resolveHeaders(
56
+ headers: MenuItem[],
57
+ range?: DefaultTheme.Config['outline'],
58
+ ): MenuItem[] {
59
+ if (range === false) {
60
+ return []
61
+ }
62
+
63
+ const levelsRange
64
+ = (typeof range === 'object' && !Array.isArray(range)
65
+ ? range.level
66
+ : range) || 2
67
+
68
+ const [high, low]: [number, number]
69
+ = typeof levelsRange === 'number'
70
+ ? [levelsRange, levelsRange]
71
+ : levelsRange === 'deep'
72
+ ? [2, 6]
73
+ : levelsRange
74
+
75
+ return buildTree(headers, high, low)
76
+ }
77
+
78
+ function buildTree(data: MenuItem[], min: number, max: number): MenuItem[] {
79
+ resolvedHeaders.length = 0
80
+
81
+ const result: MenuItem[] = []
82
+ const stack: (MenuItem | { level: number, shouldIgnore: true })[] = []
83
+
84
+ data.forEach((item) => {
85
+ const node = { ...item, children: [] }
86
+ let parent = stack[stack.length - 1]
87
+
88
+ while (parent && parent.level >= node.level) {
89
+ stack.pop()
90
+ parent = stack[stack.length - 1]
91
+ }
92
+
93
+ if (
94
+ node.element.classList.contains('ignore-header')
95
+ || (parent && 'shouldIgnore' in parent)
96
+ ) {
97
+ stack.push({ level: node.level, shouldIgnore: true })
98
+ return
99
+ }
100
+
101
+ if (node.level > max || node.level < min)
102
+ return
103
+ resolvedHeaders.push({ element: node.element, link: node.link })
104
+
105
+ if (parent)
106
+ (parent as MenuItem).children.push(node)
107
+ else result.push(node)
108
+
109
+ stack.push(node)
110
+ })
111
+
112
+ return result
113
+ }
@@ -0,0 +1,90 @@
1
+ const HASH_RE = /#.*$/
2
+ const HASH_OR_QUERY_RE = /[?#].*$/
3
+ const INDEX_OR_EXT_RE = /(?:(^|\/)index)?\.(?:md|html)$/
4
+
5
+ export const inBrowser = typeof document !== 'undefined'
6
+
7
+ export function isActive(
8
+ currentPath: string,
9
+ matchPath?: string,
10
+ asRegex: boolean = false,
11
+ ): boolean {
12
+ if (matchPath === undefined) {
13
+ return false
14
+ }
15
+
16
+ currentPath = normalize(`/${currentPath}`)
17
+
18
+ if (asRegex) {
19
+ return new RegExp(matchPath).test(currentPath)
20
+ }
21
+
22
+ if (normalize(matchPath) !== currentPath) {
23
+ return false
24
+ }
25
+
26
+ const hashMatch = matchPath.match(HASH_RE)
27
+
28
+ if (hashMatch) {
29
+ return (inBrowser ? location.hash : '') === hashMatch[0]
30
+ }
31
+
32
+ return true
33
+ }
34
+
35
+ function normalize(path: string): string {
36
+ return decodeURI(path)
37
+ .replace(HASH_OR_QUERY_RE, '')
38
+ .replace(INDEX_OR_EXT_RE, '$1')
39
+ }
40
+
41
+ export function ensureStartingSlash(path: string): string {
42
+ return /^\//.test(path) ? path : `/${path}`
43
+ }
44
+
45
+ export function isPlainObject(obj: any) {
46
+ // 首先排除 null 和非对象类型
47
+ if (obj === null || typeof obj !== 'object') {
48
+ return false
49
+ }
50
+
51
+ // 检查对象的构造函数是否是 Object
52
+ if (obj.constructor !== Object) {
53
+ return false
54
+ }
55
+
56
+ // 检查对象的原型是否是 Object.prototype
57
+ if (Object.getPrototypeOf(obj) !== Object.prototype) {
58
+ return false
59
+ }
60
+
61
+ return true
62
+ }
63
+
64
+ export function isString(value) {
65
+ return typeof value === 'string'
66
+ }
67
+
68
+ export function capitalizeFirstLetter(string: string) {
69
+ if (!string)
70
+ return '' // 如果字符串为空,返回空字符串
71
+ return string.charAt(0).toUpperCase() + string.slice(1)
72
+ }
73
+
74
+ export function throttleAndDebounce(fn: () => void, delay: number): () => void {
75
+ let timeoutId: NodeJS.Timeout
76
+ let called = false
77
+
78
+ return () => {
79
+ if (timeoutId)
80
+ clearTimeout(timeoutId)
81
+
82
+ if (!called) {
83
+ fn()
84
+ ;(called = true) && setTimeout(() => (called = false), delay)
85
+ }
86
+ else {
87
+ timeoutId = setTimeout(fn, delay)
88
+ }
89
+ }
90
+ }
@@ -0,0 +1,46 @@
1
+ type AnyFn = (...args: any[]) => unknown
2
+
3
+ export interface Throttled<T extends AnyFn> {
4
+ (...args: Parameters<T>): void
5
+ cancel: () => void
6
+ }
7
+
8
+ export function throttle<T extends AnyFn>(fn: T, delay = 200): Throttled<T> {
9
+ let lastCall = 0
10
+ let timer: ReturnType<typeof setTimeout> | null = null
11
+
12
+ const invoke = (context: unknown, args: Parameters<T>) => {
13
+ lastCall = Date.now()
14
+ fn.apply(context, args)
15
+ }
16
+
17
+ const throttled = function (this: unknown, ...args: Parameters<T>) {
18
+ const now = Date.now()
19
+ const remaining = delay - (now - lastCall)
20
+
21
+ if (remaining <= 0) {
22
+ if (timer) {
23
+ clearTimeout(timer)
24
+ timer = null
25
+ }
26
+ invoke(this, args)
27
+ return
28
+ }
29
+
30
+ if (!timer) {
31
+ timer = setTimeout(() => {
32
+ timer = null
33
+ invoke(this, args)
34
+ }, remaining)
35
+ }
36
+ } as Throttled<T>
37
+
38
+ throttled.cancel = () => {
39
+ if (timer) {
40
+ clearTimeout(timer)
41
+ timer = null
42
+ }
43
+ }
44
+
45
+ return throttled
46
+ }
@@ -0,0 +1,5 @@
1
+ import { mdExternalLinkIcon } from "./markdown/plugins/external-link-icon.mjs";
2
+ import { mdTableWrapper } from "./markdown/plugins/table-wrapper.mjs";
3
+ import { mdTag } from "./markdown/plugins/tag.mjs";
4
+ import { mdTooltip } from "./markdown/plugins/tooltip.mjs";
5
+ export { mdExternalLinkIcon, mdTableWrapper, mdTag, mdTooltip };
package/dist/index.mjs ADDED
@@ -0,0 +1,6 @@
1
+ import mdExternalLinkIcon from "./markdown/plugins/external-link-icon.mjs";
2
+ import mdTableWrapper from "./markdown/plugins/table-wrapper.mjs";
3
+ import mdTag from "./markdown/plugins/tag.mjs";
4
+ import mdTooltip from "./markdown/plugins/tooltip.mjs";
5
+
6
+ export { mdExternalLinkIcon, mdTableWrapper, mdTag, mdTooltip };
@@ -0,0 +1,6 @@
1
+ import MarkdownIt from "markdown-it";
2
+
3
+ //#region node/markdown/plugins/external-link-icon.d.ts
4
+ declare function mdExternalLinkIcon(md: MarkdownIt): void;
5
+ //#endregion
6
+ export { mdExternalLinkIcon };
@@ -0,0 +1,26 @@
1
+ //#region node/markdown/plugins/external-link-icon.ts
2
+ const renderToken = (tokens, idx, options, env, self) => self.renderToken(tokens, idx, options);
3
+ function mdExternalLinkIcon(md) {
4
+ const defaultLinkOpenRenderer = md.renderer.rules.link_open || renderToken;
5
+ const defaultLinkCloseRenderer = md.renderer.rules.link_close || renderToken;
6
+ let isExternalLink = false;
7
+ md.renderer.rules.link_open = (tokens, idx, options, env, self) => {
8
+ const token = tokens[idx];
9
+ const href = token.attrGet("href");
10
+ if (href) {
11
+ token.attrJoin("class", "vp-link");
12
+ if (/^(?:ht|f)tps?:\/\/?/.test(href)) isExternalLink = true;
13
+ }
14
+ return defaultLinkOpenRenderer(tokens, idx, options, env, self);
15
+ };
16
+ md.renderer.rules.link_close = (tokens, idx, options, env, self) => {
17
+ if (isExternalLink) {
18
+ isExternalLink = false;
19
+ return `<svg viewBox="0 0 24 24" class="link-icon"><path fill="currentColor" d="M10 6v2H5v11h11v-5h2v6a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1zm11-3v8h-2V6.413l-7.793 7.794l-1.414-1.414L17.585 5H13V3z"/></svg>${self.renderToken(tokens, idx, options)}`;
20
+ }
21
+ return defaultLinkCloseRenderer(tokens, idx, options, env, self);
22
+ };
23
+ }
24
+
25
+ //#endregion
26
+ export { mdExternalLinkIcon as default };
@@ -0,0 +1,6 @@
1
+ import MarkdownIt from "markdown-it";
2
+
3
+ //#region node/markdown/plugins/table-wrapper.d.ts
4
+ declare function mdTableWrapper(md: MarkdownIt): void;
5
+ //#endregion
6
+ export { mdTableWrapper };
@@ -0,0 +1,8 @@
1
+ //#region node/markdown/plugins/table-wrapper.ts
2
+ function mdTableWrapper(md) {
3
+ md.renderer.rules.table_open = () => "<div class=\"vp-table\"><table>";
4
+ md.renderer.rules.table_close = () => "</table></div>";
5
+ }
6
+
7
+ //#endregion
8
+ export { mdTableWrapper as default };
@@ -0,0 +1,6 @@
1
+ import MarkdownIt from "markdown-it";
2
+
3
+ //#region node/markdown/plugins/tag.d.ts
4
+ declare function mdTag(md: MarkdownIt): void;
5
+ //#endregion
6
+ export { mdTag };
@@ -0,0 +1,25 @@
1
+ //#region node/markdown/plugins/tag.ts
2
+ function mdTag(md) {
3
+ md.inline.ruler.before("emphasis", "tag", (state, silent) => {
4
+ const tagRegExp = /^\^\(([^)]*)\)/;
5
+ const str = state.src.slice(state.pos, state.posMax);
6
+ if (!tagRegExp.test(str)) return false;
7
+ if (silent) return true;
8
+ const result = str.match(tagRegExp);
9
+ if (!result) return false;
10
+ const token = state.push("html_inline", "", 0);
11
+ const value = result[1].trim();
12
+ token.content = `<span class="vp-tag ${[
13
+ "beta",
14
+ "deprecated",
15
+ "a11y",
16
+ "required"
17
+ ].includes(value) ? value : ""}">${value}</span>`;
18
+ token.level = state.level;
19
+ state.pos += result[0].length;
20
+ return true;
21
+ });
22
+ }
23
+
24
+ //#endregion
25
+ export { mdTag as default };
@@ -0,0 +1,6 @@
1
+ import MarkdownIt from "markdown-it";
2
+
3
+ //#region node/markdown/plugins/tooltip.d.ts
4
+ declare function mdTooltip(md: MarkdownIt): void;
5
+ //#endregion
6
+ export { mdTooltip };
@@ -0,0 +1,24 @@
1
+ //#region node/markdown/plugins/tooltip.ts
2
+ function mdTooltip(md) {
3
+ md.renderer.rules.tooltip = (tokens, idx) => {
4
+ const token = tokens[idx];
5
+ return `<api-typing type="${token.content}" details="${token.info}" />`;
6
+ };
7
+ md.inline.ruler.before("emphasis", "tooltip", (state, silent) => {
8
+ const tooltipRegExp = /^\^\[([^\]]*)\](`[^`]*`)?/;
9
+ const str = state.src.slice(state.pos, state.posMax);
10
+ if (!tooltipRegExp.test(str)) return false;
11
+ if (silent) return true;
12
+ const result = str.match(tooltipRegExp);
13
+ if (!result) return false;
14
+ const token = state.push("tooltip", "tooltip", 0);
15
+ token.content = result[1].replaceAll(String.raw`\|`, "|");
16
+ token.info = (result[2] || "").replace(/^`(.*)`$/, "$1");
17
+ token.level = state.level;
18
+ state.pos += result[0].length;
19
+ return true;
20
+ });
21
+ }
22
+
23
+ //#endregion
24
+ export { mdTooltip as default };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vitepress-theme-element-plus",
3
3
  "type": "module",
4
- "version": "0.0.1",
4
+ "version": "0.0.3",
5
5
  "description": "A VitePress theme for Element Plus",
6
6
  "author": "Hezhengxu",
7
7
  "license": "MIT",
@@ -17,7 +17,6 @@
17
17
  ],
18
18
  "exports": {
19
19
  ".": {
20
- "types": "./types/index.d.ts",
21
20
  "default": "./index.ts"
22
21
  },
23
22
  "./node": {
@@ -29,10 +28,11 @@
29
28
  "types": "./types/index.d.ts",
30
29
  "style": "./index.scss",
31
30
  "files": [
32
- "config",
31
+ "client",
32
+ "dist",
33
33
  "index.ts",
34
- "src",
35
- "types"
34
+ "shared",
35
+ "styles"
36
36
  ],
37
37
  "scripts": {
38
38
  "clean": "rimraf dist",
@@ -45,8 +45,10 @@
45
45
  "peerDependencies": {
46
46
  "vitepress": "2.0.0-alpha.12"
47
47
  },
48
+ "dependencies": {
49
+ "@iconify/vue": "^4"
50
+ },
48
51
  "devDependencies": {
49
- "@iconify/vue": "^4.2.1",
50
52
  "@release-it/conventional-changelog": "^10",
51
53
  "@types/glob": "^9.0.0",
52
54
  "@types/markdown-it": "^14.1.0",
@@ -54,7 +56,6 @@
54
56
  "@vitejs/plugin-vue": "^5.2.4",
55
57
  "@vueuse/core": "^11.3.0",
56
58
  "element-plus": "^2.11.7",
57
- "es-toolkit": "^1.14.0",
58
59
  "release-it": "^19",
59
60
  "rimraf": "^6.0.1",
60
61
  "sass-embedded": "^1.80.3",
@@ -0,0 +1,3 @@
1
+ export const NOT_ARTICLE_LAYOUTS = ['blog', 'tags', 'categorys', 'projects', 'home', 'page']
2
+
3
+ export const DEFAULT_PAGE_SIZE = 5
@@ -0,0 +1,37 @@
1
+
2
+ ::before,
3
+ ::after {
4
+ box-sizing: border-box;
5
+ }
6
+
7
+ html {
8
+ line-height: 1.4;
9
+ font-size: 16px;
10
+ text-size-adjust: 100%;
11
+ font-family: var(--font-family);
12
+ font-weight: 400;
13
+ -webkit-font-smoothing: antialiased;
14
+ -webkit-tap-highlight-color: transparent;
15
+ }
16
+
17
+ body {
18
+ margin: 0;
19
+ width: 100%;
20
+ min-width: 320px;
21
+ min-height: 100vh;
22
+ line-height: 1.4;
23
+ font-size: 16px;
24
+ font-weight: 400;
25
+ color: var(--text-color);
26
+ background-color: var(--bg-color);
27
+ direction: ltr;
28
+ font-synthesis: none;
29
+ text-rendering: optimizeLegibility;
30
+ -webkit-font-smoothing: antialiased;
31
+ -moz-osx-font-smoothing: grayscale;
32
+ transition: background-color var(--el-transition-duration-fast);
33
+ }
34
+
35
+ main {
36
+ display: block;
37
+ }