Skip to content

Commit

Permalink
feat: monaco
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Apr 12, 2021
1 parent ae7ed11 commit d78dcb1
Show file tree
Hide file tree
Showing 9 changed files with 192 additions and 7 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@
"eslint": "^7.24.0",
"fs-extra": "^9.1.0",
"markdown-it-prism": "^2.1.6",
"monaco-editor": "^0.23.0",
"pnpm": "^6.0.1",
"theme-vitesse": "^0.1.8",
"typescript": "^4.2.4",
"vite": "^2.1.5",
"vite-plugin-components": "^0.8.3",
Expand Down
33 changes: 33 additions & 0 deletions plugins/monaco.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Plugin, resolvePackageData } from 'vite'

export function createMonacoLoader(): Plugin {
return {
name: 'monaco-types-loader',

resolveId(id) {
if (id.startsWith('/@monaco-types/'))
return id
return null
},

load(id) {
const match = id.match(/^\/\@monaco-types\/(.*)$/)
if (match) {
const pkg = match[1]
const info = resolvePackageData(pkg, process.cwd())
if (!info)
return

if (!info.data.types)
return ''

return [
'import * as monaco from \'monaco-editor\'',
`import Type from "${info.dir}/${info.data.types}?raw"`,
...Object.keys(info.data.dependencies || {}).map(i => `import "/@monaco-types/${i}"`),
`monaco.languages.typescript.typescriptDefaults.addExtraLib(\`declare module "${pkg}" { \$\{Type\} }\`)`,
].join('\n')
}
},
}
}
11 changes: 9 additions & 2 deletions plugins/loader.ts → plugins/slides.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,24 @@ export function createSlidesLoader(): Plugin {
items = parse(raw)
},

configureServer(server) {
server.watcher.add(filepath)
},

async handleHotUpdate(ctx) {
if (ctx.file === filepath) {
raw = await ctx.read()
raw = await read()
items = parse(raw)

return [
const modules = [
'/@vite-slides/routes',
...items.map((i, idx) => `/@vite-slides/slides/${idx}.md`),
]
.map(id => ctx.server.moduleGraph.getModuleById(id))
.filter(isNotNull)

modules.map(m => ctx.server.moduleGraph.invalidateModule(m))
return modules
}
},

Expand Down
13 changes: 13 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions slides.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ import { useFullscreen } from '@vueuse/core'

<Tweet url="https://twitter.com/antfu7/status/1362676666221268995" />

---
---

# Monaco Example

<Monaco />

---
layout: end
---
86 changes: 86 additions & 0 deletions src/components/Monaco.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<template>
<div ref="el" class="monaco-editor text-base" :style="{ height, width }"></div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, defineProps, watch } from 'vue'
import { monaco } from './MonacoEnv'
import { isDark, useNavigateControls } from '~/logic'
const props = defineProps({
code: {
default:
`
import { ref, computed } from 'vue'
const counter = ref(0)
const doubled = computed(() => counter.value * 2)
`.trim(),
},
fontSize: {
default: 20,
},
lang: {
default: 'typescript',
},
lineNumbers: {
default: 'off',
},
width: {
default: '800px',
},
height: {
default: '600px',
},
})
const el = ref<HTMLElement>()
const controls = useNavigateControls()
let editor: monaco.editor.IStandaloneCodeEditor
onMounted(() => {
editor = monaco.editor.create(el.value!, {
language: props.lang,
value: props.code,
tabSize: 2,
insertSpaces: true,
detectIndentation: false,
folding: false,
lineDecorationsWidth: 4,
lineNumbersMinChars: 0,
theme: isDark.value ? 'vitesse-dark' : 'vitesse-light',
lineNumbers: props.lineNumbers as any,
fontSize: props.fontSize,
glyphMargin: false,
scrollbar: {
useShadows: false,
vertical: 'hidden',
horizontal: 'hidden',
},
overviewRulerLanes: 0,
hideCursorInOverviewRuler: true,
minimap: { enabled: false },
})
editor.onDidFocusEditorText(() => controls.paused.value = true)
editor.onDidBlurEditorText(() => controls.paused.value = false)
// @ts-expect-error
editor._themeService._theme.getTokenStyleMetadata = (type, modifiers) => {
console.log(type, modifiers)
if (type === 'keyword') {
return {
foreground: 5, // color id 5
bold: true,
underline: true,
italic: true,
}
}
}
})
watch(isDark, () => monaco.editor.setTheme(isDark.value ? 'vitesse-dark' : 'vitesse-light'))
onUnmounted(() => {
editor.dispose()
})
</script>
32 changes: 32 additions & 0 deletions src/components/MonacoEnv.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import * as monaco from 'monaco-editor'
import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
import JsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
import CssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
import HtmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
import TsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'

import '/@monaco-types/vue'
import '/@monaco-types/@vueuse/core'

import dark from 'theme-vitesse/themes/vitesse-dark.json'
import light from 'theme-vitesse/themes/vitesse-light.json'

monaco.editor.defineTheme('vitesse-light', light as any)
monaco.editor.defineTheme('vitesse-dark', dark as any)

// @ts-expect-error
self.MonacoEnvironment = {
getWorker(_: any, label: string) {
if (label === 'json')
return new JsonWorker()
if (label === 'css' || label === 'scss' || label === 'less')
return new CssWorker()
if (label === 'html' || label === 'handlebars' || label === 'razor')
return new HtmlWorker()
if (label === 'typescript' || label === 'javascript')
return new TsWorker()
return new EditorWorker()
},
}

export { monaco }
11 changes: 7 additions & 4 deletions src/logic/controls.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { computed, App, InjectionKey, inject, ref, ComputedRef } from 'vue'
import { computed, App, InjectionKey, inject, ref, ComputedRef, Ref } from 'vue'
import { Fn, useMagicKeys, whenever } from '@vueuse/core'
import { Router } from 'vue-router'

export interface NavigateControls {
next: Fn
prev: Fn
paused: Ref<boolean>
hasNext: ComputedRef<boolean>
hasPrev: ComputedRef<boolean>
install(app: App): void
Expand All @@ -18,6 +19,7 @@ export function createNavigateControls(router: Router) {
const path = computed(() => route.value.path)

const counter = ref(parseInt(path.value.split(/\//g)[1]) || 0)
const paused = ref(false)

router.afterEach(() => {
counter.value = parseInt(path.value.split(/\//g)[1]) || 0
Expand All @@ -38,13 +40,14 @@ export function createNavigateControls(router: Router) {

const { space, right, left } = useMagicKeys()

whenever(space, next)
whenever(right, next)
whenever(left, prev)
whenever(() => space.value && !paused.value, next)
whenever(() => right.value && !paused.value, next)
whenever(() => left.value && !paused.value, prev)

const navigateControls: NavigateControls = {
next,
prev,
paused,
hasNext,
hasPrev,
install(app: App) {
Expand Down
4 changes: 3 additions & 1 deletion vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import ViteComponents from 'vite-plugin-components'
import Markdown from 'vite-plugin-md'
import WindiCSS from 'vite-plugin-windicss'
import Prism from 'markdown-it-prism'
import { createSlidesLoader } from './plugins/loader'
import { createSlidesLoader } from './plugins/slides'
import { createMonacoLoader } from './plugins/monaco'

export default defineConfig({
resolve: {
Expand Down Expand Up @@ -45,6 +46,7 @@ export default defineConfig({
}),

createSlidesLoader(),
createMonacoLoader(),

ViteIcons(),

Expand Down

0 comments on commit d78dcb1

Please sign in to comment.