Skip to content

Commit

Permalink
feat(theme): 增加 twoslash 插件
Browse files Browse the repository at this point in the history
chore: 微调

fix(theme): 修复 twoslash 配置

chore: 删除注释
  • Loading branch information
FuckDoctors committed Aug 7, 2024
1 parent 4a1ecf6 commit a2df2f3
Show file tree
Hide file tree
Showing 19 changed files with 1,537 additions and 510 deletions.
8 changes: 8 additions & 0 deletions docs/.vuepress/client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { defineClientConfig } from 'vuepress/client'

// import TwoslashFloatingVue from '@shikijs/vitepress-twoslash/client'
import '@shikijs/vitepress-twoslash/style.css'
import TwoslashFloatingVue from './theme/components/twoslash/client'
import './theme/components/twoslash/style.css'

import AutoArticleListLayout from './theme/layouts/AutoArticleListLayout'
import AutoArticleList from './theme/components/AutoArticleList'
import Hanzi from './theme/components/hanzi/Hanzi.vue'
Expand Down Expand Up @@ -28,5 +33,8 @@ export default defineClientConfig({
app.component('FlippyCard', FlippyCard)
app.component('HanziCard', HanziCard)
app.component('PlaygroundIcon', PlaygroundIcon)

// twoslash
app.use(TwoslashFloatingVue)
},
})
8 changes: 8 additions & 0 deletions docs/.vuepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { seoPlugin } from '@vuepress/plugin-seo'
import { pwaPlugin } from '@vuepress/plugin-pwa'
import { sitemapPlugin } from '@vuepress/plugin-sitemap'

import { viteBundler } from '@vuepress/bundler-vite'

import { themeOptions } from './theme.js'
import themeZhaobc from './theme/index'

Expand Down Expand Up @@ -86,4 +88,10 @@ export default defineUserConfig({
hostname: 'www.zhaobc.site',
}),
],

bundler: viteBundler({
viteOptions: {
// something
},
}),
})
15 changes: 11 additions & 4 deletions docs/.vuepress/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import process from 'node:process'
import type { ThemeOptions } from 'vuepress-theme-hope'
import { hopeTheme } from 'vuepress-theme-hope'

// import { transformerTwoslash } from '@shikijs/vitepress-twoslash'
import { transformerTwoslash } from './theme/components/twoslash/index'

import * as navbar from './navbar'
import * as sidebar from './sidebar'

Expand Down Expand Up @@ -103,6 +106,8 @@ export const themeOptions: ThemeOptions = {
},

plugins: {
// backToTop: true,

// blog: true,
blog: {
// article: '/posts/',
Expand Down Expand Up @@ -131,10 +136,10 @@ export const themeOptions: ThemeOptions = {

// 组件插件
components: {
rootComponents: {
backToTop: true,
// addThis: 'ra-573c860d3e983e59',
},
// rootComponents: {
// // backToTop: true,
// // addThis: 'ra-573c860d3e983e59',
// },
components: [
'CodePen',
'StackBlitz',
Expand Down Expand Up @@ -198,10 +203,12 @@ export const themeOptions: ThemeOptions = {
},

shiki: {
lineNumbers: false,
themes: {
light: 'one-light',
dark: 'one-dark-pro',
},
transformers: [transformerTwoslash()],
},
},
}
Expand Down
2 changes: 1 addition & 1 deletion docs/.vuepress/theme/components/hanzi/Hanzi.vue
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ function handleRead() {
<div class="hanzi-main-container">
<div class="hanzi-main">
<div class="hanzi-main__left">
<div ref="printRef" class="hanzi print" />
<div ref="printRef" class="print hanzi" />
<div ref="aniRef" class="hanzi animation" />
<div ref="writingRef" class="hanzi writing" />
<div class="hanzi-controls">
Expand Down
3 changes: 3 additions & 0 deletions docs/.vuepress/theme/components/twoslash/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# README

代码来自这里:[vitepress-twoslash](https://github.com/shikijs/shiki/tree/main/packages/vitepress-twoslash)
77 changes: 77 additions & 0 deletions docs/.vuepress/theme/components/twoslash/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import type { App } from 'vue'
import FloatingVue, { recomputeAllPoppers } from 'floating-vue'
import 'floating-vue/dist/style.css'

const isMobile =
typeof navigator !== 'undefined' &&
/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
navigator.userAgent
)

export type FloatingVueConfig = Parameters<(typeof FloatingVue)['install']>[1]

/**
* Vue plugin to install FloatingVue with styles.
*
* Import this function in `.vitepress/theme/index.ts` and use `app.use(TwoslashFloatingVue)` inside the `enhanceApp` hook.
*/
const TwoslashFloatingVue = {
install: (app: App, options: FloatingVueConfig = {}) => {
if (typeof window !== 'undefined') {
// Recompute poppers when clicking on a tab
window.addEventListener(
'click',
e => {
const path = e.composedPath()
if (
path.some(
(el: any) =>
el?.classList?.contains?.('vp-code-group') ||
el?.classList?.contains?.('tabs')
)
) {
recomputeAllPoppers()
}
},
{ passive: true }
)
}

app.use(FloatingVue, {
...options,
themes: {
twoslash: {
$extend: 'dropdown',
triggers: isMobile ? ['touch'] : ['hover', 'touch'],
popperTriggers: isMobile ? ['touch'] : ['hover', 'touch'],
placement: 'bottom-start',
overflowPadding: 10,
delay: 0,
handleResize: false,
autoHide: true,
instantMove: true,
flip: false,
arrowPadding: 8,
autoBoundaryMaxSize: true,
},
'twoslash-query': {
$extend: 'twoslash',
triggers: ['click'],
popperTriggers: ['click'],
autoHide: false,
},
'twoslash-completion': {
$extend: 'twoslash-query',
triggers: ['click'],
popperTriggers: ['click'],
autoHide: false,
distance: 0,
arrowOverflow: true,
},
...options.theme,
},
})
},
}

export default TwoslashFloatingVue
100 changes: 100 additions & 0 deletions docs/.vuepress/theme/components/twoslash/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/* eslint-disable node/prefer-global/process */
import type { TransformerTwoslashOptions } from '@shikijs/twoslash/core'
import { createTransformerFactory } from '@shikijs/twoslash/core'
import type { VueSpecificOptions } from 'twoslash-vue'
import { createTwoslasher } from 'twoslash-vue'
import type { ShikiTransformer } from 'shiki'
import { removeTwoslashNotations } from 'twoslash'

import type { TwoslashFloatingVueRendererOptions } from './renderer-floating-vue'
import { rendererFloatingVue } from './renderer-floating-vue'

export * from './renderer-floating-vue'

interface TransformerTwoslashVueOptions extends TransformerTwoslashOptions {
twoslashOptions?: TransformerTwoslashOptions['twoslashOptions'] &
VueSpecificOptions
}

export interface VitePressPluginTwoslashOptions
extends TransformerTwoslashVueOptions,
TwoslashFloatingVueRendererOptions {
/**
* Requires adding `twoslash` to the code block explicitly to run twoslash
* @default true
*/
explicitTrigger?: TransformerTwoslashOptions['explicitTrigger']
}

/**
* Create a Shiki transformer for VitePress to enable twoslash integration
*
* Add this to `markdown.codeTransformers` in `.vitepress/config.ts`
*/
export function transformerTwoslash(
options: VitePressPluginTwoslashOptions = {}
): ShikiTransformer {
const { explicitTrigger = true } = options

const onError = (error: any, code: string) => {
const isCI = typeof process !== 'undefined' && process?.env?.CI
const isDev =
typeof process !== 'undefined' && process?.env?.NODE_ENV === 'development'
const shouldThrow =
(options.throws || isCI || !isDev) && options.throws !== false
console.error(
`\n\n--------\nTwoslash error in code:\n--------\n${code.split(/\n/g).slice(0, 15).join('\n').trim()}\n--------\n`
)
if (shouldThrow) {
throw error
} else {
console.error(error)
}
return removeTwoslashNotations(code)
}

const twoslash = createTransformerFactory(
createTwoslasher(options.twoslashOptions)
)({
langs: ['ts', 'tsx', 'js', 'jsx', 'json', 'vue'],
renderer: rendererFloatingVue(options),
onTwoslashError: onError,
onShikiError: onError,
...options,
explicitTrigger,
})

const trigger =
explicitTrigger instanceof RegExp ? explicitTrigger : /\btwoslash\b/

return {
...twoslash,
name: '@shikijs/vuepress-twoslash',
preprocess(code, options) {
const cleanup = options.transformers?.find(
i => i.name === 'vuepress:clean-up'
)
if (cleanup) {
options.transformers?.splice(options.transformers.indexOf(cleanup), 1)
}

// Disable v-pre for twoslash, because we need render it with FloatingVue
// 自己添加 :no-v-pre
if (!explicitTrigger || options.meta?.__raw?.match(trigger)) {
const vPre = options.transformers?.find(
i => i.name === 'vuepress:v-pre'
)
if (vPre) {
options.transformers?.splice(options.transformers.indexOf(vPre), 1)
}
}

return twoslash.preprocess!.call(this, code, options)
},
postprocess(html) {
if (this.meta.twoslash) {
return html.replace(/\{/g, '&#123;')
}
},
}
}
Loading

0 comments on commit a2df2f3

Please sign in to comment.