@slidev/client 0.48.0-beta.21 → 0.48.0-beta.23

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.
@@ -0,0 +1,169 @@
1
+ /* __imports__ */
2
+ import { createSingletonPromise } from '@antfu/utils'
3
+ import type { CodeRunner, CodeRunnerContext, CodeRunnerOutput, CodeRunnerOutputText, CodeRunnerOutputs, CodeRunnerProviders } from '@slidev/types'
4
+ import type { CodeToHastOptions } from 'shiki'
5
+ import { isDark } from '../logic/dark'
6
+
7
+ export default createSingletonPromise(async () => {
8
+ const runners: Record<string, CodeRunner> = {
9
+ javascript: runJavaScript,
10
+ js: runJavaScript,
11
+ typescript: runTypeScript,
12
+ ts: runTypeScript,
13
+ }
14
+
15
+ const { shiki, themes } = await import('#slidev/shiki')
16
+ const highlighter = await shiki
17
+ const highlight = (code: string, lang: string, options: Partial<CodeToHastOptions> = {}) => highlighter.codeToHtml(code, {
18
+ lang,
19
+ theme: typeof themes === 'string'
20
+ ? themes
21
+ : isDark.value
22
+ ? themes.dark || 'vitesse-dark'
23
+ : themes.light || 'vitesse-light',
24
+ ...options,
25
+ })
26
+
27
+ const run = async (code: string, lang: string, options: Record<string, unknown>): Promise<CodeRunnerOutputs> => {
28
+ try {
29
+ const runner = runners[lang]
30
+ if (!runner)
31
+ throw new Error(`Runner for language "${lang}" not found`)
32
+ return await runner(
33
+ code,
34
+ {
35
+ options,
36
+ highlight,
37
+ run: async (code, lang) => {
38
+ return await run(code, lang, options)
39
+ },
40
+ },
41
+ )
42
+ }
43
+ catch (e) {
44
+ console.error(e)
45
+ return {
46
+ error: `${e}`,
47
+ }
48
+ }
49
+ }
50
+
51
+ // @ts-expect-error injected in runtime
52
+ // eslint-disable-next-line unused-imports/no-unused-vars
53
+ const injection_arg = runners
54
+ // eslint-disable-next-line prefer-const
55
+ let injection_return: CodeRunnerProviders = {}
56
+
57
+ /* __async_injections__ */
58
+
59
+ Object.assign(runners, injection_return)
60
+
61
+ return {
62
+ highlight,
63
+ run,
64
+ }
65
+ })
66
+
67
+ // Ported from https://github.com/microsoft/TypeScript-Website/blob/v2/packages/playground/src/sidebar/runtime.ts
68
+ export async function runJavaScript(code: string): Promise<CodeRunnerOutputs> {
69
+ const allLogs: CodeRunnerOutput[] = []
70
+
71
+ const replace = {} as any
72
+ const logger = function (...objs: any[]) {
73
+ allLogs.push(objs.map(printObject))
74
+ }
75
+ replace.info = replace.log = replace.debug = replace.warn = replace.error = logger
76
+ replace.clear = () => allLogs.length = 0
77
+ const vmConsole = Object.assign({}, console, replace)
78
+ try {
79
+ const safeJS = `return async (console) => {${sanitizeJS(code)}}`
80
+ // eslint-disable-next-line no-new-func
81
+ await (new Function(safeJS)())(vmConsole)
82
+ }
83
+ catch (error) {
84
+ return {
85
+ error: `ERROR: ${error}`,
86
+ }
87
+ }
88
+
89
+ function printObject(arg: any): CodeRunnerOutputText {
90
+ if (typeof arg === 'string') {
91
+ return {
92
+ text: arg,
93
+ }
94
+ }
95
+ return {
96
+ text: objectToText(arg),
97
+ highlightLang: 'javascript',
98
+ }
99
+ }
100
+
101
+ function objectToText(arg: any): string {
102
+ let textRep = ''
103
+ if (arg instanceof Error) {
104
+ textRep = `Error: ${JSON.stringify(arg.message)}`
105
+ }
106
+ else if (arg === null || arg === undefined || typeof arg === 'symbol') {
107
+ textRep = String(arg)
108
+ }
109
+ else if (Array.isArray(arg)) {
110
+ textRep = `[${arg.map(objectToText).join(', ')}]`
111
+ }
112
+ else if (arg instanceof Set) {
113
+ const setIter = [...arg]
114
+ textRep = `Set (${arg.size}) {${setIter.map(objectToText).join(', ')}}`
115
+ }
116
+ else if (arg instanceof Map) {
117
+ const mapIter = [...arg.entries()]
118
+ textRep
119
+ = `Map (${arg.size}) {${mapIter
120
+ .map(([k, v]) => `${objectToText(k)} => ${objectToText(v)}`)
121
+ .join(', ')
122
+ }}`
123
+ }
124
+ else if (arg instanceof RegExp) {
125
+ textRep = arg.toString()
126
+ }
127
+ else if (typeof arg === 'string') {
128
+ textRep = JSON.stringify(arg)
129
+ }
130
+ else if (typeof arg === 'object') {
131
+ const name = arg.constructor?.name ?? ''
132
+ // No one needs to know an obj is an obj
133
+ const nameWithoutObject = name && name === 'Object' ? '' : name
134
+ const prefix = nameWithoutObject ? `${nameWithoutObject}: ` : ''
135
+
136
+ // JSON.stringify omits any keys with a value of undefined. To get around this, we replace undefined with the text __undefined__ and then do a global replace using regex back to keyword undefined
137
+ textRep
138
+ = prefix
139
+ + JSON.stringify(arg, (_, value) => (value === undefined ? '__undefined__' : value), 2).replace(
140
+ /"__undefined__"/g,
141
+ 'undefined',
142
+ )
143
+
144
+ textRep = String(textRep)
145
+ }
146
+ else {
147
+ textRep = String(arg)
148
+ }
149
+ return textRep
150
+ }
151
+
152
+ // The reflect-metadata runtime is available, so allow that to go through
153
+ function sanitizeJS(code: string) {
154
+ return code.replace(`import "reflect-metadata"`, '').replace(`require("reflect-metadata")`, '')
155
+ }
156
+
157
+ return allLogs
158
+ }
159
+
160
+ let tsModule: typeof import('typescript') | undefined
161
+
162
+ export async function runTypeScript(code: string, context: CodeRunnerContext) {
163
+ const { transpile } = tsModule ??= await import('typescript')
164
+ code = transpile(code, {
165
+ module: tsModule.ModuleKind.ESNext,
166
+ target: tsModule.ScriptTarget.ES2022,
167
+ })
168
+ return await context.run(code, 'javascript')
169
+ }
package/setup/monaco.ts CHANGED
@@ -89,16 +89,25 @@ const setup = createSingletonPromise(async () => {
89
89
  })
90
90
  : () => { }
91
91
 
92
- // monaco.languages.register({ id: 'vue' })
92
+ monaco.languages.register({ id: 'vue' })
93
+ monaco.languages.register({ id: 'html' })
94
+ monaco.languages.register({ id: 'css' })
93
95
  monaco.languages.register({ id: 'typescript' })
94
96
  monaco.languages.register({ id: 'javascript' })
95
97
 
96
98
  const { shiki, themes, shikiToMonaco } = await import('#slidev/shiki')
97
99
  const highlighter = await shiki
98
100
 
101
+ // @ts-expect-error injected in runtime
102
+ // eslint-disable-next-line unused-imports/no-unused-vars
103
+ const injection_arg = monaco
104
+ // eslint-disable-next-line prefer-const
105
+ let injection_return: MonacoSetupReturn = {}
106
+
107
+ /* __async_injections__ */
108
+
99
109
  // Use Shiki to highlight Monaco
100
110
  shikiToMonaco(highlighter, monaco)
101
-
102
111
  if (typeof themes === 'string') {
103
112
  monaco.editor.setTheme(themes)
104
113
  }
@@ -110,14 +119,6 @@ const setup = createSingletonPromise(async () => {
110
119
  })
111
120
  }
112
121
 
113
- // @ts-expect-error injected in runtime
114
- // eslint-disable-next-line unused-imports/no-unused-vars
115
- const injection_arg = monaco
116
- // eslint-disable-next-line prefer-const
117
- let injection_return: MonacoSetupReturn = {}
118
-
119
- /* __async_injections__ */
120
-
121
122
  return {
122
123
  monaco,
123
124
  ata,
package/shim-vue.d.ts CHANGED
@@ -1,15 +1,11 @@
1
1
  declare module 'vue' {
2
- import type { UnwrapNestedRefs } from 'vue'
3
- import type { SlidevContext } from './modules/context'
4
-
5
- interface ComponentCustomProperties {
6
- $slidev: UnwrapNestedRefs<SlidevContext>
2
+ type SlideContext = import('./context').SlideContext
3
+ interface ComponentCustomProperties extends SlideContext {
7
4
  }
8
5
  }
9
6
 
10
7
  declare module 'vue-router' {
11
8
  import type { TransitionGroupProps } from 'vue'
12
- import type { ClicksContext, SlideInfo } from '@slidev/types'
13
9
 
14
10
  interface RouteMeta {
15
11
  // inherited from frontmatter
@@ -21,7 +17,7 @@ declare module 'vue-router' {
21
17
  preload?: boolean
22
18
 
23
19
  // slide info
24
- slide?: Omit<SlideInfo, 'source'> & {
20
+ slide?: Omit<import('@slidev/types').SlideInfo, 'source'> & {
25
21
  noteHTML: string
26
22
  filepath: string
27
23
  start: number
@@ -30,7 +26,7 @@ declare module 'vue-router' {
30
26
  }
31
27
 
32
28
  // private fields
33
- __clicksContext: null | ClicksContext
29
+ __clicksContext: import('@slidev/types').ClicksContext | undefined
34
30
  __preloaded?: boolean
35
31
  }
36
32
  }
package/state/index.ts CHANGED
@@ -14,7 +14,7 @@ export const breakpoints = useBreakpoints({
14
14
  })
15
15
  export const windowSize = useWindowSize()
16
16
  export const magicKeys = useMagicKeys()
17
- export const isScreenVertical = computed(() => windowSize.height.value - windowSize.width.value / slideAspect > 120)
17
+ export const isScreenVertical = computed(() => windowSize.height.value - windowSize.width.value / slideAspect.value > 120)
18
18
  export const fullscreen = useFullscreen(isClient ? document.body : null)
19
19
 
20
20
  export const activeElement = useActiveElement()
package/styles/code.css CHANGED
@@ -44,9 +44,9 @@ html:not(.dark) .shiki span {
44
44
  overflow: auto;
45
45
  }
46
46
 
47
- .slidev-code .line.highlighted {
47
+ .slidev-code .slidev-code-highlighted {
48
48
  }
49
- .slidev-code .line.dishonored {
49
+ .slidev-code .slidev-code-dishonored {
50
50
  opacity: 0.3;
51
51
  pointer-events: none;
52
52
  }
@@ -1,58 +0,0 @@
1
- import { computed, defineAsyncComponent, defineComponent, h, ref, toRef } from 'vue'
2
- import type { PropType } from 'vue'
3
- import { provideLocal } from '@vueuse/core'
4
- import type { ClicksContext, RenderContext, SlideRoute } from '@slidev/types'
5
- import { injectionActive, injectionClicksContext, injectionCurrentPage, injectionRenderContext, injectionRoute } from '../constants'
6
- import SlideLoading from './SlideLoading.vue'
7
-
8
- export default defineComponent({
9
- name: 'SlideWrapper',
10
- props: {
11
- clicksContext: {
12
- type: Object as PropType<ClicksContext>,
13
- required: true,
14
- },
15
- renderContext: {
16
- type: String,
17
- default: 'main',
18
- },
19
- active: {
20
- type: Boolean,
21
- default: false,
22
- },
23
- is: {
24
- required: true,
25
- },
26
- route: {
27
- type: Object as PropType<SlideRoute>,
28
- required: true,
29
- },
30
- },
31
- setup(props) {
32
- provideLocal(injectionRoute, props.route)
33
- provideLocal(injectionCurrentPage, ref(props.route.no))
34
- provideLocal(injectionRenderContext, ref(props.renderContext as RenderContext))
35
- provideLocal(injectionActive, toRef(props, 'active'))
36
- provideLocal(injectionClicksContext, toRef(props, 'clicksContext'))
37
-
38
- const style = computed(() => {
39
- const zoom = props.route.meta?.slide?.frontmatter.zoom ?? 1
40
- return zoom === 1
41
- ? undefined
42
- : {
43
- width: `${100 / zoom}%`,
44
- height: `${100 / zoom}%`,
45
- transformOrigin: 'top left',
46
- transform: `scale(${zoom})`,
47
- }
48
- })
49
-
50
- const SlideComponent = defineAsyncComponent({
51
- loader: (props.is as any),
52
- delay: 300,
53
- loadingComponent: SlideLoading,
54
- })
55
-
56
- return () => h(SlideComponent, { style: style.value })
57
- },
58
- })
package/styles/monaco.css DELETED
@@ -1,27 +0,0 @@
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
- }