Skip to content

Commit

Permalink
refactor(layout): refactor layout to fit changes with vitepress@latest
Browse files Browse the repository at this point in the history
Related Issue: DevCloudFE#1879
  • Loading branch information
fu050409 committed Jun 21, 2024
1 parent 494a4b0 commit c0d2ee2
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 109 deletions.
47 changes: 22 additions & 25 deletions packages/devui-vue/docs/.vitepress/devui-theme/Layout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,9 @@ import { LANG_KEY, ZH_CN, EN_US } from './const';
const Home = defineAsyncComponent(() => import('./components/Home.vue'));
const NoopComponent = () => null;
const CarbonAds = __CARBON__ ? defineAsyncComponent(() => import('./components/CarbonAds.vue')) : NoopComponent;
const BuySellAds = __BSA__ ? defineAsyncComponent(() => import('./components/BuySellAds.vue')) : NoopComponent;
const AlgoliaSearchBox = __ALGOLIA__ ? defineAsyncComponent(() => import('./components/AlgoliaSearchBox.vue')) : NoopComponent;
const CarbonAds = defineAsyncComponent(() => import('./components/CarbonAds.vue'));
const BuySellAds = defineAsyncComponent(() => import('./components/BuySellAds.vue'));
const AlgoliaSearchBox = defineAsyncComponent(() => import('./components/AlgoliaSearchBox.vue'));
// generic state
const route = useRoute();
Expand All @@ -29,7 +27,8 @@ const router = useRouter();
// custom layout
const isCustomLayout = computed(() => !!frontmatter.value.customLayout);
// home
const enableHome = computed(() => !!frontmatter.value.home);
console.table(frontmatter.value);
const enableHome = computed(() => !!frontmatter.value.layout);
// automatic multilang check for AlgoliaSearchBox
const isMultiLang = computed(() => Object.keys(theme.value.locales || {}).length > 0);
Expand All @@ -47,7 +46,7 @@ const showNavbar = computed(() => {
const openSideBar = ref(false);
const showSidebar = computed(() => {
if (frontmatter.value.home || frontmatter.value.sidebar === false) {
if (frontmatter.value.layout || frontmatter.value.sidebar === false) {
return false;
}
Expand Down Expand Up @@ -182,20 +181,17 @@ const contributors = computed(() => {
<template #top>
<slot name="page-top-ads">
<div id="ads-container" v-if="theme.carbonAds && theme.carbonAds.carbon">
<CarbonAds :key="'carbon' + page.relativePath" :code="theme.carbonAds.carbon" :placement="theme.carbonAds.placement" />
<CarbonAds :key="'carbon' + page.relativePath" :code="theme.carbonAds.carbon"
:placement="theme.carbonAds.placement" />
</div>
</slot>
<slot name="page-top" />
</template>
<template #bottom>
<slot name="page-bottom" />
<slot name="page-bottom-ads">
<BuySellAds
v-if="theme.carbonAds && theme.carbonAds.custom"
:key="'custom' + page.relativePath"
:code="theme.carbonAds.custom"
:placement="theme.carbonAds.placement"
/>
<BuySellAds v-if="theme.carbonAds && theme.carbonAds.custom" :key="'custom' + page.relativePath"
:code="theme.carbonAds.custom" :placement="theme.carbonAds.placement" />
</slot>
</template>
</Page>
Expand All @@ -204,14 +200,15 @@ const contributors = computed(() => {
<div class="container-contributors" v-if="enableHome">
<div class="contributors-inner">
<h2>✨贡献者✨</h2>
<PageContributor v-if="contributors && contributors.length > 0" :contributors="contributors" :spacing="20" :avatarSize="48" />
<a href="/contributing/"><Button class="btn-become-contributor" variant="solid" color="primary">成为贡献者</Button></a>
<PageContributor v-if="contributors && contributors.length > 0" :contributors="contributors" :spacing="20"
:avatarSize="48" />
<a href="/contributing/"><Button class="btn-become-contributor" variant="solid"
color="primary">成为贡献者</Button></a>
</div>
</div>
</div>

<DevuiFooter class="footer" v-if="enableHome" />
<Debug v-if="false" />
</div>
</template>

Expand Down Expand Up @@ -313,21 +310,21 @@ body[ui-theme='galaxy-theme'] {
}
.page-contributor {
& > a > span {
&>a>span {
margin: 0 12px 8px 0 !important;
& > img,
&>img,
& svg {
width: 40px !important;
height: 40px !important;
}
}
& > a:nth-child(8n) > span {
&>a:nth-child(8n)>span {
margin: 0 12px 8px 0 !important;
}
& > a:nth-child(7n) > span {
&>a:nth-child(7n)>span {
margin: 0 !important;
}
}
Expand All @@ -338,11 +335,11 @@ body[ui-theme='galaxy-theme'] {
@media (max-width: 385px) {
.container-contributors .contributors-inner {
.page-contributor {
& > a:nth-child(7n) > span {
&>a:nth-child(7n)>span {
margin: 0 12px 8px 0 !important;
}
& > a:nth-child(6n) > span {
&>a:nth-child(6n)>span {
margin: 0 !important;
}
}
Expand All @@ -353,11 +350,11 @@ body[ui-theme='galaxy-theme'] {
@media (max-width: 330px) {
.container-contributors .contributors-inner {
.page-contributor {
& > a:nth-child(6n) > span {
&>a:nth-child(6n)>span {
margin: 0 12px 8px 0 !important;
}
& > a:nth-child(5n) > span {
&>a:nth-child(5n)>span {
margin: 0 !important;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const SideBarLink = (props) => {
}

const link = resolveLink(site.value.base, props.item.link);
const children = props.item.children;
const children = props.item.items;
const active = isActive(route, props.item.link);
const childItems = depth < maxDepth ? createChildren(active, children, headers, depth + 1) : null;
return h('li', { class: 'sidebar-link' }, [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,136 +1,116 @@
import { onMounted, onUnmounted, onUpdated } from 'vue'
import { onMounted, onUnmounted, onUpdated } from 'vue';

import type { Ref } from 'vue'
import type { Ref } from 'vue';

// 防抖节流控制
export const throttleAndDebounce = (fn: () => any, delay: number) => {
let timeout: ReturnType<typeof setTimeout>
let called = false
let timeout: ReturnType<typeof setTimeout>;
let called = false;
return () => {
if (timeout) {
clearTimeout(timeout)
clearTimeout(timeout);
}
if (!called) {
fn()
called = true
fn();
called = true;
setTimeout(() => {
called = false
}, delay)
called = false;
}, delay);
} else {
timeout = setTimeout(fn, delay)
timeout = setTimeout(fn, delay);
}
}
}
};
};

export function useActiveSidebarLinks(
container: Ref<HTMLElement>,
marker: Ref<HTMLElement>
) {
const onScroll = throttleAndDebounce(setActiveLink, 150)
export function useActiveSidebarLinks(container: Ref<HTMLElement>, marker: Ref<HTMLElement>) {
const onScroll = throttleAndDebounce(setActiveLink, 150);
function setActiveLink() {
const sidebarLinks = getSidebarLinks()
const anchors = getAnchors(sidebarLinks)
const sidebarLinks = getSidebarLinks();
const anchors = getAnchors(sidebarLinks);

if (
anchors.length &&
window.scrollY + window.innerHeight === document.body.offsetHeight
) {
activateLink(anchors[anchors.length - 1].hash)
return
if (anchors.length && window.scrollY + window.innerHeight === document.body.offsetHeight) {
activateLink(anchors[anchors.length - 1].hash);
return;
}
for (let i = 0; i < anchors.length; i++) {
const anchor = anchors[i]
const nextAnchor = anchors[i + 1]
const [isActive, hash] = isAnchorActive(i, anchor, nextAnchor)
const anchor = anchors[i];
const nextAnchor = anchors[i + 1];
const [isActive, hash] = isAnchorActive(i, anchor, nextAnchor);
if (isActive) {
history.replaceState(
null,
document.title,
hash ? (hash as string) : ' '
)
activateLink(hash as string)
return
history.replaceState(null, document.title, hash ? (hash as string) : ' ');
activateLink(hash as string);
return;
}
}
}

let prevActiveLink: HTMLAnchorElement | null = null
let prevActiveLink: HTMLAnchorElement | null = null;

function activateLink(hash: string) {
deactiveLink(prevActiveLink)
deactiveLink(prevActiveLink);

const activeLink = (prevActiveLink =
hash == null
? null
: (container.value.querySelector(
`.devui-item a[href="${decodeURIComponent(hash)}"]`
) as HTMLAnchorElement))
if (activeLink) {
activeLink.classList.add('active')
marker.value.style.opacity = '1'
marker.value.style.top = `${activeLink.offsetTop}px`
} else {
marker.value.style.opacity = '0'
marker.value.style.top = '33px'
}
// const activeLink = (prevActiveLink =
// hash == null
// ? null
// : (container.value.querySelector(
// `.devui-item a[href="${decodeURIComponent(hash)}"]`
// ) as HTMLAnchorElement))
// if (activeLink) {
// activeLink.classList.add('active')
// marker.value.style.opacity = '1'
// marker.value.style.top = `${activeLink.offsetTop}px`
// } else {
// marker.value.style.opacity = '0'
// marker.value.style.top = '33px'
// }
}

function deactiveLink(link: HTMLElement) {
link && link.classList.remove('active')
link && link.classList.remove('active');
}

onMounted(() => {
window.requestAnimationFrame(setActiveLink)
window.addEventListener('scroll', onScroll)
})
window.requestAnimationFrame(setActiveLink);
window.addEventListener('scroll', onScroll);
});

onUpdated(() => {
activateLink(location.hash)
})
activateLink(location.hash);
});

onUnmounted(() => {
window.removeEventListener('scroll', onScroll)
})
window.removeEventListener('scroll', onScroll);
});
}
function getSidebarLinks() {
return Array.from(
document.querySelectorAll('.devui-content-nav .devui-link')
) as HTMLAnchorElement[]
return Array.from(document.querySelectorAll('.devui-content-nav .devui-link')) as HTMLAnchorElement[];
}
function getAnchors(sidebarLinks: HTMLAnchorElement[]) {
return (
Array.from(
document.querySelectorAll('.content .header-anchor')
) as HTMLAnchorElement[]
).filter((anchor) =>
return (Array.from(document.querySelectorAll('.content .header-anchor')) as HTMLAnchorElement[]).filter((anchor) =>
sidebarLinks.some((sidebarLink) => sidebarLink.hash === anchor.hash)
)
);
}
function getPageOffset() {
return (document.querySelector('.nav-bar') as HTMLElement).offsetHeight
return (document.querySelector('.nav-bar') as HTMLElement).offsetHeight;
}
function getAnchorTop(anchor: HTMLAnchorElement) {
const pageOffset = getPageOffset()
const pageOffset = getPageOffset();
try {
return anchor.parentElement.offsetTop - pageOffset - 15
return anchor.parentElement.offsetTop - pageOffset - 15;
} catch (e) {
return 0
return 0;
}
}
function isAnchorActive(
index: number,
anchor: HTMLAnchorElement,
nextAnchor: HTMLAnchorElement
) {
const scrollTop = window.scrollY
function isAnchorActive(index: number, anchor: HTMLAnchorElement, nextAnchor: HTMLAnchorElement) {
const scrollTop = window.scrollY;
if (index === 0 && scrollTop === 0) {
return [true, null]
return [true, null];
}
if (scrollTop < getAnchorTop(anchor)) {
return [false, null]
return [false, null];
}
if (!nextAnchor || scrollTop < getAnchorTop(nextAnchor)) {
return [true, decodeURIComponent(anchor.hash)]
return [true, decodeURIComponent(anchor.hash)];
}
return [false, null]
return [false, null];
}
2 changes: 1 addition & 1 deletion packages/devui-vue/docs/.vitepress/theme/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ if (typeof window !== 'undefined') {
export default {
extends: DevUITheme,
Layout: () => {
return h(DefaultTheme.Layout, null, {
return h(DevUITheme.Layout ?? DefaultTheme.Layout, null, {
// https://vitepress.dev/guide/extending-default-theme#layout-slots
});
},
Expand Down

0 comments on commit c0d2ee2

Please sign in to comment.