-
-
-
-
-
diff --git a/.vitepress/theme/components/Environment.vue b/.vitepress/theme/components/Environment.vue
index 2064532..1e6d53e 100644
--- a/.vitepress/theme/components/Environment.vue
+++ b/.vitepress/theme/components/Environment.vue
@@ -1,17 +1,22 @@
+<<<<<<< HEAD
Môi trường:
{{ type }}
+=======
+
+
+ Environment:
+ {{ type }}
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
-
+
Hàm cài đặt này sẽ chỉ chạy trên môi trường Node.js, bạn có thể có quyền truy cập vào API của 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 e3001da..9defa64 100644
--- a/README.md
+++ b/README.md
@@ -15,6 +15,7 @@ Tài liệu cho [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 5453e89..04fa0ed 100644
--- a/builtin/components.md
+++ b/builtin/components.md
@@ -2,7 +2,271 @@
## Tích hợp Component
+<<<<<<< HEAD
> Các tài liệu của phần này vẫn đang được hoàn thiện. Trước đó, bạn có thể xem trực tiếp tại [source code](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
+
+
+
+![dark](/dark.png)
+
+
+
+
+![light](/light.png)
+
+
+
+~~~
+
+### `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),
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
## Tùy chỉnh Component
diff --git a/builtin/layouts.md b/builtin/layouts.md
index ffc7b45..45d31f4 100644
--- a/builtin/layouts.md
+++ b/builtin/layouts.md
@@ -7,10 +7,9 @@
=======
> As themes may override layouts behaviour, the best way to know exactly the usage, parameters and examples is referring their documentation.
-
### `center`
-Displays the content in the middle of the sreen.
+Displays the content in the middle of the screen.
### `cover`
@@ -18,7 +17,7 @@ Used to display the cover page for the presentation, may contain the presentatio
### `default`
-The most baisc layout, to display any kind of content.
+The most basic layout, to display any kind of content.
### `end`
@@ -83,6 +82,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`
@@ -135,7 +151,6 @@ url: https://github.com/slidevjs/slidev
---
```
-
### `intro`
To introduce the presentation, usually with the presentation title, a short description, the author, etc.
@@ -162,7 +177,6 @@ Separates the page content in two columns.
#### Usage
-
```md
---
layout: two-cols
@@ -180,7 +194,37 @@ This shows on the right
```
>>>>>>> ee7ae42035591cb6565a72f5217129c670a59b0c
+<<<<<<< HEAD
## Tùy chỉnh Layout
+=======
+### `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
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
Tạo một thư mục `layouts/` trong dự án gốc của bạn và chỉ cần đặt các component layout Vue tùy chỉnh của bạn bên trong nó.
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 262c565..14db718 100644
--- a/custom/config-mermaid.md
+++ b/custom/config-mermaid.md
@@ -14,4 +14,38 @@ export default defineMermaidSetup(() => {
})
```
+<<<<<<< HEAD
Trong quá trình thiết lập, bạn có thể cung cấp cài đặt mặc định tùy chỉnh cho [Mermaid](https://mermaid-js.github.io/). Tham khảo định nghĩa loại và tài liệu của chúng để biết thêm chi tiết.
+=======
+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.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
diff --git a/custom/config-monaco.md b/custom/config-monaco.md
index 31b4908..3b09c3b 100644
--- a/custom/config-monaco.md
+++ b/custom/config-monaco.md
@@ -24,28 +24,28 @@ Tìm hiểu nhiều hơn tại [Cấu hình Monaco](https://github.com/Microsoft
Để sử dụng Monaco trong các trang trình bày của bạn, chỉ cần thêm `{monaco}` vào các đoạn code của bạn:
-~~~js
-//```js
+~~~md
+```js
const count = ref(1)
const plusOne = computed(() => count.value + 1)
console.log(plusOne.value) // 2
plusOne.value++ // error
-//```
+```
~~~
Và
-~~~js
-//```js {monaco}
+~~~md
+```js {monaco}
const count = ref(1)
const plusOne = computed(() => count.value + 1)
console.log(plusOne.value) // 2
plusOne.value++ // error
-//```
+```
~~~
## Xuất trang trình bày
@@ -70,13 +70,13 @@ Khi bạn sử dụng TypeScript với Monaco, các kiểu dependencie sẽ đư
When use TypeScript with Monaco, types for dependencies will be installed to the client-side automatically.
>>>>>>> ee7ae42035591cb6565a72f5217129c670a59b0c
-~~~ts
-//```ts {monaco}
+~~~md
+```ts {monaco}
import { ref } from 'vue'
import { useMouse } from '@vueuse/core'
const counter = ref(0)
-//```
+```
~~~
<<<<<<< HEAD
@@ -125,4 +125,34 @@ export default defineMonacoSetup((monaco) => {
```
> If you are creating a theme for Slidev, use dynamic `import()` inside the setup function to get better tree-shaking and code-splitting results.
+<<<<<<< HEAD
>>>>>>> ee7ae42035591cb6565a72f5217129c670a59b0c
+=======
+
+## 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'
+ }
+ }
+})
+```
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
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 b830113..be5ad63 100644
--- a/custom/config-shortcuts.md
+++ b/custom/config-shortcuts.md
@@ -2,15 +2,25 @@
> Có hiệu lực từ v0.20
+> Since v0.35.6 (excluded), you decide which base shortcuts to keep (see `...base,` below).
+
+<<<<<<< HEAD
Tạo `./setup/shortcuts.ts` với nội dung sau:
+=======
+## Getting started
+
+Create `./setup/shortcuts.ts` with the following content:
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
```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 @@ Với việc cài đặt, bạn có thể cung cấp cài đặt tùy chỉnh ch
Hàm cấu hình nhận một đối tượng với một số hàm navigation và trả về một mảng chứa một số cấu hình phím tắt. Tham khảo định nghĩa loại để biết thêm chi tiết.
+<<<<<<< HEAD
Tham khảo [useMagicKeys | VueUse](https://vueuse.org/core/useMagicKeys/) để biết thêm chi tiết về sự kiện được nhấn phím.
+=======
+## 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.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
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 9cf0c17..40db085 100644
--- a/custom/config-vite.md
+++ b/custom/config-vite.md
@@ -2,7 +2,11 @@
+<<<<<<< HEAD
Slidev được cung cấp bởi [Vite](http://vitejs.dev/). Điều này có nghĩa là bạn có thể tận dụng hệ thống plugin tuyệt vời của Vite để tùy chỉnh các trang trình bày của mình hơn nữa.
+=======
+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.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
Nếu có file `vite.config.js` trong dự án, nó sẽ được đọc.
@@ -11,9 +15,9 @@ Slidev có các plugin sau được cấu hình sẵn:
- [@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)
<<<<<<< HEAD
Tìm hiểu thêm về [Cấu hình trước đó](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 f3347ad..4fb98a5 100644
--- a/custom/config-windicss.md
+++ b/custom/config-windicss.md
@@ -2,12 +2,20 @@
+<<<<<<< HEAD
Markdown hỗ trợ các thẻ HTML được nhúng một cách tự nhiên. Do đó, bạn có thể tạo nội dung của mình theo cách bạn muốn. Để mang lại sự tiện lợi, chúng tôi đã tích hợp sẵn [Windi CSS](https://github.com/windicss/windicss) built-in, vì vậy bạn có thể tạo thẻ HTML trực tiếp bằng các class.
+=======
+::: 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.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
Ví dụ:
```html
-
+
### Name
diff --git a/custom/directory-structure.md b/custom/directory-structure.md
index 3875e81..22ff12e 100644
--- a/custom/directory-structure.md
+++ b/custom/directory-structure.md
@@ -13,7 +13,7 @@ your-slidev/
├── styles/ # custom style
├── index.html # injections to index.html
├── slides.md # the main slides entry
- └── vite.config.ts # extending vite config
+ └── vite.config.ts # extending vite config
```
Tất cả chúng đều là tùy chọn.
@@ -48,7 +48,11 @@ your-slidev/
```
+<<<<<<< HEAD
Tính năng này được cung cấp bởi [`vite-plugin-components`](https://github.com/antfu/vite-plugin-components), hãy tìm hiểu thêm tại đây.
+=======
+This feature is powered by [`unplugin-vue-components`](https://github.com/antfu/unplugin-vue-components), learn more there.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
Slidev cũng cung cấp một số [component tích hợp](/builtin/components) để bạn sử dụng.
@@ -115,18 +119,22 @@ import './code.css'
import './layouts.css'
```
+<<<<<<< HEAD
Style sẽ được thực thi bởi [Windi CSS](http://windicss.org/) và [PostCSS](https://postcss.org/), vì vậy bạn có thể sử dụng lồng ghép css và [at-directives](https://windicss.org/features/directives.html). Ví dụ:
+=======
+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:
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
```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 +143,11 @@ Style sẽ được thực thi bởi [Windi CSS](http://windicss.org/) và [Post
}
```
+<<<<<<< HEAD
[Tìm hiểu thêm về cú pháp](https://windicss.org/features/directives.html).
+=======
+[Learn more about the syntax](https://unocss.dev/transformers/directives#apply).
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
## `index.html`
@@ -181,6 +193,12 @@ Ví dụ: đối với `index.html` tùy chỉnh sau:
## Global Layers
+<<<<<<< HEAD
Quy ước: `global-top.vue` | `global-bottom.vue`
Tìm hiểu thêm về: [Global Layers](/custom/global-layers)
+=======
+Conventions: `global-top.vue` | `global-bottom.vue`
+
+Learn more: [Global Layers](/custom/global-layers)
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
diff --git a/custom/fonts.md b/custom/fonts.md
index 15cdbc2..8617fc4 100644
--- a/custom/fonts.md
+++ b/custom/fonts.md
@@ -14,11 +14,11 @@ In your frontmatter, configure as following
---
fonts:
# basically the text
- sans: 'Robot'
- # use with `font-serif` css class from windicss
- serif: 'Robot Slab'
+ sans: Robot
+ # use with `font-serif` css class from UnoCSS
+ serif: Robot Slab
# for code blocks, inline code, etc.
- mono: 'Fira Code'
+ mono: Fira Code
---
```
@@ -28,7 +28,11 @@ Phông chữ sẽ được **nhập tự động từ [Google Fonts](https://fon
## Local Fonts
+<<<<<<< HEAD
Theo mặc định, Slidev giả định tất cả các phông chữ được chỉ định thông qua cấu hình `fonts` đến từ Google Fonts. Nếu bạn muốn sử dụng font cục bộ, hãy chỉ định `fonts.local` để chọn không tự động nhập.
+=======
+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.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
```yaml
---
@@ -36,7 +40,7 @@ fonts:
# like font-family in css, you can use `,` to separate multiple fonts for fallback
sans: 'Helvetica Neue,Robot'
# mark 'Helvetica Neue' as local font
- local: 'Helvetica Neue'
+ local: Helvetica Neue
---
```
@@ -47,7 +51,7 @@ Theo mặc định, Slidev nhập ba trọng số `200`, `400`, `600` cho mỗi
```yaml
---
fonts:
- sans: 'Robot'
+ sans: Robot
# default
weights: '200,400,600'
# import italic fonts, default `false`
@@ -64,13 +68,17 @@ Cấu hình này áp dụng cho tất cả các font web. Để có thể chi ti
```yaml
---
fonts:
- sans: 'Robot'
- serif: 'Robot Slab'
- mono: 'Fira Code'
+ sans: Robot
+ serif: Robot Slab
+ mono: Fira Code
---
```
+<<<<<<< HEAD
sẽ cho kết quả
+=======
+will result in
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
```css
.font-sans {
@@ -90,7 +98,7 @@ Nếu bạn muốn tắt font dự phòng, hãy định cấu hình như sau
---
fonts:
mono: 'Fira Code, monospace'
- fallback: false
+ fallbacks: false
---
```
@@ -104,6 +112,6 @@ Hiện tại, chỉ Google Fonts được hỗ trợ, chúng tôi dự kiến s
```yaml
---
fonts:
- provide: 'none'
+ provider: none
---
```
diff --git a/custom/global-layers.md b/custom/global-layers.md
index caa4735..fd3106a 100644
--- a/custom/global-layers.md
+++ b/custom/global-layers.md
@@ -4,18 +4,24 @@
Các Global layers cho phép bạn có các component tùy chỉnh **liên tục** trên các trang trình bày. Điều này có thể hữu ích để có chân trang, animation trang trình bày chéo, hiệu ứng toàn bộ, v.v...
+<<<<<<< HEAD
Slidev cung cấp hai layer cho cách sử dụng này, tạo `global-top.vue` hoặc `global-bottom.vue` trong dự án gốc của bạn và nó sẽ tự động nhận.
+=======
+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.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
Mối quan hệ layer:
- Global Top (`global-top.vue`)
- Slides
- Global Bottom (`global-bottom.vue`)
+- NavControls
+ - Customized Navigation Controls (`custom-nav-controls.vue`)
## Ví dụ
```html
-
+
@@ -23,7 +29,22 @@ Mối quan hệ layer:
Dòng chữ `Your Name` sẽ xuất hiện trên tất cả các slide của bạn.
+<<<<<<< HEAD
Để bật nó có điều kiện, bạn có thể áp dụng nó với [Vue Global Context](/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).
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
```html
@@ -60,3 +81,13 @@ Dòng chữ `Your Name` sẽ xuất hiện trên tất cả các slide của b
```
+
+```html
+
+
+
+
+
+```
diff --git a/custom/highlighters.md b/custom/highlighters.md
index 46f77a6..3b49141 100644
--- a/custom/highlighters.md
+++ b/custom/highlighters.md
@@ -1,34 +1,53 @@
# Đánh dấu
+<<<<<<< HEAD
Slidev đi kèm với hai công cụ đánh dấu cú pháp để bạn lựa chọn:
+=======
+Slidev comes with two syntax highlighters for you to choose from:
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
- [Prism](https://prismjs.com/)
- [Shiki](https://github.com/shikijs/shiki)
**Prism** là một trong những công cụ đánh dấu cú pháp phổ biến nhất. Việc đánh dấu được thực hiện bằng cách thêm các lớp token vào code và nó được đánh dấu bằng cách sử dụng CSS. Bạn có thể duyệt qua [chủ đề chính thức](https://github.com/PrismJS/prism-themes), hoặc tự tạo/tùy chỉnh một chủ đề rất dễ dàng bằng cách sử dụng [`prism-theme-vars`](https://github.com/antfu/prism-theme-vars).
+<<<<<<< HEAD
Mặt khác, **Shiki**, à một công cụ đánh dấu cú pháp hỗ trợ ngữ pháp TextMate. Nó tạo ra các token có màu, vì vậy không cần thêm CSS. Vì nó có hỗ trợ ngữ pháp tuyệt vời, màu sắc được tạo ra rất chính xác, giống như những gì bạn sẽ thấy trong VS Code. Shiki cũng đi kèm với [một loạt các chủ đề cài sẵn](https://github.com/shikijs/shiki/blob/master/docs/themes.md). Nhược điểm của Shiki là nó cũng yêu cầu các chủ đề TextMate (tương thích với chủ đề VS Code) để làm nổi bật, có thể khó tùy chỉnh hơn một chút.
+=======
+**Shiki** is a TextMate grammar-powered syntax highlighter. It generates colored tokens, so there is no additional CSS needed. Since it has great grammar support, the generated colors are very accurate, just like what you will see in VS Code. Shiki also comes with [a bunch of built-in themes](https://shiki.style/themes). In Slidev, we also provided the [TwoSlash](#twoslash-integration) support is also built-in.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
Chủ đề slidev thường hỗ trợ cả Prism và Shiki, nhưng tùy thuộc vào chủ đề bạn đang sử dụng, nó có thể chỉ hỗ trợ một trong số chúng.
Khi bạn có sự lựa chọn, sự cân bằng về cơ bản là:
+<<<<<<< HEAD
- **Prism** để tùy chỉnh dễ dàng hơn
- **Shiki** để đánh dấu chính xác hơn
Theo mặc định, Slidev sử dụng Prism. Bạn có thể thay đổi nó bằng cách sửa đổi frontmatter của mình:
+=======
+- **Prism** for easier customization
+- **Shiki** for accurate highlighting
+
+Slidev uses Shiki by default since v0.47. You can switch to it by adding the following to your `slides.md`:
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
```yaml
---
-highlighter: shiki
+highlighter: Prism
---
```
+<<<<<<< HEAD
## Cấu hình Prism
Để định cấu hình Prism, bạn chỉ có thể nhập css chủ đề hoặc sử dụng [`prism-theme-vars`](https://github.com/antfu/prism-theme-vars) để định cấu hình chủ đề cho cả chế độ sáng và tối. Tham khảo tài liệu của nó để biết thêm chi tiết.
## Cấu hình Shiki
+=======
+## Configure Shiki
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
@@ -40,29 +59,25 @@ import { defineShikiSetup } from '@slidev/types'
export default defineShikiSetup(() => {
return {
- theme: {
+ themes: {
dark: 'min-dark',
light: 'min-light',
},
+ transformers: [
+ // ...
+ ]
}
})
```
+<<<<<<< HEAD
Tham khảo [tài liệu của Shiki](https://github.com/shikijs/shiki/blob/master/docs/themes.md#all-themes) để biết các tên chủ đề có sẵn.
Hoặc nếu bạn muốn sử dụng chủ đề của riêng mình:
+=======
+Refer to [Shiki's docs](https://shiki.style) for available theme names.
-```ts
-/* ./setup/shiki.ts */
-
-import { defineShikiSetup } from '@slidev/types'
+## Configure Prism
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
-export default defineShikiSetup(async({ loadTheme }) => {
- return {
- theme: {
- dark: await loadTheme('path/to/theme.json')),
- light: await loadTheme('path/to/theme.json')),
- },
- }
-})
-```
+To configure your Prism, you can just import the theme CSS or use [`prism-theme-vars`](https://github.com/antfu/prism-theme-vars) to configure themes for both light and dark mode. Refer to its docs for more details.
diff --git a/custom/index.md b/custom/index.md
index def2884..6fa31be 100644
--- a/custom/index.md
+++ b/custom/index.md
@@ -1,6 +1,10 @@
# Các tùy chỉnh
+<<<<<<< HEAD
Slidev hoàn toàn có thể tùy chỉnh, từ kiểu dáng đến cấu hình công cụ. Nó cho phép bạn định cấu hình các công cụ bên dưới ([Vite](/custom/config-vite), [Windi CSS](/custom/config-windicss), [Monaco](/custom/config-monaco), v.v...)
+=======
+Slidev is fully customizable, from styling to tooling configurations. It allows you to configure the tools underneath ([Vite](/custom/config-vite), [UnoCSS](/custom/config-unocss), [Monaco](/custom/config-monaco), etc.)
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
## Cấu hình Frontmatter
@@ -9,46 +13,94 @@ Bạn có thể định cấu hình Slidev trong frontmatter của trang trình
```yaml
---
# theme id or package name
-theme: 'default'
+# Learn more: https://sli.dev/themes/use.html
+theme: default
# title of your slide, will auto infer from the first header if not specified
-title: ''
+title: Slidev
# titleTemplate for the webpage, `%s` will be replaced by the page's title
titleTemplate: '%s - Slidev'
+# information for your slides, can be a markdown string.
+info: false
+# author field for exported PDF
+author: Your Name Here
+# keywords field for exported PDF, comma-delimited.
+keywords: keyword1,keyword2
+# enable presenter mode, can be boolean, 'dev' or 'build'
+presenter: true
# enabled pdf downloading in SPA build, can also be a custom url
-download: true
-# syntax highlighter, can be 'prism' or 'shiki'
-highlighter: 'prism'
+download: false
+# filename of the export file
+exportFilename: slidev-exported
+# export options
+# use export CLI options in camelCase format
+# Learn more: https://sli.dev/guide/exporting.html
+export:
+ format: pdf
+ timeout: 30000
+ dark: false
+ withClicks: false
+ withToc: false
+# syntax highlighter, can be 'prism', 'shiki'
+highlighter: shiki
# show line numbers in code blocks
lineNumbers: false
-# enable monaco editor, default to dev only
-monaco: 'dev'
+# enable monaco editor, can be boolean, 'dev' or 'build'
+monaco: dev
+# download remote assets in local using vite-plugin-remote-assets, can be boolean, 'dev' or 'build'
+remoteAssets: false
+# controls whether texts in slides are selectable
+selectable: true
+# enable slide recording, can be boolean, 'dev' or 'build'
+record: dev
-# force color schema for the slides, could be 'auto', 'light', or 'dark'
-colorSchema: 'auto'
-# router mode for vue-router, could be "history" or "hash"
-routerMode: 'history'
+# force color schema for the slides, can be 'auto', 'light', or 'dark'
+colorSchema: auto
+# router mode for vue-router, can be "history" or "hash"
+routerMode: history
# aspect ratio for the slides
-aspectRatio: '16/9'
+aspectRatio: 16/9
# real width of the canvas, unit in px
canvasWidth: 980
+# used for theme customization, will inject root styles as `--slidev-theme-x` for attribute `x`
+themeConfig:
+ primary: '#5d8392'
+# favicon, can be a local file path or URL
+favicon: 'https://cdn.jsdelivr.net/gh/slidevjs/slidev/assets/favicon.png'
+# URL of PlantUML server used to render diagrams
+plantUmlServer: 'https://www.plantuml.com/plantuml'
# fonts will be auto imported from Google fonts
# Learn more: https://sli.dev/custom/fonts
fonts:
- sans: 'Roboto'
- serif: 'Roboto Slab'
- mono: 'Fira Code'
+ sans: Roboto
+ serif: Roboto Slab
+ mono: Fira Code
# default frontmatter applies to all slides
defaults:
- layout: 'default'
+ layout: default
# ...
+<<<<<<< HEAD
# information for your slides, can be a markdown string
info: |
## Slidev
Trang trình bày [Slidev](http://sli.dev/) đầu tiên của tôi!
+=======
+# drawing options
+# Learn more: https://sli.dev/guide/drawing.html
+drawings:
+ enabled: true
+ persist: false
+ presenterOnly: false
+ syncAll: true
+
+# HTML tag attributes
+htmlAttrs:
+ dir: ltr
+ lang: en
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
---
```
@@ -58,7 +110,28 @@ Xem [định nghĩa loại](https://github.com/slidevjs/slidev/blob/main/package
Check out the [type definitions](https://github.com/slidevjs/slidev/blob/main/packages/types/src/config.ts) for more options.
>>>>>>> ee7ae42035591cb6565a72f5217129c670a59b0c
+<<<<<<< HEAD
## Cấu trúc thư mục
+=======
+## Per slide configuration
+
+In addition, every slide accepts the following configuration in the Frontmatter block:
+
+* `clicks` (`number`): Custom clicks count (learn more [here](/guide/animations.html#custom-total-clicks-count)).
+* `disabled` (`boolean`): Completely disable and hide the slide.
+* `hide` (`boolean`): The same as `disabled`.
+* `hideInToc` (`boolean`): Hide the slide for the `` components (learn more [here](/builtin/components.html#toc)).
+* `layout` (`string`): Defines the layout component applied to the slide (learn more [here](/guide/syntax.html#front-matter-layouts) and [here](/builtin/layouts.html)).
+* `level` (`number`): Override the title level for the `` and `` components (only if `title` has also been declared, learn more [here](/builtin/components.html#titles)).
+* `preload` (`boolean`, default `true`): Preload the next slide (learn more [here](/guide/animations.html#motion)).
+* `routeAlias` (`string`): Create a route alias that can be used in the URL or with the `` component (learn more [here](/builtin/components.html#link)).
+* `src` (`string`): Includes a markdown file (learn more [here](/guide/syntax.html#multiple-entries)).
+* `title` (`string`): Override the title for the `` and `` components (learn more [here](/builtin/components.html#titles)).
+* `transition` (`string | TransitionProps`): Defines the transition between the slide and the next one (learn more [here](/guide/animations.html#slide-transitions)).
+* `zoom` (`number`): Custom zoom scale. Useful for slides with a lot of content.
+
+## Directory Structure
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
Slidev sử dụng các quy ước cấu trúc thư mục để thu nhỏ bề mặt cấu hình và làm cho các phần mở rộng trong chức năng trở nên linh hoạt và trực quan.
@@ -69,7 +142,7 @@ Tham khảo phần [Cấu trúc thư mục](/custom/directory-structure).
- [Highlighters](/custom/highlighters)
- [Configure Vue](/custom/config-vue)
- [Configure Vite](/custom/config-vite)
-- [Configure Windi CSS](/custom/config-windicss)
+- [Configure UnoCSS](/custom/config-unocss)
- [Configure Monaco](/custom/config-monaco)
- [Configure KaTeX](/custom/config-katex)
- [Configure Mermaid](/custom/config-mermaid)
diff --git a/custom/vue-context.md b/custom/vue-context.md
index b3443c6..db56914 100644
--- a/custom/vue-context.md
+++ b/custom/vue-context.md
@@ -25,6 +25,34 @@ Trang hiện tại là: {{ $slidev.nav.currentPage }}
## Thuộc tính
+### `$clicks`
+
+`$clicks` hold a number of clicks on the current slide. Can be used conditionally to show different content on clicks.
+
+```html
+
Content
+```
+
+### `$page`
+
+`$page` holds the number of the current page, 1-indexed.
+
+```md
+Page: {{ $page }}
+
+Is current page active: {{ $page === $slidev.nav.currentPage }}
+```
+
+### `$renderContext`
+
+`$renderContext` holds the current render context, can be `slide`, `overview`, `presenter` or `previewNext`
+
+```md
+
+ This content will only be rendered in slides view
+
+```
+
### `$slidev.nav`
Một đối tượng phản ứng giữ các thuộc tính và điều khiển của điều hướng trang trình bày. Ví dụ như:
@@ -41,12 +69,12 @@ $slidev.nav.go(10) // go slide #10
$slidev.nav.currentPage // current slide number
$slidev.nav.currentLayout // current layout id
-
-$slidev.nav.clicks // current clicks count
```
Để biết thêm các thuộc tính khả dụng, hãy tham khảo [nav.ts](https://github.com/slidevjs/slidev/blob/main/packages/client/logic/nav.ts).
+> Note: `$slidev.nav.clicks` is a global state while `$clicks` is local to each slide. It's recommended to **use `$clicks` over `$slidev.nav.clicks`** to avoid clicks changed been triggered on page transitions.
+
### `$slidev.configs`
Một đối tượng phản ứng giữ [các cấu hình đã được phân tích cú pháp](/custom/#frontmatter-configures) trong frontmatter đầu tiên của `slides.md`. Ví dụ
@@ -69,10 +97,16 @@ Một đối tượng phản ứng giữ các cấu hình chủ đề đã đư
---
title: My First Slidev!
themeConfig:
- primary: #213435
+ primary: # 213435
---
```
```
{{ $slidev.themeConfigs.primary }} // '#213435'
```
+
+### `$nav`
+
+> Available since v0.43.0
+
+A shorthand of `$slidev.nav`.
diff --git a/eslint.config.js b/eslint.config.js
new file mode 100644
index 0000000..f03c99f
--- /dev/null
+++ b/eslint.config.js
@@ -0,0 +1,5 @@
+import antfu from '@antfu/eslint-config'
+
+export default antfu({
+
+})
diff --git a/guide/animations.md b/guide/animations.md
index 5c8af59..82b1ae3 100644
--- a/guide/animations.md
+++ b/guide/animations.md
@@ -1,14 +1,28 @@
+<<<<<<< HEAD
# Animation
+=======
+---
+outline: deep
+---
+
+# Animations
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
## Click Animation
+> [!NOTE]
+> Since v0.48.0, we are rewritten the click animations system with much more consistent behaviors. It might change the behaviors of your existing slides in edge cases. While this page is showing the new click system, you can find more details about the refactor in [#1279](https://github.com/slidevjs/slidev/pull/1279).
+
### `v-click`
Để áp dụng "click animation" cho các element, bạn có thể sử dụng `v-click` hoặc các component ``
```md
-# Hello
+
+ Hello **World**
+<<<<<<< HEAD
@@ -22,30 +36,60 @@ Hello World
Hey!
+=======
+
+
Hey!
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
```
### `v-after`
+<<<<<<< HEAD
Việc sử dụng `v-after` tương tự như `v-click` nhưng nó sẽ hiển thị element khi kích hoạt `v-click` trước đó.
+=======
+`v-after` is only provided as a directive. It will turn the element visible when the previous `v-click` is triggered.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
```md
-
Hello
-
World
+
Hello
+
World
```
+<<<<<<< HEAD
Khi bạn nhấp vào nút "next", cả hai `Hello` và `World` sẽ cùng hiển thị.
+=======
+When you press "next", both `Hello` and `World` will show up together.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
-### `v-click-hide`
+### Hide after clicking
+<<<<<<< HEAD
Tương tự như `v-click` nhưng thay vì làm cho phần tử xuất hiện, nó làm cho element ẩn sau khi nhấn.
+=======
+Add a `.hide` modifier to `v-click` or `v-after` to make the element invisible after clicking, instead of showing up.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
+
+```md
+
Visible after 1 click
+
Hidden after 2 click
+
Hidden after 2 click
+```
+
+For `v-click` component, you can use the `hide` prop to achieve the same effect:
```md
-
Hello
+ Visible after 1 click
+ Hidden after 2 click
```
### `v-clicks`
+<<<<<<< HEAD
`v-clicks` chỉ được cung cấp như một component. Đó là một cách viết tắt để áp dụng `v-click` cho tất cả các element con của nó. Nó đặc biệt hữu ích khi làm việc với list.
+=======
+`v-clicks` is only provided as a component. It's a shorthand to apply the `v-click` directive to all its child elements. It is especially useful when working with lists and tables.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
```md
@@ -53,14 +97,146 @@ Tương tự như `v-click` nhưng thay vì làm cho phần tử xuất hiện,
- Item 1
- Item 2
- Item 3
-- Item 4
```
+<<<<<<< HEAD
Một mục sẽ hiển thị mỗi khi bạn nhấn vào "next".
### Custom Số lần Click
+=======
+An item will become visible each time you click "next".
+It accepts a `depth` prop for nested list:
+
+```md
+
+
+- Item 1
+ - Item 1.1
+ - Item 1.2
+- Item 2
+ - Item 2.1
+ - Item 2.2
+
+
+```
+
+Also, you can use the `every` prop to specify the number of items to show after each click:
+
+```md
+
+
+- Item 1 (part 1)
+- Item 1 (part 2)
+- Item 2 (part 1)
+- Item 2 (part 2)
+
+
+```
+
+### Positioning
+
+By default, the clicking animations take place one by one. You can customize the animation position of elements by using the `at` prop or the `v-click` directive with value.
+
+Like the CSS layout system, click-animated elements can be "relative" or "absolute":
+
+#### Relative Position
+
+This actual position of relative elements are calculated based on the previous relative elements:
+
+~~~md
+
visible after 1 click
+
visible after 3 clicks
+
hidden after 2 clicks
+
+```js {none|1|2}{at:'+5'}
+1 // highlighted after 7 clicks
+2 // highlighted after 8 clicks
+```
+~~~
+
+> [!NOTE]
+> The default value of `v-click` is `'+1'` when you don't specify it.
+
+In fact, `v-after` are just shortcuts for `v-click` with `at` prop:
+
+```md
+
+
+
+
+
+
+
+
+```
+
+:::info
+Only string values start with `'+'` or `'-'` like `'+1'` are treated as relative positions:
+
+| Value | Kind |
+| -------------- | -------- |
+| `'-1'`, `'+1'` | Relative |
+| `+1` === `1` | Absolute |
+| `'1'` | Absolute |
+
+So don't forget the single quotes for the relative values.
+:::
+
+#### Absolute Position
+
+The given value is the exact click count to show the element:
+
+~~~md
+
visible after 3 clicks
+
visible after 2 clicks
+
hidden after 1 click
+
+```js {none|1|2}{at:3}
+1 // highlighted after 3 clicks
+2 // highlighted after 4 clicks
+```
+~~~
+
+#### Mixed Case
+
+You can mix the absolute and relative positions:
+
+~~~md
+
visible after 1 click
+
visible after 3 clicks
+
visible after 2 click
+
visible after 1 click
+
visible after 4 clicks
+~~~
+
+The following example synchronizes the highlighting of the two code blocks:
+
+~~~md
+```js {1|2}{at:1}
+1 + 1
+'a' + 'b'
+```
+
+```js {1|2}{at:1}
+2
+'ab'
+```
+~~~
+
+### Enter & Leave
+
+> Available since v0.43.0
+
+You can also specify the enter and leave index for the `v-click` directive by passing an array. The end index is exclusive.
+
+```md
+
This will be shown on the 2nd and 3rd clicks, and hide again after the 4th.
+```
+
+### Custom Total Clicks Count
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
Theo mặc định, Slidev đếm số bước cần thiết trước khi chuyển sang trang chiếu tiếp theo. Bạn có thể ghi đè cài đặt này bằng cách chuyển tùy chọn frontmatter `clicks`:
@@ -71,6 +247,7 @@ clicks: 10
---
```
+<<<<<<< HEAD
### Ordering
Chuyển chỉ số nhấp chuột vào directive của bạn, bạn có thể tùy chỉnh thứ tự của việc revealing
@@ -100,6 +277,9 @@ clicks: 3
```
### Chuyển đổi Element
+=======
+### Element Transitions
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
Khi bạn áp dụng `v-click` cho các element của mình, nó sẽ đính kèm tên class `slidev-vclick-target` vào đó. Khi các element bị ẩn, tên class `slidev-vclick-hidden` cũng sẽ được đính kèm. Ví dụ:
@@ -128,9 +308,15 @@ Theo mặc định, một quá trình chuyển đổi opacity được áp dụn
}
```
+<<<<<<< HEAD
Bạn có thể ghi đè chúng để tùy chỉnh các hiệu ứng chuyển tiếp trong các stylesheet tùy chỉnh của mình.
Ví dụ: bạn có thể đạt được các chuyển đổi scale bằng cách:
+=======
+You can override them to customize the transition effects in your custom stylesheets.
+
+For example, you can achieve the scaling up transitions by:
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
```css
// styles.css
@@ -196,8 +382,113 @@ Văn bản `Slidev` sẽ di chuyển từ `-80px` về vị trí ban đầu khi
>
> ```
+<<<<<<< HEAD
Tìm hiểu chế độ [Demo](https://sli.dev/demo/starter/7) | [@vueuse/motion](https://motion.vueuse.org/) | [v-motion](https://motion.vueuse.org/directive-usage.html) | [Presets](https://motion.vueuse.org/presets.html)
## Chuyển trang
-> Hỗ trợ tích hợp cho các slide KHÔNG ĐƯỢC cung cấp trong phiên bản hiện tại. Chúng tôi đang có kế hoạch bổ sung hỗ trợ cho họ trong phiên bản chính tiếp theo. Trước đó, bạn vẫn có thể sử dụng các style và librarie tùy chỉnh của mình để làm điều đó.
\ No newline at end of file
+> Hỗ trợ tích hợp cho các slide KHÔNG ĐƯỢC cung cấp trong phiên bản hiện tại. Chúng tôi đang có kế hoạch bổ sung hỗ trợ cho họ trong phiên bản chính tiếp theo. Trước đó, bạn vẫn có thể sử dụng các style và librarie tùy chỉnh của mình để làm điều đó.
+=======
+Learn mode: [Demo](https://sli.dev/demo/starter/7) | [@vueuse/motion](https://motion.vueuse.org/) | [v-motion](https://motion.vueuse.org/features/directive-usage) | [Presets](https://motion.vueuse.org/features/presets)
+
+## Slide Transitions
+
+
+
+> Available since v0.39.0
+
+Slidev supports slide transitions out of the box. You can enable it by setting the `transition` frontmatter option:
+
+```md
+---
+transition: slide-left
+---
+```
+
+This will give you a nice sliding effects on slide switching. Setting it in the frontmatter will apply to all slides. You can also set different transition per slide.
+
+### Builtin Transitions
+
+- `fade` - Crossfade in/out
+- `fade-out` - Fade out and then fade in
+- `slide-left` - Slides to the left (slide to right when going backward)
+- `slide-right` - Slides to the right (slide to left when going backward)
+- `slide-up` - Slides to the top (slide to bottom when going backward)
+- `slide-down` - Slides to the bottom (slide to top when going backward)
+- `view-transition` - Slides with the view transitions API
+
+### View Transitions
+
+> Available since v0.43.0
+
+The **View Transitions API** provides a mechanism for easily creating animated transitions between different DOM states. Learn more how it works in [View Transitions API - MDN Web Docs - Mozilla](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API).
+
+:::warning
+Experimental: This is not supported by all browsers. Check the [Browser compatibility table](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API#browser_compatibility) carefully before using this.
+:::
+
+You can use the `view-transition-name` CSS property to name view transitions, which creates connections between different page elements and smooth transitions when switching slides.
+
+You can enable [MDC (Markdown Component) Syntax](/guide/syntax#mdc-syntax) support to conveniently name view-transitions:
+
+```md
+---
+transition: view-transition
+mdc: true
+---
+# View Transition {.inline-block.view-transition-title}
+---
+# View Transition {.inline-block.view-transition-title}
+```
+
+### Custom Transitions
+
+Slidev's slide transitions are powered by [Vue Transition](https://vuejs.org/guide/built-ins/transition.html). You can provide your custom transitions by:
+
+```md
+---
+transition: my-transition
+---
+```
+
+and then in your custom stylesheets:
+
+```css
+.my-transition-enter-active,
+.my-transition-leave-active {
+ transition: opacity 0.5s ease;
+}
+
+.my-transition-enter-from,
+.my-transition-leave-to {
+ opacity: 0;
+}
+```
+
+Learn more how it works in [Vue Transition](https://vuejs.org/guide/built-ins/transition.html).
+
+### Forward & Backward Transitions
+
+You can specify different transitions for forward and backward navigation using `|` as a separator in the transition name:
+
+```md
+---
+transition: go-forward | go-backward
+---
+```
+
+With this, when you go from slide 1 to slide 2, the `go-forward` transition will be applied. When you go from slide 2 to slide 1, the `go-backward` transition will be applied.
+
+### Advanced Usage
+
+The `transition` field accepts an option that will passed to the [``](https://vuejs.org/api/built-in-components.html#transition) component. For example:
+
+```md
+---
+transition:
+ name: my-transition
+ enterFromClass: custom-enter-from
+ enterActiveClass: custom-enter-active
+---
+```
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
diff --git a/guide/drawing.md b/guide/drawing.md
index c38f982..24f7a60 100644
--- a/guide/drawing.md
+++ b/guide/drawing.md
@@ -6,7 +6,7 @@ We have [drauu](https://github.com/antfu/drauu) built-in for drawing and annotat
To start, click the icon in the toolbar and start drawing. It's also available in the [Presenter Mode](/guide/presenter-mode). Drawings and annotations you created will be **synced up** automatically across all instances in real-time.
-
+
## Use with Stylus Pen
@@ -18,7 +18,7 @@ The following frontmatter configuration allows you to persist your drawings as S
```md
---
-drawings:
+drawings:
persist: true
---
```
@@ -29,7 +29,7 @@ Entirely:
```md
---
-drawings:
+drawings:
enabled: false
---
```
@@ -38,7 +38,7 @@ Only in Development:
```md
---
-drawings:
+drawings:
enabled: dev
---
```
@@ -47,7 +47,7 @@ Only in Presenter Mode:
```md
---
-drawings:
+drawings:
presenterOnly: true
---
```
@@ -58,11 +58,9 @@ By default, Slidev syncs up your drawings across all instances. If you are shari
```md
---
-drawings:
+drawings:
syncAll: false
---
```
With this config, only the drawing from the presenter instance will be able to sync with others.
-
-
diff --git a/guide/editors.md b/guide/editors.md
index 9dd0dcb..d8e8858 100644
--- a/guide/editors.md
+++ b/guide/editors.md
@@ -6,7 +6,11 @@ Nếu bạn muốn một số quản lý hiệu quả cao cho các slide của m
## Trình soạn thảo tích hợp
+<<<<<<< HEAD
Slidev đi kèm với trình soạn thảo tích hợp [CodeMirror](https://codemirror.net/) sẽ tải lại ngay lập tức và lưu các thay đổi vào file của bạn.
+=======
+Slidev comes with an integrated [CodeMirror](https://codemirror.net/) editor that will instantly reload and save the changes to your file.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
Click vào nút để mở.
@@ -40,4 +44,8 @@ The VS Code extension cung cấp một số tính năng để giúp bạn tổ c
![](https://user-images.githubusercontent.com/11247099/116809994-cc2caa00-ab73-11eb-879f-60585747c3c9.png)
-
+
+
+## Prettier Plugin
+
+Slidev also provides a Prettier plugin to format your slides. You can use it with your favorite editor that supports Prettier. Docs for the plugin can be found [here](https://github.com/slidevjs/prettier-plugin).
diff --git a/guide/exporting.md b/guide/exporting.md
index 12dd607..124f6a4 100644
--- a/guide/exporting.md
+++ b/guide/exporting.md
@@ -1,6 +1,8 @@
# Xuất slide
-## PDF
+## Slides
+
+### PDF
> Xuất sang PDF hoặc PNG dựa vào [Playwright](https://playwright.dev) để hiển thị. Do đó, bạn sẽ cần cài đặt [`playwright-chromium`](https://playwright.dev/docs/installation#download-single-browser-binary) để sử dụng tính năng này.
> Nếu bạn đang xuất trong môi trường CI, [hướng dẫn về CI](https://playwright.dev/docs/ci) có thể hữu ích.
@@ -17,6 +19,7 @@ Bây giờ xuất các slide của bạn sang PDF bằng lệnh sau
$ slidev export
```
+<<<<<<< HEAD
Sau một vài giây, các slide của bạn sẽ có sẵn tại `./slides-exports.pdf`.
<<<<<<< HEAD
@@ -84,6 +87,11 @@ Dưới đây là một số ví dụ về SPA đã xuất:
- [Composable Vue](https://talks.antfu.me/2021/composable-vue) bởi [Anthony Fu](https://github.com/antfu)
=======
## PNGs
+=======
+After a few seconds, your slides will be ready at `./slides-export.pdf`.
+
+### PNGs and Markdown
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
When passing in the `--format png` option, Slidev will export PNG images for each slide instead of a PDF.
@@ -91,7 +99,126 @@ When passing in the `--format png` option, Slidev will export PNG images for eac
$ slidev export --format png
```
+You can also compile a markdown file composed of compiled png using `--format md`.
+
+```bash
+$ slidev export --format md
+```
+
+### Dark mode
+
+In case you want to export your slides using the dark version of the theme, use the `--dark` option:
+
+```bash
+$ slidev export --dark
+```
+
+### Export Clicks Steps
+
+> Available since v0.21
+
+By default, Slidev exports one page per slide with clicks animations disabled. If you want export slides with multiple steps into multiple pages, pass the `--with-clicks` option.
+
+```bash
+$ slidev export --with-clicks
+```
+
+### Slide range
+
+You can also specify a range of slides to export with the `--range` option.
+
+```bash
+$ slidev export --range 1,4-5,6
+```
+
+### PDF outline
+
+> Available since v0.36.10
+
+You can generate the PDF outline by passing the `--with-toc` option.
+
+```bash
+$ slidev export --with-toc
+```
+
+### Output filename
+
+You can specify the output filename with the `--output` option.
+
+```bash
+$ slidev export --output my-pdf-export
+```
+
+Or in the frontmatter configuration:
+
+```yaml
+---
+exportFilename: my-pdf-export
+---
+```
+
+### Export a range of slides
+
+By default, all slides in the presentation are exported. If you want to export a specific slide or a range of slides you can set the `--range` option and specify which slides you would like to export.
+
+```bash
+$ slidev export --range 1,6-8,10
+```
+
+This option accepts both specific slide numbers and ranges.
+
+The example above would export slides 1,6,7,8, and 10.
+
+### Multiple entries
+
+You can also export multiple slides at once.
+
+```bash
+$ slidev export slides1.md slides1.md
+```
+
+Or
+
+```bash
+$ slidev export *.md
+```
+
+In this case, each input file will generate its own PDf file.
+
+## Presenter notes
+
+> Available since v0.36.8
+
+Export only the presenter notes (the last comment block for each slide) into a text document in PDF.
+
+```bash
+$ slidev export-notes
+```
+
+This command also accept multiple entries like for the [export command](#multiple-entries)
+
## Single-Page Application (SPA)
See [Static Hosting](/guide/hosting).
+<<<<<<< HEAD
>>>>>>> ee7ae42035591cb6565a72f5217129c670a59b0c
+=======
+
+## Troubleshooting
+
+### Timeout
+
+For big presentation you might want to increase the playwrigth timeout with `--timeout`
+
+```bash
+$ slidev export --timeout 60000
+```
+
+### Executable path
+
+You can set the browser executable path for playwright using `--executable-path`
+
+```bash
+$ slidev export --executable-path [path_to_chromium]
+```
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
diff --git a/guide/faq.md b/guide/faq.md
index 6330ad9..a330b94 100644
--- a/guide/faq.md
+++ b/guide/faq.md
@@ -4,7 +4,11 @@
Vì Slidev dựa trên Web nên bạn có thể áp dụng bất kỳ bố cục lưới nào tùy thích. [CSS Grids](https://css-tricks.com/snippets/css/complete-guide-grid/), [flexboxes](https://css-tricks.com/snippets/css/a-guide-to-flexbox/), hoặc thậm chí [Masonry](https://css-tricks.com/native-css-masonry-layout-in-css-grid/), bạn có toàn quyền kiểm soát.
+<<<<<<< HEAD
Vì chúng tôi đã tích hợp sẵn [Windi CSS](https://windicss.org/), đây là một cách đơn giản để bạn tham khảo:
+=======
+Since we have [UnoCSS](https://unocss.dev/) built-in, here is one simple way for you to reference:
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
```html
@@ -28,7 +32,7 @@ Go further, you can customize the size of each column like:
>>>>>>> ee7ae42035591cb6565a72f5217129c670a59b0c
```html
-
+
The first column (200px)
@@ -47,8 +51,11 @@ The third column (10% width to parent container)
```
+<<<<<<< HEAD
Tìm hiểu thêm về [Windi CSS Grids](https://windicss.org/utilities/grid.html).
+=======
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
## Positioning
Slide được xác định theo kích thước cố định (mặc định `980x552px`) và chia tỷ lệ để vừa với màn hình người dùng. Bạn có thể an toàn sử dụng position absolute trong slide của mình vì chúng sẽ scale cùng với màn hình.
@@ -100,7 +107,7 @@ Tìm hiểu thêm về [Embedded Styles](/guide/syntax.html#embedded-styles)
Bạn có thể cung cấp các style toàn cục tùy chỉnh bằng cách tạo `./style.css`, ví dụ
```css
-/* style.css */
+/* style.css */
h1 {
font-size: 10em !important;
diff --git a/guide/hosting.md b/guide/hosting.md
index f687af2..26177c0 100644
--- a/guide/hosting.md
+++ b/guide/hosting.md
@@ -8,11 +8,15 @@ You can also build the slides into a self-hostable SPA:
$ slidev build
```
-The generated application will be available under `dist/` and then you can host it on [GitHub Pages](https://pages.github.com/), [Netlify](https://netlify.app/), [Vercel](https://vercel.com/), or whatever you want. Now you can share your slides with the rest of the world with a single link.
+The generated application will be available under `dist/`.
+
+You can test the generated build using a web server (Apache, NGINX, Caddy...etc.) or in the project you can directly run: `npx vite preview`.
+
+Then you can host it on [GitHub Pages](https://pages.github.com/), [Netlify](https://netlify.app/), [Vercel](https://vercel.com/), or whatever you want. Now you can share your slides with the rest of the world with a single link.
### Base Path
-To deploy your slides under sub-routes, you will need to pass the `--base` option. For example:
+To deploy your slides under sub-routes, you will need to pass the `--base` option. The `--base` path **must begin and end** with a slash `/`; for example:
```bash
$ slidev build --base /talks/my-cool-talk/
@@ -30,9 +34,9 @@ download: true
---
```
-Slidev will generate a pdf file along with the build, and a download button will be displayed in the SPA.
+Slidev will generate a PDF file along with the build, and a download button will be displayed in the SPA.
-You can also provide a custom url to the PDF. In that case, the rendering process will be skipped.
+You can also provide a custom URL for the PDF. In that case, the rendering process will be skipped.
```md
---
@@ -40,6 +44,49 @@ download: 'https://myside.com/my-talk.pdf'
---
```
+This can also be done with the CLI option `--download` (`boolean` only).
+
+```bash
+$ slidev build --download
+```
+
+When using the download option, you can also provide the export options:
+
+* By using [CLI export options](/guide/exporting.html)
+* Or [frontmatter export options](/custom/#frontmatter-configures)
+
+### Output directory
+
+You can change the output directory using `--out`.
+
+```bash
+$ slidev build --out my-build-folder
+```
+
+### Watch mode
+
+By passing the `--watch` option the build will run in watch mode and will rebuild anytime the source changes.
+
+```bash
+$ slidev build --watch
+```
+
+### Multiple entries
+
+You can also build multiple slides at once.
+
+```bash
+$ slidev build slides1.md slides1.md
+```
+
+Or
+
+```bash
+$ slidev build *.md
+```
+
+In this case, each input file will generate a folder containing the build in the output directory.
+
## Examples
Here are a few examples of the exported SPA:
@@ -51,7 +98,7 @@ For more, check out [Showcases](/showcases).
## Hosting
-We recommend to use `npm init slidev@lastest` to scaffolding your project, which contains the necessary configuration files for hosting services out-of-box.
+We recommend to use `npm init slidev@latest` to scaffold your project, which contains the necessary configuration files for hosting services out-of-the-box.
### Netlify
@@ -59,21 +106,21 @@ We recommend to use `npm init slidev@lastest` to scaffolding your project, which
Create `netlify.toml` in your project root with the following content.
-```ts
-[build.environment]
- NODE_VERSION = "14"
-
+```toml
[build]
- publish = "dist"
- command = "npm run build"
+publish = 'dist'
+command = 'npm run build'
+
+[build.environment]
+NODE_VERSION = '20'
[[redirects]]
- from = "/*"
- to = "/index.html"
- status = 200
+from = '/*'
+to = '/index.html'
+status = 200
```
-Then go to your Netlify dashboard, create new site with the repository.
+Then go to your Netlify dashboard and create a new site with the repository.
### Vercel
@@ -89,33 +136,60 @@ Create `vercel.json` in your project root with the following content.
}
```
-Then go to your Vercel dashboard, create new site with the repository.
+Then go to your Vercel dashboard and create a new site with the repository.
-## GitHub Pages
+### GitHub Pages
- [GitHub Pages](https://pages.github.com/)
-Create `.github/workflows/deploy.yml` with following content to deploy your slides to GitHub Pages via GitHub Actions.
+To deploy your slides on GitHub Pages:
+- upload all the files of the project in your repo (i.e. named `name_of_repo`)
+- create `.github/workflows/deploy.yml` with following content to deploy your slides to GitHub Pages via GitHub Actions. In this file, replace `` with `name_of_repo`. Make sure to leave the leading and trailing slashes in place.
```yaml
name: Deploy pages
-on: push
+
+on:
+ workflow_dispatch: {}
+ push:
+ branches:
+ - main
+
jobs:
deploy:
runs-on: ubuntu-latest
+
+ permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v4
+
+ - uses: actions/setup-node@v4
with:
- node-version: '14'
+ node-version: 'lts/*'
+
- name: Install dependencies
run: npm install
+
- name: Build
- run: npm run build
- - name: Deploy pages
- uses: crazy-max/ghaction-github-pages@v2
+ run: npm run build -- --base //
+
+ - uses: actions/configure-pages@v4
+
+ - uses: actions/upload-pages-artifact@v3
with:
- build_dir: dist
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ path: dist
+
+ - name: Deploy
+ id: deployment
+ uses: actions/deploy-pages@v4
```
+- In your repository, go to Settings>Pages. Under "Build and deployment", select "Github Actions".
+- Finally, after all workflows are executed, a link to the slides should appear under Settings>Pages.
diff --git a/guide/index.md b/guide/index.md
index 4fe2d22..e047834 100644
--- a/guide/index.md
+++ b/guide/index.md
@@ -1,14 +1,28 @@
+<<<<<<< HEAD
# Bắt đầu
## Tổng quan
Slidev (slide + dev, `/slʌɪdɪv/`) là một trình tạo và trình chiếu slide dựa trên web. Nó được thiết kế để các nhà lập trình tập trung vào việc viết nội dung trong Markdown đồng thời có sự hỗ trợ của các component HTML và Vue để cung cấp layout và thiết kế hoàn hảo trên từng pixel trong bản trình bày của bạn.
+=======
+---
+outline: deep
+---
+
+# Getting Started
+
+Slidev (slide + dev, **/slaɪdɪv/**) is a web-based slides maker and presenter. It's designed for developers to focus on writing content in Markdown while also having the power of HTML and Vue components to deliver pixel-perfect layouts and designs with embedded interactive demos in your presentations.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
Nó sử dụng file markdown giàu tính năng để tạo các slide đẹp với trải nghiệm tải lại tức thì, cùng với nhiều tích hợp tích hợp như code trực tiếp, xuất PDF, ghi bản trình bày, v.v... Vì nó được cung cấp bởi web, bạn có thể làm bất cứ điều gì với Slidev - khả năng là vô tận.
Bạn có thể tìm hiểu thêm về cơ sở lý luận đằng sau dự án trong phần [Tại sao chọn Slidev](/guide/why).
+<<<<<<< HEAD
### Tính năng
+=======
+## Features
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
<<<<<<< HEAD
- 📝 [**Dựa trên Markdown**](/guide/syntax.html) - sử dụng trình soạn thảo và quy trình làm việc yêu thích của bạn
@@ -29,12 +43,12 @@ Bạn có thể tìm hiểu thêm về cơ sở lý luận đằng sau dự án
- 📝 [**Markdown-based**](/guide/syntax.html) - use your favorite editors and workflow
- 🧑💻 [**Developer Friendly**](/guide/syntax.html#code-blocks) - built-in syntax highlighting, live coding, etc.
- 🎨 [**Themable**](/themes/gallery.html) - theme can be shared and used with npm packages
-- 🌈 [**Stylish**](/guide/syntax.html#embedded-styles) - [Windi CSS](https://windicss.org/) on-demand utilities, easy-to-use embedded stylesheets
+- 🌈 [**Stylish**](/guide/syntax.html#embedded-styles) - on-demand utilities via [UnoCSS](https://github.com/unocss/unocss).
- 🤹 [**Interactive**](/custom/directory-structure.html#components) - embedding Vue components seamlessly
- 🎙 [**Presenter Mode**](/guide/presenter-mode.html) - use another window, or even your phone to control your slides
- 🎨 [**Drawing**](/guide/drawing.html) - draw and annotate on your slides
- 🧮 [**LaTeX**](/guide/syntax.html#latex) - built-in LaTeX math equations support
-- 📰 [**Diagrams**](/guide/syntax.html#diagrams) - creates diagrams with textual descriptions
+- 📰 [**Diagrams**](/guide/syntax.html#diagrams) - creates diagrams with textual descriptions
- 🌟 [**Icons**](/guide/syntax.html#icons) - Access to icons from any iconset directly
- 💻 [**Editors**](/guide/editors.html) - integrated editor, or [extension for VS Code](https://github.com/slidevjs/slidev-vscode)
- 🎥 [**Recording**](/guide/recording.html) - built-in recording and camera view
@@ -43,8 +57,9 @@ Bạn có thể tìm hiểu thêm về cơ sở lý luận đằng sau dự án
- 🛠 [**Hackable**](/custom/config-vite.html) - using Vite plugins, Vue components, or any npm packages
>>>>>>> ee7ae42035591cb6565a72f5217129c670a59b0c
-### Tech Stack
+## Scaffolding Your First Presentation
+<<<<<<< HEAD
Slidev có thể thực hiện được bằng cách kết hợp các công cụ và công nghệ này.
<<<<<<< HEAD
@@ -80,18 +95,28 @@ Với NPM:
#### Try it Online
[sli.dev/new](https://sli.dev/new)
+=======
+### Try it Online
+
+Start Slidev right in your browser: [sli.dev/new](https://sli.dev/new)
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
[![](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://sli.dev/new)
-#### Create Locally
+### Create Locally
+<<<<<<< HEAD
With NPM:
>>>>>>> ee7ae42035591cb6565a72f5217129c670a59b0c
+=======
+::: code-group
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
-```bash
-$ npm init slidev
+```bash [npm]
+npm init slidev@latest
```
+<<<<<<< HEAD
Với Yarn:
```bash
@@ -101,6 +126,21 @@ $ yarn create slidev
Làm theo lời nhắc và bắt đầu tạo slide của bạn ngay bây giờ! Để biết thêm chi tiết về cú pháp markdown, hãy đọc qua [hướng dẫn cú pháp](/guide/syntax).
### Giao diện Command Line
+=======
+```bash [yarn]
+yarn create slidev
+```
+
+```bash [pnpm]
+pnpm create slidev
+```
+
+:::
+
+Follow the prompts and start making your slides now! For more details about the markdown syntax, read through the [syntax guide](/guide/syntax).
+
+## Command Line Interface
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
Trong một dự án có cài đặt Slidev, bạn có thể sử dụng hệ nhị phân `slidev` trong các tập lệnh npm của mình.
@@ -122,7 +162,11 @@ $ npx slidev
Chạy `slidev --help` để có thêm tùy chọn.
+<<<<<<< HEAD
### Cú pháp Markdown
+=======
+## Markdown Syntax
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
Slidev đọc file `slides.md` trong dự án gốc của bạn và chuyển đổi chúng thành các slide. Bất cứ khi nào bạn thực hiện thay đổi với nó, nội dung của các slide sẽ được cập nhật ngay lập tức. Ví dụ:
@@ -137,13 +181,32 @@ Hello World
Directly use code blocks for highlighting
-//```ts
+```ts
console.log('Hello, World!')
-//```
+```
---
# Page 3
~~~
+<<<<<<< HEAD
Đọc thêm về cú pháp Slidev Markdown trong [hướng dẫn cú pháp](/guide/syntax).
+=======
+Read more about the Slidev Markdown syntax in the [syntax guide](/guide/syntax).
+
+## Tech Stack
+
+Slidev is made possible by combining these tools and technologies.
+
+- [Vite](https://vitejs.dev) - An extremely fast frontend tooling
+- [Vue 3](https://v3.vuejs.org/) powered [Markdown](https://daringfireball.net/projects/markdown/syntax) - Focus on the content while having the power of HTML and Vue components whenever needed
+- [UnoCSS](https://github.com/unocss/unocss) - On-demand utility-first CSS framework, style your slides at ease
+- [Shiki](https://github.com/shikijs/shiki), [Prism](https://github.com/PrismJS/prism), [Monaco Editor](https://github.com/Microsoft/monaco-editor) - First-class code snippets support with live coding capability
+- [RecordRTC](https://recordrtc.org) - Built-in recording and camera view
+- [VueUse](https://vueuse.org) family - [`@vueuse/core`](https://github.com/vueuse/vueuse), [`@vueuse/head`](https://github.com/vueuse/head), [`@vueuse/motion`](https://github.com/vueuse/motion), etc.
+- [Iconify](https://iconify.design/) - Iconsets collection.
+- [Drauu](https://github.com/antfu/drauu) - Drawing and annotations support
+- [KaTeX](https://katex.org/) - LaTeX math rendering.
+- [Mermaid](https://mermaid-js.github.io/mermaid) - Textual Diagrams.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
diff --git a/guide/install.md b/guide/install.md
index 7ded4f1..863481b 100644
--- a/guide/install.md
+++ b/guide/install.md
@@ -2,16 +2,25 @@
## Mẫu dành cho người mới bắt đầu
+<<<<<<< HEAD
> Slidev yêu cầu [**Node.js >=14.0**](https://nodejs.org/)
+=======
+> Slidev requires [**Node.js >=18.0**](https://nodejs.org/)
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
Cách tốt nhất để bắt đầu là sử dụng mẫu chính thức của chúng tôi.
+<<<<<<< HEAD
Với NPM:
+=======
+::: code-group
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
-```bash
-$ npm init slidev@latest
+```bash [npm]
+npm init slidev@latest
```
+<<<<<<< HEAD
Với Yarn:
```bash
@@ -19,6 +28,19 @@ $ yarn create slidev
```
Làm theo lời nhắc và nó sẽ tự động mở trình chiếu tại http://localhost:3030/ cho bạn.
+=======
+```bash [yarn]
+yarn create slidev
+```
+
+```bash [pnpm]
+pnpm create slidev
+```
+
+:::
+
+Follow the prompts and it will open up the slideshow at `http://localhost:3030/` automatically for you.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
Nó cũng bao gồm thiết lập cơ bản và một bản demo ngắn với hướng dẫn về cách bắt đầu với Slidev.
@@ -27,15 +49,16 @@ Nó cũng bao gồm thiết lập cơ bản và một bản demo ngắn với h
Nếu bạn vẫn muốn cài đặt Slidev theo cách thủ công hoặc muốn tích hợp nó vào các dự án hiện có của mình, bạn có thể thực hiện:
```bash
-$ npm install @slidev/cli @slidev/theme-default
+npm install @slidev/cli @slidev/theme-default
```
```bash
-$ touch slides.md
+touch slides.md
```
```bash
-$ npx slidev
+npx slidev
```
+<<<<<<< HEAD
> Xin lưu ý rằng nếu bạn đang sử dụng [pnpm](https://pnpm.io), bạn sẽ cần bật tùy chọn [shamefully-hoist](https://pnpm.io/npmrc#shamefully-hoist) để Slidev hoạt động bình thường:
>
> ```bash
@@ -43,25 +66,186 @@ $ npx slidev
> ```
## Cài đặt trên toàn cục
+=======
+## Install Globally
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
> Có hiệu lực từ v0.14
Bạn có thể cài đặt Slidev trên toàn cục bằng lệnh sau
```bash
-$ npm i -g @slidev/cli
+npm i -g @slidev/cli
```
Và sau đó sử dụng `slidev` ở bất cứ nơi nào mà không cần tạo dự án.
```bash
-$ slidev
+npx slidev
```
Lệnh này cũng sẽ sử dụng cục bộ `@slidev/cli` nếu nó được tìm thấy trong `node_modules`.
## Cài đặt trên Docker
+<<<<<<< HEAD
Nếu bạn cần chạy bản trình bày với container một cách nhanh chóng, bạn có thể sử dụng hình ảnh [docker](https://hub.docker.com/r/stig124/slidev) được duy trì bởi [stig124](https://github.com/Stig124), hoặc xây dựng của riêng bạn.
Tham khảo [slidevjs/container repo](https://github.com/slidevjs/container) để biết thêm chi tiết.
+=======
+If you need a rapid way to run a presentation with containers, you can use the prebuilt [docker](https://hub.docker.com/r/tangramor/slidev) image maintained by [tangramor](https://github.com/tangramor), or build your own.
+
+Just run following command in your work folder:
+
+```bash
+docker run --name slidev --rm -it \
+ --user node \
+ -v ${PWD}:/slidev \
+ -p 3030:3030 \
+ tangramor/slidev:latest
+```
+
+If your work folder is empty, it will generate a template `slides.md` and other related files under your work folder, and launch the server on port `3030`.
+
+You can access your slides from `http://localhost:3030/`
+
+### Build deployable image
+
+Or you can create your own slidev project to a docker image with Dockerfile:
+
+```Dockerfile
+FROM tangramor/slidev:latest
+
+ADD . /slidev
+
+```
+
+Create the docker image: `docker build -t myppt .`
+
+And run the container: `docker run --name myslides --rm --user node -p 3030:3030 myppt`
+
+You can visit your slides from `http://localhost:3030/`
+
+### Build hostable SPA (Single Page Application)
+
+Run command `docker exec -i slidev npx slidev build` on the running container `slidev`. It will generate static HTML files under `dist` folder.
+
+#### Host on Github Pages
+
+You can host `dist` in a static web site such as [Github Pages](https://tangramor.github.io/slidev_docker/) or Gitlab Pages.
+
+Because in Github pages the url may contain subfolder, so you need to modify the generated `index.html` to change `href="/assets/xxx` to `href="./assets/xxx`. Or you may use `--base=//` option during the build process, such as: `docker exec -i slidev npx slidev build --base=/slidev_docker/`.
+
+And to avoid Jekyll build process, you need to add an empty file `.nojekyll`.
+
+#### Host by docker
+
+You can also host it by yourself with docker:
+
+```bash
+docker run --name myslides --rm -p 80:80 -v ${PWD}/dist:/usr/share/nginx/html nginx:alpine
+```
+
+Or create a static image with following Dockerfile:
+
+```Dockerfile
+FROM nginx:alpine
+
+COPY dist /usr/share/nginx/html
+```
+
+Create the docker image: `docker build -t mystaticppt .`
+
+And run the container: `docker run --name myslides --rm -p 80:80 mystaticppt`
+
+You can visit your slides from http://localhost/
+
+Refer to the [tangramor/slidev_docker](https://github.com/tangramor/slidev_docker) for more details.
+
+## Command Line Interface (CLI)
+
+`@slidev/cli` Expose a few commands you can use with `npx slidev ...` or by adding scripts in your `package.json`:
+```json
+{
+ "script": {
+ "dev": "slidev"
+ }
+}
+```
+
+In that case you will be able to run `npm run dev`.
+
+You can pass options to any commands:
+
+* boolean option are `true` if they are present, false otherwise (example: `slidev --open`)
+* some options can have values you can add just after the option or by using the `=` character (example: `slidev --port 8080` or `slidev --port=8080`)
+
+If you use npm scripts, don't forget to add `--` after the npm command:
+```bash
+npm run slidev -- --open
+```
+
+### `slidev [entry]`
+
+Start a local server for Slidev.
+
+* `[entry]` (`string`, default: `slides.md`): path to the slides markdown entry.
+
+Options:
+
+* `--port`, `-p` (`number`, default: `3030`): port number.
+* `--open`, `-o` (`boolean`, default: `false`): open in browser.
+* `--remote [password]` (`string`): listen to public host and enable remote control, if a value is passed then the presenter mode is private and only accessible by passing the given password in the URL query `password` parameter.
+* `--bind` (`string`, default: `0.0.0.0`): specify which IP addresses the server should listen on in the remote mode.
+* `--log` (`'error', 'warn', 'info', 'silent'`, default: `'warn'`): Log level.
+* `--force`, `-f` (`boolean`, default: `false`): force the optimizer to ignore the cache and re-bundle.
+* `--theme`, `-t` (`string`): override theme.
+
+### `slidev build [entry]`
+
+Build hostable SPA.
+
+* `[entry]` (`string`, default: `slides.md`): path to the slides markdown entry.
+
+Options:
+
+* `--watch`, `-w` (`boolean`, default: `false`): build watch.
+* `--out`, `-o` (`string`, default: `dist`): output dir.
+* `--base` (`string`, default: `/`): base URL (see https://cli.vuejs.org/config/#publicpath)
+* `--download` (`boolean`, default: `false`): allow to download the slides as PDF inside the SPA.
+* `--theme`, `-t` (`string`): override theme.
+
+### `slidev export [entry]`
+
+Export slides to PDF (or other format).
+
+* `[entry]` (`string`, default: `slides.md`): path to the slides markdown entry.
+
+Options:
+
+* `--output` (`string`, default: use `exportFilename` (see https://sli.dev/custom/#frontmatter-configures) or use `[entry]-export`): path to the output.
+* `--format` (`'pdf', 'png', 'md'`, default: `'pdf'`): output format.
+* `--timeout` (`number`, default: `30000`): timeout for rendering the print page (see https://playwright.dev/docs/api/class-page#page-goto).
+* `--range` (`string`): page ranges to export (example: `'1,4-5,6'`).
+* `--dark` (`boolean`, default: `false`): export as dark theme.
+* `--with-clicks`, `-c` (`boolean`, default: `false`): export pages for every clicks (see https://sli.dev/guide/animations.html#click-animations).
+* `--theme`, `-t` (`string`): override theme.
+
+### `slidev format [entry]`
+
+Format the markdown file.
+
+* `[entry]` (`string`, default: `slides.md`): path to the slides markdown entry.
+
+### `slidev theme [subcommand]`
+
+Theme related operations.
+
+Subcommands:
+
+* `eject [entry]`: Eject current theme into local file system
+ * `[entry]` (`string`, default: `slides.md`): path to the slides markdown entry.
+ * Options:
+ * `--dir` (`string`, default: `theme`): output dir.
+ * `--theme`, `-t` (`string`): override theme.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
diff --git a/guide/navigation.md b/guide/navigation.md
index d716354..5d0a367 100644
--- a/guide/navigation.md
+++ b/guide/navigation.md
@@ -2,7 +2,11 @@
## Thanh điều hướng
+<<<<<<< HEAD
Di chuyển chuột đến góc dưới cùng bên trái của trang Slidev, thanh điều hướng sẽ hiện ra.
+=======
+Move your mouse to the bottom left corner of Slidev page to make the navigation bar appear.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
![](/screenshots/navbar.png)
@@ -28,10 +32,14 @@ Di chuyển chuột đến góc dưới cùng bên trái của trang Slidev, tha
## Tổng quan Slide
+<<<<<<< HEAD
<<<<<<< HEAD
Bằng cách nhấn o hoặc nhấn vào nút trong thanh điều hướng, bạn có thể có tổng quan về các slide của mình, vì vậy bạn có thể chuyển đổi giữa chúng một cách dễ dàng.
=======
By pressing o or clicking the button in the navigation bar, you can have the overview of your slides so you can jump between them easily.
>>>>>>> ee7ae42035591cb6565a72f5217129c670a59b0c
+=======
+By pressing o or clicking the button in the navigation bar, you can have the overview of your slides so you can jump between them easily.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
![](/screenshots/slides-overview.png)
diff --git a/guide/presenter-mode.md b/guide/presenter-mode.md
index 6bb127d..eb7ec31 100644
--- a/guide/presenter-mode.md
+++ b/guide/presenter-mode.md
@@ -1,5 +1,39 @@
# Chế độ Trình bày
+<<<<<<< HEAD
Nhấn vào nút trong bảng điều hướng hoặc truy cập http://localhost:3030/presenter theo cách thủ công, để vào chế độ người thuyết trình. Bất cứ khi nào bạn vào chế độ người thuyết trình, các phiên bản trang khác sẽ tự động đồng bộ với người trình bày.
+=======
+Click the button in the navigation panel, or visit `http://localhost:3030/presenter` manually, to enter the presenter mode. Whenever you enter the presenter mode, other page instances will automatically stay in sync with the presenter.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
![](/screenshots/presenter-mode.png)
+
+## Disabling
+
+Presenter mode is enabled by default.
+
+You can disable this feature with the following config:
+
+```md
+---
+presenter: false
+---
+```
+
+Or you can enable it only for `dev` or `build` mode by setting the mode you want in the config:
+```md
+---
+presenter: dev
+---
+```
+In that case the presenter will only be available when running `slidev` but not when running `slidev build`.
+
+## Remote restricted access
+
+You can run your presentation with remote access by running `slidev --remote`.
+
+In that case you may want to share the slides with other people but you don't want them to access the presenter mode to mess up your presentation.
+
+For this scenario you can provide a password for starting the server by running `slidev --remote=your_password`.
+
+In that case you will need to provide the password when accessing `/presenter/*` routes.
diff --git a/guide/recording.md b/guide/recording.md
index 150142b..b774125 100644
--- a/guide/recording.md
+++ b/guide/recording.md
@@ -6,7 +6,7 @@ Slidev được tích hợp chế độ record và chế độ xem camera. Bạn
Nhấn vào nút trong bảng điều hướng để hiển thị chế độ xem camera của bạn trong bản trình bày. Bạn có thể kéo để di chuyển nó và sử dụng trình xử lý ở góc dưới bên phải để thay đổi kích thước. Kích thước và vị trí sẽ tồn tại trong `localStorage` và do đó sẽ nhất quán qua nhiều lần làm mới, vì vậy không cần phải lo lắng về điều đó.
-
+
## Recording
diff --git a/guide/syntax.md b/guide/syntax.md
index 4819cad..acb47bb 100644
--- a/guide/syntax.md
+++ b/guide/syntax.md
@@ -1,8 +1,20 @@
+<<<<<<< HEAD
# Cú pháp Markdown
Slide được viết trong **một file markdown duy nhất** (theo mặc định là `./slides.md`).
Bạn có thể sử dụng [các tính năng Markdown](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) như bình thường, với sự hỗ trợ bổ sung của các component HTML và Vue. Tạo style bằng [Windi CSS](https://windicss.org) cũng được hỗ trợ. Sử dụng dấu `---` được đệm bằng một dòng mới để tách các slide của bạn.
+=======
+---
+outline: deep
+---
+
+# Markdown Syntax
+
+Slides are written within **a single markdown file** (by default `./slides.md`).
+
+You can use [the Markdown features](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) as you normally would, with the additional support of inlined HTML and Vue Components. Styling using [UnoCSS](/custom/config-unocss) is also supported. Use `---` padded with a new line to separate your slides.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
~~~md
# Slidev
@@ -30,6 +42,7 @@ You can directly use Windi CSS and Vue components to style and enrich your slide
~~~
+<<<<<<< HEAD
## Front Matter & Layout
<<<<<<< HEAD
@@ -37,6 +50,11 @@ Bạn có thể chỉ định layout và siêu dữ liệu khác cho mỗi slide
=======
Specify layouts and other metadata for each slide by converting the separators into [front matter blocks](https://jekyllrb.com/docs/front-matter/). Each frontmatter starts with a triple-dash and ends with another. Texts between them are data objects in [YAML](https://www.cloudbees.com/blog/yaml-tutorial-everything-you-need-get-started/) format. For example:
>>>>>>> ee7ae42035591cb6565a72f5217129c670a59b0c
+=======
+## Frontmatter & Layouts
+
+Specify layouts and other metadata for each slide by converting the separators into [frontmatter blocks](https://jekyllrb.com/docs/front-matter/). Each frontmatter starts with a triple-dash and ends with another. Texts between them are data objects in [YAML](https://www.cloudbees.com/blog/yaml-tutorial-everything-you-need-get-started/) format. For example:
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
~~~md
---
@@ -51,7 +69,7 @@ This is the cover page.
layout: center
background: './images/background-1.png'
class: 'text-white'
----
+---
# Page 2
@@ -66,64 +84,198 @@ This is a default page without any additional metadata.
Tham khảo [customization](/custom/) để biết thêm chi tiết.
+> The custom syntax might not be compactible with some formatters like Prettier. To improve that, we also support using a direct `yaml` code block to define the frontmatter:
+>
+> ~~~markdown
+> ---
+> layout: cover
+> ---
+>
+> # Slidev
+>
+> This is the cover page.
+>
+> ---
+>
+> ```yaml
+> # The first yaml block will be treated as the frontmatter of that slide
+> layout: center
+> background: './images/background-1.png'
+> class: 'text-white'
+> ```
+>
+> # Page 2
+>
+> This is a page with the layout `center` and a background image.
+> ~~~
+>
+> (Available since v0.44.0)
+
## Code Blocks
Một lý do lớn mà tôi xây dựng Slidev là làm cho code của tôi trông vừa phải trong các slide. Vì vậy, đúng như bạn mong đợi, bạn có thể sử dụng khối code Markdown để làm nổi bật code của mình.
-~~~ts
-//```ts
+~~~md
+```ts
console.log('Hello, World!')
-//```
+```
~~~
+<<<<<<< HEAD
<<<<<<< HEAD
### Đánh dấu dòng
=======
We support [Prism](http://prismjs.com) and [Shiki](https://github.com/shiki/shiki) as syntax highlighters. Refer to [the highlighters section](/custom/highlighters) for more details.
+=======
+We support [Prism](https://prismjs.com), [Shiki](https://github.com/shikijs/shiki) as syntax highlighters. Refer to [the highlighters section](/custom/highlighters) for more details.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
### Line Highlighting
>>>>>>> ee7ae42035591cb6565a72f5217129c670a59b0c
+<<<<<<< HEAD
Để đánh dấu các dòng cụ thể, chỉ cần thêm số dòng trong dấu ngoặc nhọn `{}`. Số dòng bắt đầu đếm từ 1.
+=======
+To highlight specific lines, simply add line numbers within bracket `{}`. Line numbers start counting from 1 by default.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
-~~~ts
-//```ts {2,3}
+~~~md
+```ts {2,3}
function add(
a: Ref | number,
b: Ref | number
) {
return computed(() => unref(a) + unref(b))
}
-//```
+```
~~~
+<<<<<<< HEAD
Để thay đổi vùng đánh dấu trong nhiều bước, bạn có thể sử dụng dấu `|` để tách chúng. Ví dụ
+=======
+You can enable line number to all slides by setting `lineNumbers: true` on the config or enable each code block individually by setting `lines:true`. You can also set the starting line for each code block and highlight the lines accordingly, defaults to 1:
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
-~~~ts
-//```ts {2-3|5|all}
+~~~md
+```ts {6,7}{lines:true, startLine:5}
function add(
a: Ref | number,
b: Ref | number
) {
return computed(() => unref(a) + unref(b))
}
-//```
+```
~~~
+<<<<<<< HEAD
Đầu tiên, điều này sẽ làm nổi bật `a: Ref | number` và `b: Ref | number`, và sau đó là `return computed(() => unref(a) + unref(b))` sau một cú nhấp chuột, và cuối cùng là toàn bộ khối. Tìm hiểu thêm trong [hướng dẫn về animation click](/guide/animations).
+=======
+To change the highlight in multiple clicks, you can use `|` to separate them:
+
+~~~md
+```ts {2-3|5|all}
+function add(
+ a: Ref | number,
+ b: Ref | number
+) {
+ return computed(() => unref(a) + unref(b))
+}
+```
+~~~
+
+This will first highlight `a: Ref | number` and `b: Ref | number`, and then `return computed(() => unref(a) + unref(b))` after one click, and lastly, the whole block.
+
+You can set the line number to `hide` to hide the code block or `none` to not highlight any line:
+
+~~~md
+```ts {hide|none}
+function add(
+ a: Ref | number,
+ b: Ref | number
+) {
+ return computed(() => unref(a) + unref(b))
+}
+```
+~~~
+
+::: tip
+Learn more in the [clicks animations guide](./animations#positioning).
+:::
+
+If the code doesn't fit into one slide, you use the `maxHeight` to set fixed height and enable scrolling:
+
+~~~md
+```ts {2|3|7|12}{maxHeight:'100px'}
+function add(
+ a: Ref | number,
+ b: Ref | number
+) {
+ return computed(() => unref(a) + unref(b))
+}
+/// ...as many lines as you want
+const c = add(1, 2)
+```
+~~~
+
+### TwoSlash Integration
+
+This feature is only available when you [set `highlighter` to `shiki`](/custom/highlighters)
+
+[TwoSlash](https://twoslash.netlify.app/) is a powerful tool for rendering TypeScript code blocks with type information on hover or inlined. It's quite useful for preparing slides for JavaScript/TypeScript-related topics.
+
+To use it, you can add `twoslash` to the code block's language identifier:
+
+~~~md
+```ts twoslash
+import { ref } from 'vue'
+
+const count = ref(0)
+// ^?
+```
+~~~
+
+It will be rendered as:
+
+```ts twoslash
+import { ref } from 'vue'
+
+const count = ref(0)
+// ^?
+```
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
### Trình soạn thảo Monaco
Bất cứ khi nào bạn muốn thực hiện một số sửa đổi trong bản trình bày, chỉ cần thêm `{monaco}` sau ngôn ngữ id - nó biến khối thành một trình soạn thảo Monaco đầy đủ tính năng!
-~~~ts
-//```ts {monaco}
+~~~md
+```ts {monaco}
console.log('HelloWorld')
-//```
+```
~~~
Tìm hiểu thêm về [configuring Monaco](/custom/config-monaco).
+#### Monaco Diff
+
+Monaco can also generate a diff between two code blocks. Use `{monaco-diff}` to turn the block into a [diff Monaco editor](https://microsoft.github.io/monaco-editor/playground.html?source=v0.36.1#example-creating-the-diffeditor-multi-line-example) and use `~~~` to separate both original and modified version of the code!
+
+````md
+```ts {monaco-diff}
+This line is removed on the right.
+just some text
+abcd
+efgh
+Some more text
+~~~
+just some text
+abcz
+zzzzefgh
+Some more text.
+This line is removed on the left.
+```
+````
+
## Embedded Styles
Bạn có thể sử dụng thẻ `
@@ -179,7 +337,7 @@ For local assets, put them into the [`public` folder](/custom/directory-structur
![Local Image](/pic.png)
```
-For you want to apply custom sizes or styles, you can convert them to the `` tag
+For you want to apply custom sizes or styles, you can convert them to the `` tag
```html
@@ -218,16 +376,29 @@ This is another note
## Icons
+<<<<<<< HEAD
Slidev cho phép bạn có quyền truy cập vào hầu hết tất cả các bộ icon mã nguồn mở phổ biến **trực tiếp** trong markdown của bạn. Được cung cấp bởi [`vite-plugin-icons`](https://github.com/antfu/vite-plugin-icons) và [Iconify](https://iconify.design/).
+=======
+Slidev allows you to have the accessing to almost all the popular open-source iconsets **directly** in your markdown after installing the corresponding package. Powered by [`unplugin-icons`](https://github.com/antfu/unplugin-icons) and [Iconify](https://iconify.design/).
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
Việc đặt tên theo chuyển đổi của [Iconify](https://iconify.design/) `{collection-name}-{icon-name}`. Ví dụ:
+<<<<<<< HEAD
- `` - từ [Material Design Icons](https://github.com/Templarian/MaterialDesign)
- `` - từ [Carbon](https://github.com/carbon-design-system/carbon/tree/main/packages/icons)
- `` - từ [Unicons Monochrome](https://github.com/Iconscout/unicons)
- `` - từ [Twemoji](https://github.com/twitter/twemoji)
- `` - từ [SVG Logos](https://github.com/gilbarbara/logos)
- Và nhiều hơn nữa...
+=======
+- `` - from [Material Design Icons](https://github.com/Templarian/MaterialDesign) - [`@iconify-json/mdi`](https://npmjs.com/package/@iconify-json/mdi)
+- `` - from [Carbon](https://github.com/carbon-design-system/carbon/tree/main/packages/icons) - [`@iconify-json/carbon`](https://npmjs.com/package/@iconify-json/carbon)
+- `` - from [Unicons Monochrome](https://github.com/Iconscout/unicons) - [`@iconify-json/uim`](https://npmjs.com/package/@iconify-json/uim)
+- `` - from [Twemoji](https://github.com/twitter/twemoji) - [`@iconify-json/twemoji`](https://npmjs.com/package/@iconify-json/twemoji)
+- `` - from [SVG Logos](https://github.com/gilbarbara/logos) - [`@iconify-json/logos`](https://npmjs.com/package/@iconify-json/logos)
+- And much more...
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
<<<<<<< HEAD
Bạn có thể duyệt và tìm kiếm tất cả các icon có sẵn với [Icônes](https://icones.js.org/).
@@ -331,7 +502,44 @@ This shows on the right
This shows on the left
```
+<<<<<<< HEAD
## Cấu hình
+=======
+## Import Code Snippets
+
+> Available since v0.47.0
+
+You can import code snippets from existing files via following syntax:
+
+```md
+<<< @/snippets/snippet.js
+```
+
+:::tip
+The value of `@` corresponds to your package's root directory. It's recommended to put snippets in `@/snippets`, for compatibility with the Monaco editor. Alternatively, you can also import from relative paths.
+:::
+
+You can also use a [VS Code region](https://code.visualstudio.com/docs/editor/codebasics#_folding) to only include the corresponding part of the code file:
+
+```md
+<<< @/snippets/snippet.js#region-name
+```
+
+To explicitly specify the language of the imported code, you can add a language identifier after:
+
+```md
+<<< @/snippets/snippet.js ts
+```
+
+Any code block features like [line highlighting](#line-highlighting) and [Monaco editor](#monaco-editor) are also supported:
+
+```md
+<<< @/snippets/snippet.js {2,3|5}{lines:true}
+<<< @/snippets/snippet.js ts {monaco}{height:200px}
+```
+
+## Configurations
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
Tất cả các cấu hình cần thiết có thể được xác định trong tệp Markdown. Ví dụ:
@@ -353,7 +561,7 @@ Tìm hiểu thêm về [cấu hình frontmatter](/custom/#frontmatter-configures
Slidev đi kèm với hỗ trợ LaTeX bên ngoài, được cung cấp bởi [KaTeX](https://katex.org/).
-
+
### Inline
@@ -367,7 +575,7 @@ $\sqrt{3x-1}+(1+x)^2$
Sử dụng hai (`$$`) để hiển thị khối. Chế độ này sử dụng các ký hiệu lớn hơn và căn giữa kết quả.
-```md
+```latex
$$
\begin{array}{c}
@@ -384,6 +592,25 @@ $$
Tìm hiểu thêm: [Demo](https://sli.dev/demo/starter/8) | [KaTeX](https://katex.org/) | [`markdown-it-katex`](https://github.com/waylonflinn/markdown-it-katex)
+### LaTex line highlighting
+
+> Available since v0.43.1
+
+To highlight specific lines, simply add line numbers within bracket `{}`. Line numbers start counting from 1 by default.
+
+```latex
+$$ {1|3|all}
+\begin{array}{c}
+\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} &
+= \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} & = 4 \pi \rho \\
+\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\
+\nabla \cdot \vec{\mathbf{B}} & = 0
+\end{array}
+$$
+```
+
+The `at` and `finally` options of [code blocks](#line-highlighting) are also available for LaTeX blocks.
+
## Diagrams
Bạn cũng có thể tạo sơ đồ / đồ thị từ mô tả bằng văn bản trong Markdown của mình, được cung cấp bởi [Mermaid](https://mermaid-js.github.io/mermaid).
@@ -507,3 +734,27 @@ src: ./content.md
src: ./content.md
---
```
+
+## MDC Syntax
+
+> Available since v0.43.0
+
+Slidev supports optional [MDC (Markdown Components) Syntax](https://content.nuxtjs.org/guide/writing/mdc) powered by [`markdown-it-mdc`](https://github.com/antfu/markdown-it-mdc).
+
+You can enable it by adding `mdc: true` to the frontmatter of your markdown file.
+
+```mdc
+---
+mdc: true
+---
+
+This is a [red text]{style="color:red"} :inline-component{prop="value"}
+
+![](/image.png){width=500px lazy}
+
+::block-component{prop="value"}
+The **default** slot
+::
+```
+
+Learn more about [the syntax](https://content.nuxt.com/guide/writing/mdc).
diff --git a/guide/why.md b/guide/why.md
index 3b3b97c..b237665 100644
--- a/guide/why.md
+++ b/guide/why.md
@@ -2,7 +2,11 @@
Có rất nhiều trình tạo slide WYSIWYG đa năng, có mục đích chung, như [Microsoft PowerPoint](https://www.microsoft.com/en-us/microsoft-365/powerpoint) và [Apple Keynote](https://www.apple.com/keynote/). Chúng hoạt động khá tốt để tạo các slide đẹp với animation, biểu đồ và nhiều thứ khác, đồng thời rất trực quan và dễ học. Vậy tại sao phải làm Slidev?
+<<<<<<< HEAD
Slidev nhằm mục đích cung cấp tính linh hoạt và tính tương tác cho các nhà lập trình để làm cho bản trình bày của họ trở nên thú vị, biểu cảm và hấp dẫn hơn bằng cách sử dụng các công cụ và công nghệ mà họ đã quen thuộc.
+=======
+Slidev aims to provide the flexibility and interactivity for developers to make their presentations even more interesting, expressive, and attractive by using the tools and technologies they are already familiar with.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
Khi làm việc với các trình soạn thảo WYSIWYG, bạn rất dễ bị phân tâm bởi các tùy chọn tạo kiểu. Slidev khắc phục điều đó bằng cách tách nội dung và hình ảnh. Điều này cho phép bạn tập trung vào một thứ tại một thời điểm, đồng thời có thể sử dụng lại các chủ đề từ cộng đồng. Slidev không tìm cách thay thế hoàn toàn các slide deck builder khác. Thay vào đó, nó tập trung vào việc phục vụ cộng đồng nhà lập trình.
@@ -32,7 +36,11 @@ Tìm hiểu thêm về [đánh dấu](/custom/highlighters) và [cấu hình Mon
## Nhanh
+<<<<<<< HEAD
Slidev được cung cấp bởi [Vite](https://vitejs.dev/), [Vue 3](https://v3.vuejs.org/) và [Windi CSS](https://windicss.org/), cung cấp cho bạn trải nghiệm tác giả tuyệt vời nhất. Mọi thay đổi bạn thực hiện sẽ phản ánh vào các slide của bạn **ngay lập tức**.
+=======
+Slidev is powered by [Vite](https://vitejs.dev/), [Vue 3](https://v3.vuejs.org/) and [UnoCSS](https://unocss.dev/), which give you the most wonderful authoring experience. Every change you made will reflect to your slides **instantly**.
+>>>>>>> 15820b064d1f419ed06cd798ae4b6dfe0c230e94
Tìm thêm về [our tech stack](/guide/#tech-stack).
@@ -66,6 +74,4 @@ $ npm init slidev
Hoặc xem trước nó:
-