mirror of
https://github.com/andatoshiki/toshiki-notebook.git
synced 2026-06-06 03:11:22 +00:00
feat: introduce new twoslash feature into vitepress with its associated plugin usage documentation
This commit is contained in:
parent
4f2b400e3e
commit
931faa61c3
6
.gitignore
vendored
6
.gitignore
vendored
@ -39,6 +39,7 @@ bower_components
|
|||||||
build/Release
|
build/Release
|
||||||
|
|
||||||
# Dependency directories
|
# Dependency directories
|
||||||
|
docs/node_modules/
|
||||||
node_modules/
|
node_modules/
|
||||||
jspm_packages/
|
jspm_packages/
|
||||||
|
|
||||||
@ -133,4 +134,7 @@ dist
|
|||||||
cache
|
cache
|
||||||
|
|
||||||
# node generated xmlhttprequest file
|
# node generated xmlhttprequest file
|
||||||
.node-xmlhttprequest-sync-*
|
.node-xmlhttprequest-sync-*]
|
||||||
|
|
||||||
|
# frontmatter cms config
|
||||||
|
.frontmatter
|
||||||
@ -4,6 +4,7 @@ import { markdown } from './config/markdown'
|
|||||||
import { metaData } from './config/constants'
|
import { metaData } from './config/constants'
|
||||||
import { head } from './config/head'
|
import { head } from './config/head'
|
||||||
import { themeConfig } from './config/theme'
|
import { themeConfig } from './config/theme'
|
||||||
|
import { withTwoslash } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
|
||||||
|
|
||||||
import { SitemapStream } from 'sitemap'
|
import { SitemapStream } from 'sitemap'
|
||||||
import { createWriteStream } from 'node:fs'
|
import { createWriteStream } from 'node:fs'
|
||||||
@ -11,7 +12,8 @@ import { resolve } from 'node:path'
|
|||||||
|
|
||||||
const links: { url: string; lastmod: PageData['lastUpdated'] }[] = []
|
const links: { url: string; lastmod: PageData['lastUpdated'] }[] = []
|
||||||
|
|
||||||
export default defineConfig({
|
export default withTwoslash(
|
||||||
|
defineConfig({
|
||||||
lang: metaData.lang, // i18n default english translation
|
lang: metaData.lang, // i18n default english translation
|
||||||
title: metaData.title, // title from metadata config
|
title: metaData.title, // title from metadata config
|
||||||
description: metaData.description, // description from metadata config
|
description: metaData.description, // description from metadata config
|
||||||
@ -59,5 +61,54 @@ export default defineConfig({
|
|||||||
await new Promise(r => writeStream.on('finish', r))
|
await new Promise(r => writeStream.on('finish', r))
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
)
|
||||||
|
// defineConfig ({
|
||||||
|
// lang: metaData.lang, // i18n default english translation
|
||||||
|
// title: metaData.title, // title from metadata config
|
||||||
|
// description: metaData.description, // description from metadata config
|
||||||
|
// markdown: markdown, // markdown config
|
||||||
|
// lastUpdated: true, // whether enabling lastupdated or not
|
||||||
|
// head, // documentation head tag options
|
||||||
|
// themeConfig, // default exported theme config
|
||||||
|
// cleanUrls: true, // clean urls configs to remove standard genreated page file type extensions
|
||||||
|
// outDir: '../dist', // specify staic pages build output dir
|
||||||
|
// // vue template options for preventing katex build crashes
|
||||||
|
// vue: {
|
||||||
|
// template: {
|
||||||
|
// compilerOptions: {
|
||||||
|
// isCustomElement: tag => customElements.includes(tag),
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// // i18n localization config
|
||||||
|
// locales: {
|
||||||
|
// '/': {
|
||||||
|
// label: 'English',
|
||||||
|
// lang: 'en-US',
|
||||||
|
// },
|
||||||
|
// '/jp/': {
|
||||||
|
// label: 'Japanese',
|
||||||
|
// title: 'Vue Test Utils',
|
||||||
|
// lang: 'jp-JP',
|
||||||
|
// description: 'La documentation officielle de Vue Test Utils',
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// ignoreDeadLinks: true,
|
||||||
|
// transformHtml: (_, id, { pageData }) => {
|
||||||
|
// if (!/[\\/]404\.html$/.test(id))
|
||||||
|
// links.push({
|
||||||
|
// url: pageData.relativePath.replace(/((^|\/)index)?\.md$/, '$2'),
|
||||||
|
// lastmod: pageData.lastUpdated,
|
||||||
|
// })
|
||||||
|
// },
|
||||||
|
// buildEnd: async ({ outDir }) => {
|
||||||
|
// const sitemap = new SitemapStream({ hostname: 'https://note.toshiki.dev/' })
|
||||||
|
// const writeStream = createWriteStream(resolve(outDir, 'sitemap.xml'))
|
||||||
|
// sitemap.pipe(writeStream)
|
||||||
|
// links.forEach(link => sitemap.write(link))
|
||||||
|
// sitemap.end()
|
||||||
|
// await new Promise(r => writeStream.on('finish', r))
|
||||||
|
// },
|
||||||
|
// })
|
||||||
|
|
||||||
customElements // custom element tags of markdown-it-katex in vitepress
|
customElements // custom element tags of markdown-it-katex in vitepress
|
||||||
|
|||||||
@ -7,8 +7,8 @@ import mdLink from 'markdown-it-link-preview'
|
|||||||
export const markdown: MarkdownOptions = {
|
export const markdown: MarkdownOptions = {
|
||||||
html: true,
|
html: true,
|
||||||
theme: {
|
theme: {
|
||||||
light: 'one-dark-pro',
|
light: 'solarized-light',
|
||||||
dark: 'material-theme-palenight',
|
dark: 'solarized-dark',
|
||||||
},
|
},
|
||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
config: md => {
|
config: md => {
|
||||||
|
|||||||
@ -60,7 +60,7 @@ export const nav: DefaultTheme.Config['nav'] = [
|
|||||||
link: '/application/markdown-it-katex/how-to-use',
|
link: '/application/markdown-it-katex/how-to-use',
|
||||||
activeMatch: '/application/markdown-it-katex/',
|
activeMatch: '/application/markdown-it-katex/',
|
||||||
},
|
},
|
||||||
{ text: '', link: '', activeMatch: '' },
|
{ text: 'vitepress-plugin-shiki-twoslash', link: '/application/vitepress-plugin-shiki-twoslash/index', activeMatch: '/application/vitepress-plugin-shiki-twoslash/index' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { groupCollapsed } from 'console'
|
||||||
import { DefaultTheme } from 'vitepress/theme'
|
import { DefaultTheme } from 'vitepress/theme'
|
||||||
|
|
||||||
export const sidebar: DefaultTheme.Config['sidebar'] = {
|
export const sidebar: DefaultTheme.Config['sidebar'] = {
|
||||||
@ -168,7 +169,7 @@ export const sidebar: DefaultTheme.Config['sidebar'] = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
'/application/': [
|
'/application/markdown-it-katex/': [
|
||||||
{
|
{
|
||||||
text: 'markdown-it-katex',
|
text: 'markdown-it-katex',
|
||||||
collapsed: false,
|
collapsed: false,
|
||||||
@ -191,4 +192,81 @@ export const sidebar: DefaultTheme.Config['sidebar'] = {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
|
'/application/vitepress-plugin-shiki-twoslash/': [
|
||||||
|
{
|
||||||
|
text: 'Guide',
|
||||||
|
collapsed: false,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
text: 'Getting Started',
|
||||||
|
link: '/application/vitepress-plugin-shiki-twoslash/',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Markdown Extensions',
|
||||||
|
link: '/application/vitepress-plugin-shiki-twoslash/guide/markdown-extensions',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Using a Custom Theme',
|
||||||
|
link: '/application/vitepress-plugin-shiki-twoslash/guide/custom-theme',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Features',
|
||||||
|
collapsed: false,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
text: 'Queries',
|
||||||
|
link: '/application/vitepress-plugin-shiki-twoslash/api/queries',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Errors',
|
||||||
|
link: '/application/vitepress-plugin-shiki-twoslash/api/errors',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Emit',
|
||||||
|
link: '/application/vitepress-plugin-shiki-twoslash/api/emit',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Cutting',
|
||||||
|
link: '/application/vitepress-plugin-shiki-twoslash/api/cutting',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Multi-file',
|
||||||
|
link: '/application/vitepress-plugin-shiki-twoslash/api/multi-file',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '@types',
|
||||||
|
link: '/application/vitepress-plugin-shiki-twoslash/api/types',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Meta Annotations',
|
||||||
|
link: '/application/vitepress-plugin-shiki-twoslash/api/annotations',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Logging',
|
||||||
|
link: '/application/vitepress-plugin-shiki-twoslash/api/logging',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Includes',
|
||||||
|
link: '/application/vitepress-plugin-shiki-twoslash/api/includes',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Config',
|
||||||
|
collapsed: false,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
text: 'Reference',
|
||||||
|
link: '/application/vitepress-plugin-shiki-twoslash/config/reference',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Compiler Flags',
|
||||||
|
link: '/application/vitepress-plugin-shiki-twoslash/config/flags',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,9 +10,13 @@ import mediumZoom from 'medium-zoom'
|
|||||||
import vitepressNprogress from '@andatoshiki/vitepress-plugin-nprogress'
|
import vitepressNprogress from '@andatoshiki/vitepress-plugin-nprogress'
|
||||||
import '@andatoshiki/vitepress-plugin-nprogress/lib/css/index.css'
|
import '@andatoshiki/vitepress-plugin-nprogress/lib/css/index.css'
|
||||||
|
|
||||||
|
import '@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css'
|
||||||
|
|
||||||
// custom styles import
|
// custom styles import
|
||||||
import './styles/index.scss'
|
import './styles/index.scss'
|
||||||
|
|
||||||
|
import './styles/component/twoslash.scss'
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
// custom components and vue template layouts
|
// custom components and vue template layouts
|
||||||
import CustomLayout from './CustomLayout.vue'
|
import CustomLayout from './CustomLayout.vue'
|
||||||
@ -22,6 +26,8 @@ import AsideSponsors from './components/AsideSponsors.vue'
|
|||||||
import Copyright from './components/Copyright.vue'
|
import Copyright from './components/Copyright.vue'
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import Comment from './components/layout/Comment.vue'
|
import Comment from './components/layout/Comment.vue'
|
||||||
|
// @ts-ignore
|
||||||
|
import ArticleMetadata from './components/ArticleMetadata.vue'
|
||||||
|
|
||||||
// import CodeTitle from './components/CodeTitle.vue'
|
// import CodeTitle from './components/CodeTitle.vue'
|
||||||
|
|
||||||
|
|||||||
129
docs/.vitepress/theme/styles/component/twoslash.scss
Normal file
129
docs/.vitepress/theme/styles/component/twoslash.scss
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
/* Dark/light theme */
|
||||||
|
:root:not(.dark) {
|
||||||
|
--vp-code-block-bg: rgba(125,125,125,0.04);
|
||||||
|
--vp-code-copy-code-active-text: var(--vp-c-text-2);
|
||||||
|
--vp-code-copy-code-hover-bg: rgba(125,125,125,0.1);
|
||||||
|
--vp-code-tab-divider: var(--vp-c-mute-dark);
|
||||||
|
--vp-code-tab-hover-text-color: var(--vp-c-text-1);
|
||||||
|
/* fix contrast: lang name on gray code block */
|
||||||
|
--vp-c-text-dark-3: rgba(180, 180, 180, 0.7);
|
||||||
|
}
|
||||||
|
:root.dark {
|
||||||
|
--vp-code-block-bg: rgba(0,0,0,0.2);
|
||||||
|
/* fix lang name: check the same above (this is the default) */
|
||||||
|
--vp-c-text-dark-3: rgba(235, 235, 235, 0.38);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide block based on theme */
|
||||||
|
html:not(.dark) pre.shiki[class*="dark"] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
html:not(.dark) pre.shiki[class*="light"] {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
html.dark pre.shiki[class*="dark"] {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
html.dark pre.shiki[class*="light"] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* VitePress Twoslash */
|
||||||
|
:root {
|
||||||
|
--vp-twoslash-c-annotation-fg: var(--vp-c-text-1);
|
||||||
|
|
||||||
|
--vp-twoslash-c-brand: var(--vp-c-brand);
|
||||||
|
|
||||||
|
--vp-twoslash-c-error-bg: var(--vp-c-red-dimm-2);
|
||||||
|
--vp-twoslash-c-error-fg: var(--vp-c-text-1);
|
||||||
|
|
||||||
|
--vp-twoslash-c-logger-error-bg: var(--vp-c-red-dimm-2);
|
||||||
|
--vp-twoslash-c-logger-error-fg: var(--vp-c-red-dark);
|
||||||
|
--vp-twoslash-c-logger-fg: var(--vp-c-text-1);
|
||||||
|
--vp-twoslash-c-logger-log-bg: var(--vp-c-mute-dark);
|
||||||
|
--vp-twoslash-c-logger-log-fg: var(--vp-c-gray);
|
||||||
|
--vp-twoslash-c-logger-warn-bg: var(--vp-c-yellow-dimm-2);
|
||||||
|
--vp-twoslash-c-logger-warn-fg: var(--vp-c-yellow-dark);
|
||||||
|
|
||||||
|
--vp-twoslash-c-lsp-bg: var(--vp-c-bg-elv);
|
||||||
|
--vp-twoslash-c-lsp-border: var(--vp-c-divider);
|
||||||
|
--vp-twoslash-c-lsp-fg: var(--vp-c-text-1);
|
||||||
|
--vp-twoslash-c-lsp-underline: var(--vp-c-text-2);
|
||||||
|
--vp-twoslash-lsp-shadow: var(--vp-shadow-2);
|
||||||
|
|
||||||
|
--vp-twoslash-c-query-bg: var(--vp-c-mute-dark);
|
||||||
|
--vp-twoslash-c-query-fg-2: var(--vp-c-text-2);
|
||||||
|
--vp-twoslash-c-query-fg: var(--vp-c-text-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fix tab color */
|
||||||
|
.vp-code-group .tabs label {
|
||||||
|
background-color: transparent;
|
||||||
|
--vp-code-tab-text-color: var(--vp-c-text-2);
|
||||||
|
--vp-code-tab-active-text-color: var(--vp-c-text-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component: Button
|
||||||
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--vp-button-brand-border: var(--vp-c-brand-light);
|
||||||
|
--vp-button-brand-text: var(--vp-c-text-dark-1);
|
||||||
|
--vp-button-brand-bg: var(--vp-c-brand);
|
||||||
|
--vp-button-brand-hover-border: var(--vp-c-brand-light);
|
||||||
|
--vp-button-brand-hover-text: var(--vp-c-text-dark-1);
|
||||||
|
--vp-button-brand-hover-bg: var(--vp-c-brand-light);
|
||||||
|
--vp-button-brand-active-border: var(--vp-c-brand-light);
|
||||||
|
--vp-button-brand-active-text: var(--vp-c-text-dark-1);
|
||||||
|
--vp-button-brand-active-bg: var(--vp-button-brand-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component: Algolia
|
||||||
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.DocSearch {
|
||||||
|
--docsearch-primary-color: var(--vp-c-brand) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Site
|
||||||
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.VPImage.logo {
|
||||||
|
height: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark [img-light] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
html:not(.dark) [img-dark] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Overrides */
|
||||||
|
|
||||||
|
.VPSocialLink {
|
||||||
|
transform: scale(0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.vp-doc th, .vp-doc td {
|
||||||
|
padding: 6px 10px;
|
||||||
|
border: 1px solid #8882;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* h3 breaks SEO => replaced with h2 with the same size */
|
||||||
|
.home-content h2 {
|
||||||
|
margin-top: 2rem;
|
||||||
|
font-size: 1.35rem;
|
||||||
|
border-bottom: none;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.resizable-img {
|
||||||
|
width: unset;
|
||||||
|
height: unset;
|
||||||
|
}
|
||||||
|
|
||||||
45
docs/.vitepress/theme/utils.ts
Normal file
45
docs/.vitepress/theme/utils.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* 格式化时间
|
||||||
|
*
|
||||||
|
* @param date 待格式化时间
|
||||||
|
* @returns 格式化后的时间(YYYY/MM/dd AM hh:mm)
|
||||||
|
*/
|
||||||
|
export function formatDate(date) {
|
||||||
|
const formatDate = new Date(date)
|
||||||
|
return formatDate.toLocaleString('en', {
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'numeric',
|
||||||
|
day: 'numeric',
|
||||||
|
hour: 'numeric',
|
||||||
|
minute: 'numeric',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 URL 路径中的指定参数
|
||||||
|
*
|
||||||
|
* @param paramName 参数名
|
||||||
|
* @returns 参数值
|
||||||
|
*/
|
||||||
|
export function getQueryParam(paramName) {
|
||||||
|
const reg = new RegExp('(^|&)' + paramName + '=([^&]*)(&|$)')
|
||||||
|
let value = decodeURIComponent(window.location.search.substr(1)).match(reg)
|
||||||
|
if (value != null) {
|
||||||
|
return unescape(value[2])
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跳转到指定链接
|
||||||
|
*
|
||||||
|
* @param paramName 参数名
|
||||||
|
* @param paramValue 参数值
|
||||||
|
*/
|
||||||
|
export function goToLink(url, paramName, paramValue) {
|
||||||
|
if (paramName) {
|
||||||
|
window.location.href = url + '?' + paramName + '=' + paramValue
|
||||||
|
} else {
|
||||||
|
window.location.href = url
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,9 +5,15 @@ lastUpdated: true
|
|||||||
showArticleMetadata: true
|
showArticleMetadata: true
|
||||||
categories:
|
categories:
|
||||||
- Chemistry
|
- Chemistry
|
||||||
tags:
|
keywords:
|
||||||
- Java
|
- chemistry
|
||||||
- JVM
|
- reaction
|
||||||
|
- mechanism
|
||||||
|
- reaction-mechanism
|
||||||
|
- tutorial
|
||||||
|
- explanation
|
||||||
|
- textbook
|
||||||
|
- reference
|
||||||
---
|
---
|
||||||
|
|
||||||
# 12-5: Reaction Mechanism
|
# 12-5: Reaction Mechanism
|
||||||
|
|||||||
@ -0,0 +1,112 @@
|
|||||||
|
---
|
||||||
|
description: 'Annotations provide a way to provide outside commentary on your code.'
|
||||||
|
title: 'Meta Annotations'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Queries
|
||||||
|
|
||||||
|
Sometimes the thing you want to say is about the code, annotations provide a way to provide outside commentary on your code.
|
||||||
|
|
||||||
|
## `@annotate: [left|right] [overrides] - [text]`
|
||||||
|
|
||||||
|
Annotate has a lot more controls than most of the other Twoslash commands, because each use of it probably needs to feel a bit different. Here's an example based on the TypeScript home page, click it to get it running so we can talk about what it does:
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
// @errors: 2304
|
||||||
|
// @strict: false
|
||||||
|
|
||||||
|
function compact(arr) {
|
||||||
|
if (orr.length > 10) return arr.trim(0, 10)
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```ts twoslash
|
||||||
|
// @errors: 2304
|
||||||
|
// @strict: false
|
||||||
|
|
||||||
|
function compact(arr) {
|
||||||
|
if (orr.length > 10) return arr.trim(0, 10)
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
First up, cool — it adds some text to the left hand side of the code. It features quite a few different options, so lets go through them one by one:
|
||||||
|
|
||||||
|
- `left` or `right`: It's currently `left`. It's worth noting the arrow flips also, and `90deg` isn't a great option. Let's look at that next.
|
||||||
|
|
||||||
|
- `{ "arrrowRot": "90deg 8px 27px" }` - This JSON object is used to manipulate the annotation, you have 3 controls for arrow positioning and rotation: `degrees x y`. I recommend keeping those in degrees and px, but it's your life. These are overrides from defaults which are okay, but not really something you ever want to ship.
|
||||||
|
|
||||||
|
- `{ "textDegree": "3deg" }` - Rotates the text, you probably want something between `-3deg` and `3deg`. Optional, defaults to `0`.
|
||||||
|
|
||||||
|
- `{ "top": "0rem" }` - Sets the y coordinates for the annotation relative to the code sample, if it's not included then it becomes `[lineNum]rem`.
|
||||||
|
|
||||||
|
What's not included in this sample is `flipped`, which can be used to flip the arrow's orientation. Here's some examples:
|
||||||
|
|
||||||
|
A horizontal right example:
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
// @errors: 2304
|
||||||
|
// @strict: false
|
||||||
|
|
||||||
|
function compact(arr) {
|
||||||
|
if (orr.length > 10) return arr.trim(0, 10)
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
// @annotate: right { "arrowRot": "-50deg -10px -10px", "top": "3rem" } - Discovered a typo, the param is arr, not orr!
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```ts twoslash
|
||||||
|
// @errors: 2304
|
||||||
|
// @strict: false
|
||||||
|
|
||||||
|
function compact(arr) {
|
||||||
|
if (orr.length > 10) return arr.trim(0, 10)
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
Upside down arrow pointing at the error, using flipped to re-flip the arrow:
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
// @errors: 2304
|
||||||
|
// @strict: false
|
||||||
|
|
||||||
|
function compact(arr) {
|
||||||
|
if (orr.length > 10) return arr.trim(0, 10)
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
// @annotate: right { "arrowRot": "190deg 8px 46px", "flipped": false, "textDegree": "-3deg", "top": "-0.7rem" } - Discovered a typo, the param is arr, not orr!
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```ts twoslash
|
||||||
|
// @errors: 2304
|
||||||
|
// @strict: false
|
||||||
|
|
||||||
|
function compact(arr) {
|
||||||
|
if (orr.length > 10) return arr.trim(0, 10)
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
// @annotate: left { "arrowRot": "90deg 8px 27px", "textDegree": "3deg", "top": "0rem" } - Discovered a typo, the param is arr, not orr!
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
@ -0,0 +1,89 @@
|
|||||||
|
---
|
||||||
|
description: 'Remove unnecessary code from your examples.'
|
||||||
|
title: 'Cutting'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Cutting
|
||||||
|
|
||||||
|
Every Twoslash code example needs to be a complete TypeScript program so it can compile. Quite often to make it compile, there is a bunch of code which isn't relevant to the user. This can be extracted out of the code examples via cut comments.
|
||||||
|
|
||||||
|
## `---cut---`
|
||||||
|
|
||||||
|
Cut works after TypeScript has generated the project and pulled out all the editor information (like identifiers, queries, highlights etc) and then amends all of their offsets and lines to re-fit the smaller output. What your user sees is everything below the `---cut---`.
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
const level: string = 'Danger'
|
||||||
|
// ---cut---
|
||||||
|
console.log(level)
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```ts twoslash
|
||||||
|
const level: string = 'Danger'
|
||||||
|
// ---cut---
|
||||||
|
console.log(level)
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
Cutting even works across [multiple files](multi-file). This is why `// @filename: [file]` is specifically the only Twoslash command which is not removed, because if it's not relevant it can be `---cut---` away.
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
// @filename: a.ts
|
||||||
|
export const helloWorld: string = 'Hi'
|
||||||
|
|
||||||
|
// @filename: b.ts
|
||||||
|
// ---cut---
|
||||||
|
import { helloWorld } from './a'
|
||||||
|
console.log(helloWorld)
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```ts twoslash
|
||||||
|
// @filename: a.ts
|
||||||
|
export const helloWorld: string = 'Hi'
|
||||||
|
|
||||||
|
// @filename: b.ts
|
||||||
|
// ---cut---
|
||||||
|
import { helloWorld } from './a'
|
||||||
|
console.log(helloWorld)
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## `---cut-after---`
|
||||||
|
|
||||||
|
The sibling to `---cut---`, which trims anything after the sigil:
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```tsx twoslash [output]
|
||||||
|
//@noErrors
|
||||||
|
const Page = () => (
|
||||||
|
// ---cut---
|
||||||
|
<Container>
|
||||||
|
<ImportantComponent />
|
||||||
|
</Container>
|
||||||
|
// ---cut-after---
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```tsx twoslash
|
||||||
|
const Page = () => (
|
||||||
|
// ---cut---
|
||||||
|
<Container>
|
||||||
|
<ImportantComponent />
|
||||||
|
</Container>
|
||||||
|
// ---cut-after---
|
||||||
|
)
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
98
docs/application/vitepress-plugin-shiki-twoslash/api/emit.md
Normal file
98
docs/application/vitepress-plugin-shiki-twoslash/api/emit.md
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
---
|
||||||
|
description: 'You can replace the contents of your code examples with the results of running TypeScript over the project.'
|
||||||
|
title: 'Emit'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Emit
|
||||||
|
|
||||||
|
Running a Twoslash code example is a full TypeScript compiler run that will create files inside the virtual file system. You can replace the contents of your code examples with the results of running TypeScript over the project.
|
||||||
|
|
||||||
|
## `@showEmit`
|
||||||
|
|
||||||
|
`// @showEmit` is the main command to tell Shiki Twoslash that you want to replace the output of your code example with the equivalent `.js` file.
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
// @showEmit
|
||||||
|
const level: string = 'Danger'
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```ts twoslash
|
||||||
|
// @showEmit
|
||||||
|
const level: string = 'Danger'
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## `@showEmittedFile: [file]`
|
||||||
|
|
||||||
|
While the `.js` file is probably the most useful file out of the box, TypeScript does emit other files if you have the right flags enabled (`.d.ts` and `.map`) but also when you have a multi-file code sample — you might need to tell Twoslash which file to show. For all these cases you can also add `@showEmittedFile: [file]` to tell Twoslash which file you want to show.
|
||||||
|
|
||||||
|
Shows emitted `.d.ts` for a TypeScript code example:
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```ts twoslash
|
||||||
|
// @declaration
|
||||||
|
// @showEmit
|
||||||
|
// @showEmittedFile: index.d.ts
|
||||||
|
export const hello = 'world'
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
// @declaration
|
||||||
|
// @showEmit
|
||||||
|
// @showEmittedFile: index.d.ts
|
||||||
|
export const hello = 'world'
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
Shows emitted `.map` files:
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```ts twoslash
|
||||||
|
// @sourceMap
|
||||||
|
// @showEmit
|
||||||
|
// @showEmittedFile: index.js.map
|
||||||
|
export const hello = 'world'
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
// @sourceMap
|
||||||
|
// @showEmit
|
||||||
|
// @showEmittedFile: index.js.map
|
||||||
|
export const hello = 'world'
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```ts twoslash
|
||||||
|
// @declaration
|
||||||
|
// @declarationMap
|
||||||
|
// @showEmit
|
||||||
|
// @showEmittedFile: index.d.ts.map
|
||||||
|
export const hello = 'world'
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
// @declaration
|
||||||
|
// @declarationMap
|
||||||
|
// @showEmit
|
||||||
|
// @showEmittedFile: index.d.ts.map
|
||||||
|
export const hello = 'world'
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
---
|
||||||
|
description: 'Raise compiler errors in your code examples to show incorrect states.'
|
||||||
|
title: 'Errors'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Errors
|
||||||
|
|
||||||
|
Most of the time, you want to avoid errors in your code examples. Strictly speaking, this usually means setting the right compiler flags and environment in each code example.
|
||||||
|
|
||||||
|
Sometimes however, you do want to raise a compiler error — to show incorrect states. In those cases, twoslash has a way to mark the compiler errors you expect.
|
||||||
|
|
||||||
|
## `@errors: [num]`
|
||||||
|
|
||||||
|
All TypeScript compiler errors have a number, this number is relatively arbitrary and can change between TypeScript versions. For our case these numbers are useul in declaring what we expect to see.
|
||||||
|
|
||||||
|
You can use `// @errors: [num]` to tell Twoslash that you expect this error to occur. This moves the compiler error message into the code example.
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
// @errors: 2588
|
||||||
|
const a = '123'
|
||||||
|
a = 132
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```ts twoslash
|
||||||
|
// @errors: 2588
|
||||||
|
const a = '123'
|
||||||
|
a = 132
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## `@noErrors`
|
||||||
|
|
||||||
|
Sometimes you have needs in which a broken TypeScript build is okay. A good example of this is using a [completion query](queries#completions), which requires a broken TypeScript project to work. You can use `// @noErrors` to supress all errors in a code sample, and not have them show inline.
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
// @noErrors
|
||||||
|
const a = '123'
|
||||||
|
a = 132
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```ts twoslash
|
||||||
|
// @noErrors
|
||||||
|
const a = '123'
|
||||||
|
a = 132
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
137
docs/application/vitepress-plugin-shiki-twoslash/api/includes.md
Normal file
137
docs/application/vitepress-plugin-shiki-twoslash/api/includes.md
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
---
|
||||||
|
description: 'Include re-usable TypeScript blocks in your code examples.'
|
||||||
|
title: 'Includes'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Includes
|
||||||
|
|
||||||
|
As your documentation grows, you may need a way of re-using code blocks to prevent code duplication. Shiki Twoslash provides a simple includes system.
|
||||||
|
|
||||||
|
## Defining a re-usable block
|
||||||
|
|
||||||
|
Re-usable code blocks are defined by the `twoslash` language, followed by the `include` keyword and the reference name of your choice.
|
||||||
|
|
||||||
|
````md
|
||||||
|
```twoslash include myBlock
|
||||||
|
type SomeString = string
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
### Incremental steps
|
||||||
|
|
||||||
|
Shiki Twoslash also provide the ability to define incremental steps through the definition of re-usable blocks. This means whenever a new step is delimited down the code, it will also include previous steps. These are **not groups**.
|
||||||
|
|
||||||
|
- Incremental steps are delimited by `// - [name of the step]`
|
||||||
|
- They are named **at the end** of the actual code
|
||||||
|
|
||||||
|
````md
|
||||||
|
```twoslash include myBlockWithSteps
|
||||||
|
type SomeString = string
|
||||||
|
// - base
|
||||||
|
type SomeUser = { name: string; mail?: SomeUserMail }
|
||||||
|
type SomeUserMail = { content: string; verified: boolean }
|
||||||
|
// - afterUserDefinitions
|
||||||
|
type SomeGroup = { name: string; members: SomeUser[] }
|
||||||
|
// - afterGroupDefinitions
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
## Including a whole block
|
||||||
|
|
||||||
|
To include a re-usable block, add `// @include: [block name]` in your code block.
|
||||||
|
|
||||||
|
```twoslash include myBlock
|
||||||
|
type SomeString = string
|
||||||
|
```
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
// @include: myBlock
|
||||||
|
const a: SomeString = 'string'
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```twoslash include myBlock
|
||||||
|
type SomeString = string
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts twoslash
|
||||||
|
// @include: myBlock
|
||||||
|
const a: SomeString = 'string'
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Including a block step
|
||||||
|
|
||||||
|
To include a re-usable block at a specific step, add `// @include: [block name]-[step name]` in your code block.
|
||||||
|
|
||||||
|
```twoslash include myBlockWithSteps
|
||||||
|
type SomeString = string
|
||||||
|
// - base
|
||||||
|
type SomeUser = { name: string; mail?: SomeUserMail }
|
||||||
|
type SomeUserMail = { content: string; verified: boolean }
|
||||||
|
// - afterUserDefinitions
|
||||||
|
type SomeGroup = { name: string; members: SomeUser[] }
|
||||||
|
// - afterGroupDefinitions
|
||||||
|
```
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
// @include: myBlockWithSteps-afterUserDefinitions
|
||||||
|
const mail: SomeUserMail = { content: 'some-email', verified: true }
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```twoslash include myBlockWithSteps
|
||||||
|
type SomeString = string
|
||||||
|
// - base
|
||||||
|
type SomeUser = { name: string; mail?: SomeUserMail }
|
||||||
|
type SomeUserMail = { content: string; verified: boolean }
|
||||||
|
// - afterUserDefinitions
|
||||||
|
type SomeGroup = { name: string; members: SomeUser[] }
|
||||||
|
// - afterGroupDefinitions
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts twoslash
|
||||||
|
// @include: myBlockWithSteps-afterUserDefinitions
|
||||||
|
const mail: SomeUserMail = { content: 'some-email', verified: true }
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Hiding re-used code
|
||||||
|
|
||||||
|
Re-using a lot of TypeScript code can easily bloat your documentation and obstruct the main point of your code block. You can hide re-used code to keep your code blocks clean and concise by [cutting](cutting) right after the `@include` statement.
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
// @include: myBlockWithSteps-afterUserDefinitions
|
||||||
|
// ---cut---
|
||||||
|
const mail: SomeUserMail = { content: 'some-email', verified: true }
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```twoslash include myBlockWithSteps
|
||||||
|
type SomeString = string
|
||||||
|
// - base
|
||||||
|
type SomeUser = { name: string; mail?: SomeUserMail }
|
||||||
|
type SomeUserMail = { content: string; verified: boolean }
|
||||||
|
// - afterUserDefinitions
|
||||||
|
type SomeGroup = { name: string; members: SomeUser[] }
|
||||||
|
// - afterGroupDefinitions
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts twoslash
|
||||||
|
// @include: myBlockWithSteps-afterUserDefinitions
|
||||||
|
// ---cut---
|
||||||
|
const mail: SomeUserMail = { content: 'some-email', verified: true }
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
description: 'Display formatted output for code examples.'
|
||||||
|
title: 'Logging'
|
||||||
|
keywords:
|
||||||
|
- console
|
||||||
|
- javascript
|
||||||
|
- typescript
|
||||||
|
- showcase
|
||||||
|
- snippets
|
||||||
|
---
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
|
||||||
|
When you first see a Twoslash code example with an inline compiler error, you instinctively trust that the compiler error is correct because the design shows that it is not a part of the code sample. The logging tools lets you do that, but abuses the systemic trust because your code is not being evaluated to generate the logs.
|
||||||
|
|
||||||
|
This feature is effectively a facade, people will trust your output and it will look better.
|
||||||
|
|
||||||
|
## `@log:`, `@warn:`, `@error:`
|
||||||
|
|
||||||
|
The names are based on the functions on the `console` object:
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
console.log('Hello log')
|
||||||
|
// @log: Hello log
|
||||||
|
|
||||||
|
console.warn('Hello warn')
|
||||||
|
// @warn: Hello warn
|
||||||
|
|
||||||
|
console.error('Hello error')
|
||||||
|
// @error: Hello error
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```ts twoslash
|
||||||
|
console.log('Hello log')
|
||||||
|
// @log: Hello log
|
||||||
|
|
||||||
|
console.warn('Hello warn')
|
||||||
|
// @warn: Hello warn
|
||||||
|
|
||||||
|
console.error('Hello error')
|
||||||
|
// @error: Hello error
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
@ -0,0 +1,160 @@
|
|||||||
|
---
|
||||||
|
description: "Twoslash code examples aren't limited to creating a single file. You can write any file to the virtual file system used by TypeScript to power your code examples."
|
||||||
|
title: 'Multi-file'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Multi-file
|
||||||
|
|
||||||
|
Twoslash code examples aren't limited to creating a single file, by using `// @filename: [file]` you can write any file to the virtual file system used by TypeScript to power your code examples.
|
||||||
|
|
||||||
|
## `@filename: [file]`
|
||||||
|
|
||||||
|
Most of the time, you don't need to think about the underlaying virtual file system in a code example, but when you have imports between them it becomes important to know. Twoslash will default to creating an `index.[type]` based on the langauge passed to the code example:
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
// I'm index.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```ts twoslash
|
||||||
|
// I'm index.ts
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```tsx twoslash [output]
|
||||||
|
// I'm index.tsx
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```tsx twoslash
|
||||||
|
// I'm index.tsx
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```js twoslash [output]
|
||||||
|
// I'm index.tjs
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```js twoslash
|
||||||
|
// I'm index.tjs
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
Then until Twoslash hits another `// @filename: [file]`, the parser keeps adding new lines into the same file. After seeing `@filename` Twoslash creates a new virtual file-system file and adds the new lines to that. You can't edit a file after it was created, but you can overwrite it.
|
||||||
|
|
||||||
|
It can be any file. For example, if you want to quickly fake a node module:
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
// @filename: node_modules/@types/mylib/index.d.ts
|
||||||
|
export function doit(): string
|
||||||
|
|
||||||
|
// @filename: index.ts
|
||||||
|
import { doit } from 'mylib'
|
||||||
|
console.log(doit)
|
||||||
|
```
|
||||||
|
|
||||||
|
This code example sets up the types for a non-existent npm module, and TypeScript picks it up as the definitions in the same way it would in a non-virtual TypeScript project.
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```ts twoslash
|
||||||
|
// @filename: node_modules/@types/mylib/index.d.ts
|
||||||
|
export function doit(): string
|
||||||
|
|
||||||
|
// @filename: index.ts
|
||||||
|
import { doit } from 'mylib'
|
||||||
|
console.log(doit)
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
You can also set up a JSON object which can be imported in a TypeScript file:
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
// @resolveJsonModule
|
||||||
|
// @filename: app.json
|
||||||
|
{ "version": "23.2.3" }
|
||||||
|
|
||||||
|
// @filename: index.ts
|
||||||
|
import appSettings from "./app.json"
|
||||||
|
appSettings.version
|
||||||
|
// ^?
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```ts twoslash
|
||||||
|
// @resolveJsonModule
|
||||||
|
// @filename: app.json
|
||||||
|
{ "version": "23.2.3" }
|
||||||
|
|
||||||
|
// @filename: index.ts
|
||||||
|
import appSettings from "./app.json"
|
||||||
|
appSettings.version
|
||||||
|
// ^?
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
Finally, the following code allows importing non-TypeScript content. There is a `.d.ts` file which globally says 'md files are OK to import' and 'the module "react" exists, but don't worry about the details'.
|
||||||
|
|
||||||
|
Then for a user, they only see the imports and exports inside `index.tsx`.
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
// @filename: ambient.d.ts
|
||||||
|
declare module '*.mdx' {
|
||||||
|
export default any
|
||||||
|
}
|
||||||
|
declare module "react"
|
||||||
|
|
||||||
|
// @filename: MultiFileDocs.mdx
|
||||||
|
## Hello world
|
||||||
|
|
||||||
|
// @filename: index.tsx
|
||||||
|
// ---cut---
|
||||||
|
import React from "react"
|
||||||
|
import MultiFileDocs from "./MultiFileDocs.mdx"
|
||||||
|
|
||||||
|
export default () => <MultiFileDocs/>
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```ts twoslash
|
||||||
|
// @filename: ambient.d.ts
|
||||||
|
declare module '*.mdx' {
|
||||||
|
export default any
|
||||||
|
}
|
||||||
|
declare module "react"
|
||||||
|
|
||||||
|
// @filename: MultiFileDocs.mdx
|
||||||
|
## Hello world
|
||||||
|
|
||||||
|
// @filename: index.tsx
|
||||||
|
// ---cut---
|
||||||
|
import React from "react"
|
||||||
|
import MultiFileDocs from "./MultiFileDocs.mdx"
|
||||||
|
|
||||||
|
export default () => <MultiFileDocs/>
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
---
|
||||||
|
description: 'One of the key features of Twoslash is the ability to use the TypeScript compiler to pull out type information about your code.'
|
||||||
|
title: 'Queries'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Queries
|
||||||
|
|
||||||
|
One of the key features of Twoslash is the ability to use the TypeScript compiler to pull out type information about your code. Twoslash comes with two different ways to query your code: `?^` and `?|`.
|
||||||
|
|
||||||
|
## Extract Type `^?`
|
||||||
|
|
||||||
|
Using `^?` you can pull out type information about a particular identifier in the line of code above it.
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
const hi = 'Hello'
|
||||||
|
const msg = hi + ', world'
|
||||||
|
// ^?
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```ts twoslash
|
||||||
|
const hi = 'Hello'
|
||||||
|
const msg = hi + ', world'
|
||||||
|
// ^?
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Completions `^|`
|
||||||
|
|
||||||
|
Using `^|` you can pull out information about a what the auto-complete looks like at a particular location.
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
// @noErrors
|
||||||
|
console.e
|
||||||
|
// ^|
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```ts twoslash
|
||||||
|
// @noErrors
|
||||||
|
console.e
|
||||||
|
// ^|
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: info
|
||||||
|
Note that the compiler flag for [`// @noErrors`](errors#noerrors) is set, because `console.e` is a failing TypeScript code sample but we don't really care about that.
|
||||||
|
:::
|
||||||
@ -0,0 +1,88 @@
|
|||||||
|
---
|
||||||
|
description: 'Using external libraries with Twoslash code examples.'
|
||||||
|
title: '@types'
|
||||||
|
---
|
||||||
|
|
||||||
|
# @types
|
||||||
|
|
||||||
|
For most examples, you probably need to import external libraries into your code examples.
|
||||||
|
|
||||||
|
Twoslash works by faking a virtual file system over your existing file system. This means any `@types` or libraries with TypeScript definitions should work out of the box with no config.
|
||||||
|
|
||||||
|
## Local Sources
|
||||||
|
|
||||||
|
Simply import locally installed libraries and Twoslash can pick up types:
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
import { defineConfig } from 'vitepress'
|
||||||
|
const config = defineConfig({})
|
||||||
|
// ^?
|
||||||
|
export default config
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```ts twoslash
|
||||||
|
import { defineConfig } from 'vitepress'
|
||||||
|
const config = defineConfig({})
|
||||||
|
// ^?
|
||||||
|
export default config
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Globals
|
||||||
|
|
||||||
|
Setting up globals is a little bit more complex, but not drastically. You need to use the [triple slash reference](https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html#-reference-types-) which adds a particular library to the global scope.
|
||||||
|
|
||||||
|
For example, setting up Node imports and globals etc.
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
/// <reference types="node" />
|
||||||
|
// ---cut---
|
||||||
|
import { writeFileSync } from 'fs'
|
||||||
|
writeFileSync('myfile.txt', '// TODO')
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```ts twoslash
|
||||||
|
/// <reference types="node" />
|
||||||
|
// ---cut---
|
||||||
|
import { writeFileSync } from 'fs'
|
||||||
|
writeFileSync('myfile.txt', '// TODO')
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
APIs like [Vitest](https://vitest.dev) are similar cases where you would use a triple slash reference.
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```ts twoslash [output]
|
||||||
|
/// <reference types="vitest/globals" />
|
||||||
|
// ---cut---
|
||||||
|
|
||||||
|
test('my tests', () => {
|
||||||
|
expect('hello').toEqual('hello')
|
||||||
|
// ^?
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```ts twoslash
|
||||||
|
/// <reference types="vitest/globals" />
|
||||||
|
// ---cut---
|
||||||
|
|
||||||
|
test('my tests', () => {
|
||||||
|
expect('hello').toEqual('hello')
|
||||||
|
// ^?
|
||||||
|
})
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
:::
|
||||||
304
docs/application/vitepress-plugin-shiki-twoslash/config/flags.md
Normal file
304
docs/application/vitepress-plugin-shiki-twoslash/config/flags.md
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
---
|
||||||
|
title: 'Compiler Flags'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Compiler Flags
|
||||||
|
|
||||||
|
```
|
||||||
|
// @allowJs
|
||||||
|
Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files..
|
||||||
|
|
||||||
|
// @allowSyntheticDefaultImports
|
||||||
|
Allow 'import x from y' when a module doesn't have a default export..
|
||||||
|
|
||||||
|
// @allowUmdGlobalAccess
|
||||||
|
Allow accessing UMD globals from modules..
|
||||||
|
|
||||||
|
// @allowUnreachableCode
|
||||||
|
Disable error reporting for unreachable code..
|
||||||
|
|
||||||
|
// @allowUnusedLabels
|
||||||
|
Disable error reporting for unused labels..
|
||||||
|
|
||||||
|
// @alwaysStrict
|
||||||
|
Ensure 'use strict' is always emitted..
|
||||||
|
|
||||||
|
// @assumeChangesOnlyAffectDirectDependencies
|
||||||
|
Have recompiles in projects that use `incremental` and `watch` mode assume that changes within a file will only affect files directly depending on it..
|
||||||
|
|
||||||
|
// @baseUrl
|
||||||
|
Specify the base directory to resolve non-relative module names..
|
||||||
|
|
||||||
|
// @charset
|
||||||
|
No longer supported. In early versions, manually set the text encoding for reading files..
|
||||||
|
|
||||||
|
// @checkJs
|
||||||
|
Enable error reporting in type-checked JavaScript files..
|
||||||
|
|
||||||
|
// @composite
|
||||||
|
Enable constraints that allow a TypeScript project to be used with project references..
|
||||||
|
|
||||||
|
// @declaration
|
||||||
|
Generate .d.ts files from TypeScript and JavaScript files in your project..
|
||||||
|
|
||||||
|
// @declarationDir
|
||||||
|
Specify the output directory for generated declaration files..
|
||||||
|
|
||||||
|
// @declarationMap
|
||||||
|
Create sourcemaps for d.ts files..
|
||||||
|
|
||||||
|
// @diagnostics
|
||||||
|
Output compiler performance information after building..
|
||||||
|
|
||||||
|
// @disableReferencedProjectLoad
|
||||||
|
Reduce the number of projects loaded automatically by TypeScript..
|
||||||
|
|
||||||
|
// @disableSizeLimit
|
||||||
|
Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server..
|
||||||
|
|
||||||
|
// @disableSolutionSearching
|
||||||
|
Opt a project out of multi-project reference checking when editing..
|
||||||
|
|
||||||
|
// @disableSourceOfProjectReferenceRedirect
|
||||||
|
Disable preferring source files instead of declaration files when referencing composite projects.
|
||||||
|
|
||||||
|
// @downlevelIteration
|
||||||
|
Emit more compliant, but verbose and less performant JavaScript for iteration..
|
||||||
|
|
||||||
|
// @emitBOM
|
||||||
|
Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files..
|
||||||
|
|
||||||
|
// @emitDeclarationOnly
|
||||||
|
Only output d.ts files and not JavaScript files..
|
||||||
|
|
||||||
|
// @emitDecoratorMetadata
|
||||||
|
Emit design-type metadata for decorated declarations in source files..
|
||||||
|
|
||||||
|
// @esModuleInterop
|
||||||
|
Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility..
|
||||||
|
|
||||||
|
// @exactOptionalPropertyTypes
|
||||||
|
Interpret optional property types as written, rather than adding 'undefined'..
|
||||||
|
|
||||||
|
// @experimentalDecorators
|
||||||
|
Enable experimental support for TC39 stage 2 draft decorators..
|
||||||
|
|
||||||
|
// @explainFiles
|
||||||
|
Print files read during the compilation including why it was included..
|
||||||
|
|
||||||
|
// @extendedDiagnostics
|
||||||
|
Output more detailed compiler performance information after building..
|
||||||
|
|
||||||
|
// @forceConsistentCasingInFileNames
|
||||||
|
Ensure that casing is correct in imports..
|
||||||
|
|
||||||
|
// @generateCpuProfile
|
||||||
|
Emit a v8 CPU profile of the compiler run for debugging..
|
||||||
|
|
||||||
|
// @importHelpers
|
||||||
|
Allow importing helper functions from tslib once per project, instead of including them per-file..
|
||||||
|
|
||||||
|
// @importsNotUsedAsValues
|
||||||
|
Specify emit/checking behavior for imports that are only used for types.
|
||||||
|
|
||||||
|
// @incremental
|
||||||
|
Enable incremental compilation.
|
||||||
|
|
||||||
|
// @inlineSourceMap
|
||||||
|
Include sourcemap files inside the emitted JavaScript..
|
||||||
|
|
||||||
|
// @inlineSources
|
||||||
|
Include source code in the sourcemaps inside the emitted JavaScript..
|
||||||
|
|
||||||
|
// @isolatedModules
|
||||||
|
Ensure that each file can be safely transpiled without relying on other imports..
|
||||||
|
|
||||||
|
// @jsx
|
||||||
|
Specify what JSX code is generated..
|
||||||
|
|
||||||
|
// @jsxFactory
|
||||||
|
Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'.
|
||||||
|
|
||||||
|
// @jsxFragmentFactory
|
||||||
|
Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'..
|
||||||
|
|
||||||
|
// @jsxImportSource
|
||||||
|
Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.`.
|
||||||
|
|
||||||
|
// @keyofStringsOnly
|
||||||
|
Make keyof only return strings instead of string, numbers or symbols. Legacy option..
|
||||||
|
|
||||||
|
// @lib
|
||||||
|
Specify a set of bundled library declaration files that describe the target runtime environment..
|
||||||
|
|
||||||
|
// @listEmittedFiles
|
||||||
|
Print the names of emitted files after a compilation..
|
||||||
|
|
||||||
|
// @listFiles
|
||||||
|
Print all of the files read during the compilation..
|
||||||
|
|
||||||
|
// @mapRoot
|
||||||
|
Specify the location where debugger should locate map files instead of generated locations..
|
||||||
|
|
||||||
|
// @maxNodeModuleJsDepth
|
||||||
|
Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`..
|
||||||
|
|
||||||
|
// @module
|
||||||
|
Specify what module code is generated..
|
||||||
|
|
||||||
|
// @moduleResolution
|
||||||
|
Specify how TypeScript looks up a file from a given module specifier..
|
||||||
|
|
||||||
|
// @newLine
|
||||||
|
Set the newline character for emitting files..
|
||||||
|
|
||||||
|
// @noEmit
|
||||||
|
Disable emitting file from a compilation..
|
||||||
|
|
||||||
|
// @noEmitHelpers
|
||||||
|
Disable generating custom helper functions like `__extends` in compiled output..
|
||||||
|
|
||||||
|
// @noEmitOnError
|
||||||
|
Disable emitting files if any type checking errors are reported..
|
||||||
|
|
||||||
|
// @noErrorTruncation
|
||||||
|
Disable truncating types in error messages..
|
||||||
|
|
||||||
|
// @noFallthroughCasesInSwitch
|
||||||
|
Enable error reporting for fallthrough cases in switch statements..
|
||||||
|
|
||||||
|
// @noImplicitAny
|
||||||
|
Enable error reporting for expressions and declarations with an implied `any` type...
|
||||||
|
|
||||||
|
// @noImplicitOverride
|
||||||
|
Add `undefined` to a type when accessed using an index..
|
||||||
|
|
||||||
|
// @noImplicitReturns
|
||||||
|
Enable error reporting for codepaths that do not explicitly return in a function..
|
||||||
|
|
||||||
|
// @noImplicitThis
|
||||||
|
Enable error reporting when `this` is given the type `any`..
|
||||||
|
|
||||||
|
// @noImplicitUseStrict
|
||||||
|
Disable adding 'use strict' directives in emitted JavaScript files..
|
||||||
|
|
||||||
|
// @noLib
|
||||||
|
Disable including any library files, including the default lib.d.ts..
|
||||||
|
|
||||||
|
// @noPropertyAccessFromIndexSignature
|
||||||
|
Enforces using indexed accessors for keys declared using an indexed type.
|
||||||
|
|
||||||
|
// @noResolve
|
||||||
|
Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project..
|
||||||
|
|
||||||
|
// @noStrictGenericChecks
|
||||||
|
Disable strict checking of generic signatures in function types..
|
||||||
|
|
||||||
|
// @noUncheckedIndexedAccess
|
||||||
|
Include 'undefined' in index signature results.
|
||||||
|
|
||||||
|
// @noUnusedLocals
|
||||||
|
Enable error reporting when a local variables aren't read..
|
||||||
|
|
||||||
|
// @noUnusedParameters
|
||||||
|
Raise an error when a function parameter isn't read.
|
||||||
|
|
||||||
|
// @out
|
||||||
|
Deprecated setting. Use `outFile` instead..
|
||||||
|
|
||||||
|
// @outDir
|
||||||
|
Specify an output folder for all emitted files..
|
||||||
|
|
||||||
|
// @outFile
|
||||||
|
Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output..
|
||||||
|
|
||||||
|
// @paths
|
||||||
|
Specify a set of entries that re-map imports to additional lookup locations..
|
||||||
|
|
||||||
|
// @plugins
|
||||||
|
List of language service plugins..
|
||||||
|
|
||||||
|
// @preserveConstEnums
|
||||||
|
Disable erasing `const enum` declarations in generated code..
|
||||||
|
|
||||||
|
// @preserveSymlinks
|
||||||
|
Disable resolving symlinks to their realpath. This correlates to the same flag in node..
|
||||||
|
|
||||||
|
// @preserveWatchOutput
|
||||||
|
Disable wiping the console in watch mode.
|
||||||
|
|
||||||
|
// @pretty
|
||||||
|
Enable color and formatting in output to make compiler errors easier to read.
|
||||||
|
|
||||||
|
// @reactNamespace
|
||||||
|
Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit..
|
||||||
|
|
||||||
|
// @removeComments
|
||||||
|
Disable emitting comments..
|
||||||
|
|
||||||
|
// @resolveJsonModule
|
||||||
|
Enable importing .json files.
|
||||||
|
|
||||||
|
// @rootDir
|
||||||
|
Specify the root folder within your source files..
|
||||||
|
|
||||||
|
// @rootDirs
|
||||||
|
Allow multiple folders to be treated as one when resolving modules..
|
||||||
|
|
||||||
|
// @skipDefaultLibCheck
|
||||||
|
Skip type checking .d.ts files that are included with TypeScript..
|
||||||
|
|
||||||
|
// @skipLibCheck
|
||||||
|
Skip type checking all .d.ts files..
|
||||||
|
|
||||||
|
// @sourceMap
|
||||||
|
Create source map files for emitted JavaScript files..
|
||||||
|
|
||||||
|
// @sourceRoot
|
||||||
|
Specify the root path for debuggers to find the reference source code..
|
||||||
|
|
||||||
|
// @strict
|
||||||
|
Enable all strict type-checking options..
|
||||||
|
|
||||||
|
// @strictBindCallApply
|
||||||
|
Check that the arguments for `bind`, `call`, and `apply` methods match the original function..
|
||||||
|
|
||||||
|
// @strictFunctionTypes
|
||||||
|
When assigning functions, check to ensure parameters and the return values are subtype-compatible..
|
||||||
|
|
||||||
|
// @strictNullChecks
|
||||||
|
When type checking, take into account `null` and `undefined`..
|
||||||
|
|
||||||
|
// @strictPropertyInitialization
|
||||||
|
Check for class properties that are declared but not set in the constructor..
|
||||||
|
|
||||||
|
// @stripInternal
|
||||||
|
Disable emitting declarations that have `@internal` in their JSDoc comments..
|
||||||
|
|
||||||
|
// @suppressExcessPropertyErrors
|
||||||
|
Disable reporting of excess property errors during the creation of object literals..
|
||||||
|
|
||||||
|
// @suppressImplicitAnyIndexErrors
|
||||||
|
Suppress `noImplicitAny` errors when indexing objects that lack index signatures..
|
||||||
|
|
||||||
|
// @target
|
||||||
|
Set the JavaScript language version for emitted JavaScript and include compatible library declarations..
|
||||||
|
|
||||||
|
// @traceResolution
|
||||||
|
Log paths used during the `moduleResolution` process..
|
||||||
|
|
||||||
|
// @tsBuildInfoFile
|
||||||
|
Specify the folder for .tsbuildinfo incremental compilation files..
|
||||||
|
|
||||||
|
// @typeRoots
|
||||||
|
Specify multiple folders that act like `./node_modules/@types`..
|
||||||
|
|
||||||
|
// @types
|
||||||
|
Specify type package names to be included without being referenced in a source file..
|
||||||
|
|
||||||
|
// @useDefineForClassFields
|
||||||
|
Emit ECMAScript-standard-compliant class fields..
|
||||||
|
|
||||||
|
// @useUnknownInCatchVariables
|
||||||
|
Type catch clause variables as 'unknown' instead of 'any'..
|
||||||
|
```
|
||||||
@ -0,0 +1,132 @@
|
|||||||
|
---
|
||||||
|
description: 'You can configure Twoslash to change code example output.'
|
||||||
|
title: 'Config'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Config
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
You can configure VitePress Twoslash using the `twoslash` property added to `defineConfig`.
|
||||||
|
|
||||||
|
```ts twoslash
|
||||||
|
// .vitepress/config.[ext]
|
||||||
|
import { defineConfig } from 'vitepress'
|
||||||
|
import { withTwoslash, TwoslashConfigSettings } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
|
||||||
|
|
||||||
|
export default withTwoslash(
|
||||||
|
defineConfig({
|
||||||
|
twoslash: {
|
||||||
|
// Your VitePress Twoslash options
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
::: info
|
||||||
|
In addition to the below config options, VitePress Twoslash also supports all [`shiki`](https://github.com/shikijs/shiki) `HighlighterOptions` and [`@typescript/twoslash`](https://github.com/microsoft/TypeScript-Website/tree/v2/packages/ts-twoslasher) `TwoSlashOptions`.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
### `addTryButton`
|
||||||
|
|
||||||
|
A way to turn on the try buttons seen on the TS website.
|
||||||
|
|
||||||
|
- **Type**: `boolean`
|
||||||
|
- **Default**: `false`
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export default withTwoslash(
|
||||||
|
defineConfig({
|
||||||
|
twoslash: {
|
||||||
|
addTryButton: true, // [!code focus]
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### `alwayRaiseForTwoslashExceptions`
|
||||||
|
|
||||||
|
Instead of showing twoslash exceptions inline, throw the entire process like it will on CI.
|
||||||
|
|
||||||
|
- **Type**: `boolean`
|
||||||
|
- **Default**: `false`
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export default withTwoslash(
|
||||||
|
defineConfig({
|
||||||
|
twoslash: {
|
||||||
|
alwayRaiseForTwoslashExceptions: true, // [!code focus]
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### `disableImplicitReactImport`
|
||||||
|
|
||||||
|
A way to disable implicit React imports on tsx/jsx language codeblocks
|
||||||
|
|
||||||
|
- **Type**: `boolean`
|
||||||
|
- **Default**: `false`
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export default withTwoslash(
|
||||||
|
defineConfig({
|
||||||
|
twoslash: {
|
||||||
|
disableImplicitReactImport: true, // [!code focus]
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### `includeJSDocInHover`
|
||||||
|
|
||||||
|
Include JSDoc comments in the hovers.
|
||||||
|
|
||||||
|
- **Type**: `boolean`
|
||||||
|
- **Default**: `false`
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export default withTwoslash(
|
||||||
|
defineConfig({
|
||||||
|
twoslash: {
|
||||||
|
includeJSDocInHover: true, // [!code focus]
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### `ignoreCodeblocksWithCodefenceMeta`
|
||||||
|
|
||||||
|
Ignore transforming certain code blocks.
|
||||||
|
|
||||||
|
- **Type**: `boolean`
|
||||||
|
- **Default**: `false`
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export default withTwoslash(
|
||||||
|
defineConfig({
|
||||||
|
twoslash: {
|
||||||
|
ignoreCodeblocksWithCodefenceMeta: true, // [!code focus]
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### `wrapFragments`
|
||||||
|
|
||||||
|
A way to add a div wrapper for multi-theme outputs.
|
||||||
|
|
||||||
|
- **Type**: `boolean`
|
||||||
|
- **Default**: `false`
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export default withTwoslash(
|
||||||
|
defineConfig({
|
||||||
|
twoslash: {
|
||||||
|
wrapFragments: true, // [!code focus]
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
```
|
||||||
@ -0,0 +1,77 @@
|
|||||||
|
---
|
||||||
|
description: 'Customize the Twoslash interface to match your theme.'
|
||||||
|
title: 'Using a Custom Theme'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Using a Custom Theme
|
||||||
|
|
||||||
|
Twoslash uses your `markdown.theme` for syntax highlighting, but there are a few other things you can do to customize the look and feel of your code examples — particulary the generated Twoslash interface.
|
||||||
|
|
||||||
|
## CSS Variables
|
||||||
|
|
||||||
|
The following CSS variables (and their defaults) are available to style Twoslash interface:
|
||||||
|
|
||||||
|
```css
|
||||||
|
:root {
|
||||||
|
--vp-twoslash-c-annotation-fg: var(--vp-c-text-1);
|
||||||
|
|
||||||
|
--vp-twoslash-c-brand: var(--vp-c-brand);
|
||||||
|
|
||||||
|
--vp-twoslash-c-error-bg: var(--vp-c-red-dimm-2);
|
||||||
|
--vp-twoslash-c-error-fg: var(--vp-c-text-1);
|
||||||
|
|
||||||
|
--vp-twoslash-c-logger-error-bg: var(--vp-c-red-dimm-2);
|
||||||
|
--vp-twoslash-c-logger-error-fg: var(--vp-c-red-dark);
|
||||||
|
--vp-twoslash-c-logger-fg: var(--vp-c-text-1);
|
||||||
|
--vp-twoslash-c-logger-log-bg: var(--vp-c-mute-dark);
|
||||||
|
--vp-twoslash-c-logger-log-fg: var(--vp-c-gray);
|
||||||
|
--vp-twoslash-c-logger-warn-bg: var(--vp-c-yellow-dimm-2);
|
||||||
|
--vp-twoslash-c-logger-warn-fg: var(--vp-c-yellow-dark);
|
||||||
|
|
||||||
|
--vp-twoslash-c-lsp-bg: var(--vp-c-bg-elv);
|
||||||
|
--vp-twoslash-c-lsp-border: var(--vp-c-divider);
|
||||||
|
--vp-twoslash-c-lsp-fg: var(--vp-c-text-1);
|
||||||
|
--vp-twoslash-c-lsp-underline: var(--vp-c-text-2);
|
||||||
|
--vp-twoslash-lsp-shadow: var(--vp-shadow-2);
|
||||||
|
|
||||||
|
--vp-twoslash-c-query-bg: var(--vp-c-mute-darker);
|
||||||
|
--vp-twoslash-c-query-fg-2: var(--vp-c-text-2);
|
||||||
|
--vp-twoslash-c-query-fg: var(--vp-c-text-1);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dark/Light Theme
|
||||||
|
|
||||||
|
If you pass a responsive theme to `markdown.theme`, you probably also want to hide/show the correct theme based on the user's settings.
|
||||||
|
|
||||||
|
```ts twoslash
|
||||||
|
import { defineConfig } from 'vitepress'
|
||||||
|
// ---cut---
|
||||||
|
export default defineConfig({
|
||||||
|
markdown: {
|
||||||
|
theme: { dark: 'vitesse-dark', light: 'vitesse-light' },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
You can do this with the following CSS:
|
||||||
|
|
||||||
|
```css
|
||||||
|
/*
|
||||||
|
* Hide block based on theme
|
||||||
|
* `[class*='-dark']` matches `'vitesse-dark'`
|
||||||
|
* `[class*='-light']` matches `'vitesse-light'`
|
||||||
|
*/
|
||||||
|
html:not(.dark) pre.shiki[class*='-dark'] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
html:not(.dark) pre.shiki[class*='-light'] {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
html.dark pre.shiki[class*='-dark'] {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
html.dark pre.shiki[class*='-light'] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
```
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
---
|
||||||
|
title: 'Markdown Extensions'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Markdown Extensions
|
||||||
|
|
||||||
|
## Code Groups
|
||||||
|
|
||||||
|
[Code Groups](https://vitepress.dev/guide/markdown#code-groups) and Twoslash [multi-file](/api/multi-file) support.
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```ts twoslash [index.ts]
|
||||||
|
// @module: esnext
|
||||||
|
// @filename: name.ts
|
||||||
|
export const name = 'twoslash'
|
||||||
|
// @filename: index.ts
|
||||||
|
// ---cut---
|
||||||
|
import { name } from './name'
|
||||||
|
export function hello(name: string) {
|
||||||
|
console.log(`Hello, ${name}!`)
|
||||||
|
}
|
||||||
|
hello(name)
|
||||||
|
// ^?
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts twoslash [name.ts]
|
||||||
|
export const name = 'twoslash'
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Unsupported Extensions
|
||||||
|
|
||||||
|
Since VitePress Twoslash uses it's own [Shiki](https://github.com/shikijs/shiki) highlighter, the following syntax highlighting extensions are not currently compatible.
|
||||||
|
|
||||||
|
- [Line Highlighting in Code Blocks](https://vitepress.dev/guide/markdown#line-highlighting-in-code-blocks)
|
||||||
|
- [Focus in Code Blocks](https://vitepress.dev/guide/markdown#focus-in-code-blocks)
|
||||||
|
- [Colored Diffs in Code Blocks](https://vitepress.dev/guide/markdown#colored-diffs-in-code-blocks)
|
||||||
|
- [Errors and Warnings in Code Blocks](https://vitepress.dev/guide/markdown#errors-and-warnings-in-code-blocks)
|
||||||
|
- [Line Numbers](https://vitepress.dev/guide/markdown#line-numbers)
|
||||||
|
- [Import Code Snippets](https://vitepress.dev/guide/markdown#import-code-snippets)
|
||||||
|
|
||||||
|
If you are interested in adding support, please start a new [GitHub Discussion](https://github.com/andatoshiki/@andatoshiki/vitepress-plugin-shiki-twoslash).
|
||||||
149
docs/application/vitepress-plugin-shiki-twoslash/index.md
Normal file
149
docs/application/vitepress-plugin-shiki-twoslash/index.md
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
---
|
||||||
|
description: Static code examples for VitePress using Shiki Twoslash.
|
||||||
|
title: "VitePress Twoslash: VitePress Plugin for Shiki Twoslash"
|
||||||
|
titleTemplate: false
|
||||||
|
keywords:
|
||||||
|
- getting-started
|
||||||
|
- intro
|
||||||
|
---
|
||||||
|
|
||||||
|
# @andatoshiki/vitepress-plugin-shiki-twoslash
|
||||||
|
|
||||||
|
> Static code examples for [VitePress](https://vitepress.dev) using [Shiki Twoslash](https://github.com/shikijs/twoslash) — powered by the syntax engine of Visual Studio Code and the TypeScript compiler.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Try moving your cursor into the code block below:
|
||||||
|
|
||||||
|
```ts twoslash
|
||||||
|
// Removes 'readonly' attributes from a type's properties
|
||||||
|
type CreateMutable<Type> = {
|
||||||
|
-readonly [Property in keyof Type]: Type[Property]
|
||||||
|
}
|
||||||
|
|
||||||
|
type LockedAccount = {
|
||||||
|
readonly id: string
|
||||||
|
readonly name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
type UnlockedAccount = CreateMutable<LockedAccount>
|
||||||
|
```
|
||||||
|
|
||||||
|
Pretty neat, right? To some extent, anything your editor can show you about code, Twoslash can show. For example, here is the real auto-complete for a VitePress config:
|
||||||
|
|
||||||
|
```ts twoslash
|
||||||
|
// @noErrors
|
||||||
|
import { defineConfig } from 'vitepress'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
ti,
|
||||||
|
//^|
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
The name Twoslash refers to specially formatted comments (e.g. `// ^?`) which can be used to set up your environment, like compiler flags or separate input files. It couldn't be easier to set up and start creating incredible code examples!
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
Install `@andatoshiki/vitepress-plugin-shiki-twoslash` (requires `vitepress@>=1.0.0-alpha.61`).
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```bash [pnpm]
|
||||||
|
pnpm add @andatoshiki/vitepress-plugin-shiki-twoslash
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash [npm]
|
||||||
|
npm i @andatoshiki/vitepress-plugin-shiki-twoslash
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash [yarn]
|
||||||
|
yarn add @andatoshiki/vitepress-plugin-shiki-twoslash
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: warning
|
||||||
|
Until `shiki-twoslash` uses the same version of `shiki` as VitePress, you must override the following packages' `shiki` versions for syntax highlighting to look the same.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"pnpm": {
|
||||||
|
"overrides": {
|
||||||
|
"remark-shiki-twoslash>shiki": "^0.14.1",
|
||||||
|
"shiki-twoslash>shiki": "^0.14.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Tracked in an upstream issue: https://github.com/shikijs/twoslash/issues/180
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Configure
|
||||||
|
|
||||||
|
First, wrap your VitePress config file with the `withTwoslash` wrapper.
|
||||||
|
|
||||||
|
```ts twoslash
|
||||||
|
// .vitepress/config.[ext]
|
||||||
|
import { defineConfig } from 'vitepress'
|
||||||
|
import { withTwoslash } from '@andatoshiki/vitepress-plugin-shiki-twoslash'
|
||||||
|
|
||||||
|
export default withTwoslash(
|
||||||
|
defineConfig({
|
||||||
|
// Your VitePress config
|
||||||
|
})
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, import `@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css` into your theme.
|
||||||
|
|
||||||
|
```ts twoslash
|
||||||
|
// .vitepress/theme/index.ts
|
||||||
|
import defaultTheme from 'vitepress/theme'
|
||||||
|
import '@andatoshiki/vitepress-plugin-shiki-twoslash/styles.css'
|
||||||
|
|
||||||
|
export default defaultTheme
|
||||||
|
```
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
You can [configure VitePress Twoslash](./config/reference) using the `twoslash` property added to `defineConfig`.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Add Twoslash
|
||||||
|
|
||||||
|
Finally, add the `twoslash` attribute to markdown fenced code blocks.
|
||||||
|
|
||||||
|
````md [markdown]
|
||||||
|
```ts twoslash
|
||||||
|
// Removes 'readonly' attributes from a type's properties
|
||||||
|
type CreateMutable<Type> = {
|
||||||
|
-readonly [Property in keyof Type]: Type[Property]
|
||||||
|
}
|
||||||
|
|
||||||
|
type LockedAccount = {
|
||||||
|
readonly id: string
|
||||||
|
readonly name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
type UnlockedAccount = CreateMutable<LockedAccount>
|
||||||
|
// ^?
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
And your code blocks will be twoslashified!
|
||||||
|
|
||||||
|
```ts twoslash [twoslash]
|
||||||
|
// Removes 'readonly' attributes from a type's properties
|
||||||
|
type CreateMutable<Type> = {
|
||||||
|
-readonly [Property in keyof Type]: Type[Property]
|
||||||
|
}
|
||||||
|
|
||||||
|
type LockedAccount = {
|
||||||
|
readonly id: string
|
||||||
|
readonly name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
type UnlockedAccount = CreateMutable<LockedAccount>
|
||||||
|
// ^?
|
||||||
|
```
|
||||||
15
package.json
15
package.json
@ -27,6 +27,8 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@andatoshiki/markdown-it-image-caption": "0.0.2",
|
"@andatoshiki/markdown-it-image-caption": "0.0.2",
|
||||||
"@andatoshiki/vitepress-plugin-nprogress": "^0.0.1",
|
"@andatoshiki/vitepress-plugin-nprogress": "^0.0.1",
|
||||||
|
"@andatoshiki/vitepress-plugin-shiki-twoslash": "0.0.1",
|
||||||
|
"@antv/g2plot": "^2.4.31",
|
||||||
"@arco-design/web-vue": "^2.46.0",
|
"@arco-design/web-vue": "^2.46.0",
|
||||||
"@luckrya/markdown-it-link-to-card": "^0.3.3",
|
"@luckrya/markdown-it-link-to-card": "^0.3.3",
|
||||||
"@mdit-vue/shared": "^0.12.0",
|
"@mdit-vue/shared": "^0.12.0",
|
||||||
@ -35,6 +37,7 @@
|
|||||||
"artplayer": "^4.6.2",
|
"artplayer": "^4.6.2",
|
||||||
"blueimp-md5": "^2.19.0",
|
"blueimp-md5": "^2.19.0",
|
||||||
"conventional-changelog-cli": "^2.2.2",
|
"conventional-changelog-cli": "^2.2.2",
|
||||||
|
"dayjs": "^1.11.8",
|
||||||
"dplayer": "^1.27.1",
|
"dplayer": "^1.27.1",
|
||||||
"feed": "^4.2.2",
|
"feed": "^4.2.2",
|
||||||
"flv.js": "^1.6.2",
|
"flv.js": "^1.6.2",
|
||||||
@ -68,9 +71,19 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@andatoshiki/markdown-it-katex": "^0.0.3",
|
"@andatoshiki/markdown-it-katex": "^0.0.3",
|
||||||
"markdown-it": "^13.0.1"
|
"@types/react": "^18.2.9",
|
||||||
|
"markdown-it": "^13.0.1",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"vitest": "^0.32.0"
|
||||||
},
|
},
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
|
"overrides": {
|
||||||
|
"remark-shiki-twoslash>shiki": "^0.14.1",
|
||||||
|
"shiki-twoslash>shiki": "^0.14.1",
|
||||||
|
"@antv/g-base": "0.5.11",
|
||||||
|
"@antv/path-util": "2.0.15",
|
||||||
|
"@antv/attr": "0.3.5"
|
||||||
|
},
|
||||||
"peerDependencyRules": {
|
"peerDependencyRules": {
|
||||||
"ignoreMissing": [
|
"ignoreMissing": [
|
||||||
"@algolia/client-search"
|
"@algolia/client-search"
|
||||||
|
|||||||
1040
pnpm-lock.yaml
1040
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
4
pnpm-workspace.yaml
Normal file
4
pnpm-workspace.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
prefer-workspace-packages: true
|
||||||
|
packages:
|
||||||
|
- '.'
|
||||||
|
- 'docs'
|
||||||
Loading…
Reference in New Issue
Block a user