@slidev/client 0.48.0-beta.15 → 0.48.0-beta.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/builtin/CodeBlockWrapper.vue +10 -3
- package/builtin/Monaco.vue +105 -88
- package/builtin/ShikiMagicMove.vue +2 -2
- package/builtin/Tweet.vue +3 -11
- package/internals/PrintContainer.vue +1 -1
- package/logic/nav.ts +3 -6
- package/modules/mermaid.ts +2 -2
- package/package.json +8 -4
- package/setup/monaco.ts +102 -44
- package/shim.d.ts +1 -1
- package/styles/monaco.css +27 -0
- package/composables/useTweetScript.ts +0 -17
- package/iframes/monaco/index.css +0 -28
- package/iframes/monaco/index.html +0 -7
- package/iframes/monaco/index.ts +0 -260
|
@@ -56,8 +56,12 @@ onUnmounted(() => {
|
|
|
56
56
|
clicks!.unregister(id)
|
|
57
57
|
})
|
|
58
58
|
|
|
59
|
+
watchEffect(() => {
|
|
60
|
+
el.value?.classList.toggle('slidev-code-line-numbers', props.lines)
|
|
61
|
+
})
|
|
62
|
+
|
|
59
63
|
onMounted(() => {
|
|
60
|
-
if (!clicks || clicks.disabled)
|
|
64
|
+
if (!clicks || clicks.disabled || !props.ranges?.length)
|
|
61
65
|
return
|
|
62
66
|
|
|
63
67
|
const { start, end, delta } = clicks.resolve(props.at, props.ranges.length - 1)
|
|
@@ -121,9 +125,12 @@ function copyCode() {
|
|
|
121
125
|
|
|
122
126
|
<template>
|
|
123
127
|
<div
|
|
124
|
-
ref="el"
|
|
128
|
+
ref="el"
|
|
129
|
+
class="slidev-code-wrapper relative group"
|
|
130
|
+
:class="{
|
|
125
131
|
'slidev-code-line-numbers': props.lines,
|
|
126
|
-
}"
|
|
132
|
+
}"
|
|
133
|
+
:style="{
|
|
127
134
|
'max-height': props.maxHeight,
|
|
128
135
|
'overflow-y': props.maxHeight ? 'scroll' : undefined,
|
|
129
136
|
'--start': props.startLine,
|
package/builtin/Monaco.vue
CHANGED
|
@@ -12,11 +12,10 @@ Learn more: https://sli.dev/guide/syntax.html#monaco-editor
|
|
|
12
12
|
-->
|
|
13
13
|
|
|
14
14
|
<script setup lang="ts">
|
|
15
|
-
import { computed, onMounted, ref } from 'vue'
|
|
16
|
-
import { useEventListener } from '@vueuse/core'
|
|
17
15
|
import type * as monaco from 'monaco-editor'
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
16
|
+
import { computed, nextTick, onMounted, ref } from 'vue'
|
|
17
|
+
import { debounce } from '@antfu/utils'
|
|
18
|
+
import lz from 'lz-string'
|
|
20
19
|
import { makeId } from '../logic/utils'
|
|
21
20
|
|
|
22
21
|
const props = withDefaults(defineProps<{
|
|
@@ -25,109 +24,127 @@ const props = withDefaults(defineProps<{
|
|
|
25
24
|
lang?: string
|
|
26
25
|
readonly?: boolean
|
|
27
26
|
lineNumbers?: 'on' | 'off' | 'relative' | 'interval'
|
|
28
|
-
height?: number | string
|
|
27
|
+
height?: number | string // Posible values: 'initial', 'auto', '100%', '200px', etc.
|
|
29
28
|
editorOptions?: monaco.editor.IEditorOptions
|
|
29
|
+
ata?: boolean
|
|
30
30
|
}>(), {
|
|
31
31
|
codeLz: '',
|
|
32
32
|
lang: 'typescript',
|
|
33
33
|
readonly: false,
|
|
34
34
|
lineNumbers: 'off',
|
|
35
|
-
height: '
|
|
35
|
+
height: 'initial',
|
|
36
|
+
ata: true,
|
|
36
37
|
})
|
|
37
38
|
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
const diff = ref(props.diffLz ? decompressFromBase64(props.diffLz) : null)
|
|
41
|
-
const lineHeight = +(getComputedStyle(document.body).getPropertyValue('--slidev-code-line-height') || '18').replace('px', '') || 18
|
|
42
|
-
const editorHeight = ref(0)
|
|
43
|
-
const calculatedHeight = computed(() => code.value.split(/\r?\n/g).length * lineHeight)
|
|
44
|
-
const height = computed(() => {
|
|
45
|
-
return props.height === 'auto' ? `${Math.max(calculatedHeight.value, editorHeight.value) + 20}px` : props.height
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
const iframe = ref<HTMLIFrameElement>()
|
|
39
|
+
const code = lz.decompressFromBase64(props.codeLz).trimEnd()
|
|
40
|
+
const diff = props.diffLz && lz.decompressFromBase64(props.diffLz).trimEnd()
|
|
49
41
|
|
|
50
|
-
const
|
|
51
|
-
'
|
|
52
|
-
'
|
|
53
|
-
'--slidev-code-background',
|
|
54
|
-
'--slidev-code-line-height',
|
|
55
|
-
'--slidev-code-padding',
|
|
56
|
-
'--slidev-code-margin',
|
|
57
|
-
'--slidev-code-radius',
|
|
58
|
-
]
|
|
59
|
-
|
|
60
|
-
function getStyleObject(el: Element) {
|
|
61
|
-
const object: Record<string, string> = {}
|
|
62
|
-
const style = getComputedStyle(el)
|
|
63
|
-
for (const v of cssVars)
|
|
64
|
-
object[v] = style.getPropertyValue(v)
|
|
65
|
-
return object
|
|
42
|
+
const langMap: Record<string, string> = {
|
|
43
|
+
ts: 'typescript',
|
|
44
|
+
js: 'javascript',
|
|
66
45
|
}
|
|
46
|
+
const lang = langMap[props.lang] ?? props.lang
|
|
47
|
+
const extMap: Record<string, string> = {
|
|
48
|
+
typescript: 'mts',
|
|
49
|
+
javascript: 'mjs',
|
|
50
|
+
ts: 'mts',
|
|
51
|
+
js: 'mjs',
|
|
52
|
+
}
|
|
53
|
+
const ext = extMap[props.lang] ?? props.lang
|
|
67
54
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
frame.setAttribute('sandbox', [
|
|
71
|
-
'allow-forms',
|
|
72
|
-
'allow-modals',
|
|
73
|
-
'allow-pointer-lock',
|
|
74
|
-
'allow-popups',
|
|
75
|
-
'allow-same-origin',
|
|
76
|
-
'allow-scripts',
|
|
77
|
-
'allow-top-navigation-by-user-activation',
|
|
78
|
-
].join(' '))
|
|
79
|
-
|
|
80
|
-
let src = __DEV__
|
|
81
|
-
? `${location.origin}${__SLIDEV_CLIENT_ROOT__}/`
|
|
82
|
-
: import.meta.env.BASE_URL
|
|
83
|
-
src += `iframes/monaco/index.html?id=${id}&lineNumbers=${props.lineNumbers}&lang=${props.lang}`
|
|
84
|
-
if (diff.value)
|
|
85
|
-
src += '&diff=1'
|
|
86
|
-
frame.src = src
|
|
55
|
+
const outer = ref<HTMLDivElement>()
|
|
56
|
+
const container = ref<HTMLDivElement>()
|
|
87
57
|
|
|
88
|
-
|
|
58
|
+
const contentHeight = ref(0)
|
|
59
|
+
const initialHeight = ref<number>()
|
|
60
|
+
const height = computed(() => {
|
|
61
|
+
if (props.height === 'auto')
|
|
62
|
+
return `${contentHeight.value}px`
|
|
63
|
+
if (props.height === 'initial')
|
|
64
|
+
return `${initialHeight.value}px`
|
|
65
|
+
return props.height
|
|
89
66
|
})
|
|
90
67
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
68
|
+
onMounted(async () => {
|
|
69
|
+
// Lazy load monaco, so it will be bundled in async chunk
|
|
70
|
+
const { default: setup } = await import('../setup/monaco')
|
|
71
|
+
const { ata, monaco } = await setup()
|
|
72
|
+
const model = monaco.editor.createModel(code, lang, monaco.Uri.parse(`file:///${makeId()}.${ext}`))
|
|
73
|
+
const commonOptions = {
|
|
74
|
+
automaticLayout: true,
|
|
75
|
+
readOnly: props.readonly,
|
|
76
|
+
lineNumbers: props.lineNumbers,
|
|
77
|
+
minimap: { enabled: false },
|
|
78
|
+
overviewRulerBorder: false,
|
|
79
|
+
overviewRulerLanes: 0,
|
|
80
|
+
padding: { top: 10, bottom: 10 },
|
|
81
|
+
lineNumbersMinChars: 3,
|
|
82
|
+
bracketPairColorization: { enabled: false },
|
|
83
|
+
tabSize: 2,
|
|
84
|
+
fontSize: 11.5,
|
|
85
|
+
fontFamily: 'var(--slidev-code-font-family)',
|
|
86
|
+
scrollBeyondLastLine: false,
|
|
87
|
+
...props.editorOptions,
|
|
88
|
+
} satisfies monaco.editor.IStandaloneEditorConstructionOptions & monaco.editor.IDiffEditorConstructionOptions
|
|
101
89
|
|
|
102
|
-
|
|
103
|
-
if (
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
90
|
+
let editableEditor: monaco.editor.IStandaloneCodeEditor
|
|
91
|
+
if (diff) {
|
|
92
|
+
const diffModel = monaco.editor.createModel(diff, lang, monaco.Uri.parse(`file:///${makeId()}.${ext}`))
|
|
93
|
+
const editor = monaco.editor.createDiffEditor(container.value!, {
|
|
94
|
+
renderOverviewRuler: false,
|
|
95
|
+
...commonOptions,
|
|
96
|
+
})
|
|
97
|
+
editor.setModel({
|
|
98
|
+
original: model,
|
|
99
|
+
modified: diffModel,
|
|
100
|
+
})
|
|
101
|
+
const originalEditor = editor.getOriginalEditor()
|
|
102
|
+
const modifiedEditor = editor.getModifiedEditor()
|
|
103
|
+
const onContentSizeChange = () => {
|
|
104
|
+
const newHeight = Math.max(originalEditor.getContentHeight(), modifiedEditor.getContentHeight()) + 4
|
|
105
|
+
initialHeight.value ??= newHeight
|
|
106
|
+
contentHeight.value = newHeight
|
|
107
|
+
nextTick(() => editor.layout())
|
|
108
|
+
}
|
|
109
|
+
originalEditor.onDidContentSizeChange(onContentSizeChange)
|
|
110
|
+
modifiedEditor.onDidContentSizeChange(onContentSizeChange)
|
|
111
|
+
editableEditor = modifiedEditor
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
const editor = monaco.editor.create(container.value!, {
|
|
115
|
+
model,
|
|
116
|
+
lineDecorationsWidth: 0,
|
|
117
|
+
...commonOptions,
|
|
118
|
+
})
|
|
119
|
+
editor.onDidContentSizeChange((e) => {
|
|
120
|
+
const newHeight = e.contentHeight + 4
|
|
121
|
+
initialHeight.value ??= newHeight
|
|
122
|
+
contentHeight.value = newHeight
|
|
123
|
+
nextTick(() => editableEditor.layout())
|
|
124
|
+
})
|
|
125
|
+
editableEditor = editor
|
|
126
|
+
}
|
|
127
|
+
if (props.ata) {
|
|
128
|
+
ata(editableEditor.getValue())
|
|
129
|
+
editableEditor.onDidChangeModelContent(debounce(1000, () => {
|
|
130
|
+
ata(editableEditor.getValue())
|
|
131
|
+
}))
|
|
132
|
+
}
|
|
133
|
+
const originalLayoutContentWidget = editableEditor.layoutContentWidget.bind(editableEditor)
|
|
134
|
+
editableEditor.layoutContentWidget = (widget: any) => {
|
|
135
|
+
originalLayoutContentWidget(widget)
|
|
136
|
+
const id = widget.getId()
|
|
137
|
+
if (id === 'editor.contrib.resizableContentHoverWidget') {
|
|
138
|
+
widget._resizableNode.domNode.style.transform = widget._positionPreference === 1
|
|
139
|
+
? /* ABOVE */ `translateY(calc(100% * (var(--slidev-slide-scale) - 1)))`
|
|
140
|
+
: /* BELOW */ `` // reset
|
|
117
141
|
}
|
|
118
|
-
return
|
|
119
142
|
}
|
|
120
|
-
if (payload.type !== 'slidev-monaco')
|
|
121
|
-
return
|
|
122
|
-
if (payload.data?.height)
|
|
123
|
-
editorHeight.value = payload.data?.height
|
|
124
|
-
if (payload?.data?.code && code.value !== payload.data.code)
|
|
125
|
-
code.value = payload.data.code
|
|
126
|
-
if (payload?.data?.diff && diff.value !== payload.data.diff)
|
|
127
|
-
diff.value = payload.data.diff
|
|
128
143
|
})
|
|
129
144
|
</script>
|
|
130
145
|
|
|
131
146
|
<template>
|
|
132
|
-
<
|
|
147
|
+
<div ref="outer" class="slidev-monaco-container" :style="{ height }">
|
|
148
|
+
<div ref="container" class="absolute inset-0.5" />
|
|
149
|
+
</div>
|
|
133
150
|
</template>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { ShikiMagicMovePrecompiled } from 'shiki-magic-move/vue'
|
|
3
3
|
import type { KeyedTokensInfo } from 'shiki-magic-move/types'
|
|
4
4
|
import { onMounted, onUnmounted, ref, watchEffect } from 'vue'
|
|
5
|
-
import
|
|
5
|
+
import lz from 'lz-string'
|
|
6
6
|
import { useSlideContext } from '../context'
|
|
7
7
|
import { makeId } from '../logic/utils'
|
|
8
8
|
|
|
@@ -13,7 +13,7 @@ const props = defineProps<{
|
|
|
13
13
|
at?: string | number
|
|
14
14
|
}>()
|
|
15
15
|
|
|
16
|
-
const steps = JSON.parse(decompressFromBase64(props.stepsLz)) as KeyedTokensInfo[]
|
|
16
|
+
const steps = JSON.parse(lz.decompressFromBase64(props.stepsLz)) as KeyedTokensInfo[]
|
|
17
17
|
const { $clicksContext: clicks, $scale: scale } = useSlideContext()
|
|
18
18
|
const id = makeId()
|
|
19
19
|
const index = ref(0)
|
package/builtin/Tweet.vue
CHANGED
|
@@ -7,9 +7,8 @@ Usage:
|
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
9
|
<script setup lang="ts">
|
|
10
|
-
import {
|
|
10
|
+
import { onMounted, ref } from 'vue'
|
|
11
11
|
import { isDark } from '../logic/dark'
|
|
12
|
-
import { useTweetScript } from '../composables/useTweetScript'
|
|
13
12
|
|
|
14
13
|
const props = defineProps<{
|
|
15
14
|
id: string | number
|
|
@@ -20,11 +19,10 @@ const props = defineProps<{
|
|
|
20
19
|
|
|
21
20
|
const tweet = ref<HTMLElement | null>()
|
|
22
21
|
|
|
23
|
-
const vm = getCurrentInstance()!
|
|
24
22
|
const loaded = ref(false)
|
|
25
23
|
const tweetNotFound = ref(false)
|
|
26
24
|
|
|
27
|
-
async
|
|
25
|
+
onMounted(async () => {
|
|
28
26
|
// @ts-expect-error global
|
|
29
27
|
const element = await window.twttr.widgets.createTweet(
|
|
30
28
|
props.id.toString(),
|
|
@@ -38,13 +36,7 @@ async function create() {
|
|
|
38
36
|
loaded.value = true
|
|
39
37
|
if (element === undefined)
|
|
40
38
|
tweetNotFound.value = true
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// @ts-expect-error global
|
|
44
|
-
if (window?.twttr?.widgets)
|
|
45
|
-
onMounted(create)
|
|
46
|
-
else
|
|
47
|
-
useTweetScript(vm, create)
|
|
39
|
+
})
|
|
48
40
|
</script>
|
|
49
41
|
|
|
50
42
|
<template>
|
package/logic/nav.ts
CHANGED
|
@@ -135,16 +135,13 @@ export function go(page: number | string, clicks?: number) {
|
|
|
135
135
|
export function useSwipeControls(root: Ref<HTMLElement | undefined>) {
|
|
136
136
|
const swipeBegin = ref(0)
|
|
137
137
|
const { direction, distanceX, distanceY } = usePointerSwipe(root, {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
return
|
|
138
|
+
pointerTypes: ['touch'],
|
|
139
|
+
onSwipeStart() {
|
|
141
140
|
if (isDrawing.value)
|
|
142
141
|
return
|
|
143
142
|
swipeBegin.value = timestamp()
|
|
144
143
|
},
|
|
145
|
-
onSwipeEnd(
|
|
146
|
-
if (e.pointerType !== 'touch')
|
|
147
|
-
return
|
|
144
|
+
onSwipeEnd() {
|
|
148
145
|
if (!swipeBegin.value)
|
|
149
146
|
return
|
|
150
147
|
if (isDrawing.value)
|
package/modules/mermaid.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import mermaid from 'mermaid/dist/mermaid.esm.mjs'
|
|
2
|
-
import
|
|
2
|
+
import lz from 'lz-string'
|
|
3
3
|
import { clearUndefined } from '@antfu/utils'
|
|
4
4
|
import setupMermaid from '../setup/mermaid'
|
|
5
5
|
import { makeId } from '../logic/utils'
|
|
@@ -20,7 +20,7 @@ export async function renderMermaid(lzEncoded: string, options: any) {
|
|
|
20
20
|
...clearUndefined(setupMermaid() || {}),
|
|
21
21
|
...clearUndefined(options),
|
|
22
22
|
})
|
|
23
|
-
const code = decompressFromBase64(lzEncoded)
|
|
23
|
+
const code = lz.decompressFromBase64(lzEncoded)
|
|
24
24
|
const id = makeId()
|
|
25
25
|
const { svg } = await mermaid.render(id, code)
|
|
26
26
|
cache.set(key, svg)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slidev/client",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.48.0-beta.
|
|
4
|
+
"version": "0.48.0-beta.17",
|
|
5
5
|
"description": "Presentation slides for developers",
|
|
6
6
|
"author": "antfu <anthonyfu117@hotmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -29,8 +29,10 @@
|
|
|
29
29
|
"@antfu/utils": "^0.7.7",
|
|
30
30
|
"@iconify-json/carbon": "^1.1.30",
|
|
31
31
|
"@iconify-json/ph": "^1.1.11",
|
|
32
|
+
"@shikijs/monaco": "^1.1.7",
|
|
32
33
|
"@shikijs/vitepress-twoslash": "^1.1.7",
|
|
33
34
|
"@slidev/rough-notation": "^0.1.0",
|
|
35
|
+
"@typescript/ata": "^0.9.4",
|
|
34
36
|
"@unhead/vue": "^1.8.10",
|
|
35
37
|
"@unocss/reset": "^0.58.5",
|
|
36
38
|
"@vueuse/core": "^10.8.0",
|
|
@@ -46,16 +48,18 @@
|
|
|
46
48
|
"katex": "^0.16.9",
|
|
47
49
|
"lz-string": "^1.5.0",
|
|
48
50
|
"mermaid": "^10.8.0",
|
|
49
|
-
"monaco-editor": "^0.
|
|
51
|
+
"monaco-editor": "^0.46.0",
|
|
52
|
+
"nanoid": "^5.0.6",
|
|
50
53
|
"prettier": "^3.2.5",
|
|
51
54
|
"recordrtc": "^5.6.2",
|
|
52
55
|
"resolve": "^1.22.8",
|
|
56
|
+
"shiki": "^1.1.7",
|
|
53
57
|
"shiki-magic-move": "^0.1.0",
|
|
54
58
|
"unocss": "^0.58.5",
|
|
55
59
|
"vue": "^3.4.20",
|
|
56
60
|
"vue-router": "^4.3.0",
|
|
57
|
-
"@slidev/
|
|
58
|
-
"@slidev/
|
|
61
|
+
"@slidev/parser": "0.48.0-beta.17",
|
|
62
|
+
"@slidev/types": "0.48.0-beta.17"
|
|
59
63
|
},
|
|
60
64
|
"devDependencies": {
|
|
61
65
|
"vite": "^5.1.4"
|
package/setup/monaco.ts
CHANGED
|
@@ -1,52 +1,114 @@
|
|
|
1
|
-
import { getCurrentInstance, onMounted } from 'vue'
|
|
2
|
-
import * as monaco from 'monaco-editor'
|
|
3
1
|
import { createSingletonPromise } from '@antfu/utils'
|
|
4
2
|
import type { MonacoSetupReturn } from '@slidev/types'
|
|
3
|
+
import * as monaco from 'monaco-editor'
|
|
4
|
+
import { watchEffect } from 'vue'
|
|
5
|
+
import { setupTypeAcquisition } from '@typescript/ata'
|
|
6
|
+
import ts from 'typescript'
|
|
7
|
+
|
|
8
|
+
import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
|
|
9
|
+
import CssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
|
|
10
|
+
import HtmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
|
|
11
|
+
import JsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
|
|
12
|
+
import TsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
|
|
13
|
+
|
|
14
|
+
// @ts-expect-error missing types
|
|
15
|
+
import { ContextViewService } from 'monaco-editor/esm/vs/platform/contextview/browser/contextViewService'
|
|
16
|
+
|
|
17
|
+
// @ts-expect-error missing types
|
|
18
|
+
import { SyncDescriptor } from 'monaco-editor/esm/vs/platform/instantiation/common/descriptors'
|
|
19
|
+
|
|
20
|
+
// @ts-expect-error missing types
|
|
21
|
+
import { StandaloneServices } from 'monaco-editor/esm/vs/editor/standalone/browser/standaloneServices'
|
|
22
|
+
|
|
23
|
+
import { isDark } from '../logic/dark'
|
|
24
|
+
import configs from '#slidev/configs'
|
|
5
25
|
|
|
6
26
|
/* __imports__ */
|
|
27
|
+
window.MonacoEnvironment = {
|
|
28
|
+
getWorker(_, label) {
|
|
29
|
+
if (label === 'json')
|
|
30
|
+
return new JsonWorker()
|
|
31
|
+
if (label === 'css' || label === 'scss' || label === 'less')
|
|
32
|
+
return new CssWorker()
|
|
33
|
+
if (label === 'html' || label === 'handlebars' || label === 'razor')
|
|
34
|
+
return new HtmlWorker()
|
|
35
|
+
if (label === 'typescript' || label === 'javascript')
|
|
36
|
+
return new TsWorker()
|
|
37
|
+
return new EditorWorker()
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
class ContextViewService2 extends ContextViewService {
|
|
42
|
+
showContextView(...args: any) {
|
|
43
|
+
super.showContextView(...args)
|
|
44
|
+
// @ts-expect-error missing types
|
|
45
|
+
const contextView = this.contextView.view as HTMLElement
|
|
46
|
+
contextView.style.left = `calc(${contextView.style.left} / var(--slidev-slide-scale))`
|
|
47
|
+
contextView.style.top = `calc(${contextView.style.top} / var(--slidev-slide-scale))`
|
|
48
|
+
// Reset the scale to 1. Otherwise, the sub-menu will be in the wrong position.
|
|
49
|
+
contextView.style.transform = `scale(calc(1 / var(--slidev-slide-scale)))`
|
|
50
|
+
contextView.style.transformOrigin = '0 0'
|
|
51
|
+
}
|
|
52
|
+
}
|
|
7
53
|
|
|
8
54
|
const setup = createSingletonPromise(async () => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
55
|
+
// Initialize services first, otherwise we can't override them.
|
|
56
|
+
StandaloneServices.initialize({
|
|
57
|
+
contextViewService: new SyncDescriptor(ContextViewService2, [], true),
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
const defaults = monaco.languages.typescript.typescriptDefaults
|
|
61
|
+
|
|
62
|
+
defaults.setCompilerOptions({
|
|
63
|
+
...defaults.getCompilerOptions(),
|
|
15
64
|
strict: true,
|
|
65
|
+
moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
|
|
66
|
+
module: monaco.languages.typescript.ModuleKind.ESNext,
|
|
16
67
|
})
|
|
17
68
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
getWorker(_: any, label: string) {
|
|
37
|
-
if (label === 'json')
|
|
38
|
-
return new JsonWorker()
|
|
39
|
-
if (label === 'css' || label === 'scss' || label === 'less')
|
|
40
|
-
return new CssWorker()
|
|
41
|
-
if (label === 'html' || label === 'handlebars' || label === 'razor')
|
|
42
|
-
return new HtmlWorker()
|
|
43
|
-
if (label === 'typescript' || label === 'javascript')
|
|
44
|
-
return new TsWorker()
|
|
45
|
-
return new EditorWorker()
|
|
69
|
+
// Load types from server
|
|
70
|
+
import('#slidev/monaco-types')
|
|
71
|
+
|
|
72
|
+
const ata = configs.monacoTypesSource === 'cdn'
|
|
73
|
+
? setupTypeAcquisition({
|
|
74
|
+
projectName: 'TypeScript Playground',
|
|
75
|
+
typescript: ts as any, // Version mismatch. No problem found so far.
|
|
76
|
+
logger: console,
|
|
77
|
+
delegate: {
|
|
78
|
+
receivedFile: (code: string, path: string) => {
|
|
79
|
+
defaults.addExtraLib(code, `file://${path}`)
|
|
80
|
+
const uri = monaco.Uri.file(path)
|
|
81
|
+
if (monaco.editor.getModel(uri) === null)
|
|
82
|
+
monaco.editor.createModel(code, 'javascript', uri)
|
|
83
|
+
},
|
|
84
|
+
progress: (downloaded: number, total: number) => {
|
|
85
|
+
// eslint-disable-next-line no-console
|
|
86
|
+
console.debug(`[Typescript ATA] ${downloaded} / ${total}`)
|
|
46
87
|
},
|
|
47
|
-
}
|
|
48
|
-
})
|
|
49
|
-
|
|
88
|
+
},
|
|
89
|
+
})
|
|
90
|
+
: () => { }
|
|
91
|
+
|
|
92
|
+
// monaco.languages.register({ id: 'vue' })
|
|
93
|
+
monaco.languages.register({ id: 'typescript' })
|
|
94
|
+
monaco.languages.register({ id: 'javascript' })
|
|
95
|
+
|
|
96
|
+
const { shiki, themes, shikiToMonaco } = await import('#slidev/shiki')
|
|
97
|
+
const highlighter = await shiki
|
|
98
|
+
|
|
99
|
+
// Use Shiki to highlight Monaco
|
|
100
|
+
shikiToMonaco(highlighter, monaco)
|
|
101
|
+
|
|
102
|
+
if (typeof themes === 'string') {
|
|
103
|
+
monaco.editor.setTheme(themes)
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
watchEffect(() => {
|
|
107
|
+
monaco.editor.setTheme(isDark.value
|
|
108
|
+
? themes.dark || 'vitesse-dark'
|
|
109
|
+
: themes.light || 'vitesse-light')
|
|
110
|
+
})
|
|
111
|
+
}
|
|
50
112
|
|
|
51
113
|
// @ts-expect-error injected in runtime
|
|
52
114
|
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
@@ -56,15 +118,11 @@ const setup = createSingletonPromise(async () => {
|
|
|
56
118
|
|
|
57
119
|
/* __async_injections__ */
|
|
58
120
|
|
|
59
|
-
if (getCurrentInstance())
|
|
60
|
-
await new Promise<void>(resolve => onMounted(resolve))
|
|
61
|
-
|
|
62
121
|
return {
|
|
63
122
|
monaco,
|
|
123
|
+
ata,
|
|
64
124
|
...injection_return,
|
|
65
125
|
}
|
|
66
126
|
})
|
|
67
127
|
|
|
68
128
|
export default setup
|
|
69
|
-
|
|
70
|
-
setup()
|
package/shim.d.ts
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
div[widgetid='messageoverlay'] {
|
|
2
|
+
transform: translateY(calc(100% * (var(--slidev-slide-scale) - 1)));
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.slidev-monaco-container {
|
|
6
|
+
position: relative;
|
|
7
|
+
margin: var(--slidev-code-margin);
|
|
8
|
+
padding: var(--slidev-code-padding);
|
|
9
|
+
line-height: var(--slidev-code-line-height);
|
|
10
|
+
border-radius: var(--slidev-code-radius);
|
|
11
|
+
background: var(--slidev-code-background);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.slidev-monaco-container .monaco-editor {
|
|
15
|
+
--monaco-monospace-font: var(--slidev-code-font-family);
|
|
16
|
+
--vscode-editor-background: var(--slidev-code-background);
|
|
17
|
+
--vscode-editorGutter-background: var(--slidev-code-background);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Revert styles */
|
|
21
|
+
.slidev-monaco-container .monaco-editor a {
|
|
22
|
+
border-bottom: none;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.slidev-monaco-container .monaco-editor a:hover {
|
|
26
|
+
border-bottom: none;
|
|
27
|
+
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { createSharedComposable, useScriptTag } from '@vueuse/core'
|
|
2
|
-
import type { ComponentInternalInstance } from 'vue'
|
|
3
|
-
import { onMounted } from 'vue'
|
|
4
|
-
|
|
5
|
-
export const useTweetScript = createSharedComposable(
|
|
6
|
-
(vm: ComponentInternalInstance, create: () => void) =>
|
|
7
|
-
useScriptTag(
|
|
8
|
-
'https://platform.twitter.com/widgets.js',
|
|
9
|
-
() => {
|
|
10
|
-
if (vm.isMounted)
|
|
11
|
-
create()
|
|
12
|
-
else
|
|
13
|
-
onMounted(create, vm)
|
|
14
|
-
},
|
|
15
|
-
{ async: true },
|
|
16
|
-
),
|
|
17
|
-
)
|
package/iframes/monaco/index.css
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
html,
|
|
2
|
-
body,
|
|
3
|
-
#container {
|
|
4
|
-
padding: 0;
|
|
5
|
-
margin: 0;
|
|
6
|
-
background: var(--slidev-code-background);
|
|
7
|
-
width: 100%;
|
|
8
|
-
height: 200%;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
#container {
|
|
12
|
-
padding: var(--slidev-code-padding);
|
|
13
|
-
margin: var(--slidev-code-margin);
|
|
14
|
-
border-radius: var(--slidev-code-radius);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
.monaco-editor .monaco-hover {
|
|
18
|
-
border-radius: var(--slidev-code-radius);
|
|
19
|
-
overflow: hidden;
|
|
20
|
-
border: none;
|
|
21
|
-
outline: none;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
.monaco-editor .lines-content,
|
|
25
|
-
.monaco-editor .view-line,
|
|
26
|
-
.monaco-editor .view-lines {
|
|
27
|
-
user-select: none;
|
|
28
|
-
}
|
package/iframes/monaco/index.ts
DELETED
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
import '/@slidev/styles'
|
|
2
|
-
import './index.css'
|
|
3
|
-
|
|
4
|
-
import type * as monaco from 'monaco-editor'
|
|
5
|
-
import { formatCode } from '../../setup/prettier'
|
|
6
|
-
import setupMonaco from '../../setup/monaco'
|
|
7
|
-
import '/@slidev/monaco-types'
|
|
8
|
-
|
|
9
|
-
const url = new URL(location.href)
|
|
10
|
-
const props = {
|
|
11
|
-
id: url.searchParams.get('id'),
|
|
12
|
-
code: '',
|
|
13
|
-
diff: '',
|
|
14
|
-
lang: url.searchParams.get('lang') ?? 'typescript',
|
|
15
|
-
readonly: false,
|
|
16
|
-
lineNumbers: url.searchParams.get('lineNumbers') ?? 'off',
|
|
17
|
-
dark: false,
|
|
18
|
-
style: '',
|
|
19
|
-
editorOptions: {},
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const styleObject = document.createElement('style')
|
|
23
|
-
let originalEditor: monaco.editor.IStandaloneCodeEditor
|
|
24
|
-
let modifiedEditor: monaco.editor.IStandaloneCodeEditor
|
|
25
|
-
let format: () => void = () => { }
|
|
26
|
-
let update: () => void = () => { }
|
|
27
|
-
|
|
28
|
-
document.body.appendChild(styleObject)
|
|
29
|
-
|
|
30
|
-
function lang() {
|
|
31
|
-
switch (props.lang) {
|
|
32
|
-
case 'ts':
|
|
33
|
-
case 'tsx':
|
|
34
|
-
return 'typescript'
|
|
35
|
-
case 'jsx':
|
|
36
|
-
case 'js':
|
|
37
|
-
return 'javascript'
|
|
38
|
-
default:
|
|
39
|
-
return props.lang
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function ext() {
|
|
44
|
-
switch (lang()) {
|
|
45
|
-
case 'typescript':
|
|
46
|
-
return 'ts'
|
|
47
|
-
case 'javascript':
|
|
48
|
-
return 'js'
|
|
49
|
-
default:
|
|
50
|
-
return lang()
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function post(data: any, type = 'slidev-monaco') {
|
|
55
|
-
if (window.parent === window)
|
|
56
|
-
return
|
|
57
|
-
|
|
58
|
-
window.parent.postMessage(
|
|
59
|
-
{
|
|
60
|
-
type,
|
|
61
|
-
id: props.id,
|
|
62
|
-
data,
|
|
63
|
-
},
|
|
64
|
-
location.origin,
|
|
65
|
-
)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
async function start() {
|
|
69
|
-
const { monaco, theme = {}, editorOptions = {} } = await setupMonaco()
|
|
70
|
-
|
|
71
|
-
const style = getComputedStyle(document.documentElement)
|
|
72
|
-
const container = document.getElementById('container')!
|
|
73
|
-
|
|
74
|
-
const model = monaco.editor.createModel(
|
|
75
|
-
props.code,
|
|
76
|
-
lang(),
|
|
77
|
-
monaco.Uri.parse(`file:///root/${Date.now()}.${ext()}`),
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
if (url.searchParams.get('diff')) {
|
|
81
|
-
// Diff editor
|
|
82
|
-
const diffModel = monaco.editor.createModel(
|
|
83
|
-
props.diff,
|
|
84
|
-
lang(),
|
|
85
|
-
monaco.Uri.parse(`file:///root/${Date.now()}.${ext()}`),
|
|
86
|
-
)
|
|
87
|
-
const monacoEditor = monaco.editor.createDiffEditor(container, {
|
|
88
|
-
fontSize: +style.getPropertyValue('--slidev-code-font-size').replace(/px/g, ''),
|
|
89
|
-
fontFamily: style.getPropertyValue('--slidev-code-font-family'),
|
|
90
|
-
lineHeight: +style.getPropertyValue('--slidev-code-line-height').replace(/px/g, ''),
|
|
91
|
-
lineDecorationsWidth: 0,
|
|
92
|
-
lineNumbersMinChars: 0,
|
|
93
|
-
scrollBeyondLastLine: false,
|
|
94
|
-
scrollBeyondLastColumn: 0,
|
|
95
|
-
automaticLayout: true,
|
|
96
|
-
readOnly: props.readonly,
|
|
97
|
-
theme: 'vitesse-dark',
|
|
98
|
-
lineNumbers: props.lineNumbers as any,
|
|
99
|
-
glyphMargin: false,
|
|
100
|
-
scrollbar: {
|
|
101
|
-
useShadows: false,
|
|
102
|
-
vertical: 'hidden',
|
|
103
|
-
horizontal: 'hidden',
|
|
104
|
-
},
|
|
105
|
-
overviewRulerLanes: 0,
|
|
106
|
-
minimap: { enabled: false },
|
|
107
|
-
enableSplitViewResizing: false,
|
|
108
|
-
renderOverviewRuler: false,
|
|
109
|
-
// renderSideBySide: false,
|
|
110
|
-
...editorOptions,
|
|
111
|
-
})
|
|
112
|
-
monacoEditor.setModel({
|
|
113
|
-
original: model,
|
|
114
|
-
modified: diffModel,
|
|
115
|
-
})
|
|
116
|
-
originalEditor = monacoEditor.getOriginalEditor()
|
|
117
|
-
modifiedEditor = monacoEditor.getModifiedEditor()
|
|
118
|
-
|
|
119
|
-
format = async () => {
|
|
120
|
-
model.setValue((await formatCode(props.code, lang())).trim())
|
|
121
|
-
diffModel.setValue((await formatCode(props.diff, lang())).trim())
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// ctrl+s to format
|
|
125
|
-
originalEditor.onKeyDown((e) => {
|
|
126
|
-
if ((e.ctrlKey || e.metaKey) && e.code === 'KeyS') {
|
|
127
|
-
e.preventDefault()
|
|
128
|
-
format()
|
|
129
|
-
}
|
|
130
|
-
})
|
|
131
|
-
modifiedEditor.onKeyDown((e) => {
|
|
132
|
-
if ((e.ctrlKey || e.metaKey) && e.code === 'KeyS') {
|
|
133
|
-
e.preventDefault()
|
|
134
|
-
format()
|
|
135
|
-
}
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
update = () => {
|
|
139
|
-
monaco.editor.setTheme(props.dark
|
|
140
|
-
? (theme.dark || 'vitesse-dark')
|
|
141
|
-
: (theme.light || 'vitesse-light'))
|
|
142
|
-
styleObject.innerHTML = `:root { ${props.style} }`
|
|
143
|
-
|
|
144
|
-
if (originalEditor.getValue().toString() !== props.code) {
|
|
145
|
-
const selection = originalEditor.getSelection()
|
|
146
|
-
originalEditor.setValue(props.code)
|
|
147
|
-
if (selection)
|
|
148
|
-
originalEditor.setSelection(selection)
|
|
149
|
-
}
|
|
150
|
-
originalEditor.updateOptions(props.editorOptions)
|
|
151
|
-
|
|
152
|
-
if (modifiedEditor.getValue().toString() !== props.diff) {
|
|
153
|
-
const selection = modifiedEditor.getSelection()
|
|
154
|
-
modifiedEditor.setValue(props.diff)
|
|
155
|
-
if (selection)
|
|
156
|
-
modifiedEditor.setSelection(selection)
|
|
157
|
-
}
|
|
158
|
-
modifiedEditor.updateOptions(props.editorOptions)
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
diffModel.onDidChangeContent(() => {
|
|
162
|
-
onCodeChange(diffModel.getValue().toString())
|
|
163
|
-
})
|
|
164
|
-
|
|
165
|
-
function onCodeChange(diff: string) {
|
|
166
|
-
props.diff = diff
|
|
167
|
-
post({ diff })
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
else {
|
|
171
|
-
// Normal editor
|
|
172
|
-
originalEditor = monaco.editor.create(container, {
|
|
173
|
-
model,
|
|
174
|
-
tabSize: 2,
|
|
175
|
-
insertSpaces: true,
|
|
176
|
-
detectIndentation: false,
|
|
177
|
-
folding: false,
|
|
178
|
-
fontSize: +style.getPropertyValue('--slidev-code-font-size').replace(/px/g, ''),
|
|
179
|
-
fontFamily: style.getPropertyValue('--slidev-code-font-family'),
|
|
180
|
-
lineHeight: +style.getPropertyValue('--slidev-code-line-height').replace(/px/g, ''),
|
|
181
|
-
lineDecorationsWidth: 0,
|
|
182
|
-
lineNumbersMinChars: 0,
|
|
183
|
-
scrollBeyondLastLine: false,
|
|
184
|
-
scrollBeyondLastColumn: 0,
|
|
185
|
-
automaticLayout: true,
|
|
186
|
-
readOnly: props.readonly,
|
|
187
|
-
theme: 'vitesse-dark',
|
|
188
|
-
lineNumbers: props.lineNumbers as any,
|
|
189
|
-
glyphMargin: false,
|
|
190
|
-
scrollbar: {
|
|
191
|
-
useShadows: false,
|
|
192
|
-
vertical: 'hidden',
|
|
193
|
-
horizontal: 'hidden',
|
|
194
|
-
},
|
|
195
|
-
overviewRulerLanes: 0,
|
|
196
|
-
minimap: { enabled: false },
|
|
197
|
-
...editorOptions,
|
|
198
|
-
})
|
|
199
|
-
|
|
200
|
-
format = async () => {
|
|
201
|
-
model.setValue((await formatCode(props.code, lang())).trim())
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// ctrl+s to format
|
|
205
|
-
originalEditor.onKeyDown((e) => {
|
|
206
|
-
if ((e.ctrlKey || e.metaKey) && e.code === 'KeyS') {
|
|
207
|
-
e.preventDefault()
|
|
208
|
-
format()
|
|
209
|
-
}
|
|
210
|
-
})
|
|
211
|
-
|
|
212
|
-
update = () => {
|
|
213
|
-
monaco.editor.setTheme(props.dark
|
|
214
|
-
? (theme.dark || 'vitesse-dark')
|
|
215
|
-
: (theme.light || 'vitesse-light'))
|
|
216
|
-
styleObject.innerHTML = `:root { ${props.style} }`
|
|
217
|
-
|
|
218
|
-
if (originalEditor.getValue().toString() !== props.code) {
|
|
219
|
-
const selection = originalEditor.getSelection()
|
|
220
|
-
originalEditor.setValue(props.code)
|
|
221
|
-
if (selection)
|
|
222
|
-
originalEditor.setSelection(selection)
|
|
223
|
-
}
|
|
224
|
-
originalEditor.updateOptions(props.editorOptions)
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
originalEditor.onDidContentSizeChange(() => {
|
|
229
|
-
post({ height: Math.max(originalEditor.getContentHeight(), modifiedEditor?.getContentHeight() ?? 0) })
|
|
230
|
-
})
|
|
231
|
-
|
|
232
|
-
model.onDidChangeContent(() => {
|
|
233
|
-
onCodeChange(model.getValue().toString())
|
|
234
|
-
})
|
|
235
|
-
|
|
236
|
-
function onCodeChange(code: string) {
|
|
237
|
-
props.code = code
|
|
238
|
-
post({ code })
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
update()
|
|
242
|
-
|
|
243
|
-
post({}, 'slidev-monaco-loaded')
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
window.addEventListener('message', (payload) => {
|
|
247
|
-
if (payload.source === window)
|
|
248
|
-
return
|
|
249
|
-
if (payload.origin !== location.origin)
|
|
250
|
-
return
|
|
251
|
-
if (typeof payload.data !== 'string')
|
|
252
|
-
return
|
|
253
|
-
const { type, data, id } = JSON.parse(payload.data)
|
|
254
|
-
if (type === 'slidev-monaco' && id === props.id) {
|
|
255
|
-
Object.assign(props, data)
|
|
256
|
-
update()
|
|
257
|
-
}
|
|
258
|
-
})
|
|
259
|
-
|
|
260
|
-
start()
|