-
-
-
-
-
diff --git a/.vitepress/theme/components/Environment.vue b/.vitepress/theme/components/Environment.vue
index 64b4cbb..5283e69 100644
--- a/.vitepress/theme/components/Environment.vue
+++ b/.vitepress/theme/components/Environment.vue
@@ -1,17 +1,22 @@
+<<<<<<< HEAD
Окружение:
{{ type }}
+=======
+
+
+ Environment:
+ {{ type }}
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
-
+
Эта функция настройки будет работать только на стороне Node.js, вы также можете получить доступ к API Node.
diff --git a/.vitepress/theme/components/Home.vue b/.vitepress/theme/components/Home.vue
deleted file mode 100644
index 59b6eff..0000000
--- a/.vitepress/theme/components/Home.vue
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
diff --git a/.vitepress/theme/components/Tweet.vue b/.vitepress/theme/components/TheTweet.vue
similarity index 63%
rename from .vitepress/theme/components/Tweet.vue
rename to .vitepress/theme/components/TheTweet.vue
index 1dd52a1..f822111 100644
--- a/.vitepress/theme/components/Tweet.vue
+++ b/.vitepress/theme/components/TheTweet.vue
@@ -1,14 +1,14 @@
-
-
-
-
-
+
+
+
+
+
+
-
diff --git a/.vitepress/theme/components/ThemeGallery.vue b/.vitepress/theme/components/ThemeGallery.vue
index 57d159c..ee92e0c 100644
--- a/.vitepress/theme/components/ThemeGallery.vue
+++ b/.vitepress/theme/components/ThemeGallery.vue
@@ -1,10 +1,10 @@
-
-
diff --git a/.vitepress/theme/components/icons/ArrowLeft.vue b/.vitepress/theme/components/icons/ArrowLeft.vue
deleted file mode 100644
index 3f64f1a..0000000
--- a/.vitepress/theme/components/icons/ArrowLeft.vue
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
diff --git a/.vitepress/theme/components/icons/ArrowRight.vue b/.vitepress/theme/components/icons/ArrowRight.vue
deleted file mode 100644
index 19d2186..0000000
--- a/.vitepress/theme/components/icons/ArrowRight.vue
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
diff --git a/.vitepress/theme/components/icons/Moon.vue b/.vitepress/theme/components/icons/Moon.vue
deleted file mode 100644
index 69567db..0000000
--- a/.vitepress/theme/components/icons/Moon.vue
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
diff --git a/.vitepress/theme/components/icons/OutboundLink.vue b/.vitepress/theme/components/icons/OutboundLink.vue
deleted file mode 100644
index 4d74eee..0000000
--- a/.vitepress/theme/components/icons/OutboundLink.vue
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
diff --git a/.vitepress/theme/components/icons/README.md b/.vitepress/theme/components/icons/README.md
deleted file mode 100644
index 58b1801..0000000
--- a/.vitepress/theme/components/icons/README.md
+++ /dev/null
@@ -1 +0,0 @@
-Download from https://icones.js.org/collection/carbon
diff --git a/.vitepress/theme/components/icons/Sun.vue b/.vitepress/theme/components/icons/Sun.vue
deleted file mode 100644
index 9cd6bdf..0000000
--- a/.vitepress/theme/components/icons/Sun.vue
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
diff --git a/.vitepress/theme/composables/activeSidebarLink.ts b/.vitepress/theme/composables/activeSidebarLink.ts
deleted file mode 100644
index 9cf3aba..0000000
--- a/.vitepress/theme/composables/activeSidebarLink.ts
+++ /dev/null
@@ -1,131 +0,0 @@
-import { onMounted, onUnmounted, onUpdated } from 'vue-demi'
-
-export function useActiveSidebarLinks() {
- let rootActiveLink: HTMLAnchorElement | null = null
- let activeLink: HTMLAnchorElement | null = null
-
- const onScroll = throttleAndDebounce(setActiveLink, 300)
-
- function setActiveLink(): void {
- const sidebarLinks = getSidebarLinks()
- const anchors = getAnchors(sidebarLinks)
-
- for (let i = 0; i < anchors.length; i++) {
- const anchor = anchors[i]
- const nextAnchor = anchors[i + 1]
-
- const [isActive, hash] = isAnchorActive(i, anchor, nextAnchor)
-
- if (isActive) {
- history.replaceState(null, document.title, hash || ' ')
- activateLink(hash)
- return
- }
- }
- }
-
- function activateLink(hash: string | null): void {
- deactiveLink(activeLink)
- deactiveLink(rootActiveLink)
-
- activeLink = document.querySelector(`.sidebar a[href="${hash}"]`)
-
- if (!activeLink)
- return
-
- activeLink.classList.add('active')
-
- // also add active class to parent h2 anchors
- const rootLi = activeLink.closest('.sidebar-links > ul > li')
-
- if (rootLi && rootLi !== activeLink.parentElement) {
- rootActiveLink = rootLi.querySelector('a')
- rootActiveLink && rootActiveLink.classList.add('active')
- }
- else {
- rootActiveLink = null
- }
- }
-
- function deactiveLink(link: HTMLAnchorElement | null): void {
- link && link.classList.remove('active')
- }
-
- onMounted(() => {
- setActiveLink()
- window.addEventListener('scroll', onScroll)
- })
-
- onUpdated(() => {
- // sidebar update means a route change
- activateLink(decodeURIComponent(location.hash))
- })
-
- onUnmounted(() => {
- window.removeEventListener('scroll', onScroll)
- })
-}
-
-function getSidebarLinks(): HTMLAnchorElement[] {
- return [].slice.call(
- document.querySelectorAll('.sidebar a.sidebar-link-item'),
- )
-}
-
-function getAnchors(sidebarLinks: HTMLAnchorElement[]): HTMLAnchorElement[] {
- return [].slice
- .call(document.querySelectorAll('.header-anchor'))
- .filter((anchor: HTMLAnchorElement) =>
- sidebarLinks.some(sidebarLink => sidebarLink.hash === anchor.hash),
- ) as HTMLAnchorElement[]
-}
-
-function getPageOffset(): number {
- return (document.querySelector('.nav-bar') as HTMLElement).offsetHeight
-}
-
-function getAnchorTop(anchor: HTMLAnchorElement): number {
- const pageOffset = getPageOffset()
-
- return anchor.parentElement!.offsetTop - pageOffset - 15
-}
-
-function isAnchorActive(
- index: number,
- anchor: HTMLAnchorElement,
- nextAnchor: HTMLAnchorElement,
-): [boolean, string | null] {
- const scrollTop = window.scrollY
-
- if (index === 0 && scrollTop === 0)
- return [true, null]
-
- if (scrollTop < getAnchorTop(anchor))
- return [false, null]
-
- if (!nextAnchor || scrollTop < getAnchorTop(nextAnchor))
- return [true, decodeURIComponent(anchor.hash)]
-
- return [false, null]
-}
-
-function throttleAndDebounce(fn: () => void, delay: number): () => void {
- let timeout: NodeJS.Timeout
- let called = false
-
- return () => {
- if (timeout)
- clearTimeout(timeout)
-
- if (!called) {
- fn()
- called = true
- setTimeout(() => {
- called = false
- }, delay)
- }
- else {
- timeout = setTimeout(fn, delay)
- }
- }
-}
diff --git a/.vitepress/theme/composables/editLink.ts b/.vitepress/theme/composables/editLink.ts
deleted file mode 100644
index f2a3114..0000000
--- a/.vitepress/theme/composables/editLink.ts
+++ /dev/null
@@ -1,90 +0,0 @@
-import { computed } from 'vue-demi'
-import { useSiteDataByRoute, usePageData } from 'vitepress'
-import { endingSlashRE, isNullish, isExternal } from '../utils'
-
-const bitbucketRE = /bitbucket.org/
-
-export function useEditLink() {
- const site = useSiteDataByRoute()
- const page = usePageData()
-
- const url = computed(() => {
- const showEditLink = isNullish(page.value.frontmatter.editLink)
- ? site.value.themeConfig.editLinks
- : page.value.frontmatter.editLink
-
- const {
- repo,
- docsDir = '',
- docsBranch = 'main',
- docsRepo = repo,
- } = site.value.themeConfig
-
- const { relativePath } = page.value
-
- if (!showEditLink || !relativePath || !repo)
- return null
-
- return createUrl(repo, docsRepo, docsDir, docsBranch, relativePath)
- })
-
- const text = computed(() => {
- return site.value.themeConfig.editLinkText || 'Edit this page'
- })
-
- return {
- url,
- text,
- }
-}
-
-function createUrl(
- repo: string,
- docsRepo: string,
- docsDir: string,
- docsBranch: string,
- path: string,
-): string {
- return bitbucketRE.test(repo)
- ? createBitbucketUrl(repo, docsRepo, docsDir, docsBranch, path)
- : createGitHubUrl(repo, docsRepo, docsDir, docsBranch, path)
-}
-
-function createGitHubUrl(
- repo: string,
- docsRepo: string,
- docsDir: string,
- docsBranch: string,
- path: string,
-): string {
- const base = isExternal(docsRepo)
- ? docsRepo
- : `https://github.com/${docsRepo}`
-
- return (
- `${base.replace(endingSlashRE, '')
- }/edit`
- + `/${docsBranch}/${
- docsDir ? `${docsDir.replace(endingSlashRE, '')}/` : ''
- }${path}`
- )
-}
-
-function createBitbucketUrl(
- repo: string,
- docsRepo: string,
- docsDir: string,
- docsBranch: string,
- path: string,
-): string {
- const base = isExternal(docsRepo) ? docsRepo : repo
-
- return (
- `${base.replace(endingSlashRE, '')
- }/src`
- + `/${docsBranch}/${
- docsDir ? `${docsDir.replace(endingSlashRE, '')}/` : ''
- }${path
- }?mode=edit&spa=0&at=${docsBranch}&fileviewer=file-view-default`
- )
-}
diff --git a/.vitepress/theme/composables/nav.ts b/.vitepress/theme/composables/nav.ts
deleted file mode 100644
index 4097a41..0000000
--- a/.vitepress/theme/composables/nav.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import { computed } from 'vue-demi'
-import { useRoute, useSiteData, inBrowser } from 'vitepress'
-import type { DefaultTheme } from '../config'
-
-export function useLocaleLinks() {
- const route = useRoute()
- const site = useSiteData()
-
- return computed(() => {
- const theme = site.value.themeConfig as DefaultTheme.Config
- const locales = theme.locales
-
- if (!locales)
- return null
-
- const localeKeys = Object.keys(locales)
-
- if (localeKeys.length <= 1)
- return null
-
- // handle site base
- const siteBase = inBrowser ? site.value.base : '/'
-
- const siteBaseWithoutSuffix = siteBase.endsWith('/')
- ? siteBase.slice(0, -1)
- : siteBase
-
- // remove site base in browser env
- const routerPath = route.path.slice(siteBaseWithoutSuffix.length)
-
- const currentLangBase = localeKeys.find((key) => {
- return key === '/' ? false : routerPath.startsWith(key)
- })
-
- const currentContentPath = currentLangBase
- ? routerPath.substring(currentLangBase.length - 1)
- : routerPath
-
- const candidates = localeKeys.map((v) => {
- const localePath = v.endsWith('/') ? v.slice(0, -1) : v
-
- return {
- text: locales[v].label,
- link: `${localePath}${currentContentPath}`,
- }
- })
-
- const currentLangKey = currentLangBase || '/'
-
- const selectText = locales[currentLangKey].selectText
- ? locales[currentLangKey].selectText
- : 'Languages'
-
- return {
- text: selectText,
- items: candidates,
- } as DefaultTheme.NavItemWithChildren
- })
-}
diff --git a/.vitepress/theme/composables/navLink.ts b/.vitepress/theme/composables/navLink.ts
deleted file mode 100644
index 2bf3172..0000000
--- a/.vitepress/theme/composables/navLink.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import { computed, Ref } from 'vue-demi'
-import { useRoute } from 'vitepress'
-import type { DefaultTheme } from '../config'
-import { isExternal as isExternalCheck } from '../utils'
-import { useUrl } from '../composables/url'
-
-export function useNavLink(item: Ref) {
- const route = useRoute()
- const { withBase } = useUrl()
-
- const isExternal = isExternalCheck(item.value.link)
-
- const props = computed(() => {
- const link = interpret(item.value.link)
- const routePath = normalizePath(`/${route.data.relativePath}`)
-
- let active = false
- if (item.value.activeMatch) {
- active = new RegExp(item.value.activeMatch).test(routePath)
- }
- else {
- const itemPath = normalizePath(withBase(link))
- active
- = itemPath === '/'
- ? itemPath === routePath
- : routePath.startsWith(itemPath)
- }
-
- return {
- 'class': {
- active,
- isExternal,
- },
- 'href': isExternal ? link : withBase(link),
- 'target': item.value.target || isExternal ? '_blank' : null,
- 'rel': item.value.rel || isExternal ? 'noopener noreferrer' : null,
- 'aria-label': item.value.ariaLabel,
- }
- })
-
- return {
- props,
- isExternal,
- }
-}
-
-function interpret(path = '') {
- return path
- .replace(/{{pathname}}/, typeof window === 'undefined' ? '/' : location.pathname)
-}
-
-function normalizePath(path: string): string {
- return path
- .replace(/#.*$/, '')
- .replace(/\?.*$/, '')
- .replace(/\.(html|md)$/, '')
- .replace(/\/index$/, '/')
-}
diff --git a/.vitepress/theme/composables/nextAndPrevLinks.ts b/.vitepress/theme/composables/nextAndPrevLinks.ts
deleted file mode 100644
index 2b20c28..0000000
--- a/.vitepress/theme/composables/nextAndPrevLinks.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import { computed } from 'vue-demi'
-import { useSiteDataByRoute, usePageData } from 'vitepress'
-import { isArray, ensureStartingSlash } from '../utils'
-import { getSideBarConfig, getFlatSideBarLinks } from '../support/sideBar'
-
-export function useNextAndPrevLinks() {
- const site = useSiteDataByRoute()
- const page = usePageData()
-
- const path = computed(() => {
- return ensureStartingSlash(page.value.relativePath)
- })
-
- const candidates = computed(() => {
- const config = getSideBarConfig(site.value.themeConfig.sidebar, path.value)
-
- return isArray(config) ? getFlatSideBarLinks(config) : []
- })
-
- const index = computed(() => {
- return candidates.value.findIndex((item) => {
- return item.link === path.value
- })
- })
-
- const next = computed(() => {
- if (
- site.value.themeConfig.nextLinks !== false
- && index.value > -1
- && index.value < candidates.value.length - 1
- )
- return candidates.value[index.value + 1]
- })
-
- const prev = computed(() => {
- if (site.value.themeConfig.prevLinks !== false && index.value > 0)
- return candidates.value[index.value - 1]
- })
-
- const hasLinks = computed(() => !!next.value || !!prev.value)
-
- return {
- next,
- prev,
- hasLinks,
- }
-}
diff --git a/.vitepress/theme/composables/repo.ts b/.vitepress/theme/composables/repo.ts
deleted file mode 100644
index d0909df..0000000
--- a/.vitepress/theme/composables/repo.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import { computed } from 'vue-demi'
-import { useSiteDataByRoute } from 'vitepress'
-import type { DefaultTheme } from '../config'
-
-export const platforms = ['GitHub', 'GitLab', 'Bitbucket'].map((platform) => {
- return [platform, new RegExp(platform, 'i')] as const
-})
-
-export function useRepo() {
- const site = useSiteDataByRoute()
-
- return computed(() => {
- const theme = site.value.themeConfig as DefaultTheme.Config
- const name = theme.docsRepo || theme.repo
-
- if (!name)
- return null
-
- const link = getRepoUrl(name)
- const text = getRepoText(link, theme.repoLabel)
-
- return { text, link }
- })
-}
-
-function getRepoUrl(repo: string): string {
- // if the full url is not provided, default to GitHub repo
- return /^https?:/.test(repo) ? repo : `https://github.com/${repo}`
-}
-
-function getRepoText(url: string, text?: string): string {
- if (text)
- return text
-
- // if no label is provided, deduce it from the repo url
- const hosts = url.match(/^https?:\/\/[^/]+/)
-
- if (!hosts)
- return 'Source'
-
- const platform = platforms.find(([, re]) => re.test(hosts[0]))
-
- if (platform && platform[0])
- return platform[0]
-
- return 'Source'
-}
diff --git a/.vitepress/theme/composables/sideBar.ts b/.vitepress/theme/composables/sideBar.ts
deleted file mode 100644
index 0384769..0000000
--- a/.vitepress/theme/composables/sideBar.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-import { computed } from 'vue-demi'
-import { useRoute, useSiteDataByRoute } from 'vitepress'
-// import { Header } from '/@types/shared'
-import { useActiveSidebarLinks } from '../composables/activeSidebarLink'
-import { getSideBarConfig } from '../support/sideBar'
-import { DefaultTheme } from '../config'
-
-export function useSideBar() {
- const route = useRoute()
- const site = useSiteDataByRoute()
-
- useActiveSidebarLinks()
-
- return computed(() => {
- // at first, we'll check if we can find the sidebar setting in frontmatter.
- const headers = route.data.headers
- const frontSidebar = route.data.frontmatter.sidebar
- const sidebarDepth = route.data.frontmatter.sidebarDepth
-
- // if it's `false`, we'll just return an empty array here.
- if (frontSidebar === false)
- return []
-
- // if it's `atuo`, render headers of the current page
- if (frontSidebar === 'auto')
- return resolveAutoSidebar(headers, sidebarDepth)
-
- // now, there's no sidebar setting at frontmatter; let's see the configs
- const themeSidebar = getSideBarConfig(
- site.value.themeConfig.sidebar,
- route.path,
- )
-
- if (themeSidebar === false)
- return []
-
- if (themeSidebar === 'auto')
- return resolveAutoSidebar(headers, sidebarDepth)
-
- return themeSidebar
- })
-}
-
-function resolveAutoSidebar(
- headers: any[],
- depth: number,
-): DefaultTheme.SideBarItem[] {
- const ret: DefaultTheme.SideBarItem[] = []
-
- if (headers === undefined)
- return []
-
- let lastH2: DefaultTheme.SideBarItem | undefined
- headers.forEach(({ level, title, slug }) => {
- if (level - 1 > depth)
- return
-
- const item: DefaultTheme.SideBarItem = {
- text: title,
- link: `#${slug}`,
- }
- if (level === 2) {
- lastH2 = item
- ret.push(item)
- }
- else if (lastH2) {
- ((lastH2 as any).children || ((lastH2 as any).children = [])).push(item)
- }
- })
-
- return ret
-}
diff --git a/.vitepress/theme/composables/url.ts b/.vitepress/theme/composables/url.ts
deleted file mode 100644
index 7ea91fc..0000000
--- a/.vitepress/theme/composables/url.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { useSiteData, joinPath } from 'vitepress'
-
-export function useUrl() {
- const site = useSiteData()
-
- function withBase(path: string): string {
- if (!path)
- return ''
- return joinPath(site.value.base, path)
- }
-
- return {
- withBase,
- }
-}
diff --git a/.vitepress/theme/composables/versions.ts b/.vitepress/theme/composables/versions.ts
deleted file mode 100644
index 28c22ce..0000000
--- a/.vitepress/theme/composables/versions.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from '../../../../meta/packages'
diff --git a/.vitepress/theme/config.ts b/.vitepress/theme/config.ts
deleted file mode 100644
index 408f30f..0000000
--- a/.vitepress/theme/config.ts
+++ /dev/null
@@ -1,129 +0,0 @@
-/* eslint-disable no-use-before-define */
-/* eslint-disable @typescript-eslint/no-namespace */
-
-export namespace DefaultTheme {
- export interface Config {
- logo?: string
- nav?: NavItem[] | false
- sidebar?: SideBarConfig | MultiSideBarConfig
-
- /**
- * GitHub repository following the format /.
- *
- * @example `"vuejs/vue-next"`
- */
- repo?: string
-
- /**
- * Customize the header label. Defaults to GitHub/Gitlab/Bitbucket
- * depending on the provided repo.
- *
- * @exampe `"Contribute!"`
- */
- repoLabel?: string
-
- /**
- * If your docs are in a different repository from your main project.
- *
- * @example `"vuejs/docs-next"`
- */
- docsRepo?: string
-
- /**
- * If your docs are not at the root of the repo.
- *
- * @example `"docs"`
- */
- docsDir?: string
-
- /**
- * If your docs are in a different branch. Defaults to `main`.
- *
- * @example `"next"`
- */
- docsBranch?: string
-
- /**
- * Enable links to edit pages at the bottom of the page.
- */
- editLinks?: boolean
-
- /**
- * Custom text for edit link. Defaults to "Edit this page".
- */
- editLinkText?: string
-
- /**
- * Show last updated time at the bottom of the page. Defaults to `false`.
- * If given a string, it will be displayed as a prefix (default value:
- * "Last Updated").
- */
- lastUpdated?: string | boolean
-
- prevLinks?: boolean
- nextLinks?: boolean
-
- locales?: Record>
- }
-
- // navbar --------------------------------------------------------------------
-
- export type NavItem = NavItemWithLink | NavItemWithChildren
-
- export interface NavItemBase {
- text: string
- target?: string
- rel?: string
- ariaLabel?: string
- activeMatch?: string
- }
-
- export interface NavItemWithLink extends NavItemBase {
- link: string
- }
-
- export interface NavItemWithChildren extends NavItemBase {
- items: NavItemWithLink[]
- }
-
- // sidebar -------------------------------------------------------------------
-
- export type SideBarConfig = SideBarItem[] | 'auto' | false
-
- export interface MultiSideBarConfig {
- [path: string]: SideBarConfig
- }
-
- export type SideBarItem = SideBarLink | SideBarGroup
-
- export interface SideBarLink {
- text: string
- link: string
- }
-
- export interface SideBarGroup {
- text: string
- link?: string
-
- /**
- * @default false
- */
- collapsable?: boolean
-
- children: SideBarItem[]
- }
-
- // locales -------------------------------------------------------------------
-
- export interface LocaleConfig {
- /**
- * Text for the language dropdown.
- */
- selectText?: string
-
- /**
- * Label for this locale in the language dropdown.
- */
- label?: string
- }
-}
diff --git a/.vitepress/theme/index.ts b/.vitepress/theme/index.ts
index 5e15d50..aed8830 100644
--- a/.vitepress/theme/index.ts
+++ b/.vitepress/theme/index.ts
@@ -1,18 +1,16 @@
-import Layout from './Layout.vue'
-import NotFound from './NotFound.vue'
+import Theme from 'vitepress/theme'
+import type { EnhanceAppContext } from 'vitepress'
+import TwoSlash from '@shikijs/vitepress-twoslash/client'
-import 'windi-base.css'
-import 'windi-components.css'
+import '@shikijs/vitepress-twoslash/style.css'
import './styles/vars.css'
-import './styles/layout.css'
-import './styles/code.css'
-import './styles/custom-blocks.css'
-import './styles/sidebar-links.css'
-import 'windi-utilities.css'
+import './styles/demo.css'
+import './styles/custom.css'
+import 'uno.css'
-const theme = {
- Layout,
- NotFound,
+export default {
+ extends: Theme,
+ enhanceApp({ app }: EnhanceAppContext) {
+ app.use(TwoSlash as any)
+ },
}
-
-export default theme
diff --git a/.vitepress/theme/styles/code.css b/.vitepress/theme/styles/code.css
deleted file mode 100644
index 218eb9f..0000000
--- a/.vitepress/theme/styles/code.css
+++ /dev/null
@@ -1,120 +0,0 @@
-/* https://github.com/antfu/prism-theme-vars */
-@import 'prism-theme-vars/base.css';
-@import 'prism-theme-vars/marker.css';
-
-:root {
- --prism-font-family: var(--font-family-mono);
- --prism-font-size: 0.85rem;
- --prism-marker-opacity: 0;
-}
-
-html:not(.dark) {
- --prism-foreground: #393a34;
- --prism-background: #fafafa;
- --prism-inline-background: #f5f5f5;
- --prism-comment: #a0ada0;
- --prism-string: #b56959;
- --prism-literal: #2f8a89;
- --prism-number: #296aa3;
- --prism-keyword: #1c6b48;
- --prism-function: #6c7834;
- --prism-boolean: #296aa3;
- --prism-constant: #a65e2b;
- --prism-deleted: #a14f55;
- --prism-class: #2993a3;
- --prism-builtin: #ab5959;
- --prism-property: #b58451;
- --prism-namespace: #b05a78;
- --prism-punctuation: #8e8f8b;
- --prism-decorator: #bd8f8f;
- --prism-regex: #ab5e3f;
- --prism-json-property: #698c96;
-}
-
-html.dark {
- --prism-scheme: dark;
- --prism-foreground: #d4cfbf;
- --prism-background: #181818;
- --prism-comment: #758575;
- --prism-string: #d48372;
- --prism-literal: #429988;
- --prism-keyword: #4d9375;
- --prism-boolean: #6394bf;
- --prism-number: #6394bf;
- --prism-variable: #c2b36e;
- --prism-function: #a1b567;
- --prism-deleted: #bc6066;
- --prism-class: #54b1bf;
- --prism-builtin: #e0a569;
- --prism-property: #dd8e6e;
- --prism-namespace: #db889a;
- --prism-punctuation: #858585;
- --prism-decorator: #bd8f8f;
- --prism-regex: #ab5e3f;
- --prism-json-property: #6b8b9e;
- --prism-line-number: #888888;
- --prism-line-number-gutter: #eeeeee;
- --prism-line-highlight-background: #444444;
- --prism-selection-background: #444444;
- --prism-inline-background: theme('colors.dark.300');
-}
-
-
-.token.title {
- color: var(--prism-keyword);
-}
-
-/* Overrides */
-
-pre, code {
- @apply font-mono;
-}
-
-:not(pre) > code {
- background: var(--prism-inline-background);
- padding: 1px 6px;
- border-radius: 3px;
-}
-
-a > code {
- color: var(--c-brand-dark);
-}
-
-div[class*='language-'] {
- position: relative;
-}
-
-div[class*='language-'] pre {
- margin: 0;
- z-index: 1;
-}
-
-div[class*='language-'] code {
- font-size: var(--prism-font-size);
- font-family: var(--prism-font-family);
-}
-
-.token.important {
- font-weight: normal;
-}
-
-/* Line highlighting */
-
-.highlight-lines {
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- padding: var(--prism-block-padding-y) 0;
- width: 100%;
- line-height: var(--prism-line-height);
- font-family: var(--prism-font-family);
- font-size: var(--prism-font-size);
- user-select: none;
- overflow: hidden;
- z-index: -1;
-}
-
-.highlight-lines .highlighted {
- background-color: var(--prism-line-highlight-background);
-}
diff --git a/.vitepress/theme/styles/custom-blocks.css b/.vitepress/theme/styles/custom-blocks.css
deleted file mode 100644
index d65bea1..0000000
--- a/.vitepress/theme/styles/custom-blocks.css
+++ /dev/null
@@ -1,67 +0,0 @@
-.custom-block.tip,
-.custom-block.warning,
-.custom-block.danger {
- margin: 2rem 0 1rem 0;
- border-left: .5rem solid;
- padding: .1rem 1.5rem;
- overflow-x: auto;
-}
-
-.custom-block.tip {
- background-color: var(--c-bg-secondary);
- border-color: #42b983;
-}
-
-.custom-block.warning {
- border-color: #e7c000;
- background-color: rgba(255, 229, 100, .3);
-}
-
-.custom-block.warning .custom-block-title {
- color: #b29400;
-}
-
-.custom-block.warning a {
- color: var(--c-text);
-}
-
-.custom-block.danger {
- border-color: #c00;
- background-color: #ffe6e6;
-}
-
-.custom-block.danger .custom-block-title {
- color: #900;
-}
-
-.custom-block.danger a {
- color: var(--c-text);
-}
-
-.custom-block.details {
- position: relative;
- display: block;
- border-radius: 2px;
- margin: 1.6em 0;
- padding: 1.6em;
- background-color: #eee;
-}
-
-.custom-block.details h4 {
- margin-top: 0;
-}
-
-.custom-block.details figure:last-child,
-.custom-block.details p:last-child {
- margin-bottom: 0;
- padding-bottom: 0;
-}
-
-.custom-block.details summary {
- outline: none;
- cursor: pointer;
-}
-
-.custom-block-title {
- display: none;
-}
diff --git a/.vitepress/theme/styles/custom.css b/.vitepress/theme/styles/custom.css
new file mode 100644
index 0000000..45d334d
--- /dev/null
+++ b/.vitepress/theme/styles/custom.css
@@ -0,0 +1,19 @@
+.icon-btn {
+ --uno: inline-block cursor-pointer select-none important-outline-none;
+ --uno: opacity-75 transition duration-200 ease-in-out align-middle rounded p-2;
+ --uno: hover:(opacity-100 bg-gray-400 bg-opacity-10);
+}
+
+.icon-btn.disabled {
+ --uno: opacity-25 pointer-events-none;
+}
+
+.inline-icon-btn {
+ --uno: text-primary-deep;
+ --uno: inline-block rounded p-0.5 text-2xl align-middle;
+ --uno: border border-primary border-opacity-20 border-solid;
+}
+
+[data-tweet-id] {
+ border-radius: 13px;
+}
diff --git a/.vitepress/theme/styles/demo.css b/.vitepress/theme/styles/demo.css
new file mode 100644
index 0000000..64a5be3
--- /dev/null
+++ b/.vitepress/theme/styles/demo.css
@@ -0,0 +1,170 @@
+html:not(.dark) {
+ --prism-foreground: #393a34;
+ --prism-background: #fafafa;
+ --prism-inline-background: #f5f5f5;
+ --prism-comment: #a0ada0;
+ --prism-string: #b56959;
+ --prism-literal: #2f8a89;
+ --prism-number: #296aa3;
+ --prism-keyword: #1c6b48;
+ --prism-function: #6c7834;
+ --prism-boolean: #296aa3;
+ --prism-constant: #a65e2b;
+ --prism-deleted: #a14f55;
+ --prism-class: #2993a3;
+ --prism-builtin: #ab5959;
+ --prism-property: #b58451;
+ --prism-namespace: #b05a78;
+ --prism-punctuation: #8e8f8b;
+ --prism-decorator: #bd8f8f;
+ --prism-regex: #ab5e3f;
+ --prism-json-property: #698c96;
+}
+
+html.dark {
+ --prism-scheme: dark;
+ --prism-foreground: #d4cfbf;
+ --prism-background: #181818;
+ --prism-comment: #758575;
+ --prism-string: #d48372;
+ --prism-literal: #429988;
+ --prism-keyword: #4d9375;
+ --prism-boolean: #6394bf;
+ --prism-number: #6394bf;
+ --prism-variable: #c2b36e;
+ --prism-function: #a1b567;
+ --prism-deleted: #bc6066;
+ --prism-class: #54b1bf;
+ --prism-builtin: #e0a569;
+ --prism-property: #dd8e6e;
+ --prism-namespace: #db889a;
+ --prism-punctuation: #858585;
+ --prism-decorator: #bd8f8f;
+ --prism-regex: #ab5e3f;
+ --prism-json-property: #6b8b9e;
+ --prism-line-number: #888888;
+ --prism-line-number-gutter: #eeeeee;
+ --prism-line-highlight-background: #444444;
+ --prism-selection-background: #444444;
+ --prism-inline-background: theme('colors.dark.300');
+}
+
+.token.title {
+ color: var(--prism-keyword);
+}
+
+.token.comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+ color: var(--prism-comment);
+ font-style: var(--prism-comment-style);
+}
+
+.token.namespace {
+ color: var(--prism-namespace);
+}
+
+.token.interpolation {
+ color: var(--prism-interpolation);
+}
+
+.token.string {
+ color: var(--prism-string);
+}
+
+.token.punctuation {
+ color: var(--prism-punctuation);
+}
+
+.token.operator {
+ color: var(--prism-operator);
+}
+
+.token.keyword.module,
+.token.keyword.control-flow {
+ color: var(--prism-keyword-control);
+}
+
+.token.url,
+.token.symbol,
+.token.inserted {
+ color: var(--prism-symbol);
+}
+
+.token.constant {
+ color: var(--prism-constant);
+}
+
+.token.string.url {
+ text-decoration: var(--prism-url-decoration);
+}
+
+.token.boolean,
+.language-json .token.boolean {
+ color: var(--prism-boolean);
+}
+
+.token.number,
+.language-json .token.number {
+ color: var(--prism-number);
+}
+
+.token.variable {
+ color: var(--prism-variable);
+}
+
+.token.keyword {
+ color: var(--prism-keyword);
+}
+
+.token.atrule,
+.token.attr-value,
+.token.selector {
+ color: var(--prism-selector);
+}
+
+.token.function {
+ color: var(--prism-function);
+}
+
+.token.deleted {
+ color: var(--prism-deleted);
+}
+
+.token.important,
+.token.bold {
+ font-weight: bold;
+}
+
+.token.italic {
+ font-style: italic;
+}
+
+.token.class-name {
+ color: var(--prism-class);
+}
+
+.token.tag,
+.token.builtin {
+ color: var(--prism-builtin);
+}
+
+.token.attr-name,
+.token.property,
+.token.entity {
+ color: var(--prism-property);
+}
+
+.language-json .token.property {
+ color: var(--prism-json-property);
+}
+
+.token.regex {
+ color: var(--prism-regex);
+}
+
+.token.decorator,
+.token.annotation {
+ color: var(--prism-decorator);
+}
diff --git a/.vitepress/theme/styles/layout.css b/.vitepress/theme/styles/layout.css
deleted file mode 100644
index 306966a..0000000
--- a/.vitepress/theme/styles/layout.css
+++ /dev/null
@@ -1,312 +0,0 @@
-*,
-::before,
-::after {
- box-sizing: border-box;
- border-width: 0;
- border-style: solid;
- border-color: #e5e7eb;
-}
-/*
-* {
- scrollbar-color: var(--c-divider-light) var(--c-bg);
-}
-::-webkit-scrollbar {
- width: var(--scrollbar-width);
-}
-::-webkit-scrollbar:horizontal {
- height: var(--scrollbar-width);
-}
-::-webkit-scrollbar-track {
- background: var(--c-bg);
- border-radius: 10px;
-}
-::-webkit-scrollbar-thumb {
- background: transparent;
- border-radius: 10px;
- background-clip: padding-box;
-}
-::-webkit-scrollbar-thumb:hover {
- background: var(--c-divider-dark);
-}
-*:hover::-webkit-scrollbar-thumb {
- background: var(--c-divider-light);
-} */
-
-html {
- line-height: 1.4;
- font-size: 16px;
- -webkit-text-size-adjust: 100%;
-}
-
-body {
- margin: 0;
- width: 100%;
- min-width: 320px;
- min-height: 100vh;
- line-height: 1.4;
- font-family: var(--font-family-base);
- font-size: 16px;
- font-weight: 400;
- color: var(--c-text);
- background-color: var(--c-bg);
- direction: ltr;
- font-synthesis: none;
- text-rendering: optimizeLegibility;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- overflow-x: hidden;
-}
-
-main {
- display: block;
-}
-
-h1,
-h2,
-h3,
-h4,
-h5,
-h6 {
- margin: 0;
- line-height: 1.25;
-}
-
-h1,
-h2,
-h3,
-h4,
-h5,
-h6,
-strong,
-b {
- font-weight: 600;
-}
-
-h1:hover .header-anchor,
-h1:focus .header-anchor,
-h2:hover .header-anchor,
-h2:focus .header-anchor,
-h3:hover .header-anchor,
-h3:focus .header-anchor,
-h4:hover .header-anchor,
-h4:focus .header-anchor,
-h5:hover .header-anchor,
-h5:focus .header-anchor,
-h6:hover .header-anchor,
-h6:focus .header-anchor {
- opacity: 1;
-}
-
-h1 {
- margin-top: 1.5rem;
- font-size: 1.9rem;
-}
-
-@media screen and (min-width: 420px) {
- h1 {
- font-size: 2.2rem;
- }
-}
-
-h2 {
- margin-top: 2.25rem;
- margin-bottom: 1.25rem;
- border-bottom: 1px solid var(--c-divider);
- padding-bottom: 0.3rem;
- line-height: 1.25;
- font-size: 1.65rem;
- /* overflow-x: auto; */
-}
-
-h2 + h3 {
- margin-top: 1.5rem;
-}
-
-h3 {
- margin-top: 2rem;
- font-size: 1.35rem;
-}
-
-h4 {
- font-size: 1.15rem;
-}
-
-p,
-ol,
-ul {
- margin: 1rem 0;
- line-height: 1.7;
-}
-
-a,
-area,
-button,
-[role="button"],
-input,
-label,
-select,
-summary,
-textarea {
- touch-action: manipulation;
-}
-
-a {
- text-decoration: none;
- color: var(--c-brand);
-}
-
-a:hover {
- text-decoration: underline;
-}
-
-a.header-anchor {
- float: left;
- margin-top: 0.125em;
- margin-left: -0.87em;
- padding-right: 0.23em;
- font-size: 0.85em;
- opacity: 0;
-}
-
-a.header-anchor:hover,
-a.header-anchor:focus {
- text-decoration: none;
-}
-
-figure {
- margin: 0;
-}
-
-img {
- max-width: 100%;
-}
-
-ul,
-ol {
- padding-left: 1.25em;
-}
-
-li > ul,
-li > ol {
- margin: 0;
-}
-
-table {
- @apply w-full;
-}
-
-tr {
- @apply border-b border-gray-400 border-opacity-20;
-}
-
-th {
- @apply text-left font-600;
-}
-
-td, th {
- @apply p-1 py-2;
-}
-
-blockquote {
- margin: 1rem 0;
- border-left: 0.2rem solid #8885;
- padding: 0.25rem 0 0.25rem 1rem;
- font-size: 1rem;
- color: var(--c-text);
- @apply bg-gray-400 bg-opacity-10;
-}
-
-kbd {
- @apply border border-gray-400 border-b-2 border-opacity-20 rounded;
- @apply bg-gray-400 bg-opacity-5 py-0.5 px-2 text-sm text-center font-mono;
-}
-
-blockquote > p {
- margin: 0;
-}
-
-form {
- margin: 0;
-}
-
-.theme.sidebar-open .sidebar-mask {
- display: block;
-}
-
-.theme.no-navbar > h1,
-.theme.no-navbar > h2,
-.theme.no-navbar > h3,
-.theme.no-navbar > h4,
-.theme.no-navbar > h5,
-.theme.no-navbar > h6 {
- margin-top: 1.5rem;
- padding-top: 0;
-}
-
-.theme.no-navbar aside {
- top: 0;
-}
-
-@media screen and (min-width: 720px) {
- .theme.no-sidebar aside {
- display: none;
- }
-
- .theme.no-sidebar main {
- margin-left: 0;
- }
-}
-
-.sidebar-mask {
- position: fixed;
- z-index: 2;
- display: none;
- width: 100vw;
- height: 100vh;
-}
-
-.nav-btn {
- display: flex;
- font-size: 1.05rem;
- border: 0;
- outline: none;
- background: none;
- color: var(--c-text);
- opacity: 0.8;
- cursor: pointer;
-}
-.nav-btn:hover {
- opacity: 1;
-}
-.nav-btn svg {
- margin: auto;
-}
-.external-link {
- font-size: 0.95rem;
- opacity: 0.7;
-}
-
-.icon-btn {
- @apply inline-block cursor-pointer select-none !outline-none;
- @apply opacity-75 transition duration-200 ease-in-out align-middle rounded p-2;
- @apply hover:(opacity-100 bg-gray-400 bg-opacity-10);
-}
-
-.icon-btn.disabled {
- @apply opacity-25 pointer-events-none;
-}
-
-.inline-icon-btn {
- @apply text-primary-deep;
- @apply inline-block rounded p-0.5 text-2xl align-middle;
- @apply border border-primary border-opacity-20 border-solid;
-}
-
-p > img {
- @apply rounded-2xl
-}
-
-li > svg {
- vertical-align: middle;
- transform: translateY(-10%);
-}
diff --git a/.vitepress/theme/styles/sidebar-links.css b/.vitepress/theme/styles/sidebar-links.css
deleted file mode 100644
index b87e43c..0000000
--- a/.vitepress/theme/styles/sidebar-links.css
+++ /dev/null
@@ -1,102 +0,0 @@
-.sidebar-links {
- margin: 0;
- padding: 0;
- list-style: none;
-}
-
-.sidebar-link-item {
- display: block;
- margin: 0;
- border-left: .25rem solid transparent;
- color: var(--c-text);
-}
-
-a.sidebar-link-item:hover {
- text-decoration: none;
- color: var(--c-brand);
-}
-
-a.sidebar-link-item.active {
- color: var(--c-brand);
-}
-
-.sidebar > .sidebar-links {
- padding: .75rem 0 5rem;
-}
-
-@media (min-width: 720px) {
- .sidebar > .sidebar-links {
- padding: 1.5rem 0;
- }
-}
-
-.sidebar > .sidebar-links > .sidebar-link + .sidebar-link {
- padding-top: .5rem;
-}
-
-@media (min-width: 720px) {
- .sidebar > .sidebar-links > .sidebar-link + .sidebar-link {
- padding-top: 1.25rem;
- }
-}
-
-.sidebar > .sidebar-links > .sidebar-link > .sidebar-link-item {
- padding: .35rem 1.5rem .35rem 1.25rem;
- font-size: 1.1rem;
- font-weight: 700;
-}
-
-.sidebar > .sidebar-links > .sidebar-link > a.sidebar-link-item.active {
- border-left-color: var(--c-brand);
- font-weight: 600;
-}
-
-.sidebar > .sidebar-links > .sidebar-link > .sidebar-links > .sidebar-link > .sidebar-link-item {
- display: block;
- padding: .35rem 1.5rem .35rem 2rem;
- line-height: 1.4;
- font-size: 1rem;
- font-weight: 400;
-}
-
-.sidebar > .sidebar-links > .sidebar-link > .sidebar-links > .sidebar-link > a.sidebar-link-item.active {
- border-left-color: var(--c-brand);
- font-weight: 600;
-}
-
-.sidebar >
-.sidebar-links >
-.sidebar-link >
-.sidebar-links >
-.sidebar-link >
-.sidebar-links >
-.sidebar-link >
-.sidebar-link-item {
- display: block;
- padding: .3rem 1.5rem .3rem 3rem;
- line-height: 1.4;
- font-size: .9rem;
- font-weight: 400;
-}
-
-.sidebar >
-.sidebar-links >
-.sidebar-link >
-.sidebar-links >
-.sidebar-link >
-.sidebar-links >
-.sidebar-link >
-.sidebar-links >
-.sidebar-link >
-.sidebar-link-item {
- display: block;
- padding: .3rem 1.5rem .3rem 4rem;
- line-height: 1.4;
- font-size: .9rem;
- font-weight: 400;
-}
-/*
-a.sidebar-link-item {
- font-family: monospace;
- letter-spacing: -0.5px;
-} */
diff --git a/.vitepress/theme/styles/vars.css b/.vitepress/theme/styles/vars.css
index eddc7b6..a5f6998 100644
--- a/.vitepress/theme/styles/vars.css
+++ b/.vitepress/theme/styles/vars.css
@@ -1,104 +1,152 @@
-/** Base Styles */
+/**
+ * Customize default theme styling by overriding CSS variables:
+ * https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css
+ */
+
+/**
+ * Colors
+ *
+ * Each colors have exact same color scale system with 3 levels of solid
+ * colors with different brightness, and 1 soft color.
+ *
+ * - `XXX-1`: The most solid color used mainly for colored text. It must
+ * satisfy the contrast ratio against when used on top of `XXX-soft`.
+ *
+ * - `XXX-2`: The color used mainly for hover state of the button.
+ *
+ * - `XXX-3`: The color for solid background, such as bg color of the button.
+ * It must satisfy the contrast ratio with pure white (#ffffff) text on
+ * top of it.
+ *
+ * - `XXX-soft`: The color used for subtle background such as custom container
+ * or badges. It must satisfy the contrast ratio when putting `XXX-1` colors
+ * on top of it.
+ *
+ * The soft color must be semi transparent alpha channel. This is crucial
+ * because it allows adding multiple "soft" colors on top of each other
+ * to create a accent, such as when having inline code block inside
+ * custom containers.
+ *
+ * - `default`: The color used purely for subtle indication without any
+ * special meanings attched to it such as bg color for menu hover state.
+ *
+ * - `brand`: Used for primary brand colors, such as link text, button with
+ * brand theme, etc.
+ *
+ * - `tip`: Used to indicate useful information. The default theme uses the
+ * brand color for this by default.
+ *
+ * - `warning`: Used to indicate warning to the users. Used in custom
+ * container, badges, etc.
+ *
+ * - `danger`: Used to show error, or dangerous message to the users. Used
+ * in custom container, badges, etc.
+ * -------------------------------------------------------------------------- */
+
:root {
+ --vp-c-brand-1: #3AB9D4;
+ --vp-c-brand-2: #60c4db;
+ --vp-c-brand-3: #6fcce1;
+ --vp-c-brand-soft: #3AB9D450;
+ --vp-c-bg-alt: #f9f9f9;
+
+ --vp-font-family-mono: theme('fontFamily.mono');
+}
+
+.dark {
+ --vp-c-brand-1: #6fcce1;
+ --vp-c-brand-2: #60c4db;
+ --vp-c-brand-3: #3AB9D4;
+ --vp-c-brand-soft: #3AB9D450;
+ --vp-c-bg-alt: #18181b;
+ --vp-c-gutter: #8883;
+}
+
+:root {
+ --vp-c-default-1: var(--vp-c-gray-1);
+ --vp-c-default-2: var(--vp-c-gray-2);
+ --vp-c-default-3: var(--vp-c-gray-3);
+ --vp-c-default-soft: var(--vp-c-gray-soft);
+
+ --vp-c-tip-1: var(--vp-c-brand-1);
+ --vp-c-tip-2: var(--vp-c-brand-2);
+ --vp-c-tip-3: var(--vp-c-brand-3);
+ --vp-c-tip-soft: var(--vp-c-brand-soft);
+}
+
+:root {
+ -vp-c-text-1: rgba(42, 40, 47);
+ -vp-c-text-2: rgba(42, 40, 47, 0.78);
+ -vp-c-text-3: rgba(42, 40, 47, 0.56);
+ --black-text-1: rgba(42, 40, 47);
+}
- /**
- * Colors
- * --------------------------------------------------------------------- */
- --c-bg: #fff;
- --c-bg-semi: rgba(255,255,255,0.8);
- --c-bg-secondary: #f3f5f7;
-
- --c-white: #ffffff;
- --c-black: #000000;
-
- --c-divider-light: rgba(60, 60, 67, .12);
- --c-divider-dark: rgba(84, 84, 88, .48);
-
- --c-text-light-1: #2c3e50;
- --c-text-light-2: #476582;
- --c-text-light-3: #90a4b7;
-
- --c-brand: #3AB9D4;
- --c-brand-active: #3AB9D4;
- --c-brand-dark: #3AB9D4;
- --c-brand-light: #3AB9D4;
-
- --c-disabled-bg: #e5e5e5;
- --c-disabled-fg: #666;
-
- --code-bg-color: #f8f8f8;
- --code-inline-bg-color: rgba(27, 31, 35, .04);
- --code-highlight: rgba(0, 0, 0, .04);
-
- /**
- * Typography
- * --------------------------------------------------------------------- */
-
- --font-family-base: 'Inter', apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
- --font-family-mono: 'IBM Plex Mono', source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
-
- /**
- * Z Indexes
- *
- * Algolia SearchBox has a z-index of 200, so make sure not to go above
- * that value.
- * --------------------------------------------------------------------- */
-
- --z-index-navbar: 10;
- --z-index-sidebar: 6;
-
- /**
- * Shadows
- * --------------------------------------------------------------------- */
-
- --shadow-1: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);
- --shadow-2: 0 3px 12px rgba(0, 0, 0, .07), 0 1px 4px rgba(0, 0, 0, .07);
- --shadow-3: 0 12px 32px rgba(0, 0, 0, .1), 0 2px 6px rgba(0, 0, 0, .08);
- --shadow-4: 0 14px 44px rgba(0, 0, 0, .12), 0 3px 9px rgba(0, 0, 0, .12);
- --shadow-5: 0 18px 56px rgba(0, 0, 0, .16), 0 4px 12px rgba(0, 0, 0, .16);
-
- /**
- * Sizes
- * --------------------------------------------------------------------- */
-
- --header-height: 3.6rem;
- --sidebar-width: 17.5rem;
- --scrollbar-width: 0;
+.dark {
+ --vp-c-text-1: rgba(255, 255, 245, 0.86);
+ --vp-c-text-2: rgba(235, 235, 245, 0.6);
+ --vp-c-text-3: rgba(235, 235, 245, 0.38);
}
-html.dark {
- --c-bg: #111;
- --c-bg-semi: rgba(17,17,17,0.8);
- --c-bg-secondary: #222;
- --c-text: #f5f7fa;
- --c-text-light: #f9f9f9;
- --c-text-lighter: #ffffff;
-
- --c-divider-light: rgba(200, 200, 200, .12);
- --c-divider-dark: rgba(200, 200, 200, .48);
- --code-bg-color: #191919;
- --code-inline-bg-color: rgba(255, 255, 255, .04);
- --code-highlight: rgba(0, 0, 0, .66);
-
- --c-disabled-bg: #333;
- --c-disabled-fg: #aaa;
+/**
+ * Component: Button
+ * -------------------------------------------------------------------------- */
+
+:root {
+ --vp-button-brand-border: transparent;
+ --vp-button-brand-text: var(--vp-c-white);
+ --vp-button-brand-bg: var(--vp-c-brand-1);
+ --vp-button-brand-hover-border: transparent;
+ --vp-button-brand-hover-text: var(--vp-c-white);
+ --vp-button-brand-hover-bg: var(--vp-c-brand-2);
+ --vp-button-brand-active-border: transparent;
+ --vp-button-brand-active-text: var(--vp-c-white);
+ --vp-button-brand-active-bg: var(--vp-c-brand-1);
+}
+
+.dark {
+ --vp-button-brand-text: var(--black-text-1);
+ --vp-button-brand-bg: var(--vp-c-brand-2);
+ --vp-button-brand-hover-text: var(--black-text-1);
+ --vp-button-brand-hover-bg: var(--vp-c-brand-1);
+ --vp-button-brand-active-text: var(--black-text-1);
+ --vp-button-brand-active-bg: var(--vp-c-brand-3);
}
-/** Fallback Styles */
+/**
+ * Component: Home
+ * -------------------------------------------------------------------------- */
+
:root {
- --c-divider: var(--c-divider-light);
+ --vp-home-hero-name-color: var(--vp-c-brand-1);
+}
- --c-text: var(--c-text-light-1);
- --c-text-light: var(--c-text-light-2);
- --c-text-lighter: var(--c-text-light-3);
+@media (min-width: 640px) {
+ :root {
+ --vp-home-hero-image-filter: blur(56px);
+ }
+}
+
+@media (min-width: 960px) {
+ :root {
+ --vp-home-hero-image-filter: blur(72px);
+ }
+}
- --c-bg: var(--c-white);
+/**
+ * Component: Custom Block
+ * -------------------------------------------------------------------------- */
- --code-line-height: 24px;
- --code-font-family: var(--font-family-mono);
- --code-font-size: 14px;
+:root {
+ --vp-custom-block-tip-border: transparent;
+ --vp-custom-block-tip-text: var(--vp-c-text-1);
+ --vp-custom-block-tip-bg: var(--vp-c-brand-soft);
+ --vp-custom-block-tip-code-bg: var(--vp-c-brand-soft);
}
-.no-sidebar {
- --sidebar-width: 0;
+/**
+ * Component: Algolia
+ * -------------------------------------------------------------------------- */
+
+.DocSearch {
+ --docsearch-primary-color: var(--vp-c-brand-1) !important;
}
diff --git a/.vitepress/theme/support/sideBar.ts b/.vitepress/theme/support/sideBar.ts
deleted file mode 100644
index 0d6b201..0000000
--- a/.vitepress/theme/support/sideBar.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-import type { DefaultTheme } from '../config'
-import {
- isArray,
- ensureSlash,
- ensureStartingSlash,
- removeExtention,
-} from '../utils'
-
-export function isSideBarConfig(
- sidebar: DefaultTheme.SideBarConfig | DefaultTheme.MultiSideBarConfig,
-): sidebar is DefaultTheme.SideBarConfig {
- return sidebar === false || sidebar === 'auto' || isArray(sidebar)
-}
-
-export function isSideBarGroup(
- item: DefaultTheme.SideBarItem,
-): item is DefaultTheme.SideBarGroup {
- return (item as DefaultTheme.SideBarGroup).children !== undefined
-}
-
-/**
- * Get the `SideBarConfig` from sidebar option. This method will ensure to get
- * correct sidebar config from `MultiSideBarConfig` with various path
- * combinations such as matching `guide/` and `/guide/`. If no matching config
- * was found, it will return `auto` as a fallback.
- */
-export function getSideBarConfig(
- sidebar: DefaultTheme.SideBarConfig | DefaultTheme.MultiSideBarConfig,
- path: string,
-): DefaultTheme.SideBarConfig {
- if (isSideBarConfig(sidebar))
- return sidebar
-
- // get the very first segment of the path to compare with nulti sidebar keys
- // and make sure it's surrounded by slash
- path = removeExtention(path)
- path = ensureStartingSlash(path).split('/')[1] || '/'
- path = ensureSlash(path)
-
- for (const dir of Object.keys(sidebar)) {
- // make sure the multi sidebar key is surrounded by slash too
- if (path === ensureSlash(dir))
- return sidebar[dir]
- }
-
- return 'auto'
-}
-
-/**
- * Get flat sidebar links from the sidebar items. This method is useful for
- * creating the "next and prev link" feature. It will ignore any items that
- * don't have `link` property and removes `.md` or `.html` extension if a
- * link contains it.
- */
-export function getFlatSideBarLinks(
- sidebar: DefaultTheme.SideBarItem[],
-): DefaultTheme.SideBarLink[] {
- return sidebar.reduce((links, item) => {
- if (item.link)
- links.push({ text: item.text, link: removeExtention(item.link) })
-
- if (isSideBarGroup(item))
- links = [...links, ...getFlatSideBarLinks(item.children)]
-
- return links
- }, [])
-}
diff --git a/.vitepress/theme/utils.ts b/.vitepress/theme/utils.ts
deleted file mode 100644
index aad8b5a..0000000
--- a/.vitepress/theme/utils.ts
+++ /dev/null
@@ -1,77 +0,0 @@
-export const hashRE = /#.*$/
-export const extRE = /(index)?\.(md|html)$/
-export const endingSlashRE = /\/$/
-export const outboundRE = /^[a-z]+:/i
-
-export function isNullish(value: any): value is null | undefined {
- return value === null || value === undefined
-}
-
-export function isArray(value: any): value is any[] {
- return Array.isArray(value)
-}
-
-export function isExternal(path: string): boolean {
- return outboundRE.test(path)
-}
-
-export function isActive(route: any, path?: string): boolean {
- if (path === undefined)
- return false
-
- const routePath = normalize(route.path)
- const pagePath = normalize(path)
-
- return routePath === pagePath
-}
-
-export function normalize(path: string): string {
- return decodeURI(path).replace(hashRE, '').replace(extRE, '')
-}
-
-export function joinUrl(base: string, path: string): string {
- const baseEndsWithSlash = base.endsWith('/')
- const pathStartsWithSlash = path.startsWith('/')
-
- if (baseEndsWithSlash && pathStartsWithSlash)
- return base.slice(0, -1) + path
-
- if (!baseEndsWithSlash && !pathStartsWithSlash)
- return `${base}/${path}`
-
- return base + path
-}
-
-/**
- * get the path without filename (the last segment). for example, if the given
- * path is `/guide/getting-started.html`, this method will return `/guide/`.
- * Always with a trailing slash.
- */
-export function getPathDirName(path: string): string {
- const segments = path.split('/')
-
- if (segments[segments.length - 1])
- segments.pop()
-
- return ensureEndingSlash(segments.join('/'))
-}
-
-export function ensureSlash(path: string): string {
- return ensureEndingSlash(ensureStartingSlash(path))
-}
-
-export function ensureStartingSlash(path: string): string {
- return /^\//.test(path) ? path : `/${path}`
-}
-
-export function ensureEndingSlash(path: string): string {
- return /(\.html|\/)$/.test(path) ? path : `${path}/`
-}
-
-/**
- * Remove `.md` or `.html` extention from the given path. It also converts
- * `index` to slush.
- */
-export function removeExtention(path: string): string {
- return path.replace(/(index)?(\.(md|html))?$/, '') || '/'
-}
diff --git a/.vitepress/themes.ts b/.vitepress/themes.ts
index 9c285e0..6961e0e 100644
--- a/.vitepress/themes.ts
+++ b/.vitepress/themes.ts
@@ -127,26 +127,6 @@ export const official: ThemeInfo[] = [
]
export const community: ThemeInfo[] = [
- {
- id: 'slidev-theme-flayyer',
- name: 'Flayyer',
- description: 'This theme is inspired by the layout of Flayyer and the way that it works.',
- author: {
- name: 'Daniel Esteves',
- link: 'https://github.com/danestves',
- },
- repo: 'https://github.com/danestves/slidev-theme-flayyer',
- previews: [
- 'https://i.imgur.com/grKiGIK.png',
- 'https://i.imgur.com/tAvcf5S.png',
- 'https://i.imgur.com/mj42LcL.png',
- 'https://i.imgur.com/41QWv3c.png',
- ],
- tags: [
- 'dark',
- 'light',
- ],
- },
{
id: 'slidev-theme-geist',
name: 'Vercel',
@@ -192,6 +172,27 @@ export const community: ThemeInfo[] = [
'light',
],
},
+ {
+ id: 'slidev-theme-eloc',
+ name: 'Eloc',
+ description: 'Focus on writing, present in a concise style.',
+ author: {
+ name: 'Amio',
+ link: 'https://github.com/amio',
+ },
+ repo: 'https://github.com/zthxxx/slides/tree/master/packages/slidev-theme-eloc',
+ previews: [
+ 'https://cdn.jsdelivr.net/gh/zthxxx/slides@master/packages/slidev-theme-eloc/screenshot/01.png',
+ 'https://cdn.jsdelivr.net/gh/zthxxx/slides@master/packages/slidev-theme-eloc/screenshot/02.png',
+ 'https://cdn.jsdelivr.net/gh/zthxxx/slides@master/packages/slidev-theme-eloc/screenshot/03.png',
+ 'https://cdn.jsdelivr.net/gh/zthxxx/slides@master/packages/slidev-theme-eloc/screenshot/04.png',
+ 'https://cdn.jsdelivr.net/gh/zthxxx/slides@master/packages/slidev-theme-eloc/screenshot/05.png',
+ ],
+ tags: [
+ 'dark',
+ 'light',
+ ],
+ },
{
id: 'slidev-theme-purplin',
name: 'Purplin',
@@ -315,6 +316,116 @@ export const community: ThemeInfo[] = [
'light',
],
},
+ {
+ id: 'slidev-theme-academic',
+ name: 'Academic',
+ description: 'Academic presentations with Slidev made simple',
+ author: {
+ name: 'Alexander Eble',
+ link: 'https://github.com/alexanderdavide',
+ },
+ repo: 'https://github.com/alexanderdavide/slidev-theme-academic',
+ previews: [
+ 'https://cdn.jsdelivr.net/gh/alexanderdavide/slidev-theme-academic@assets/example-export/01.png',
+ 'https://cdn.jsdelivr.net/gh/alexanderdavide/slidev-theme-academic@assets/example-export/02.png',
+ 'https://cdn.jsdelivr.net/gh/alexanderdavide/slidev-theme-academic@assets/example-export/08.png',
+ 'https://cdn.jsdelivr.net/gh/alexanderdavide/slidev-theme-academic@assets/example-export/04.png',
+ 'https://cdn.jsdelivr.net/gh/alexanderdavide/slidev-theme-academic@assets/example-export/05.png',
+ 'https://cdn.jsdelivr.net/gh/alexanderdavide/slidev-theme-academic@assets/example-export/06.png',
+ 'https://cdn.jsdelivr.net/gh/alexanderdavide/slidev-theme-academic@assets/example-export/07.png',
+ ],
+ tags: [
+ 'dark',
+ 'light',
+ ],
+ },
+ {
+ id: 'slidev-theme-mokkapps',
+ name: 'Mokkapps',
+ description: 'A theme for my personal brand "Mokkapps"',
+ author: {
+ name: 'Michael Hoffmann',
+ link: 'https://github.com/mokkapps',
+ },
+ repo: 'https://github.com/mokkapps/slidev-theme-mokkapps',
+ previews: [
+ 'https://cdn.jsdelivr.net/gh/mokkapps/slidev-theme-mokkapps@master/screenshots/dark/001.png',
+ 'https://cdn.jsdelivr.net/gh/mokkapps/slidev-theme-mokkapps@master/screenshots/dark/002.png',
+ 'https://cdn.jsdelivr.net/gh/mokkapps/slidev-theme-mokkapps@master/screenshots/dark/003.png',
+ 'https://cdn.jsdelivr.net/gh/mokkapps/slidev-theme-mokkapps@master/screenshots/dark/004.png',
+ 'https://cdn.jsdelivr.net/gh/mokkapps/slidev-theme-mokkapps@master/screenshots/dark/005.png',
+ 'https://cdn.jsdelivr.net/gh/mokkapps/slidev-theme-mokkapps@master/screenshots/dark/006.png',
+ 'https://cdn.jsdelivr.net/gh/mokkapps/slidev-theme-mokkapps@master/screenshots/dark/007.png',
+ 'https://cdn.jsdelivr.net/gh/mokkapps/slidev-theme-mokkapps@master/screenshots/dark/008.png',
+ 'https://cdn.jsdelivr.net/gh/mokkapps/slidev-theme-mokkapps@master/screenshots/dark/009.png',
+ 'https://cdn.jsdelivr.net/gh/mokkapps/slidev-theme-mokkapps@master/screenshots/dark/010.png',
+ 'https://cdn.jsdelivr.net/gh/mokkapps/slidev-theme-mokkapps@master/screenshots/dark/011.png',
+ ],
+ tags: [
+ 'dark',
+ 'light',
+ ],
+ },
+ {
+ id: 'slidev-theme-the-unnamed',
+ name: 'The unnamed',
+ description: 'A theme based on The unnamed VS Code theme',
+ author: {
+ name: 'Elio Struyf',
+ link: 'https://elio.dev',
+ },
+ repo: 'https://github.com/estruyf/slidev-theme-the-unnamed',
+ previews: [
+ 'https://cdn.jsdelivr.net/gh/estruyf/slidev-theme-the-unnamed@main/assets/cover.png',
+ 'https://cdn.jsdelivr.net/gh/estruyf/slidev-theme-the-unnamed@main/assets/about-me.png',
+ 'https://cdn.jsdelivr.net/gh/estruyf/slidev-theme-the-unnamed@main/assets/default.png',
+ 'https://cdn.jsdelivr.net/gh/estruyf/slidev-theme-the-unnamed@main/assets/section.png',
+ ],
+ tags: [
+ 'dark',
+ ],
+ },
+ {
+ id: 'slidev-theme-dracula',
+ name: 'Dracula',
+ description: 'One the best dark theme meets slidev',
+ author: {
+ name: 'JD Solanki (jd-solanki)',
+ link: 'https://github.com/jd-solanki',
+ },
+ repo: 'https://github.com/jd-solanki/slidev-theme-dracula',
+ previews: [
+ 'https://cdn.jsdelivr.net/gh/jd-solanki/slidev-theme-dracula/screenshots/screenshot-1.png',
+ 'https://cdn.jsdelivr.net/gh/jd-solanki/slidev-theme-dracula/screenshots/screenshot-2.png',
+ 'https://cdn.jsdelivr.net/gh/jd-solanki/slidev-theme-dracula/screenshots/screenshot-3.png',
+ 'https://cdn.jsdelivr.net/gh/jd-solanki/slidev-theme-dracula/screenshots/screenshot-4.png',
+ 'https://cdn.jsdelivr.net/gh/jd-solanki/slidev-theme-dracula/screenshots/screenshot-5.png',
+ ],
+ tags: [
+ 'dark',
+ 'minimalism',
+ ],
+ },
+ {
+ id: 'slidev-theme-frankfurt',
+ name: 'Frankfurt',
+ description: 'Inspired by the Beamer theme Frankfurt',
+ author: {
+ name: 'Mu-Tsun Tsai',
+ link: 'https://github.com/MuTsunTsai',
+ },
+ repo: 'https://github.com/MuTsunTsai/slidev-theme-frankfurt',
+ previews: [
+ 'https://cdn.jsdelivr.net/gh/MuTsunTsai/slidev-theme-frankfurt/screenshots/01.png',
+ 'https://cdn.jsdelivr.net/gh/MuTsunTsai/slidev-theme-frankfurt/screenshots/04.png',
+ 'https://cdn.jsdelivr.net/gh/MuTsunTsai/slidev-theme-frankfurt/screenshots/06.png',
+ 'https://cdn.jsdelivr.net/gh/MuTsunTsai/slidev-theme-frankfurt/screenshots/07.png',
+ ],
+ tags: [
+ 'dark',
+ 'light',
+ ],
+ },
// Add yours here!
{
id: '',
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..eae23ff
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,43 @@
+{
+ // Enable the ESlint flat config support
+ "eslint.experimental.useFlatConfig": true,
+
+ // Disable the default formatter, use eslint instead
+ "prettier.enable": false,
+ "editor.formatOnSave": false,
+
+ // Auto fix
+ "editor.codeActionsOnSave": {
+ "source.fixAll.eslint": "explicit",
+ "source.organizeImports": "never"
+ },
+
+ // Silent the stylistic rules in you IDE, but still auto fix them
+ "eslint.rules.customizations": [
+ { "rule": "style/*", "severity": "off" },
+ { "rule": "format/*", "severity": "off" },
+ { "rule": "*-indent", "severity": "off" },
+ { "rule": "*-spacing", "severity": "off" },
+ { "rule": "*-spaces", "severity": "off" },
+ { "rule": "*-order", "severity": "off" },
+ { "rule": "*-dangle", "severity": "off" },
+ { "rule": "*-newline", "severity": "off" },
+ { "rule": "*quotes", "severity": "off" },
+ { "rule": "*semi", "severity": "off" }
+ ],
+
+ // Enable eslint for all supported languages
+ "eslint.validate": [
+ "javascript",
+ "javascriptreact",
+ "typescript",
+ "typescriptreact",
+ "vue",
+ "html",
+ "markdown",
+ "json",
+ "jsonc",
+ "yaml",
+ "toml"
+ ]
+}
diff --git a/README.md b/README.md
index d3f0f88..cc88fa2 100644
--- a/README.md
+++ b/README.md
@@ -15,6 +15,7 @@ Documentation for [Slidev](https://github.com/slidevjs/slidev)
| Deutsch | [docs-de](https://github.com/slidevjs/docs-de) | [de.sli.dev](https://de.sli.dev) | [@fabiankachlock](https://github.com/fabiankachlock) |
| Português (BR) | [docs-br](https://github.com/slidevjs/docs-br) | [br.sli.dev](https://br.sli.dev) | [@luisfelipesdn12](https://github.com/luisfelipesdn12) |
| Ελληνικά | [docs-el](https://github.com/slidevjs/docs-el) | [el.sli.dev](https://el.sli.dev) | [@GeopJr](https://github.com/GeopJr) |
+| 日本語 | [docs-ja](https://github.com/slidevjs/docs-el) | [ja.sli.dev](https://ja.sli.dev) | [@IkumaTadokoro](https://github.com/IkumaTadokoro) |
## Start Server Locally
diff --git a/TRANSLATIONS.md b/TRANSLATIONS.md
index cc55854..d927008 100644
--- a/TRANSLATIONS.md
+++ b/TRANSLATIONS.md
@@ -19,7 +19,7 @@ In case it's already been translated but you're wondering how to maintain it, sk
- [ ] Fork the main docs repo: [slidevjs/docs](https://github.com/slidevjs/docs)
- [ ] Translate README.md, you can take one of the already translated repositories as an example.
-- [ ] Share your repo's link to the `#translations` channel telling people you are working on it and find collaborators.
+- [ ] Share your repo's link to the `#translations` channel telling people you are working on it and find collaborators.
## Translating Markdown files
@@ -46,7 +46,6 @@ In case it's already been translated but you're wondering how to maintain it, sk
- [ ] `config-shortcuts.md` - Configuring Shortcuts
- [ ] `config-vite.md` - Configuring Vite
- [ ] `config-vue.md` - Configuring Vue
-- [ ] `config-windicss.md`- Configuring Windicss
- [ ] `directory-structure.md` - Configuring the directory structure
- [ ] `fonts.md` - Configuring fonts
- [ ] `global-layers.md` - Configuring the global layers
@@ -77,6 +76,11 @@ In case it's already been translated but you're wondering how to maintain it, sk
- [ ] `use.md` - How to use Slidev themes
- [ ] `write-a-theme.md` - Write your own theme
+### addons/
+
+- [ ] `use.md` - How to use Slidev addons
+- [ ] `write-an-addon.md` - Write your own addon
+
## Publishing your translations
- [ ] When you finish the translation (at least 90%), `@antfu` in the Discord and we will invite you to the org and make the translation official.
@@ -88,7 +92,6 @@ In case it's already been translated but you're wondering how to maintain it, sk
- `docschina-bot` will periodically submit merge requests from the `slidev/docs` repository. Switch to the branch created in the pull request, make any changes necessary and merge it. [example](https://github.com/slidevjs/docs-fr/pull/13).
- Sometimes it will occur that a merge request is made and you haven't merged the previous one. The latest PR always checks your main branch against the English one; so you can just close the previous PR(s), move your work to the latest one and merge it.
-
[Working-in-progress translation list](https://discord.com/channels/851817370623410197/851822360955977760/852614294017146900)
Thanks again!
diff --git a/addons/use.md b/addons/use.md
new file mode 100644
index 0000000..d1ca9e2
--- /dev/null
+++ b/addons/use.md
@@ -0,0 +1,38 @@
+# Use Addon
+
+Addons are sets of additional components, layouts, styles, configuration...etc. that you can use in your presentation.
+
+They are quite similar to [themes](/themes/use), but in general:
+
+* they don't affect the global styles of your slides
+* you can use multiple addons in one presentation
+
+To use addons, you have to install them manually via:
+
+```bash
+$ npm install [slidev-addon-package1] [slidev-addon-package2]
+```
+
+And then declare the addons either in your frontmatter:
+
+```yaml
+---
+addons:
+ - slidev-addon-package1
+ - slidev-addon-package2
+---
+```
+
+Or in your `package.json` file:
+
+```json
+// package.json
+{
+ "slidev": {
+ "addons": [
+ "slidev-addon-package1",
+ "slidev-addon-package2"
+ ]
+ }
+}
+```
diff --git a/addons/write-an-addon.md b/addons/write-an-addon.md
new file mode 100644
index 0000000..e5197a5
--- /dev/null
+++ b/addons/write-an-addon.md
@@ -0,0 +1,71 @@
+# Write an Addon
+
+> Available since v0.32.1
+
+## Capability
+
+An addon can contribute to the following points:
+
+- Global styles (use with caution has it is more the role of [themes](/themes/use))
+- Provide custom layouts or override the existing one
+- Provide custom components or override the existing one
+- Extend UnoCSS/Windi CSS configurations
+- Configure tools like Monaco and Prism
+
+## Conventions
+
+Addons are published to npm registry, and they should follow the conventions below:
+
+- Package name should start with `slidev-addon-`, for example: `slidev-addon-awesome`
+- Add `slidev-addon` and `slidev` in the `keywords` field of your `package.json`
+
+## Setup
+
+### Initialization
+
+To create your addon, start by creating a directory with create a `package.json` file (you can use `npm init`).
+
+Then, install slidev dependencies:
+
+```bash
+$ npm install -D @slidev/cli
+```
+
+### Testing
+
+To set up the testing playground for your addon, you can create an `example.md` file with some content.
+
+And optionally, you can also add some scripts to your `packages.json`
+
+```json
+// package.json
+{
+ "scripts": {
+ "dev": "slidev example.md",
+ "build": "slidev build example.md",
+ "export": "slidev export example.md",
+ "screenshot": "slidev export example.md --format png"
+ }
+}
+```
+
+To publish your addon, simply run `npm publish` and you are good to go. There is no build process required (which means you can directly publish `.vue` and `.ts` files, Slidev is smart enough to understand them).
+
+Addon contribution points follow the same conventions as local customization, please refer to [the docs for the naming conventions](/custom/).
+
+## Addon metadata
+
+### Slidev Version
+
+If the addon is relying on a specific feature of Slidev that are newly introduced, you can set the minimal Slidev version required to have your addon working properly:
+
+```json
+// package.json
+{
+ "engines": {
+ "slidev": ">=0.32.1"
+ }
+}
+```
+
+If users are using older versions of Slidev, an error will be thrown.
diff --git a/builtin/components.md b/builtin/components.md
index a7f9768..87ec412 100644
--- a/builtin/components.md
+++ b/builtin/components.md
@@ -2,7 +2,271 @@
## Встроенные компоненты
+<<<<<<< HEAD
> Документация в процессе разработки. А пока, вы можете взглянуть напрямую [в исходный код](https://github.com/slidevjs/slidev/blob/main/packages/client/builtin).
+=======
+### `Arrow`
+
+Draw an arrow.
+
+#### Usage
+
+~~~md
+
+~~~
+
+Or:
+
+~~~md
+
+~~~
+
+Parameters:
+
+* `x1` (`string | number`, required): start point x position
+* `y1` (`string | number`, required): start point y position
+* `x2` (`string | number`, required): end point x position
+* `y2` (`string | number`, required): end point x position
+* `width` (`string | number`, default: `2`): line width
+* `color` (`string`, default: `'currentColor'`): line color
+
+### `AutoFitText`
+
+> Experimental
+
+Box inside which the font size will automatically adapt to fit the content. Similar to PowerPoint or Keynote TextBox.
+
+#### Usage
+
+~~~md
+
+~~~
+
+Parameters:
+
+* `max` (`string | number`, default `100`): Maximum font size
+* `min` (`string | number`, default `30`): Minimum font size
+* `modelValue` (`string`, default `''`): text content
+
+### `LightOrDark`
+
+Use it to display one thing or another depending on the active light or dark theme.
+
+#### Usage
+
+Use it with the two named Slots `#dark` and `#light`:
+~~~md
+
+ Dark mode is on
+ Light mode is on
+
+~~~
+
+Provided props on `LightOrDark` component will be available using scoped slot props:
+~~~md
+
+
+
+
+
+
+
+
+~~~
+
+You can provide markdown in the slots, but you will need to surround the content with blank lines:
+~~~md
+
+
+
+
+
+
+
+
+
+
+
+
+~~~
+
+### `Link`
+
+Insert a link you can use to navigate to a given slide.
+
+#### Usage
+
+~~~md
+Go to slide 42
+
+
+~~~
+
+Parameters:
+
+* `to` (`string | number`): The path of the slide to navigate to (slides starts from `1`)
+* `title` (`string`): The title to display
+
+One can use a string as `to`, provided the corresponding route exists, e.g.
+
+~~~md
+---
+routeAlias: solutions
+---
+# Now some solutions!
+~~~
+
+### `RenderWhen`
+
+Render slot only when the context match (for example when we are in presenter view).
+
+#### Usage
+
+~~~md
+This will only be rendered in presenter view.
+~~~
+
+Context type: `'main' | 'slide' | 'overview' | 'presenter' | 'previewNext'`
+
+Parameters:
+
+* `context` (`Context | Context[]`): context or array of contexts you want the slot to be rendered
+
+### `SlideCurrentNo`
+
+Current slide number.
+
+#### Usage
+
+~~~md
+
+~~~
+
+### `SlidesTotal`
+
+Total number of slides.
+
+#### Usage
+
+~~~md
+
+~~~
+
+### `Titles`
+
+Insert the main title from a slide parsed as HTML.
+
+Titles and title levels get automatically retrieved from the first title element of each slides.
+
+You can override this automatic behaviour for a slide by using the front matter syntax:
+```yml
+---
+title: Amazing slide title
+level: 2
+---
+```
+
+#### Usage
+
+The `` component is a virtual component you can import with:
+```js
+import Titles from '/@slidev/titles.md'
+```
+
+Then you can use it with:
+~~~md
+
+~~~
+
+Parameters:
+
+* `no` (`string | number`): The number of the slide to display the title from (slides starts from `1`)
+
+### `Toc`
+
+Insert a Table Of Content.
+
+If you want a slide to not appear in the `` component, you can use in the front matter block of the slide:
+```yml
+---
+hideInToc: true
+---
+```
+
+Titles are displayed using the [`` component](#titles)
+
+#### Usage
+
+~~~md
+
+~~~
+
+Parameters:
+
+* `columns` (`string | number`, default: `1`): The number of columns of the display
+* `listClass` (`string | string[]`, default: `''`): Classes to apply to the table of contents list
+* `maxDepth` (`string | number`, default: `Infinity`): The maximum depth level of title to display
+* `minDepth` (`string | number`, default: `1`): The minimum depth level of title to display
+* `mode` (`'all' | 'onlyCurrentTree'| 'onlySiblings'`, default: `'all'`):
+ * `'all'`: Display all items
+ * `'onlyCurrentTree'`: Display only items that are in current tree (active item, parents and children of active item)
+ * `'onlySiblings'`: Display only items that are in current tree and their direct siblings
+
+### `Transform`
+
+Apply scaling or transforming to elements.
+
+#### Usage
+
+~~~md
+
+
+
+~~~
+
+Parameters:
+
+* `scale` (`number | string`, default `1`): transform scale value
+* `origin` (`string`, default `'top left'`): transform origin value
+
+### `Tweet`
+
+Embed a tweet.
+
+#### Usage
+
+~~~md
+
+~~~
+
+Parameters:
+
+* `id` (`number | string`, required): id of the tweet
+* `scale` (`number | string`, default `1`): transform scale value
+* `conversation` (`string`, default `'none'`): [tweet embed parameter](https://developer.twitter.com/en/docs/twitter-for-websites/embedded-tweets/guides/embedded-tweet-parameter-reference)
+* `cards` (`'hidden' | 'visible'`, default `'visible'`): [tweet embed parameter](https://developer.twitter.com/en/docs/twitter-for-websites/embedded-tweets/guides/embedded-tweet-parameter-reference)
+
+### `VAfter`, `VClick` and `VClicks`
+
+See https://sli.dev/guide/animations.html
+### `Youtube`
+
+Embed a youtube video.
+
+#### Usage
+
+~~~md
+
+~~~
+
+Parameters:
+
+* `id` (`string`, required): id of the youtube video
+* `width` (`number`): width of the video
+* `height` (`number`): height of the video
+
+You can also make the video start at specific time if you add `?start=1234` to the id value (where 1234 are seconds),
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
## Кастомные компоненты
diff --git a/builtin/layouts.md b/builtin/layouts.md
index 7cb00c0..9ed1a4a 100644
--- a/builtin/layouts.md
+++ b/builtin/layouts.md
@@ -4,10 +4,13 @@
> Поскольку темы могут переопределять поведение макетов, лучший способ узнать точное использование, параметры и примеры - обратиться к их документации.
-
### `center`
+<<<<<<< HEAD
Отображает содержимое в центре экрана.
+=======
+Displays the content in the middle of the screen.
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
### `cover`
@@ -15,7 +18,11 @@
### `default`
+<<<<<<< HEAD
Самый простой макет для отображения любого вида контента.
+=======
+The most basic layout, to display any kind of content.
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
### `end`
@@ -80,6 +87,23 @@ image: ./path/to/the/image
---
```
+You can change the default background size (`cover`) by adding the `backgroundSize` attribute:
+
+```yaml
+---
+layout: image
+image: ./path/to/the/image
+backgroundSize: contain
+---
+```
+
+```yaml
+---
+layout: image-left
+image: ./path/to/the/image
+backgroundSize: 20em 70%
+---
+```
### `iframe-left`
@@ -132,7 +156,6 @@ url: https://github.com/slidevjs/slidev
---
```
-
### `intro`
Представление презентации, обычно с указанием названия презентации, краткого описания, автора и т.д.
@@ -159,7 +182,6 @@ url: https://github.com/slidevjs/slidev
#### Использование
-
```md
---
layout: two-cols
@@ -176,7 +198,37 @@ layout: two-cols
Это отобразится справа
```
+<<<<<<< HEAD
## Кастомные шаблоны
+=======
+### `two-cols-header`
+
+Separates the upper and lower lines of the page content, and the second line separates the left and right columns.
+
+#### Usage
+
+```md
+---
+layout: two-cols-header
+---
+
+This spans both
+
+::left::
+
+# Left
+
+This shows on the left
+
+::right::
+
+# Right
+
+This shows on the right
+```
+
+## Custom Layouts
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
Создайте папку `layouts/` в корне вашего проекта, и просто вставьте в неё ваши кастомные Vue-компоненты.
diff --git a/components.d.ts b/components.d.ts
new file mode 100644
index 0000000..b34c1cc
--- /dev/null
+++ b/components.d.ts
@@ -0,0 +1,62 @@
+/* eslint-disable */
+/* prettier-ignore */
+// @ts-nocheck
+// Generated by unplugin-vue-components
+// Read more: https://github.com/vuejs/core/pull/3399
+export {}
+
+declare module 'vue' {
+ export interface GlobalComponents {
+ Arrow: typeof import('./.vitepress/@slidev/client/builtin/Arrow.vue')['default']
+ AutoFitText: typeof import('./.vitepress/@slidev/client/builtin/AutoFitText.vue')['default']
+ 'Carbon:chevronLeft': typeof import('~icons/carbon/chevron-left')['default']
+ 'Carbon:chevronRight': typeof import('~icons/carbon/chevron-right')['default']
+ CarbonApps: typeof import('~icons/carbon/apps')['default']
+ CarbonArrowLeft: typeof import('~icons/carbon/arrow-left')['default']
+ CarbonArrowRight: typeof import('~icons/carbon/arrow-right')['default']
+ CarbonBadge: typeof import('~icons/carbon/badge')['default']
+ CarbonDownload: typeof import('~icons/carbon/download')['default']
+ CarbonEdit: typeof import('~icons/carbon/edit')['default']
+ CarbonInformation: typeof import('~icons/carbon/information')['default']
+ CarbonMaximize: typeof import('~icons/carbon/maximize')['default']
+ CarbonMinimize: typeof import('~icons/carbon/minimize')['default']
+ CarbonMoon: typeof import('~icons/carbon/moon')['default']
+ CarbonPen: typeof import('~icons/carbon/pen')['default']
+ CarbonSettingsAdjust: typeof import('~icons/carbon/settings-adjust')['default']
+ CarbonSun: typeof import('~icons/carbon/sun')['default']
+ CarbonUserAvatar: typeof import('~icons/carbon/user-avatar')['default']
+ CarbonUserSpeaker: typeof import('~icons/carbon/user-speaker')['default']
+ CarbonVideo: typeof import('~icons/carbon/video')['default']
+ CodeBlockWrapper: typeof import('./.vitepress/@slidev/client/builtin/CodeBlockWrapper.vue')['default']
+ Demo: typeof import('./.vitepress/theme/components/Demo.vue')['default']
+ DemoEditor: typeof import('./.vitepress/theme/components/DemoEditor.vue')['default']
+ DemoSlide: typeof import('./.vitepress/theme/components/DemoSlide.vue')['default']
+ Environment: typeof import('./.vitepress/theme/components/Environment.vue')['default']
+ LandingPage: typeof import('./.vitepress/theme/components/LandingPage.vue')['default']
+ Link: typeof import('./.vitepress/@slidev/client/builtin/Link.vue')['default']
+ LogosVue: typeof import('~icons/logos/vue')['default']
+ MdiAccountCircle: typeof import('~icons/mdi/account-circle')['default']
+ Mermaid: typeof import('./.vitepress/@slidev/client/builtin/Mermaid.vue')['default']
+ Monaco: typeof import('./.vitepress/@slidev/client/builtin/Monaco.vue')['default']
+ PlantUml: typeof import('./.vitepress/@slidev/client/builtin/PlantUml.vue')['default']
+ RenderWhen: typeof import('./.vitepress/@slidev/client/builtin/RenderWhen.vue')['default']
+ RouterLink: typeof import('vue-router')['RouterLink']
+ RouterView: typeof import('vue-router')['RouterView']
+ ShowCaseInfo: typeof import('./.vitepress/theme/components/ShowCaseInfo.vue')['default']
+ ShowCases: typeof import('./.vitepress/theme/components/ShowCases.vue')['default']
+ SlideCurrentNo: typeof import('./.vitepress/@slidev/client/builtin/SlideCurrentNo.vue')['default']
+ SlidesTotal: typeof import('./.vitepress/@slidev/client/builtin/SlidesTotal.vue')['default']
+ Starport: typeof import('vue-starport')['Starport']
+ StarportCarrier: typeof import('vue-starport')['StarportCarrier']
+ ThemeGallery: typeof import('./.vitepress/theme/components/ThemeGallery.vue')['default']
+ ThemeInfo: typeof import('./.vitepress/theme/components/ThemeInfo.vue')['default']
+ TheTweet: typeof import('./.vitepress/theme/components/TheTweet.vue')['default']
+ Toc: typeof import('./.vitepress/@slidev/client/builtin/Toc.vue')['default']
+ TocList: typeof import('./.vitepress/@slidev/client/builtin/TocList.vue')['default']
+ Transform: typeof import('./.vitepress/@slidev/client/builtin/Transform.vue')['default']
+ Tweet: typeof import('./.vitepress/@slidev/client/builtin/Tweet.vue')['default']
+ TwemojiCatWithTearsOfJoy: typeof import('~icons/twemoji/cat-with-tears-of-joy')['default']
+ UimRocket: typeof import('~icons/uim/rocket')['default']
+ Youtube: typeof import('./.vitepress/@slidev/client/builtin/Youtube.vue')['default']
+ }
+}
diff --git a/custom/config-mermaid.md b/custom/config-mermaid.md
index a925cfe..6270c7b 100644
--- a/custom/config-mermaid.md
+++ b/custom/config-mermaid.md
@@ -14,5 +14,39 @@ export default defineMermaidSetup(() => {
})
```
+<<<<<<< HEAD
С помощью этой записи вы можете указать дефолтные настройки для [Mermaid](https://mermaid-js.github.io/). Посмотрите определения типов и их документацию для получения более подробной информации.
+=======
+With the setup, you can provide a custom default setting for [Mermaid](https://mermaid-js.github.io/). Refer to the type definitions and its documentation for more details.
+
+## Custom theme/styles
+
+In case you want to create your custom Mermaid themes or styles, you can do this by defining `themeVariables` like in the following example:
+
+```ts
+import { defineMermaidSetup } from '@slidev/types'
+
+export default defineMermaidSetup(() => {
+ return {
+ theme: 'base',
+ themeVariables: {
+ // General theme variables
+ noteBkgColor: '#181d29',
+ noteTextColor: '#F3EFF5cc',
+ noteBorderColor: '#404551',
+
+ // Sequence diagram variables
+ actorBkg: '#0E131F',
+ actorBorder: '#44FFD2',
+ actorTextColor: '#F3EFF5',
+ actorLineColor: '#F3EFF5',
+ signalColor: '#F3EFF5',
+ signalTextColor: '#F3EFF5',
+ }
+ }
+})
+```
+
+You can find all theme variables on the [Mermaid Theme Configuration](https://mermaid.js.org/config/theming.html) page.
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
diff --git a/custom/config-monaco.md b/custom/config-monaco.md
index 05ea0e7..18dd4c4 100644
--- a/custom/config-monaco.md
+++ b/custom/config-monaco.md
@@ -18,28 +18,28 @@ export default defineMonacoSetup(async (monaco) => {
Чтобы использовать Monaco в своих слайдах, просто добавьте `{monaco}` в фрагменты кода:
-~~~js
-//```js
+~~~md
+```js
const count = ref(1)
const plusOne = computed(() => count.value + 1)
console.log(plusOne.value) // 2
plusOne.value++ // error
-//```
+```
~~~
На
-~~~js
-//```js {monaco}
+~~~md
+```js {monaco}
const count = ref(1)
const plusOne = computed(() => count.value + 1)
console.log(plusOne.value) // 2
plusOne.value++ // error
-//```
+```
~~~
## Экспорт
@@ -56,13 +56,13 @@ monaco: true # по умолчанию "dev"
Когда вы используете TypeScript с Monaco, типы для зависимостей будут автоматически установлены на клиентской стороне.
-~~~ts
-//```ts {monaco}
+~~~md
+```ts {monaco}
import { ref } from 'vue'
import { useMouse } from '@vueuse/core'
const counter = ref(0)
-//```
+```
~~~
В приведённом выше примере убедитесь, что `vue` и `@vueuse/core` установлены локально как dependencies / devDependencies, Slidev сделает все остальное, чтобы типы для редактора работали автоматически!
@@ -107,4 +107,35 @@ export default defineMonacoSetup((monaco) => {
})
```
+<<<<<<< HEAD
> Если вы создаете тему для Slidev, используйте динамический `import()` внутри функции настройки, чтобы получить лучшие результаты при tree-shaking и code-splitting.
+=======
+> If you are creating a theme for Slidev, use dynamic `import()` inside the setup function to get better tree-shaking and code-splitting results.
+
+## Configure the Editor
+
+> Available since v0.43.0
+
+If you would like to customize the Monaco editor you may pass an `editorOptions` object that matches the [Monaco IEditorOptions](https://microsoft.github.io/monaco-editor/docs.html#interfaces/editor.IEditorOptions.html) definition.
+
+~~~md
+```ts {monaco} { editorOptions: { wordWrap:'on'} }
+console.log('HelloWorld')
+```
+~~~
+
+Alternatively if you would like these options to be applied to every Monaco instance, you can return them in the `defineMonacoSetup` function
+
+```ts
+// ./setup/monaco.ts
+import { defineMonacoSetup } from '@slidev/types'
+
+export default defineMonacoSetup(() => {
+ return {
+ editorOptions: {
+ wordWrap: 'on'
+ }
+ }
+})
+```
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
diff --git a/custom/config-parser.md b/custom/config-parser.md
new file mode 100644
index 0000000..4784932
--- /dev/null
+++ b/custom/config-parser.md
@@ -0,0 +1,172 @@
+# Configure and Extend the Parser
+
+Slidev parses your presentation file (e.g. `slides.md`) in three steps:
+
+1. A "preparsing" step is carried out: the file is split into slides using the `---` separator, and considering the possible frontmatter blocks.
+2. Each slide is parsed with an external library.
+3. Slidev resolves the special frontmatter property `src: ....`, which allows to include other md files.
+
+## Markdown Parser
+
+Configuring the markdown parser used in step 2 can be done by [configuring Vite internal plugins](/custom/config-vite#configure-internal-plugins).
+
+## Preparser Extensions
+
+> Available since v0.37.0
+
+:::warning
+Important: when modifying the preparser configuration, you need to stop and start slidev again (restart might not be sufficient).
+:::
+
+The preparser (step 1 above) is highly extensible and allows to implement custom syntaxes for your md files. Extending the preparser is considered **an advanced feature** and is susceptible to break [editor integrations](/guide/editors) due to implicit changes in the syntax.
+
+To customize it, create a `./setup/preparser.ts` file with the following content:
+
+```ts
+import { definePreparserSetup } from '@slidev/types'
+
+export default definePreparserSetup(({ filepath, headmatter }) => {
+ return [
+ {
+ transformRawLines(lines) {
+ for (const i in lines) {
+ if (lines[i] === '@@@')
+ lines[i] = 'HELLO'
+ }
+ },
+ }
+ ]
+})
+```
+
+This example systematically replaces any `@@@` line by a line with `hello`. It illustrates the structure of a preparser configuration file and some of the main concepts the preparser involves:
+- `definePreparserSetup` must be called with a function as parameter.
+- The function receives the file path (of the root presentation file) and headmatter (from the md file). It could use this information (e.g., enable extensions based on the presentation file).
+- The function must return a list of preparser extensions.
+- An extension can contain:
+ - a `transformRawLines(lines)` function that runs just after parsing the headmatter of the md file and receives a list of all lines (from the md file). The function can mutate the list arbitrarily.
+ - a `transformSlide(content, frontmatter)` function that is called for each slide, just after splitting the file, and receives the slide content as a string and the frontmatter of the slide as an object. The function can mutate the frontmatter and must return the content string (possibly modified, possibly `undefined` if no modifications have been done).
+ - a `name`
+
+## Example Preparser Extensions
+
+### Use case 1: compact syntax top-level presentation
+
+Imagine a situation where (part of) your presentation is mainly showing cover images and including other md files. You might want a compact notation where for instance (part of) `slides.md` is as follows:
+
+```md
+@cover: /nice.jpg
+# Welcome
+@src: page1.md
+@src: page2.md
+@cover: /break.jpg
+@src: pages3-4.md
+@cover: https://source.unsplash.com/collection/94734566/1920x1080
+# Questions?
+see you next time
+```
+
+To allow these `@src:` and `@cover:` syntaxes, create a `./setup/preparser.ts` file with the following content:
+
+```ts
+import { definePreparserSetup } from '@slidev/types'
+
+export default definePreparserSetup(() => {
+ return [
+ {
+ transformRawLines(lines) {
+ let i = 0
+ while (i < lines.length) {
+ const l = lines[i]
+ if (l.match(/^@cover:/i)) {
+ lines.splice(
+ i,
+ 1,
+ '---',
+ 'layout: cover',
+ `background: ${l.replace(/^@cover: */i, '')}`,
+ '---',
+ ''
+ )
+ continue
+ }
+ if (l.match(/^@src:/i)) {
+ lines.splice(
+ i,
+ 1,
+ '---',
+ `src: ${l.replace(/^@src: */i, '')}`,
+ '---',
+ ''
+ )
+ continue
+ }
+ i++
+ }
+ }
+ },
+ ]
+})
+```
+
+And that's it.
+
+### Use case 2: using custom frontmatter to wrap slides
+
+Imagine a case where you often want to scale some of your slides but still want to use a variety of existing layouts so create a new layout would not be suited.
+For instance, you might want to write your `slides.md` as follows:
+
+```md
+---
+layout: quote
+_scale: 0.75
+---
+
+# Welcome
+
+> great!
+
+---
+_scale: 4
+---
+# Break
+
+---
+
+# Ok
+
+---
+layout: center
+_scale: 2.5
+---
+# Questions?
+see you next time
+```
+
+Here we used an underscore in `_scale` to avoid possible conflicts with existing frontmatter properties (indeed, the case of `scale`, without underscore would cause potential problems).
+
+To handle this `_scale: ...` syntax in the frontmatter, create a `./setup/preparser.ts` file with the following content:
+
+```ts
+import { definePreparserSetup } from '@slidev/types'
+
+export default definePreparserSetup(() => {
+ return [
+ {
+ transformSlide(content, frontmatter) {
+ if ('_scale' in frontmatter) {
+ return [
+ ``,
+ '',
+ content,
+ '',
+ ''
+ ].join('\n')
+ }
+ },
+ },
+ ]
+})
+```
+
+And that's it.
diff --git a/custom/config-shortcuts.md b/custom/config-shortcuts.md
index feafe61..ee46351 100644
--- a/custom/config-shortcuts.md
+++ b/custom/config-shortcuts.md
@@ -2,15 +2,25 @@
> Доступно с версии v0.20
+> Since v0.35.6 (excluded), you decide which base shortcuts to keep (see `...base,` below).
+
+<<<<<<< HEAD
Создайте `./setup/shortcuts.ts` со следующим содержанием:
+=======
+## Getting started
+
+Create `./setup/shortcuts.ts` with the following content:
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
```ts
-import { defineShortcutsSetup, NavOperations } from '@slidev/types'
+import type { NavOperations, ShortcutOptions } from '@slidev/types'
+import { defineShortcutsSetup } from '@slidev/types'
-export default defineShortcutsSetup((nav: NavOperations) => {
+export default defineShortcutsSetup((nav: NavOperations, base: ShortcutOptions[]) => {
return [
+ ...base, // keep the existing shortcuts
{
key: 'enter',
fn: () => nav.next(),
@@ -29,4 +39,50 @@ export default defineShortcutsSetup((nav: NavOperations) => {
Функция получает объект с некоторыми методами навигации и возвращает массив, содержащий некоторую конфигурацию горячих клавиш. Посмотрите определения типов для получения более подробной информации.
-Подробнее о событиях нажатия клавиш в [useMagicKeys | VueUse](https://vueuse.org/core/useMagicKeys/).
\ No newline at end of file
+<<<<<<< HEAD
+Подробнее о событиях нажатия клавиш в [useMagicKeys | VueUse](https://vueuse.org/core/useMagicKeys/).
+=======
+## Advanced key binding
+
+The `key` type only allows for strings, but you can still bind multiple keys by using following convention:
+
+```ts
+import type { NavOperations, ShortcutOptions } from '@slidev/types'
+import { defineShortcutsSetup } from '@slidev/types'
+
+export default defineShortcutsSetup((nav: NavOperations, base: ShortcutOptions[]) => {
+ return [
+ ...base,
+ {
+ key: 'ShiftLeft+ArrowRight',
+ fn: () => nav.next(),
+ autoRepeat: true,
+ }
+ ]
+})
+```
+
+## Advanced navigation features
+
+The `nav` navigation operations allows you to access some functionalities than basic _next slide_ or _previous slide_. See the following for use-cases:
+
+```ts
+import { NavOperations, defineShortcutsSetup } from '@slidev/types'
+
+export default defineShortcutsSetup((nav: NavOperations) => {
+ return [
+ {
+ key: 'e',
+
+ // Set the `e` keyboard shortcut to be used as a bookmark
+ // or quick-access of sorts, to navigate specifically to
+ // slide number 42
+ fn: () => nav.go(42),
+ autoRepeat: true,
+ }
+ ]
+})
+```
+
+Refer to [useMagicKeys | VueUse](https://vueuse.org/core/useMagicKeys/) for more details about key pressed event.
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
diff --git a/custom/config-unocss.md b/custom/config-unocss.md
new file mode 100644
index 0000000..65ef03b
--- /dev/null
+++ b/custom/config-unocss.md
@@ -0,0 +1,46 @@
+# Configure UnoCSS
+
+
+
+[UnoCSS](https://unocss.dev) is now the default CSS framework for Slidev since v0.42.0. UnoCSS is an fast atomic CSS engine that has full flexibility and extensibility.
+
+By default, Slidev enables the following presets out-of-box:
+
+- [@unocss/preset-uno](https://unocss.dev/presets/uno) - Tailwind / Windi CSS compatible utilities
+- [@unocss/preset-attributify](https://unocss.dev/presets/attributify) - Attributify mode
+- [@unocss/preset-icons](https://unocss.dev/presets/icons) - Use any icons as class
+- [@unocss/preset-web-fonts](https://unocss.dev/presets/web-fonts) - Use web fonts at ease
+- [@unocss/transformer-directives](https://unocss.dev/transformers/directives) - Use `@apply` in CSS
+
+Slidev also adds shortcuts as can be seen in its [source code](https://github.com/slidevjs/slidev/blob/main/packages/client/uno.config.ts).
+
+You can therefore style your content the way you want. For example:
+
+```html
+
+
+### Name
+
+- Item 1
+- Item 2
+
+
+```
+
+## Configurations
+
+You can create `uno.config.ts` under the root of your project to extend the builtin configurations
+
+```ts
+import { defineConfig } from 'unocss'
+
+export default defineConfig({
+ shortcuts: {
+ // custom the default background
+ 'bg-main': 'bg-white text-[#181818] dark:(bg-[#121212] text-[#ddd])',
+ },
+ // ...
+})
+```
+
+Learn more about [UnoCSS configurations](https://unocss.dev/guide/config-file)
diff --git a/custom/config-vite.md b/custom/config-vite.md
index 8793f81..9593f93 100644
--- a/custom/config-vite.md
+++ b/custom/config-vite.md
@@ -2,7 +2,11 @@
+<<<<<<< HEAD
Под капотом Slidev работает на [Vite](http://vitejs.dev/). Это означает, что вы можете использовать отличную систему плагинов Vite, чтобы ещё больше настраивать свои слайды.
+=======
+Slidev is powered by [Vite](https://vitejs.dev/) under the hood. This means you can leverage Vite's great plugin system to customize your slides even further.
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
Создайте `vite.config.ts`, если хотите настроить Vite.
@@ -11,9 +15,9 @@
- [@vitejs/plugin-vue](https://github.com/vitejs/vite/tree/main/packages/plugin-vue)
- [unplugin-vue-components](https://github.com/antfu/unplugin-vue-components)
- [unplugin-icons](https://github.com/antfu/unplugin-icons)
-- [vite-plugin-md](https://github.com/antfu/vite-plugin-md)
-- [vite-plugin-windicss](https://github.com/windicss/vite-plugin-windicss)
+- [vite-plugin-vue-markdown](https://github.com/antfu/vite-plugin-vue-markdown)
- [vite-plugin-remote-assets](https://github.com/antfu/vite-plugin-remote-assets)
+- [unocss/vite](https://github.com/unocss/unocss/tree/main/packages/vite)
Узнайте больше о [предварительных настройках здесь](https://github.com/slidevjs/slidev/blob/main/packages/slidev/node/plugins/preset.ts).
diff --git a/custom/config-windicss.md b/custom/config-windicss.md
index a7f5356..635c6c0 100644
--- a/custom/config-windicss.md
+++ b/custom/config-windicss.md
@@ -2,12 +2,20 @@
+<<<<<<< HEAD
Markdown, естественно, поддерживает встроенные разметки HTML. Таким образом, вы можете стилизовать свой контент так, как захотите. Для некоторого удобства у нас есть встроенный [Windi CSS](https://github.com/windicss/windicss), так что вы можете стилизовать разметку напрямую с помощью utility-классов.
+=======
+::: warning
+Since Slidev v0.47.0, we no longer support Windi CSS. Please migrate to [UnoCSS](/custom/config-unocss).
+:::
+
+Markdown naturally supports embedded HTML markups. You can therefore style your content the way you want.
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
Например:
```html
-
+
### Имя
diff --git a/custom/directory-structure.md b/custom/directory-structure.md
index e31e5a9..bc45952 100644
--- a/custom/directory-structure.md
+++ b/custom/directory-structure.md
@@ -9,11 +9,19 @@ your-slidev/
├── components/ # кастомные компоненты
├── layouts/ # кастомные шаблоны
├── public/ # static assets
+<<<<<<< HEAD
├── setup/ # кастомные настройки / хуки
├── styles/ # кастомные стили
├── index.html # инъекции в index.html
├── slides.md # описание слайдов
└── vite.config.ts # расширение конфигурации vite
+=======
+ ├── setup/ # custom setup / hooks
+ ├── styles/ # custom style
+ ├── index.html # injections to index.html
+ ├── slides.md # the main slides entry
+ └── vite.config.ts # extending vite config
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
```
Все они необязательны.
@@ -48,7 +56,11 @@ your-slidev/
```
+<<<<<<< HEAD
Эта функция работает благодаря [`vite-plugin-components`](https://github.com/antfu/vite-plugin-components).
+=======
+This feature is powered by [`unplugin-vue-components`](https://github.com/antfu/unplugin-vue-components), learn more there.
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
Slidev также предоставляет вам некоторые [встроенные компоненты](/builtin/components).
@@ -115,18 +127,22 @@ import './code.css'
import './layouts.css'
```
+<<<<<<< HEAD
Стили будут обрабатываться через [Windi CSS](http://windicss.org/) и [PostCSS](https://postcss.org/), поэтому вы можете использовать вложенные css стили и [at-директивы](https://windicss.org/features/directives.html) прямо из коробки. Например:
+=======
+Styles will be processed by [UnoCSS](https://unocss.dev/) and [PostCSS](https://postcss.org/), so you can use css nesting and [at-directives](https://unocss.dev/transformers/directives#apply) out-of-box. For example:
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
```less
.slidev-layout {
- @apply px-14 py-10 text-[1.1rem];
+ --uno: px-14 py-10 text-[1.1rem];
h1, h2, h3, h4, p, div {
- @apply select-none;
+ --uno: select-none;
}
pre, code {
- @apply select-text;
+ --uno: select-text;
}
a {
@@ -135,7 +151,11 @@ import './layouts.css'
}
```
+<<<<<<< HEAD
[Подробнее о синтаксисе](https://windicss.org/features/directives.html).
+=======
+[Learn more about the syntax](https://unocss.dev/transformers/directives#apply).
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
## `index.html`
@@ -183,5 +203,9 @@ import './layouts.css'
Соглашения: `global-top.vue` | `global-bottom.vue`
+<<<<<<< HEAD
Подробнее: [Глобальные слои](/custom/global-layers)
+=======
+Learn more: [Global Layers](/custom/global-layers)
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
diff --git a/custom/fonts.md b/custom/fonts.md
index c48badf..f80bf9c 100644
--- a/custom/fonts.md
+++ b/custom/fonts.md
@@ -9,12 +9,21 @@
```yaml
---
fonts:
+<<<<<<< HEAD
# основной текст
sans: 'Robot'
# использование с css классом `font-serif` от windicss
serif: 'Robot Slab'
# для блоков кода, inline-кода и т.д.
mono: 'Fira Code'
+=======
+ # basically the text
+ sans: Robot
+ # use with `font-serif` css class from UnoCSS
+ serif: Robot Slab
+ # for code blocks, inline code, etc.
+ mono: Fira Code
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
---
```
@@ -24,15 +33,24 @@ fonts:
## Локальные шрифты
+<<<<<<< HEAD
По умолчанию Slidev считает, что все шрифты, указанные в конфигурациях `fonts`, взяты из Google Fonts. Если вы хотите использовать локальные шрифты, укажите `fonts.local`, чтобы отключить автоматический импорт.
+=======
+By default, Slidev assumes all the fonts specified via `fonts` configurations come from Google Fonts. If you want to use local fonts, specify the `fonts.local` to opt-out the auto-importing.
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
```yaml
---
fonts:
# вы можете использовать `,` чтобы использовать несколько шрифтов для fallback'а (как font-family в css)
sans: 'Helvetica Neue,Robot'
+<<<<<<< HEAD
# пометить 'Helvetica Neue' как локальный шрифт
local: 'Helvetica Neue'
+=======
+ # mark 'Helvetica Neue' as local font
+ local: Helvetica Neue
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
---
```
@@ -43,8 +61,13 @@ fonts:
```yaml
---
fonts:
+<<<<<<< HEAD
sans: 'Robot'
# по умолчанию
+=======
+ sans: Robot
+ # default
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
weights: '200,400,600'
# импорт курсивных шрифтов, по умолчанию `false`
italic: false
@@ -60,13 +83,17 @@ fonts:
```yaml
---
fonts:
- sans: 'Robot'
- serif: 'Robot Slab'
- mono: 'Fira Code'
+ sans: Robot
+ serif: Robot Slab
+ mono: Fira Code
---
```
+<<<<<<< HEAD
сбилдится в
+=======
+will result in
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
```css
.font-sans {
@@ -86,7 +113,7 @@ fonts:
---
fonts:
mono: 'Fira Code, monospace'
- fallback: false
+ fallbacks: false
---
```
@@ -100,8 +127,6 @@ fonts:
```yaml
---
fonts:
- provide: 'none'
+ provider: none
---
```
-
-
diff --git a/custom/global-layers.md b/custom/global-layers.md
index 5f8777f..25b18d4 100644
--- a/custom/global-layers.md
+++ b/custom/global-layers.md
@@ -4,18 +4,30 @@
Глобальные слои позволяют иметь кастомные компоненты, **постоянно** доступные в слайдах. Это может быть полезно для футера, анимации смены слайдов, глобальных эффектов и т.д.
+<<<<<<< HEAD
Slidev предоставляет два слоя для этого: создайте `global-top.vue` или `global-bottom.vue` в корне вашего проекта, и он будет загружен автоматически.
+=======
+Slidev provides three layers for this usage, create `global-top.vue`, `global-bottom.vue` or `custom-nav-controls.vue` under your project root and it will pick up automatically.
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
Связь слоёв:
+<<<<<<< HEAD
- Глобальный Top (`global-top.vue`)
- Слайды
- Глобальный Bottom (`global-bottom.vue`)
+=======
+- Global Top (`global-top.vue`)
+- Slides
+- Global Bottom (`global-bottom.vue`)
+- NavControls
+ - Customized Navigation Controls (`custom-nav-controls.vue`)
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
## Примеры
```html
-
+
@@ -23,7 +35,22 @@ Slidev предоставляет два слоя для этого: созда
Текст `Ваше имя` будет отображаться на всех ваших слайдах.
+<<<<<<< HEAD
Чтобы использовать при определённых условиях, вы можете применить его с помощью [глобального контекста Vue](/custom/vue-context).
+=======
+```html
+
+
+
+
+```
+
+The button `Next` will appear in NavControls.
+
+To enable it conditionally, you can apply it with the [Vue Global Context](/custom/vue-context).
+>>>>>>> 55df176a16c5693491d5823c68f1af798e1f718f
```html
@@ -60,3 +87,13 @@ Slidev предоставляет два слоя для этого: созда