Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
程序yang
unidocs-zh
提交
5253cc24
U
unidocs-zh
项目概览
程序yang
/
unidocs-zh
与 Fork 源项目一致
Fork自
DCloud / unidocs-zh
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
unidocs-zh
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
5253cc24
编写于
4月 12, 2022
作者:
D
DCloud_LXH
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: add toc
上级
da91ce87
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
271 addition
and
7 deletion
+271
-7
docs/.vuepress/config.js
docs/.vuepress/config.js
+1
-0
docs/.vuepress/markdown/createMarkdownArray.js
docs/.vuepress/markdown/createMarkdownArray.js
+3
-5
docs/.vuepress/theme/components/Navbar.vue
docs/.vuepress/theme/components/Navbar.vue
+4
-0
docs/.vuepress/theme/components/Sticker.vue
docs/.vuepress/theme/components/Sticker.vue
+64
-0
docs/.vuepress/theme/components/Toc.vue
docs/.vuepress/theme/components/Toc.vue
+166
-0
docs/.vuepress/theme/layouts/Layout.vue
docs/.vuepress/theme/layouts/Layout.vue
+5
-1
docs/.vuepress/theme/styles/index.styl
docs/.vuepress/theme/styles/index.styl
+5
-0
docs/.vuepress/theme/styles/palette.styl
docs/.vuepress/theme/styles/palette.styl
+2
-1
docs/.vuepress/theme/util/index.js
docs/.vuepress/theme/util/index.js
+21
-0
未找到文件。
docs/.vuepress/config.js
浏览文件 @
5253cc24
...
...
@@ -36,6 +36,7 @@ const config = {
docsDir
:
'
docs
'
,
editLinks
:
true
,
editLinkText
:
'
帮助我们改善此页面!
'
,
lastUpdated
:
'
上次更新
'
,
// smoothScroll: true,
algolia
:
{
apiKey
:
'
2fdcc4e76c8e260671ad70065e60b2e7
'
,
...
...
docs/.vuepress/markdown/createMarkdownArray.js
浏览文件 @
5253cc24
...
...
@@ -45,15 +45,13 @@ function createMarkdownArray(contents = [], childrenName = 'children') {
}
}
function
removeParent
(
childs
=
[])
{
// 移除最后一项 parent 节点,防止循环引用报错
(
function
removeParent
(
childs
=
[])
{
childs
.
forEach
(
child
=>
{
if
(
child
.
parent
)
delete
child
.
parent
if
(
child
[
childrenName
])
removeParent
(
child
[
childrenName
])
})
}
// 移除最后一项 parent 节点,防止循环引用报错
removeParent
(
markdownArray
[
markdownArray
.
length
-
1
][
childrenName
])
})(
markdownArray
[
markdownArray
.
length
-
1
][
childrenName
])
return
markdownArray
}
...
...
docs/.vuepress/theme/components/Navbar.vue
浏览文件 @
5253cc24
...
...
@@ -121,6 +121,7 @@ export default {
this
.
mainNavBar
=
document
.
querySelector
(
'
.main-navbar
'
)
this
.
subNavBar
=
document
.
querySelector
(
'
.sub-navbar
'
)
this
.
pageContainer
=
document
.
querySelector
(
'
.page
'
)
this
.
vuepressToc
=
document
.
querySelector
(
'
.vuepress-toc
'
)
this
.
navbarHeight
=
this
.
navbar
.
clientHeight
this
.
subNavBarHeight
=
this
.
subNavBar
.
clientHeight
this
.
mainNavBarHeight
=
this
.
mainNavBar
.
clientHeight
...
...
@@ -134,6 +135,7 @@ export default {
window
.
removeEventListener
(
'
scroll
'
,
this
.
onWindowScroll
)
this
.
fixedNavbar
=
false
this
.
sideBar
&&
this
.
sideBar
.
removeAttribute
(
'
style
'
)
this
.
vuepressToc
&&
this
.
vuepressToc
.
removeAttribute
(
'
style
'
)
this
.
navbar
&&
this
.
navbar
.
removeAttribute
(
'
style
'
)
this
.
pageContainer
&&
this
.
pageContainer
.
removeAttribute
(
'
style
'
)
},
...
...
@@ -144,6 +146,7 @@ export default {
let
sideTop
=
this
.
navbarHeight
-
scrollTop
sideTop
<=
this
.
subNavBarHeight
&&
(
sideTop
=
this
.
subNavBarHeight
)
this
.
sideBar
&&
(
this
.
sideBar
.
style
.
top
=
`
${
sideTop
+
1
}
px`
)
this
.
vuepressToc
&&
(
this
.
vuepressToc
.
style
.
top
=
`
${
sideTop
+
1
}
px`
)
}
if
(
scrollTop
>=
this
.
mainNavBarHeight
)
{
...
...
@@ -182,6 +185,7 @@ export default {
this
.
navbarHeight
=
this
.
navbar
.
clientHeight
this
.
subNavBarHeight
=
this
.
subNavBar
.
clientHeight
this
.
sideBar
.
style
.
top
=
`
${
this
.
navbarHeight
+
1
}
px`
this
.
vuepressToc
.
style
.
top
=
`
${
this
.
navbarHeight
+
1
}
px`
})
}
}
...
...
docs/.vuepress/theme/components/Sticker.vue
0 → 100644
浏览文件 @
5253cc24
<
template
>
<component
:is=
"tag || 'div'"
class=
"sticker"
:class=
"needFloat ? ['stick-float'] : undefined"
:style=
"needFloat ?
{ bottom: `${stickBottom}px` } : undefined"
>
<slot></slot>
</component>
</
template
>
<
script
>
import
{
findContainerInVm
}
from
'
../util
'
;
export
default
{
props
:
[
'
stick
'
,
'
tag
'
],
data
()
{
return
{
needFloat
:
false
,
stickBottom
:
0
,
};
},
watch
:
{
stick
()
{
this
.
unStick
();
this
.
stickHandle
();
},
},
mounted
()
{
this
.
stickHandle
();
},
beforeDestroy
()
{
this
.
unStick
();
},
methods
:
{
stickHandle
()
{
if
(
!
this
.
stick
)
return
;
const
stickElement
=
findContainerInVm
(
this
.
stick
,
this
);
if
(
!
stickElement
)
return
;
this
.
_stickerScroll
=
()
=>
{
const
rect
=
this
.
$el
.
getBoundingClientRect
();
const
scrollTop
=
document
.
body
.
scrollTop
+
document
.
documentElement
.
scrollTop
;
this
.
needFloat
=
document
.
body
.
offsetHeight
-
scrollTop
-
rect
.
height
<
stickElement
.
offsetHeight
;
this
.
stickBottom
=
stickElement
.
offsetHeight
;
};
this
.
_stickerScroll
();
window
.
addEventListener
(
'
scroll
'
,
this
.
_stickerScroll
);
},
unStick
()
{
this
.
needFloat
=
false
;
this
.
stickBottom
=
0
;
window
.
removeEventListener
(
'
scroll
'
,
this
.
_stickerScroll
);
},
},
};
</
script
>
<
style
lang=
"stylus"
>
.sticker
position fixed
&.stick-float
top auto
position absolute
</
style
>
docs/.vuepress/theme/components/Toc.vue
0 → 100644
浏览文件 @
5253cc24
<
template
>
<Sticker
v-if=
"visible"
class=
"vuepress-toc"
v-bind=
"$attrs"
:style=
"
{ top: initVisibleTop }">
<h5>
ON THIS PAGE
</h5>
<div
v-for=
"(item, index) in $page.headers"
ref=
"chairTocItem"
:key=
"index"
class=
"vuepress-toc-item"
:class=
"[`vuepress-toc-h$
{item.level}`, { active: activeIndex === index }]"
>
<a
:href=
"`#$
{item.slug}`" :title="item.title">
{{
item
.
title
}}
</a>
</div>
</Sticker>
</
template
>
<
script
>
import
Sticker
from
'
./Sticker.vue
'
;
let
initTop
;
// get offset top
function
getAbsoluteTop
(
dom
)
{
return
dom
&&
dom
.
getBoundingClientRect
?
dom
.
getBoundingClientRect
().
top
+
document
.
body
.
scrollTop
+
document
.
documentElement
.
scrollTop
:
0
;
}
export
default
{
components
:
{
Sticker
,
},
data
()
{
return
{
activeIndex
:
0
,
initVisibleTop
:
'
0px
'
,
};
},
computed
:
{
visible
()
{
return
(
this
.
$frontmatter
&&
this
.
$frontmatter
.
toc
!==
false
// && !!(this.$page && this.$page.headers && this.$page.headers.length)
);
},
},
watch
:
{
activeIndex
()
{
const
items
=
this
.
$refs
.
chairTocItem
||
[];
const
dom
=
items
[
this
.
activeIndex
];
if
(
!
dom
)
return
;
const
rect
=
dom
.
getBoundingClientRect
();
const
wrapperRect
=
this
.
$el
.
getBoundingClientRect
();
const
top
=
rect
.
top
-
wrapperRect
.
top
;
if
(
top
<
20
)
{
this
.
$el
.
scrollTop
=
this
.
$el
.
scrollTop
+
top
-
20
;
}
else
if
(
top
+
rect
.
height
>
wrapperRect
.
height
)
{
this
.
$el
.
scrollTop
+=
rect
.
top
-
(
wrapperRect
.
height
-
rect
.
height
);
}
},
$route
()
{},
},
mounted
()
{
// sync visible to parent component
const
syncVisible
=
()
=>
{
this
.
$emit
(
'
visible-change
'
,
this
.
visible
);
};
syncVisible
();
this
.
$watch
(
'
visible
'
,
syncVisible
);
// binding event
setTimeout
(()
=>
this
.
triggerEvt
(),
1000
);
this
.
_onScroll
=
()
=>
this
.
onScroll
();
this
.
_onHashChange
=
()
=>
{
const
hash
=
decodeURIComponent
(
location
.
hash
.
substring
(
1
));
const
index
=
(
this
.
$page
.
headers
||
[]).
findIndex
(
h
=>
h
.
slug
===
hash
);
if
(
index
>=
0
)
this
.
activeIndex
=
index
;
const
dom
=
hash
&&
document
.
getElementById
(
hash
);
if
(
dom
)
window
.
scrollTo
(
0
,
getAbsoluteTop
(
dom
)
-
20
);
};
window
.
addEventListener
(
'
scroll
'
,
this
.
_onScroll
);
// window.addEventListener('hashchange', this._onHashChange);
},
beforeDestroy
()
{
window
.
removeEventListener
(
'
scroll
'
,
this
.
_onScroll
);
window
.
removeEventListener
(
'
hashchange
'
,
this
.
_onHashChange
);
},
methods
:
{
onScroll
()
{
if
(
initTop
===
undefined
)
{
initTop
=
getAbsoluteTop
(
this
.
$el
);
}
// update position
const
scrollTop
=
document
.
body
.
scrollTop
+
document
.
documentElement
.
scrollTop
;
const
headings
=
this
.
$page
.
headers
||
[];
// change active toc with scrolling
let
i
=
0
;
const
addLink
=
index
=>
{
this
.
activeIndex
=
index
;
};
for
(;
i
<
headings
.
length
;
i
++
)
{
const
dom
=
document
.
getElementById
(
headings
[
i
].
slug
);
const
top
=
getAbsoluteTop
(
dom
);
if
(
top
-
50
<
scrollTop
)
{
addLink
(
i
);
}
else
{
if
(
!
i
)
addLink
(
i
);
break
;
}
}
},
triggerEvt
()
{
this
.
_onScroll
();
this
.
_onHashChange
();
},
},
};
</
script
>
<
style
lang=
"stylus"
>
.table-of-contents
display none !important
.vuepress-toc
position fixed
display none
max-height 89vh
width $vuepress-toc-width
overflow-y auto
// margin-top $navbarHeight
top 0
right 0
box-sizing border-box
background-color #fff
/* background: #fff; */
z-index 0
.vuepress-toc-item
position relative
padding 0.1rem 0.6rem 0.1rem 1.5rem
line-height 1.5rem
border-left 2px solid rgba(0, 0, 0, 0.08)
overflow hidden
a
display block
color $textColor
width 100%
box-sizing border-box
font-size 14px
font-weight 400
text-decoration none
transition color 0.3s
overflow hidden
text-overflow ellipsis
white-space nowrap
&.active
border-left-color $accentColor
a
color $accentColor
&:hover
a
color $accentColor
for i in range(3, 6)
.vuepress-toc-h{i} a
padding-left 1rem * (i - 2)
// for vuepress-toc
@media (min-width: 1300px)
.vuepress-toc
display block
</
style
>
docs/.vuepress/theme/layouts/Layout.vue
浏览文件 @
5253cc24
...
...
@@ -43,6 +43,8 @@
<Footer
/>
</
template
>
</Page>
<Toc
/>
</div>
</template>
...
...
@@ -53,6 +55,7 @@ import Page from '@theme/components/Page.vue'
import
Sidebar
from
'
@theme/components/Sidebar.vue
'
import
Footer
from
'
@theme/components/Footer.vue
'
;
import
SiderBarBottom
from
'
../components/SiderBarBottom.vue
'
;
import
Toc
from
'
../components/Toc
'
;
import
{
resolveSidebarItems
,
forbidScroll
,
BaiduStat
}
from
'
../util
'
import
navProvider
from
'
../mixin/navProvider
'
;
...
...
@@ -65,7 +68,8 @@ export default {
Sidebar
,
Navbar
,
Footer
,
SiderBarBottom
SiderBarBottom
,
Toc
},
data
()
{
return
{
...
...
docs/.vuepress/theme/styles/index.styl
浏览文件 @
5253cc24
...
...
@@ -81,6 +81,11 @@ body.forbid_scroll
main.page
padding-bottom 0px
padding-right 0px
@media (min-width: 1300px)
&
padding-right $vuepress-toc-width
{$contentClass}:not(.custom)
> *:first-child
...
...
docs/.vuepress/theme/styles/palette.styl
浏览文件 @
5253cc24
...
...
@@ -4,4 +4,5 @@ $contentWidth = 1200px
$navbarHeight = 9rem
$navbar-sub-navbar-height = 5rem
$navbar-background-color = #f7f7f7
$search-container-color = #f5f6f7
\ No newline at end of file
$search-container-color = #f5f6f7
$vuepress-toc-width = 220px
\ No newline at end of file
docs/.vuepress/theme/util/index.js
浏览文件 @
5253cc24
...
...
@@ -300,4 +300,25 @@ export function debounce(fn, delay) {
clearTimeout
(
timeout
)
}
return
newFn
}
/*
* find parent vm by ref
* @param {String} ref
* @param {Vue} vm
* @param {any} def default value
* @returns {Element}
*/
export
function
findContainerInVm
(
ref
,
vm
,
def
)
{
if
(
!
ref
)
return
def
let
container
let
parent
=
vm
while
((
parent
=
parent
.
$parent
)
&&
!
container
)
{
container
=
parent
.
$refs
[
ref
]
}
// Ensure it's html element (ref could be component)
if
(
container
&&
container
.
$el
)
{
container
=
container
.
$el
}
return
container
||
def
}
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录