Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
DCloud
unidocs-zh
提交
5253cc24
unidocs-zh
项目概览
DCloud
/
unidocs-zh
通知
3200
Star
106
Fork
813
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
94
列表
看板
标记
里程碑
合并请求
70
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
unidocs-zh
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
94
Issue
94
列表
看板
标记
里程碑
合并请求
70
合并请求
70
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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录