vitepress-theme-element-plus 1.3.0 → 1.3.2

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 (42) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +3 -3
  3. package/client/components/A11yTag.vue +29 -29
  4. package/client/components/ApiTyping.vue +54 -54
  5. package/client/components/Backdrop.vue +41 -41
  6. package/client/components/Bili.vue +94 -94
  7. package/client/components/Content.vue +148 -148
  8. package/client/components/DeprecatedTag.vue +19 -19
  9. package/client/components/Doc.vue +185 -185
  10. package/client/components/DocAside.vue +46 -46
  11. package/client/components/DocAsideOutline.vue +145 -145
  12. package/client/components/DocFooter.vue +162 -162
  13. package/client/components/Footer.vue +100 -100
  14. package/client/components/FooterCopyright.vue +27 -27
  15. package/client/components/Layout.vue +156 -156
  16. package/client/components/Link.vue +41 -41
  17. package/client/components/LocalNav.vue +160 -160
  18. package/client/components/Nav.vue +69 -69
  19. package/client/components/NavBar.vue +203 -203
  20. package/client/components/NavBarTitle.vue +89 -89
  21. package/client/components/Sidebar.vue +129 -129
  22. package/client/components/SidebarGroup.vue +51 -51
  23. package/client/components/SidebarItem.vue +304 -304
  24. package/client/components/ThemeToggler.vue +129 -129
  25. package/client/components/VPNavBarSearch.vue +23 -23
  26. package/client/hooks/useBackTop.ts +71 -71
  27. package/client/hooks/useLangs.ts +50 -50
  28. package/client/hooks/useSidebarControl.ts +78 -78
  29. package/client/hooks/useSize.ts +69 -69
  30. package/client/icons/dark.vue +8 -8
  31. package/client/icons/light.vue +8 -8
  32. package/client/utils/client/common.ts +49 -49
  33. package/client/utils/client/outline.ts +133 -126
  34. package/client/utils/common.ts +90 -90
  35. package/index.ts +45 -45
  36. package/package.json +2 -2
  37. package/shared/constants.ts +3 -3
  38. package/styles/base.scss +105 -105
  39. package/styles/code.scss +290 -290
  40. package/styles/doc-content.scss +363 -363
  41. package/styles/index.scss +71 -71
  42. package/styles/tag-content.scss +30 -30
@@ -1,126 +1,133 @@
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
- titleTags: string[]
12
- children?: MenuItem[]
13
- }
14
-
15
- export function resolveTitle(theme: DefaultTheme.Config): string {
16
- return (
17
- (typeof theme.outline === 'object'
18
- && !Array.isArray(theme.outline)
19
- && theme.outline.label)
20
- || theme.outlineTitle
21
- || 'On this page'
22
- )
23
- }
24
-
25
- export function getHeaders(range: DefaultTheme.Config['outline']): MenuItem[] {
26
- const headers = Array.from(document.querySelectorAll('.VPDoc :where(h1,h2,h3,h4,h5,h6)'))
27
- .filter(el => el.id && el.hasChildNodes())
28
- .map((el) => {
29
- const level = Number(el.tagName[1])
30
- const { text, tags } = serializeHeader(el)
31
- return {
32
- element: el as HTMLHeadElement,
33
- title: text,
34
- titleTags: tags,
35
- link: `#${el.id}`,
36
- level,
37
- }
38
- })
39
-
40
- return resolveHeaders(headers, range)
41
- }
42
-
43
- function serializeHeader(h: Element): { text: string, tags: string[] } {
44
- let text = ''
45
- const tags: string[] = []
46
- for (const node of Array.from(h.childNodes)) {
47
- if (node.nodeType === 1) {
48
- const element = node as HTMLElement
49
- if (ignoreRE.test(element.className))
50
- continue
51
- if (element.classList.contains('el-tag') || element.classList.contains('vp-tag')) {
52
- tags.push(element.outerHTML)
53
- continue
54
- }
55
- text += element.textContent ?? ''
56
- }
57
- else if (node.nodeType === 3) {
58
- const value = node.textContent ?? ''
59
- text += value
60
- }
61
- }
62
- return {
63
- text: text.trim(),
64
- tags,
65
- }
66
- }
67
-
68
- export function resolveHeaders(
69
- headers: MenuItem[],
70
- range?: DefaultTheme.Config['outline'],
71
- ): MenuItem[] {
72
- if (range === false) {
73
- return []
74
- }
75
-
76
- const levelsRange
77
- = (typeof range === 'object' && !Array.isArray(range)
78
- ? range.level
79
- : range) || 2
80
-
81
- const [high, low]: [number, number]
82
- = typeof levelsRange === 'number'
83
- ? [levelsRange, levelsRange]
84
- : levelsRange === 'deep'
85
- ? [2, 6]
86
- : levelsRange
87
-
88
- return buildTree(headers, high, low)
89
- }
90
-
91
- function buildTree(data: MenuItem[], min: number, max: number): MenuItem[] {
92
- resolvedHeaders.length = 0
93
-
94
- const result: MenuItem[] = []
95
- const stack: (MenuItem | { level: number, shouldIgnore: true })[] = []
96
-
97
- data.forEach((item) => {
98
- const node = { ...item, children: [] }
99
- let parent = stack[stack.length - 1]
100
-
101
- while (parent && parent.level >= node.level) {
102
- stack.pop()
103
- parent = stack[stack.length - 1]
104
- }
105
-
106
- if (
107
- node.element.classList.contains('ignore-header')
108
- || (parent && 'shouldIgnore' in parent)
109
- ) {
110
- stack.push({ level: node.level, shouldIgnore: true })
111
- return
112
- }
113
-
114
- if (node.level > max || node.level < min)
115
- return
116
- resolvedHeaders.push({ element: node.element, link: node.link })
117
-
118
- if (parent)
119
- (parent as MenuItem).children.push(node)
120
- else result.push(node)
121
-
122
- stack.push(node)
123
- })
124
-
125
- return result
126
- }
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
+ titleTags: string[]
12
+ children?: MenuItem[]
13
+ }
14
+
15
+ export function resolveTitle(theme: DefaultTheme.Config): string {
16
+ return (
17
+ (typeof theme.outline === 'object'
18
+ && !Array.isArray(theme.outline)
19
+ && theme.outline.label)
20
+ || theme.outlineTitle
21
+ || 'On this page'
22
+ )
23
+ }
24
+
25
+ export function getHeaders(range: DefaultTheme.Config['outline']): MenuItem[] {
26
+ const headers = Array.from(document.querySelectorAll('.VPDoc :where(h1,h2,h3,h4,h5,h6)'))
27
+ .filter(el => el.id && el.hasChildNodes())
28
+ .map((el) => {
29
+ const level = Number(el.tagName[1])
30
+ const { text, tags } = serializeHeader(el)
31
+ return {
32
+ element: el as HTMLHeadElement,
33
+ title: text,
34
+ titleTags: tags,
35
+ link: `#${el.id}`,
36
+ level,
37
+ }
38
+ })
39
+
40
+ return resolveHeaders(headers, range)
41
+ }
42
+
43
+ function serializeHeader(h: Element): { text: string, tags: string[] } {
44
+ let text = ''
45
+ const tags: string[] = []
46
+ for (const node of Array.from(h.childNodes)) {
47
+ if (node.nodeType === 1) {
48
+ const element = node as HTMLElement
49
+ if (ignoreRE.test(element.className))
50
+ continue
51
+ if (element.classList.contains('el-tag') || element.classList.contains('vp-tag')) {
52
+ const cloned = element.cloneNode(true) as HTMLElement
53
+ const transitionClassRE = /(?:^|-)enter-(?:active|from|to)$|(?:^|-)leave-(?:active|from|to)$/
54
+ for (const cls of Array.from(cloned.classList)) {
55
+ if (transitionClassRE.test(cls) || cls.startsWith('el-zoom-in-center-')) {
56
+ cloned.classList.remove(cls)
57
+ }
58
+ }
59
+ tags.push(cloned.outerHTML)
60
+ continue
61
+ }
62
+ text += element.textContent ?? ''
63
+ }
64
+ else if (node.nodeType === 3) {
65
+ const value = node.textContent ?? ''
66
+ text += value
67
+ }
68
+ }
69
+ return {
70
+ text: text.trim(),
71
+ tags,
72
+ }
73
+ }
74
+
75
+ export function resolveHeaders(
76
+ headers: MenuItem[],
77
+ range?: DefaultTheme.Config['outline'],
78
+ ): MenuItem[] {
79
+ if (range === false) {
80
+ return []
81
+ }
82
+
83
+ const levelsRange
84
+ = (typeof range === 'object' && !Array.isArray(range)
85
+ ? range.level
86
+ : range) || 2
87
+
88
+ const [high, low]: [number, number]
89
+ = typeof levelsRange === 'number'
90
+ ? [levelsRange, levelsRange]
91
+ : levelsRange === 'deep'
92
+ ? [2, 6]
93
+ : levelsRange
94
+
95
+ return buildTree(headers, high, low)
96
+ }
97
+
98
+ function buildTree(data: MenuItem[], min: number, max: number): MenuItem[] {
99
+ resolvedHeaders.length = 0
100
+
101
+ const result: MenuItem[] = []
102
+ const stack: (MenuItem | { level: number, shouldIgnore: true })[] = []
103
+
104
+ data.forEach((item) => {
105
+ const node = { ...item, children: [] }
106
+ let parent = stack[stack.length - 1]
107
+
108
+ while (parent && parent.level >= node.level) {
109
+ stack.pop()
110
+ parent = stack[stack.length - 1]
111
+ }
112
+
113
+ if (
114
+ node.element.classList.contains('ignore-header')
115
+ || (parent && 'shouldIgnore' in parent)
116
+ ) {
117
+ stack.push({ level: node.level, shouldIgnore: true })
118
+ return
119
+ }
120
+
121
+ if (node.level > max || node.level < min)
122
+ return
123
+ resolvedHeaders.push({ element: node.element, link: node.link })
124
+
125
+ if (parent)
126
+ (parent as MenuItem).children.push(node)
127
+ else result.push(node)
128
+
129
+ stack.push(node)
130
+ })
131
+
132
+ return result
133
+ }
@@ -1,90 +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
- }
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
+ }
package/index.ts CHANGED
@@ -1,45 +1,45 @@
1
- import type { DefaultTheme, Theme } from 'vitepress'
2
- import VPTheme from 'vitepress/theme'
3
- import Layout from './client/components/Layout.vue'
4
- import 'element-plus/theme-chalk/base.css'
5
- import 'element-plus/theme-chalk/el-tag.css'
6
- import 'element-plus/theme-chalk/dark/css-vars.css'
7
- import './styles/index.scss'
8
- import './styles/base.scss'
9
- import './styles/code.scss'
10
- import './styles/doc-content.scss'
11
- import './styles/tag-content.scss'
12
-
13
- const EPTheme: Theme = {
14
- extends: VPTheme,
15
- Layout,
16
- }
17
- // #region snippet
18
- export interface FooterBlogrollLink {
19
- text: string
20
- link: string
21
- }
22
-
23
- export interface FooterBlogrollSection {
24
- title: string
25
- children: FooterBlogrollLink[]
26
- }
27
-
28
- export interface EPThemeFooter extends DefaultTheme.Footer {
29
- /**
30
- * 友情链接配置
31
- */
32
- blogroll?: FooterBlogrollSection[]
33
- }
34
-
35
- export interface EPThemeConfig extends DefaultTheme.Config {
36
- /**
37
- * 文档版本号
38
- */
39
- version?: string
40
- footer?: EPThemeFooter
41
- }
42
- // #endregion snippet
43
-
44
- export { Layout }
45
- export default EPTheme
1
+ import type { DefaultTheme, Theme } from 'vitepress'
2
+ import VPTheme from 'vitepress/theme'
3
+ import Layout from './client/components/Layout.vue'
4
+ import 'element-plus/theme-chalk/base.css'
5
+ import 'element-plus/theme-chalk/el-tag.css'
6
+ import 'element-plus/theme-chalk/dark/css-vars.css'
7
+ import './styles/index.scss'
8
+ import './styles/base.scss'
9
+ import './styles/code.scss'
10
+ import './styles/doc-content.scss'
11
+ import './styles/tag-content.scss'
12
+
13
+ const EPTheme: Theme = {
14
+ extends: VPTheme,
15
+ Layout,
16
+ }
17
+ // #region snippet
18
+ export interface FooterBlogrollLink {
19
+ text: string
20
+ link: string
21
+ }
22
+
23
+ export interface FooterBlogrollSection {
24
+ title: string
25
+ children: FooterBlogrollLink[]
26
+ }
27
+
28
+ export interface EPThemeFooter extends DefaultTheme.Footer {
29
+ /**
30
+ * 友情链接配置
31
+ */
32
+ blogroll?: FooterBlogrollSection[]
33
+ }
34
+
35
+ export interface EPThemeConfig extends DefaultTheme.Config {
36
+ /**
37
+ * 文档版本号
38
+ */
39
+ version?: string
40
+ footer?: EPThemeFooter
41
+ }
42
+ // #endregion snippet
43
+
44
+ export { Layout }
45
+ export default EPTheme
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vitepress-theme-element-plus",
3
3
  "type": "module",
4
- "version": "1.3.0",
4
+ "version": "1.3.2",
5
5
  "description": "A VitePress theme for Element Plus",
6
6
  "author": "Hezhengxu",
7
7
  "license": "MIT",
@@ -35,7 +35,7 @@
35
35
  "styles"
36
36
  ],
37
37
  "peerDependencies": {
38
- "vitepress": "2.0.0-alpha.12"
38
+ "vitepress": "^2.0.0-alpha.12"
39
39
  },
40
40
  "dependencies": {
41
41
  "@iconify/vue": "^4"
@@ -1,3 +1,3 @@
1
- export const NOT_ARTICLE_LAYOUTS = ['blog', 'tags', 'categorys', 'projects', 'home', 'page']
2
-
3
- export const DEFAULT_PAGE_SIZE = 5
1
+ export const NOT_ARTICLE_LAYOUTS = ['blog', 'tags', 'categorys', 'projects', 'home', 'page']
2
+
3
+ export const DEFAULT_PAGE_SIZE = 5