feat(docs): migrate bs docs

This commit is contained in:
DarkSky
2026-04-29 17:23:23 +08:00
parent bf6fc66943
commit 0ccfacbc29
105 changed files with 5537 additions and 243 deletions
@@ -0,0 +1,26 @@
<script lang="ts" setup>
import { computed } from 'vue';
const props = defineProps<{
name: string;
icon?: string;
}>();
const src = computed(() => {
if (props.icon) return props.icon;
return `https://raw.githubusercontent.com/PKief/vscode-material-icon-theme/main/icons/${props.name.toLowerCase()}.svg`;
});
</script>
<template>
<img :src="src" :alt="`${name} Logo`" />
</template>
<style scoped>
img {
display: inline;
transform: translateY(5px);
margin-right: 8px;
width: 20px;
}
</style>
@@ -0,0 +1,79 @@
<template>
<h1>BlockSuite Blog</h1>
<div class="blog-posts-container">
<div class="blog-post" v-for="post in posts">
<a :href="post.url">
<h2 class="blog-post-title">{{ post.title }}</h2>
</a>
<div class="blog-post-excerpt">
{{ post.excerpt }}
<a class="blog-post-read-more" :href="post.url">Read more </a>
</div>
<div class="blog-post-date">{{ post.date.formatted }}</div>
</div>
</div>
</template>
<script setup>
import { usePosts } from '../composables/use-posts';
const { posts } = usePosts();
</script>
<style scoped>
h1 {
margin: auto;
margin-top: 30px;
margin-bottom: 50px;
font-size: 50px;
font-weight: bolder;
line-height: 50px;
text-align: center;
}
@media (max-width: 768px) {
h1 {
font-size: 40px;
line-height: 40px;
}
}
.blog-posts-container {
max-width: 800px;
margin: auto;
padding-left: 30px;
padding-right: 30px;
}
.blog-post {
margin-bottom: 40px;
padding-bottom: 20px;
border-bottom: 1px solid #eaecef;
}
.blog-post-title {
margin: 0;
font-size: 24px;
font-weight: bold;
color: var(--vp-c-text-1);
}
.blog-post-date {
font-size: 14px;
color: var(--vp-c-text-3);
}
.blog-post-excerpt {
margin-top: 10px;
margin-bottom: 5px;
line-height: 1.6;
}
.dark .blog-post {
border-bottom: 1px solid #343a40;
}
.blog-post-read-more:hover {
text-decoration: underline;
}
</style>
@@ -0,0 +1,36 @@
<template>
<div class="blog-post-meta">
<span class="post-date">{{ post.date.formatted }}</span> by
<span v-html="formattedAuthors"></span>
</div>
</template>
<script setup>
import { computed } from 'vue';
import { usePosts } from '../composables/use-posts';
const { post } = usePosts();
const formattedAuthors = computed(() => {
return post.value.authors
.map(
author =>
`<a class="author" href="${author.link}" target="_blank">${author.name}</a>`
)
.join(', ');
});
</script>
<style>
.blog-post-meta {
margin-top: 8px;
font-size: 14px;
}
.author {
color: var(--vp-c-text-1) !important;
}
.post-date {
color: var(--vp-c-text-2);
}
</style>
@@ -0,0 +1,36 @@
<template>
<!-- 'code-options' is a build-in prop, do not edit it -->
<Sandbox
:rtl="rtl"
:template="'vanilla-ts'"
:light-theme="lightTheme"
:dark-theme="darkTheme"
:options="{
...props, // do not forget it
coderHeight: Number(props.coderHeight),
previewHeight: Number(props.previewHeight),
showLineNumbers: true,
}"
:custom-setup="{
...props, // do not forget it
deps: {
yjs: 'latest',
'@toeverything/theme': 'latest',
'@blocksuite/presets': 'canary',
},
}"
:code-options="codeOptions"
>
<slot />
</Sandbox>
</template>
<script setup lang="ts">
import { Sandbox, sandboxProps } from 'vitepress-plugin-sandpack';
const props = defineProps({
...sandboxProps,
coderHeight: String,
previewHeight: String,
});
</script>
@@ -0,0 +1,6 @@
<template>
<img
style="width: 70%; height: 100%; margin: auto; opacity: 0.8"
src="https://raw.githubusercontent.com/toeverything/blocksuite/master/assets/logo.svg"
/>
</template>
@@ -0,0 +1,44 @@
import { format, formatDistance } from 'date-fns';
import { createContentLoader } from 'vitepress';
interface Post {
title: string;
authors: { name: string; link: string }[];
url: string;
date: {
raw: string;
time: number;
formatted: string;
since: string;
};
}
function formatDate(raw: string) {
const date = new Date(raw);
date.setUTCHours(8);
return {
raw: date.toISOString().split('T')[0],
time: +date,
formatted: format(date, 'yyyy/MM/dd'),
since: formatDistance(date, new Date(), { addSuffix: true }),
};
}
const data = [] as Post[];
export { data };
export default createContentLoader('blog/*.md', {
includeSrc: true,
transform(raw) {
return raw
.filter(item => item.url !== '/blog/')
.map(({ url, frontmatter }) => ({
title: frontmatter.title,
authors: frontmatter.authors ?? [],
excerpt: frontmatter.excerpt ?? '',
url,
date: formatDate(frontmatter.date),
}))
.sort((a, b) => b.date.time - a.date.time);
},
});
@@ -0,0 +1,19 @@
import { useRoute } from 'vitepress';
import { computed } from 'vue';
import { data as posts } from './posts.data';
export function usePosts() {
const route = useRoute();
const path = route.path;
function findCurrentIndex() {
const result = posts.findIndex(p => p.url === route.path);
if (result === -1) console.error(`blog post missing: ${route.path}`);
return result;
}
const post = computed(() => posts[findCurrentIndex()]);
return { posts, post, path };
}
@@ -0,0 +1,29 @@
// https://vitepress.dev/guide/custom-theme
import 'vitepress-plugin-sandpack/dist/style.css';
import './style.css';
import Theme from 'vitepress/theme';
import { h } from 'vue';
import BlogListLayout from './components/blog-list-layout.vue';
import BlogPostMeta from './components/blog-post-meta.vue';
import CodeSandbox from './components/code-sandbox.vue';
import HeroLogo from './components/hero-logo.vue';
import Icon from './components/icon.vue';
export default {
...Theme,
Layout: () => {
return h(Theme.Layout, null, {
// https://vitepress.dev/guide/extending-default-theme#layout-slots
'home-hero-image': () => h(HeroLogo),
// 'home-features-after': () => h(Playground),
});
},
enhanceApp({ app }) {
app.component('Icon', Icon);
app.component('BlogListLayout', BlogListLayout);
app.component('BlogPostMeta', BlogPostMeta);
app.component('CodeSandbox', CodeSandbox);
},
};
@@ -0,0 +1,226 @@
/**
* Customize default theme styling by overriding CSS variables:
* https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css
*/
/**
* Colors
* -------------------------------------------------------------------------- */
:root {
--vp-c-brand: #646cff;
--vp-c-brand-light: #747bff;
--vp-c-brand-lighter: #9499ff;
--vp-c-brand-lightest: #bcc0ff;
--vp-c-brand-dark: #535bf2;
--vp-c-brand-darker: #454ce1;
--vp-c-brand-dimm: rgba(100, 108, 255, 0.08);
}
/**
* Component: Button
* -------------------------------------------------------------------------- */
:root {
--vp-button-brand-border: var(--vp-c-brand-light);
--vp-button-brand-text: var(--vp-c-white);
--vp-button-brand-bg: var(--vp-c-brand);
--vp-button-brand-hover-border: var(--vp-c-brand-light);
--vp-button-brand-hover-text: var(--vp-c-white);
--vp-button-brand-hover-bg: var(--vp-c-brand-light);
--vp-button-brand-active-border: var(--vp-c-brand-light);
--vp-button-brand-active-text: var(--vp-c-white);
--vp-button-brand-active-bg: var(--vp-button-brand-bg);
}
/**
* Component: Home
* -------------------------------------------------------------------------- */
:root {
--vp-home-hero-name-color: transparent;
--vp-home-hero-name-background: -webkit-linear-gradient(
120deg,
#bd34fe 30%,
#41d1ff
);
--vp-home-hero-image-background-image: linear-gradient(
-45deg,
#bd34fe 50%,
#47caff 50%
);
--vp-home-hero-image-filter: blur(40px);
}
@media (min-width: 640px) {
:root {
--vp-home-hero-image-filter: blur(56px);
}
}
@media (min-width: 960px) {
:root {
--vp-home-hero-image-filter: blur(72px);
}
}
/**
* Component: Custom Block
* -------------------------------------------------------------------------- */
:root {
--vp-custom-block-tip-border: var(--vp-c-brand);
--vp-custom-block-tip-text: var(--vp-c-brand-darker);
--vp-custom-block-tip-bg: var(--vp-c-brand-dimm);
}
.dark {
--vp-custom-block-tip-border: var(--vp-c-brand);
--vp-custom-block-tip-text: var(--vp-c-brand-lightest);
--vp-custom-block-tip-bg: var(--vp-c-brand-dimm);
}
/**
* Component: Algolia
* -------------------------------------------------------------------------- */
.DocSearch {
--docsearch-primary-color: var(--vp-c-brand) !important;
}
/**
* VitePress: Custom fix
* -------------------------------------------------------------------------- */
/*
Use lighter colors for links in dark mode for a11y.
Also specify some classes twice to have higher specificity
over scoped class data attribute.
*/
.dark .vp-doc a,
.dark .vp-doc a > code,
.dark .VPNavBarMenuLink.VPNavBarMenuLink:hover,
.dark .VPNavBarMenuLink.VPNavBarMenuLink.active,
.dark .link.link:hover,
.dark .link.link.active,
.dark .edit-link-button.edit-link-button,
.dark .pager-link .title {
color: var(--vp-c-brand-lighter);
}
.dark .vp-doc a:hover,
.dark .vp-doc a > code:hover {
color: var(--vp-c-brand-lightest);
opacity: 1;
}
/* Transition by color instead of opacity */
.dark .vp-doc .custom-block a {
transition: color 0.25s;
}
html[class='dark'] {
--affine-theme-mode: dark;
--affine-popover-shadow:
0px 1px 10px -6px rgba(24, 39, 75, 0.08),
0px 3px 16px -6px rgba(24, 39, 75, 0.04);
--affine-font-h-1: 28px;
--affine-font-h-2: 26px;
--affine-font-h-3: 24px;
--affine-font-h-4: 22px;
--affine-font-h-5: 20px;
--affine-font-h-6: 18px;
--affine-font-base: 16px;
--affine-font-sm: 14px;
--affine-font-xs: 12px;
--affine-line-height: calc(1em + 8px);
--affine-z-index-modal: 1000;
--affine-z-index-popover: 1000;
--affine-font-family:
Avenir Next, Poppins, apple-system, BlinkMacSystemFont, Helvetica Neue,
Tahoma, PingFang SC, Microsoft Yahei, Arial, Hiragino Sans GB, sans-serif,
Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
--affine-font-number-family:
Roboto Mono, apple-system, BlinkMacSystemFont, Helvetica Neue, Tahoma,
PingFang SC, Microsoft Yahei, Arial, Hiragino Sans GB, sans-serif,
Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
--affine-font-code-family:
Space Mono, Consolas, Menlo, Monaco, Courier, monospace, apple-system,
BlinkMacSystemFont, Helvetica Neue, Tahoma, PingFang SC, Microsoft Yahei,
Arial, Hiragino Sans GB, sans-serif, Apple Color Emoji, Segoe UI Emoji,
Segoe UI Symbol, Noto Color Emoji;
--affine-paragraph-space: 8px;
--affine-popover-radius: 10px;
--affine-zoom: 1;
--affine-scale: calc(1 / var(--affine-zoom));
--affine-brand-color: rgb(84, 56, 255);
--affine-primary-color: rgb(118, 95, 254);
--affine-secondary-color: rgb(144, 150, 245);
--affine-tertiary-color: rgb(30, 30, 30);
--affine-hover-color: rgba(255, 255, 255, 0.1);
--affine-icon-color: rgb(168, 168, 160);
--affine-border-color: rgb(57, 57, 57);
--affine-divider-color: rgb(114, 114, 114);
--affine-placeholder-color: rgb(62, 62, 63);
--affine-quote-color: rgb(100, 95, 130);
--affine-link-color: rgb(185, 191, 227);
--affine-edgeless-grid-color: rgb(49, 49, 49);
--affine-success-color: rgb(77, 213, 181);
--affine-warning-color: rgb(255, 123, 77);
--affine-error-color: rgb(212, 140, 130);
--affine-processing-color: rgb(195, 215, 255);
--affine-text-emphasis-color: rgb(208, 205, 220);
--affine-text-primary-color: rgb(234, 234, 234);
--affine-text-secondary-color: rgb(156, 156, 160);
--affine-text-disable-color: rgb(119, 117, 125);
--affine-black-10: rgba(255, 255, 255, 0.1);
--affine-black-30: rgba(255, 255, 255, 0.3);
--affine-black-50: rgba(255, 255, 255, 0.5);
--affine-black-60: rgba(255, 255, 255, 0.6);
--affine-black-80: rgba(255, 255, 255, 0.8);
--affine-black-90: rgba(255, 255, 255, 0.9);
--affine-black: rgb(255, 255, 255);
--affine-white-10: rgba(0, 0, 0, 0.1);
--affine-white-30: rgba(0, 0, 0, 0.3);
--affine-white-50: rgba(0, 0, 0, 0.5);
--affine-white-60: rgba(0, 0, 0, 0.6);
--affine-white-80: rgba(0, 0, 0, 0.8);
--affine-white-90: rgba(0, 0, 0, 0.9);
--affine-white: rgb(0, 0, 0);
--affine-background-code-block: rgb(41, 44, 51);
--affine-background-tertiary-color: rgb(30, 30, 30);
--affine-background-processing-color: rgb(255, 255, 255);
--affine-background-error-color: rgb(255, 255, 255);
--affine-background-warning-color: rgb(255, 255, 255);
--affine-background-success-color: rgb(255, 255, 255);
--affine-background-primary-color: rgb(20, 20, 20);
--affine-background-hover-color: rgb(47, 47, 47);
--affine-background-secondary-color: rgb(32, 32, 32);
--affine-background-modal-color: rgba(0, 0, 0, 0.8);
--affine-background-overlay-panel-color: rgb(30, 30, 30);
--affine-tag-blue: rgb(10, 84, 170);
--affine-tag-green: rgb(55, 135, 79);
--affine-tag-teal: rgb(33, 145, 138);
--affine-tag-white: rgb(84, 84, 84);
--affine-tag-purple: rgb(59, 38, 141);
--affine-tag-red: rgb(139, 63, 63);
--affine-tag-pink: rgb(194, 132, 132);
--affine-tag-yellow: rgb(187, 165, 61);
--affine-tag-orange: rgb(231, 161, 58);
--affine-tag-gray: rgb(41, 41, 41);
--affine-palette-yellow: rgb(255, 232, 56);
--affine-palette-orange: rgb(255, 175, 56);
--affine-palette-tangerine: rgb(255, 99, 31);
--affine-palette-red: rgb(252, 63, 85);
--affine-palette-magenta: rgb(255, 56, 179);
--affine-palette-purple: rgb(182, 56, 255);
--affine-palette-navy: rgb(59, 37, 204);
--affine-palette-blue: rgb(79, 144, 255);
--affine-palette-green: rgb(16, 203, 134);
--affine-palette-grey: rgb(153, 153, 153);
--affine-palette-white: rgb(255, 255, 255);
--affine-palette-black: rgb(0, 0, 0);
}