@slidev/client 0.48.0-beta.3 → 0.48.0-beta.4
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/Tweet.vue +4 -15
- package/builtin/VClicks.ts +1 -1
- package/composables/useTweetScript.ts +17 -0
- package/constants.ts +54 -0
- package/internals/DrawingControls.vue +41 -8
- package/internals/SlideWrapper.ts +24 -9
- package/logic/drawings.ts +6 -3
- package/logic/nav.ts +1 -1
- package/package.json +8 -8
- package/routes.ts +4 -11
- package/setup/codemirror.ts +7 -0
package/builtin/Tweet.vue
CHANGED
|
@@ -7,9 +7,9 @@ Usage:
|
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
9
|
<script setup lang="ts">
|
|
10
|
-
import { useScriptTag } from '@vueuse/core'
|
|
11
10
|
import { getCurrentInstance, onMounted, ref } from 'vue'
|
|
12
11
|
import { isDark } from '../logic/dark'
|
|
12
|
+
import { useTweetScript } from '../composables/useTweetScript'
|
|
13
13
|
|
|
14
14
|
const props = defineProps<{
|
|
15
15
|
id: string | number
|
|
@@ -41,21 +41,10 @@ async function create() {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
// @ts-expect-error global
|
|
44
|
-
if (window?.twttr?.widgets)
|
|
44
|
+
if (window?.twttr?.widgets)
|
|
45
45
|
onMounted(create)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
useScriptTag(
|
|
49
|
-
'https://platform.twitter.com/widgets.js',
|
|
50
|
-
() => {
|
|
51
|
-
if (vm.isMounted)
|
|
52
|
-
create()
|
|
53
|
-
else
|
|
54
|
-
onMounted(create, vm)
|
|
55
|
-
},
|
|
56
|
-
{ async: true },
|
|
57
|
-
)
|
|
58
|
-
}
|
|
46
|
+
else
|
|
47
|
+
useTweetScript(vm, create)
|
|
59
48
|
</script>
|
|
60
49
|
|
|
61
50
|
<template>
|
package/builtin/VClicks.ts
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
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/constants.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ComputedRef, InjectionKey, Ref, UnwrapNestedRefs } from 'vue'
|
|
2
2
|
import type { RouteRecordRaw } from 'vue-router'
|
|
3
3
|
import type { ClicksContext, RenderContext } from '@slidev/types'
|
|
4
|
+
import { objectOmit } from '@vueuse/core'
|
|
4
5
|
import type { SlidevContext } from './modules/context'
|
|
5
6
|
|
|
6
7
|
export const injectionClicksContext: InjectionKey<Ref<ClicksContext>> = Symbol('slidev-clicks-context')
|
|
@@ -24,3 +25,56 @@ export const TRUST_ORIGINS = [
|
|
|
24
25
|
'localhost',
|
|
25
26
|
'127.0.0.1',
|
|
26
27
|
]
|
|
28
|
+
|
|
29
|
+
const FRONTMATTER_FIELDS = [
|
|
30
|
+
'clicks',
|
|
31
|
+
'disabled',
|
|
32
|
+
'hide',
|
|
33
|
+
'hideInToc',
|
|
34
|
+
'layout',
|
|
35
|
+
'level',
|
|
36
|
+
'preload',
|
|
37
|
+
'routeAlias',
|
|
38
|
+
'src',
|
|
39
|
+
'title',
|
|
40
|
+
'transition',
|
|
41
|
+
'zoom',
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
const HEADMATTER_FIELDS = [
|
|
45
|
+
...FRONTMATTER_FIELDS,
|
|
46
|
+
'theme',
|
|
47
|
+
'titleTemplate',
|
|
48
|
+
'info',
|
|
49
|
+
'author',
|
|
50
|
+
'keywords',
|
|
51
|
+
'presenter',
|
|
52
|
+
'download',
|
|
53
|
+
'exportFilename',
|
|
54
|
+
'export',
|
|
55
|
+
'highlighter',
|
|
56
|
+
'lineNumbers',
|
|
57
|
+
'monaco',
|
|
58
|
+
'remoteAssets',
|
|
59
|
+
'selectable',
|
|
60
|
+
'record',
|
|
61
|
+
'colorSchema',
|
|
62
|
+
'routerMode',
|
|
63
|
+
'aspectRatio',
|
|
64
|
+
'canvasWidth',
|
|
65
|
+
'themeConfig',
|
|
66
|
+
'favicon',
|
|
67
|
+
'plantUmlServer',
|
|
68
|
+
'fonts',
|
|
69
|
+
'defaults',
|
|
70
|
+
'drawings',
|
|
71
|
+
'htmlAttrs',
|
|
72
|
+
'mdc',
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
export function filterFrontmatter(frontmatter: Record<string, any>, pageNo: number) {
|
|
76
|
+
return {
|
|
77
|
+
...objectOmit(frontmatter, pageNo === 0 ? HEADMATTER_FIELDS : FRONTMATTER_FIELDS),
|
|
78
|
+
frontmatter,
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { Menu } from 'floating-vue'
|
|
3
|
+
import 'floating-vue/dist/style.css'
|
|
2
4
|
import {
|
|
3
5
|
brush,
|
|
4
6
|
brushColors,
|
|
@@ -21,19 +23,24 @@ function undo() {
|
|
|
21
23
|
function redo() {
|
|
22
24
|
drauu.redo()
|
|
23
25
|
}
|
|
26
|
+
|
|
27
|
+
let lastDrawingMode: typeof drawingMode.value = 'stylus'
|
|
24
28
|
function setDrawingMode(mode: typeof drawingMode.value) {
|
|
25
29
|
drawingMode.value = mode
|
|
26
30
|
drawingEnabled.value = true
|
|
31
|
+
if (mode !== 'eraseLine')
|
|
32
|
+
lastDrawingMode = mode
|
|
27
33
|
}
|
|
28
34
|
function setBrushColor(color: typeof brush.color) {
|
|
29
35
|
brush.color = color
|
|
30
36
|
drawingEnabled.value = true
|
|
37
|
+
drawingMode.value = lastDrawingMode
|
|
31
38
|
}
|
|
32
39
|
</script>
|
|
33
40
|
|
|
34
41
|
<template>
|
|
35
42
|
<Draggable
|
|
36
|
-
class="flex flex-wrap text-xl p-2 gap-1 rounded-md bg-main shadow transition-opacity duration-200"
|
|
43
|
+
class="flex flex-wrap text-xl p-2 gap-1 rounded-md bg-main shadow transition-opacity duration-200 z-20"
|
|
37
44
|
dark="border border-gray-400 border-opacity-10"
|
|
38
45
|
:class="drawingEnabled ? '' : drawingPinned ? 'opacity-40 hover:opacity-90' : 'opacity-0 pointer-events-none'"
|
|
39
46
|
storage-key="slidev-drawing-pos"
|
|
@@ -57,23 +64,41 @@ function setBrushColor(color: typeof brush.color) {
|
|
|
57
64
|
<IconButton title="Draw a rectangle" :class="{ shallow: drawingMode !== 'rectangle' }" @click="setDrawingMode('rectangle')">
|
|
58
65
|
<carbon:checkbox />
|
|
59
66
|
</IconButton>
|
|
60
|
-
|
|
61
|
-
<!-- <IconButton title="Erase" :class="{ shallow: drawingMode != 'eraseLine' }" @click="setDrawingMode('eraseLine')">
|
|
67
|
+
<IconButton title="Erase" :class="{ shallow: drawingMode !== 'eraseLine' }" @click="setDrawingMode('eraseLine')">
|
|
62
68
|
<carbon:erase />
|
|
63
|
-
</IconButton>
|
|
69
|
+
</IconButton>
|
|
64
70
|
|
|
65
71
|
<VerticalDivider />
|
|
66
72
|
|
|
73
|
+
<Menu>
|
|
74
|
+
<IconButton title="Adjust stroke width" :class="{ shallow: drawingMode === 'eraseLine' }">
|
|
75
|
+
<svg viewBox="0 0 32 32" width="1.2em" height="1.2em">
|
|
76
|
+
<line x1="2" y1="15" x2="22" y2="4" stroke="currentColor" stroke-width="1" stroke-linecap="round" />
|
|
77
|
+
<line x1="2" y1="24" x2="28" y2="10" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
|
|
78
|
+
<line x1="7" y1="31" x2="29" y2="19" stroke="currentColor" stroke-width="3" stroke-linecap="round" />
|
|
79
|
+
</svg>
|
|
80
|
+
</IconButton>
|
|
81
|
+
<template #popper>
|
|
82
|
+
<div class="flex bg-main p-2">
|
|
83
|
+
<div class="inline-block w-7 text-center">
|
|
84
|
+
{{ brush.size }}
|
|
85
|
+
</div>
|
|
86
|
+
<div class="pt-.5">
|
|
87
|
+
<input v-model="brush.size" type="range" min="1" max="15" @change="drawingMode = lastDrawingMode">
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
</template>
|
|
91
|
+
</Menu>
|
|
67
92
|
<IconButton
|
|
68
93
|
v-for="color of brushColors"
|
|
69
94
|
:key="color"
|
|
70
95
|
title="Set brush color"
|
|
71
|
-
:class="brush.color === color ? 'active' : 'shallow'"
|
|
96
|
+
:class="brush.color === color && drawingMode !== 'eraseLine' ? 'active' : 'shallow'"
|
|
72
97
|
@click="setBrushColor(color)"
|
|
73
98
|
>
|
|
74
99
|
<div
|
|
75
|
-
class="w-6 h-6 transition-all transform border
|
|
76
|
-
:class="brush.color !== color ? 'rounded-1/2 scale-85' : 'rounded-md'"
|
|
100
|
+
class="w-6 h-6 transition-all transform border"
|
|
101
|
+
:class="brush.color !== color ? 'rounded-1/2 scale-85 border-white' : 'rounded-md border-gray-300/50'"
|
|
77
102
|
:style="drawingEnabled ? { background: color } : { borderColor: color }"
|
|
78
103
|
/>
|
|
79
104
|
</IconButton>
|
|
@@ -87,7 +112,7 @@ function setBrushColor(color: typeof brush.color) {
|
|
|
87
112
|
<carbon:redo />
|
|
88
113
|
</IconButton>
|
|
89
114
|
<IconButton title="Delete" :class="{ disabled: !canClear }" @click="clearDrauu()">
|
|
90
|
-
<carbon:
|
|
115
|
+
<carbon:trash-can />
|
|
91
116
|
</IconButton>
|
|
92
117
|
|
|
93
118
|
<VerticalDivider />
|
|
@@ -106,3 +131,11 @@ function setBrushColor(color: typeof brush.color) {
|
|
|
106
131
|
</IconButton>
|
|
107
132
|
</Draggable>
|
|
108
133
|
</template>
|
|
134
|
+
|
|
135
|
+
<style lang="postcss">
|
|
136
|
+
.v-popper--theme-menu {
|
|
137
|
+
.v-popper__arrow-inner {
|
|
138
|
+
@apply border-main;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
</style>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { defineComponent, h, provide, ref, toRef } from 'vue'
|
|
1
|
+
import { computed, defineComponent, h, provide, ref, toRef } from 'vue'
|
|
2
2
|
import type { PropType } from 'vue'
|
|
3
3
|
import type { ClicksContext, RenderContext } from '@slidev/types'
|
|
4
|
+
import type { RouteRecordRaw } from 'vue-router'
|
|
4
5
|
import { injectionActive, injectionClicksContext, injectionCurrentPage, injectionRenderContext, injectionRoute } from '../constants'
|
|
5
6
|
|
|
6
7
|
export default defineComponent({
|
|
@@ -20,23 +21,37 @@ export default defineComponent({
|
|
|
20
21
|
},
|
|
21
22
|
is: {
|
|
22
23
|
type: Object,
|
|
23
|
-
|
|
24
|
+
required: true,
|
|
24
25
|
},
|
|
25
26
|
route: {
|
|
26
|
-
type: Object
|
|
27
|
-
|
|
27
|
+
type: Object as PropType<RouteRecordRaw>,
|
|
28
|
+
required: true,
|
|
28
29
|
},
|
|
29
30
|
},
|
|
30
31
|
setup(props) {
|
|
31
|
-
provide(injectionRoute, props.route
|
|
32
|
-
provide(injectionCurrentPage, ref(+props.route
|
|
32
|
+
provide(injectionRoute, props.route)
|
|
33
|
+
provide(injectionCurrentPage, ref(+props.route.path))
|
|
33
34
|
provide(injectionRenderContext, ref(props.renderContext as RenderContext))
|
|
34
35
|
provide(injectionActive, toRef(props, 'active'))
|
|
35
36
|
provide(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
|
+
return {
|
|
51
|
+
style,
|
|
52
|
+
}
|
|
36
53
|
},
|
|
37
54
|
render() {
|
|
38
|
-
|
|
39
|
-
return h(this.$props.is)
|
|
40
|
-
return this.$slots?.default?.()
|
|
55
|
+
return h(this.$props.is, { style: this.style })
|
|
41
56
|
},
|
|
42
57
|
})
|
package/logic/drawings.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { createDrauu } from 'drauu'
|
|
|
4
4
|
import { toReactive, useLocalStorage } from '@vueuse/core'
|
|
5
5
|
import { drawingState, onPatch, patch } from '../state/drawings'
|
|
6
6
|
import { configs } from '../env'
|
|
7
|
+
import { isInputting } from '../state'
|
|
7
8
|
import { currentPage, isPresenter } from './nav'
|
|
8
9
|
|
|
9
10
|
export const brushColors = [
|
|
@@ -40,11 +41,13 @@ export const drawingMode = computed({
|
|
|
40
41
|
set(v: DrawingMode | 'arrow') {
|
|
41
42
|
_mode.value = v
|
|
42
43
|
if (v === 'arrow') {
|
|
43
|
-
|
|
44
|
+
// eslint-disable-next-line ts/no-use-before-define
|
|
45
|
+
drauu.mode = 'line'
|
|
44
46
|
brush.arrowEnd = true
|
|
45
47
|
}
|
|
46
48
|
else {
|
|
47
|
-
|
|
49
|
+
// eslint-disable-next-line ts/no-use-before-define
|
|
50
|
+
drauu.mode = v
|
|
48
51
|
brush.arrowEnd = false
|
|
49
52
|
}
|
|
50
53
|
},
|
|
@@ -110,7 +113,7 @@ drauu.on('start', () => isDrawing.value = true)
|
|
|
110
113
|
drauu.on('end', () => isDrawing.value = false)
|
|
111
114
|
|
|
112
115
|
window.addEventListener('keydown', (e) => {
|
|
113
|
-
if (!drawingEnabled.value)
|
|
116
|
+
if (!drawingEnabled.value || isInputting.value)
|
|
114
117
|
return
|
|
115
118
|
|
|
116
119
|
const noModifier = !e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey
|
package/logic/nav.ts
CHANGED
|
@@ -177,7 +177,7 @@ export async function downloadPDF() {
|
|
|
177
177
|
export async function openInEditor(url?: string) {
|
|
178
178
|
if (url == null) {
|
|
179
179
|
const slide = currentRoute.value?.meta?.slide
|
|
180
|
-
if (!slide
|
|
180
|
+
if (!slide)
|
|
181
181
|
return false
|
|
182
182
|
url = `${slide.filepath}:${slide.start}`
|
|
183
183
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slidev/client",
|
|
3
|
-
"version": "0.48.0-beta.
|
|
3
|
+
"version": "0.48.0-beta.4",
|
|
4
4
|
"description": "Presentation slides for developers",
|
|
5
5
|
"author": "antfu <anthonyfu117@hotmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -22,15 +22,15 @@
|
|
|
22
22
|
"@antfu/utils": "^0.7.7",
|
|
23
23
|
"@iconify-json/carbon": "^1.1.30",
|
|
24
24
|
"@iconify-json/ph": "^1.1.11",
|
|
25
|
-
"@shikijs/vitepress-twoslash": "^1.1.
|
|
25
|
+
"@shikijs/vitepress-twoslash": "^1.1.6",
|
|
26
26
|
"@unhead/vue": "^1.8.10",
|
|
27
27
|
"@unocss/reset": "^0.58.5",
|
|
28
|
-
"@vueuse/core": "^10.
|
|
29
|
-
"@vueuse/math": "^10.
|
|
28
|
+
"@vueuse/core": "^10.8.0",
|
|
29
|
+
"@vueuse/math": "^10.8.0",
|
|
30
30
|
"@vueuse/motion": "^2.0.0",
|
|
31
31
|
"codemirror": "^5.65.16",
|
|
32
32
|
"defu": "^6.1.4",
|
|
33
|
-
"drauu": "^0.
|
|
33
|
+
"drauu": "^0.4.0",
|
|
34
34
|
"file-saver": "^2.0.5",
|
|
35
35
|
"floating-vue": "^5.2.2",
|
|
36
36
|
"fuse.js": "^7.0.0",
|
|
@@ -39,15 +39,15 @@
|
|
|
39
39
|
"katex": "^0.16.9",
|
|
40
40
|
"mermaid": "^10.8.0",
|
|
41
41
|
"monaco-editor": "^0.37.1",
|
|
42
|
-
"nanoid": "^5.0.
|
|
42
|
+
"nanoid": "^5.0.6",
|
|
43
43
|
"prettier": "^3.2.5",
|
|
44
44
|
"recordrtc": "^5.6.2",
|
|
45
45
|
"resolve": "^1.22.8",
|
|
46
46
|
"unocss": "^0.58.5",
|
|
47
47
|
"vue": "^3.4.19",
|
|
48
48
|
"vue-router": "^4.2.5",
|
|
49
|
-
"@slidev/parser": "0.48.0-beta.
|
|
50
|
-
"@slidev/types": "0.48.0-beta.
|
|
49
|
+
"@slidev/parser": "0.48.0-beta.4",
|
|
50
|
+
"@slidev/types": "0.48.0-beta.4"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"vite": "^5.1.3"
|
package/routes.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { RouteLocationNormalized, RouteRecordRaw } from 'vue-router'
|
|
2
2
|
import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router'
|
|
3
3
|
import type { TransitionGroupProps } from 'vue'
|
|
4
|
-
import type { ClicksContext } from '@slidev/types'
|
|
4
|
+
import type { ClicksContext, SlideInfo } from '@slidev/types'
|
|
5
5
|
|
|
6
6
|
// @ts-expect-error missing types
|
|
7
7
|
import _rawRoutes, { redirects } from '/@slidev/routes'
|
|
@@ -84,19 +84,12 @@ declare module 'vue-router' {
|
|
|
84
84
|
preload?: boolean
|
|
85
85
|
|
|
86
86
|
// slide info
|
|
87
|
-
slide?: {
|
|
87
|
+
slide?: Omit<SlideInfo, 'source'> & {
|
|
88
|
+
noteHTML: string
|
|
89
|
+
filepath: string
|
|
88
90
|
start: number
|
|
89
|
-
end: number
|
|
90
|
-
note?: string
|
|
91
|
-
noteHTML?: string
|
|
92
91
|
id: number
|
|
93
92
|
no: number
|
|
94
|
-
filepath: string
|
|
95
|
-
title?: string
|
|
96
|
-
level?: number
|
|
97
|
-
raw: string
|
|
98
|
-
content: string
|
|
99
|
-
frontmatter: Record<string, any>
|
|
100
93
|
}
|
|
101
94
|
|
|
102
95
|
// private fields
|
package/setup/codemirror.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Ref, WritableComputedRef } from 'vue'
|
|
2
|
+
import { onClickOutside } from '@vueuse/core'
|
|
2
3
|
import { watch } from 'vue'
|
|
3
4
|
import * as _CodeMirror from 'codemirror'
|
|
4
5
|
import 'codemirror/mode/javascript/javascript'
|
|
@@ -47,5 +48,11 @@ export async function useCodeMirror(
|
|
|
47
48
|
{ immediate: true },
|
|
48
49
|
)
|
|
49
50
|
|
|
51
|
+
onClickOutside(cm.getWrapperElement(), () => {
|
|
52
|
+
const el = cm.getInputField()
|
|
53
|
+
if (document.activeElement === el)
|
|
54
|
+
el.blur()
|
|
55
|
+
})
|
|
56
|
+
|
|
50
57
|
return cm
|
|
51
58
|
}
|