@slidev/client 51.7.1 → 51.8.0
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 +24 -3
- package/builtin/CodeGroup.vue +52 -0
- package/internals/RecordingDialog.vue +52 -1
- package/internals/TitleIcon.vue +85 -0
- package/logic/recording.ts +7 -4
- package/package.json +5 -5
- package/styles/code.css +58 -0
- package/styles/vars.css +8 -0
|
@@ -12,12 +12,13 @@ Learn more: https://sli.dev/guide/syntax.html#line-highlighting
|
|
|
12
12
|
-->
|
|
13
13
|
|
|
14
14
|
<script setup lang="ts">
|
|
15
|
-
import type { PropType } from 'vue'
|
|
15
|
+
import type { PropType, Ref } from 'vue'
|
|
16
16
|
import { useClipboard } from '@vueuse/core'
|
|
17
|
-
import { computed, onMounted, onUnmounted, ref, watchEffect } from 'vue'
|
|
17
|
+
import { computed, inject, onMounted, onUnmounted, ref, watchEffect } from 'vue'
|
|
18
18
|
import { CLASS_VCLICK_HIDDEN, CLICKS_MAX } from '../constants'
|
|
19
19
|
import { useSlideContext } from '../context'
|
|
20
20
|
import { configs } from '../env'
|
|
21
|
+
import TitleIcon from '../internals/TitleIcon.vue'
|
|
21
22
|
import { makeId, updateCodeHighlightRange } from '../logic/utils'
|
|
22
23
|
|
|
23
24
|
const props = defineProps({
|
|
@@ -45,6 +46,10 @@ const props = defineProps({
|
|
|
45
46
|
type: String,
|
|
46
47
|
default: undefined,
|
|
47
48
|
},
|
|
49
|
+
title: {
|
|
50
|
+
type: String,
|
|
51
|
+
default: undefined,
|
|
52
|
+
},
|
|
48
53
|
})
|
|
49
54
|
|
|
50
55
|
const { $clicksContext: clicks } = useSlideContext()
|
|
@@ -115,6 +120,13 @@ function copyCode() {
|
|
|
115
120
|
if (code)
|
|
116
121
|
copy(code)
|
|
117
122
|
}
|
|
123
|
+
|
|
124
|
+
// code block title
|
|
125
|
+
const activeTitle = inject<Ref<string> | null>('activeTitle', null)
|
|
126
|
+
|
|
127
|
+
const isBlockTitleShow = computed(() => {
|
|
128
|
+
return activeTitle === null && props.title
|
|
129
|
+
})
|
|
118
130
|
</script>
|
|
119
131
|
|
|
120
132
|
<template>
|
|
@@ -123,17 +135,26 @@ function copyCode() {
|
|
|
123
135
|
class="slidev-code-wrapper relative group"
|
|
124
136
|
:class="{
|
|
125
137
|
'slidev-code-line-numbers': props.lines,
|
|
138
|
+
'active': activeTitle === title,
|
|
126
139
|
}"
|
|
127
140
|
:style="{
|
|
128
141
|
'max-height': props.maxHeight,
|
|
129
142
|
'overflow-y': props.maxHeight ? 'scroll' : undefined,
|
|
130
143
|
'--start': props.startLine,
|
|
131
144
|
}"
|
|
145
|
+
:data-title="title"
|
|
132
146
|
>
|
|
147
|
+
<div v-if="isBlockTitleShow" class="slidev-code-block-title">
|
|
148
|
+
<TitleIcon :title="title" />
|
|
149
|
+
<div class="leading-1em">
|
|
150
|
+
{{ title.replace(/~([^~]+)~/g, '').trim() }}
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
133
153
|
<slot />
|
|
134
154
|
<button
|
|
135
155
|
v-if="configs.codeCopy"
|
|
136
|
-
class="slidev-code-copy absolute
|
|
156
|
+
class="slidev-code-copy absolute right-0 transition opacity-0 group-hover:opacity-20 hover:!opacity-100"
|
|
157
|
+
:class="isBlockTitleShow ? 'top-10' : 'top-0'"
|
|
137
158
|
:title="copied ? 'Copied' : 'Copy'" @click="copyCode()"
|
|
138
159
|
>
|
|
139
160
|
<ph-check-circle v-if="copied" class="p-2 w-8 h-8" />
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { onMounted, provide, ref, useTemplateRef } from 'vue'
|
|
3
|
+
import TitleIcon from '../internals/TitleIcon.vue'
|
|
4
|
+
|
|
5
|
+
const codeGroupBlocksRef = useTemplateRef('codeGroupBlocksRef')
|
|
6
|
+
const activeTitle = ref('')
|
|
7
|
+
|
|
8
|
+
provide('activeTitle', activeTitle)
|
|
9
|
+
const tabs = ref<string[]>([])
|
|
10
|
+
|
|
11
|
+
onMounted(() => {
|
|
12
|
+
const codeGroupBlocks = codeGroupBlocksRef.value
|
|
13
|
+
let isActiveSet = false
|
|
14
|
+
|
|
15
|
+
codeGroupBlocks?.querySelectorAll('.slidev-code-wrapper')?.forEach((block) => {
|
|
16
|
+
const title = block.getAttribute('data-title') || ''
|
|
17
|
+
if (title) {
|
|
18
|
+
if (!isActiveSet) {
|
|
19
|
+
activeTitle.value = title
|
|
20
|
+
isActiveSet = true
|
|
21
|
+
}
|
|
22
|
+
tabs.value.push(title)
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
})
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<template>
|
|
29
|
+
<div class="slidev-code-group">
|
|
30
|
+
<div class="slidev-code-group-tabs">
|
|
31
|
+
<div v-for="tab in tabs" :key="tab" class="flex items-center">
|
|
32
|
+
<div
|
|
33
|
+
class="slidev-code-tab"
|
|
34
|
+
:style="{
|
|
35
|
+
borderColor: activeTitle === tab ? 'var(--slidev-theme-primary)' : 'transparent',
|
|
36
|
+
color: activeTitle === tab ? 'var(--slidev-code-tab-active-text-color)' : 'var(--slidev-code-tab-text-color)',
|
|
37
|
+
}"
|
|
38
|
+
@click="activeTitle = tab"
|
|
39
|
+
>
|
|
40
|
+
<TitleIcon :title="tab" />
|
|
41
|
+
|
|
42
|
+
<div>
|
|
43
|
+
{{ tab.replace(/~([^~]+)~/g, '').trim() }}
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
<div ref="codeGroupBlocksRef" class="slidev-code-group-blocks">
|
|
49
|
+
<slot />
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</template>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { useVModel } from '@vueuse/core'
|
|
3
3
|
import { nextTick } from 'vue'
|
|
4
|
-
import { getFilename, mimeType, recordCamera, recorder, recordingName } from '../logic/recording'
|
|
4
|
+
import { bitRate, frameRate, getFilename, mimeType, recordCamera, recorder, recordingName, resolution } from '../logic/recording'
|
|
5
5
|
import DevicesSelectors from './DevicesSelectors.vue'
|
|
6
6
|
import Modal from './Modal.vue'
|
|
7
7
|
|
|
@@ -18,6 +18,14 @@ const value = useVModel(props, 'modelValue', emit)
|
|
|
18
18
|
|
|
19
19
|
const { startRecording } = recorder
|
|
20
20
|
|
|
21
|
+
const frameRateOptions = [15, 24, 30, 60]
|
|
22
|
+
const resolutionOptions = [
|
|
23
|
+
{ value: '1280x720', label: '720p (1280x720)' },
|
|
24
|
+
{ value: '1920x1080', label: '1080p (1920x1080)' },
|
|
25
|
+
{ value: '2560x1440', label: '1440p (2560x1440)' },
|
|
26
|
+
{ value: '3840x2160', label: '2160p (3840x2160)' },
|
|
27
|
+
]
|
|
28
|
+
|
|
21
29
|
function close() {
|
|
22
30
|
value.value = false
|
|
23
31
|
}
|
|
@@ -27,6 +35,7 @@ async function start() {
|
|
|
27
35
|
await nextTick()
|
|
28
36
|
startRecording({
|
|
29
37
|
mimeType: mimeType.value,
|
|
38
|
+
bitsPerSecond: bitRate.value * 1024,
|
|
30
39
|
})
|
|
31
40
|
}
|
|
32
41
|
</script>
|
|
@@ -51,6 +60,48 @@ async function start() {
|
|
|
51
60
|
<div>This will be used in the output filename that might <br>help you better organize your recording chips.</div>
|
|
52
61
|
</div>
|
|
53
62
|
</div>
|
|
63
|
+
|
|
64
|
+
<div class="form-text">
|
|
65
|
+
<label for="framerate">Frame Rate</label>
|
|
66
|
+
<select
|
|
67
|
+
v-model="frameRate"
|
|
68
|
+
class="bg-transparent text-current border border-main rounded px-2 py-1"
|
|
69
|
+
name="framerate"
|
|
70
|
+
>
|
|
71
|
+
<option v-for="rate in frameRateOptions" :key="rate" :value="rate">
|
|
72
|
+
{{ rate }} fps
|
|
73
|
+
</option>
|
|
74
|
+
</select>
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
<div class="form-text">
|
|
78
|
+
<label for="resolution">Resolution</label>
|
|
79
|
+
<select
|
|
80
|
+
v-model="resolution"
|
|
81
|
+
class="bg-transparent text-current border border-main rounded px-2 py-1"
|
|
82
|
+
name="resolution"
|
|
83
|
+
>
|
|
84
|
+
<option v-for="res in resolutionOptions" :key="res.value" :value="res.value">
|
|
85
|
+
{{ res.label }}
|
|
86
|
+
</option>
|
|
87
|
+
</select>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
<div class="form-text">
|
|
91
|
+
<label for="bitrate">Bitrate</label>
|
|
92
|
+
<div class="relative">
|
|
93
|
+
<input
|
|
94
|
+
v-model.number="bitRate"
|
|
95
|
+
type="number"
|
|
96
|
+
min="1000"
|
|
97
|
+
step="1000"
|
|
98
|
+
class="bg-transparent text-current border border-main rounded px-2 py-1 w-full pr-12"
|
|
99
|
+
name="bitrate"
|
|
100
|
+
>
|
|
101
|
+
<span class="absolute right-3 top-1/2 transform -translate-y-1/2 text-sm opacity-50">kbps</span>
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
|
|
54
105
|
<div class="form-check">
|
|
55
106
|
<input
|
|
56
107
|
v-model="recordCamera"
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
defineProps<{
|
|
3
|
+
title: string
|
|
4
|
+
}>()
|
|
5
|
+
|
|
6
|
+
const builtinIcons: Record<string, string> = {
|
|
7
|
+
// package managers
|
|
8
|
+
'pnpm': 'i-vscode-icons:file-type-light-pnpm',
|
|
9
|
+
'npm': 'i-vscode-icons:file-type-npm',
|
|
10
|
+
'yarn': 'i-vscode-icons:file-type-yarn',
|
|
11
|
+
'bun': 'i-vscode-icons:file-type-bun',
|
|
12
|
+
'deno': 'i-vscode-icons:file-type-deno',
|
|
13
|
+
// frameworks
|
|
14
|
+
'vue': 'i-vscode-icons:file-type-vue',
|
|
15
|
+
'svelte': 'i-vscode-icons:file-type-svelte',
|
|
16
|
+
'angular': 'i-vscode-icons:file-type-angular',
|
|
17
|
+
'react': 'i-vscode-icons:file-type-reactjs',
|
|
18
|
+
'next': 'i-vscode-icons:file-type-light-next',
|
|
19
|
+
'nuxt': 'i-vscode-icons:file-type-nuxt',
|
|
20
|
+
'solid': 'logos:solidjs-icon',
|
|
21
|
+
'astro': 'i-vscode-icons:file-type-light-astro',
|
|
22
|
+
// bundlers
|
|
23
|
+
'rollup': 'i-vscode-icons:file-type-rollup',
|
|
24
|
+
'webpack': 'i-vscode-icons:file-type-webpack',
|
|
25
|
+
'vite': 'i-vscode-icons:file-type-vite',
|
|
26
|
+
'esbuild': 'i-vscode-icons:file-type-esbuild',
|
|
27
|
+
// configuration files
|
|
28
|
+
'package.json': 'i-vscode-icons:file-type-node',
|
|
29
|
+
'tsconfig.json': 'i-vscode-icons:file-type-tsconfig',
|
|
30
|
+
'.npmrc': 'i-vscode-icons:file-type-npm',
|
|
31
|
+
'.editorconfig': 'i-vscode-icons:file-type-editorconfig',
|
|
32
|
+
'.eslintrc': 'i-vscode-icons:file-type-eslint',
|
|
33
|
+
'.eslintignore': 'i-vscode-icons:file-type-eslint',
|
|
34
|
+
'eslint.config': 'i-vscode-icons:file-type-eslint',
|
|
35
|
+
'.gitignore': 'i-vscode-icons:file-type-git',
|
|
36
|
+
'.gitattributes': 'i-vscode-icons:file-type-git',
|
|
37
|
+
'.env': 'i-vscode-icons:file-type-dotenv',
|
|
38
|
+
'.env.example': 'i-vscode-icons:file-type-dotenv',
|
|
39
|
+
'.vscode': 'i-vscode-icons:file-type-vscode',
|
|
40
|
+
'tailwind.config': 'vscode-icons:file-type-tailwind',
|
|
41
|
+
'uno.config': 'i-vscode-icons:file-type-unocss',
|
|
42
|
+
'unocss.config': 'i-vscode-icons:file-type-unocss',
|
|
43
|
+
'.oxlintrc': 'i-vscode-icons:file-type-oxlint',
|
|
44
|
+
'vue.config': 'i-vscode-icons:file-type-vueconfig',
|
|
45
|
+
// filename extensions
|
|
46
|
+
'.mts': 'i-vscode-icons:file-type-typescript',
|
|
47
|
+
'.cts': 'i-vscode-icons:file-type-typescript',
|
|
48
|
+
'.ts': 'i-vscode-icons:file-type-typescript',
|
|
49
|
+
'.tsx': 'i-vscode-icons:file-type-typescript',
|
|
50
|
+
'.mjs': 'i-vscode-icons:file-type-js',
|
|
51
|
+
'.cjs': 'i-vscode-icons:file-type-js',
|
|
52
|
+
'.json': 'i-vscode-icons:file-type-json',
|
|
53
|
+
'.js': 'i-vscode-icons:file-type-js',
|
|
54
|
+
'.jsx': 'i-vscode-icons:file-type-js',
|
|
55
|
+
'.md': 'i-vscode-icons:file-type-markdown',
|
|
56
|
+
'.py': 'i-vscode-icons:file-type-python',
|
|
57
|
+
'.ico': 'i-vscode-icons:file-type-favicon',
|
|
58
|
+
'.html': 'i-vscode-icons:file-type-html',
|
|
59
|
+
'.css': 'i-vscode-icons:file-type-css',
|
|
60
|
+
'.scss': 'i-vscode-icons:file-type-scss',
|
|
61
|
+
'.yml': 'i-vscode-icons:file-type-light-yaml',
|
|
62
|
+
'.yaml': 'i-vscode-icons:file-type-light-yaml',
|
|
63
|
+
'.php': 'i-vscode-icons:file-type-php',
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function matchIcon(title: string) {
|
|
67
|
+
const colonMatch = title.match(/~([^~]+)~/g)
|
|
68
|
+
if (colonMatch && colonMatch.length > 0) {
|
|
69
|
+
const icon = colonMatch[0].slice(1, -1)
|
|
70
|
+
return icon
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const sortedKeys = Object.keys(builtinIcons).sort((a, b) => b.length - a.length)
|
|
74
|
+
for (const key of sortedKeys) {
|
|
75
|
+
if (title.toLowerCase().includes(key.toLowerCase())) {
|
|
76
|
+
return builtinIcons[key]
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return ''
|
|
80
|
+
}
|
|
81
|
+
</script>
|
|
82
|
+
|
|
83
|
+
<template>
|
|
84
|
+
<div v-if="matchIcon(title)" :class="`${matchIcon(title)} w-3.5 h-3.5 relative`" />
|
|
85
|
+
</template>
|
package/logic/recording.ts
CHANGED
|
@@ -12,6 +12,9 @@ type MimeType = Defined<RecorderOptions['mimeType']>
|
|
|
12
12
|
export const recordingName = ref('')
|
|
13
13
|
export const recordCamera = ref(true)
|
|
14
14
|
export const mimeType = useLocalStorage<MimeType>('slidev-record-mimetype', 'video/webm')
|
|
15
|
+
export const frameRate = useLocalStorage<number>('slidev-record-framerate', 30)
|
|
16
|
+
export const bitRate = useLocalStorage<number>('slidev-record-bitrate', 8192)
|
|
17
|
+
export const resolution = useLocalStorage<string>('slidev-record-resolution', '1920x1080')
|
|
15
18
|
|
|
16
19
|
export const mimeExtMap: Record<string, string> = {
|
|
17
20
|
'video/webm': 'webm',
|
|
@@ -78,7 +81,6 @@ export function useRecording() {
|
|
|
78
81
|
|
|
79
82
|
const config: RecorderOptions = {
|
|
80
83
|
type: 'video',
|
|
81
|
-
bitsPerSecond: 4 * 256 * 8 * 1024,
|
|
82
84
|
// Extending recording limit as default is only 1h (see https://github.com/muaz-khan/RecordRTC/issues/144)
|
|
83
85
|
timeSlice: 24 * 60 * 60 * 1000,
|
|
84
86
|
}
|
|
@@ -141,12 +143,13 @@ export function useRecording() {
|
|
|
141
143
|
const { default: Recorder } = await import('recordrtc')
|
|
142
144
|
await startCameraStream()
|
|
143
145
|
|
|
146
|
+
const [width, height] = resolution.value.split('x').map(Number)
|
|
144
147
|
streamCapture.value = await navigator.mediaDevices.getDisplayMedia({
|
|
145
148
|
video: {
|
|
146
149
|
// aspectRatio: 1.6,
|
|
147
|
-
frameRate:
|
|
148
|
-
width
|
|
149
|
-
height
|
|
150
|
+
frameRate: frameRate.value,
|
|
151
|
+
width,
|
|
152
|
+
height,
|
|
150
153
|
// @ts-expect-error missing types
|
|
151
154
|
cursor: 'motion',
|
|
152
155
|
resizeMode: 'crop-and-scale',
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slidev/client",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "51.
|
|
4
|
+
"version": "51.8.0",
|
|
5
5
|
"description": "Presentation slides for developers",
|
|
6
6
|
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"@shikijs/monaco": "^3.4.2",
|
|
37
37
|
"@shikijs/vitepress-twoslash": "^3.4.2",
|
|
38
38
|
"@slidev/rough-notation": "^0.1.0",
|
|
39
|
-
"@typescript/ata": "^0.9.
|
|
40
|
-
"@unhead/vue": "^2.0.
|
|
39
|
+
"@typescript/ata": "^0.9.8",
|
|
40
|
+
"@unhead/vue": "^2.0.10",
|
|
41
41
|
"@unocss/reset": "^66.1.2",
|
|
42
42
|
"@vueuse/core": "^13.2.0",
|
|
43
43
|
"@vueuse/math": "^13.2.0",
|
|
@@ -61,8 +61,8 @@
|
|
|
61
61
|
"vue": "^3.5.14",
|
|
62
62
|
"vue-router": "^4.5.1",
|
|
63
63
|
"yaml": "^2.8.0",
|
|
64
|
-
"@slidev/parser": "51.
|
|
65
|
-
"@slidev/types": "51.
|
|
64
|
+
"@slidev/parser": "51.8.0",
|
|
65
|
+
"@slidev/types": "51.8.0"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
68
|
"vite": "^6.3.5"
|
package/styles/code.css
CHANGED
|
@@ -44,6 +44,64 @@ html:not(.dark) .shiki span {
|
|
|
44
44
|
overflow: auto;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
.slidev-code-block-title,
|
|
48
|
+
.slidev-code-group-tabs {
|
|
49
|
+
background: var(--slidev-code-background);
|
|
50
|
+
color: var(--slidev-code-tab-text-color);
|
|
51
|
+
padding-left: var(--slidev-code-padding);
|
|
52
|
+
padding-right: var(--slidev-code-padding);
|
|
53
|
+
font-size: var(--slidev-code-tab-font-size);
|
|
54
|
+
border-radius: var(--slidev-code-radius) var(--slidev-code-radius) 0 0;
|
|
55
|
+
box-shadow: inset 0 -1px var(--slidev-code-tab-divider);
|
|
56
|
+
display: flex;
|
|
57
|
+
gap: 8px;
|
|
58
|
+
align-items: center;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.slidev-code-block-title {
|
|
62
|
+
padding: var(--slidev-code-padding);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.slidev-code-tab {
|
|
66
|
+
font-size: var(--slidev-code-tab-font-size);
|
|
67
|
+
white-space: nowrap;
|
|
68
|
+
cursor: pointer;
|
|
69
|
+
transition: color 0.25s;
|
|
70
|
+
padding: var(--slidev-code-padding);
|
|
71
|
+
border-bottom: 2px solid transparent;
|
|
72
|
+
color: var(--slidev-code-tab-text-color);
|
|
73
|
+
position: relative;
|
|
74
|
+
display: flex;
|
|
75
|
+
align-items: center;
|
|
76
|
+
gap: 8px;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.slidev-code-tab:hover {
|
|
80
|
+
color: var(--slidev-code-tab-active-text-color) !important;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.slidev-code-group-blocks .slidev-code-wrapper {
|
|
84
|
+
margin: 0 !important;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.slidev-code-group-blocks .slidev-code {
|
|
88
|
+
border-radius: 0 0 var(--slidev-code-radius) var(--slidev-code-radius) !important;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.slidev-code-group-blocks .slidev-code-wrapper.active {
|
|
92
|
+
display: block;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.slidev-code-group-blocks .slidev-code-wrapper {
|
|
96
|
+
display: none;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.slidev-code-block-title + .slidev-code,
|
|
100
|
+
.slidev-code-group-tabs + .slidev-code {
|
|
101
|
+
border-top-left-radius: 0 !important;
|
|
102
|
+
border-top-right-radius: 0 !important;
|
|
103
|
+
}
|
|
104
|
+
|
|
47
105
|
.slidev-code .slidev-code-highlighted {
|
|
48
106
|
}
|
|
49
107
|
.slidev-code .slidev-code-dishonored {
|
package/styles/vars.css
CHANGED
|
@@ -12,9 +12,17 @@
|
|
|
12
12
|
--slidev-transition-duration: 0.5s;
|
|
13
13
|
--slidev-slide-container-background: black;
|
|
14
14
|
--slidev-controls-foreground: white;
|
|
15
|
+
|
|
16
|
+
--slidev-code-tab-divider: #e5e5e5;
|
|
17
|
+
--slidev-code-tab-text-color: #67676c;
|
|
18
|
+
--slidev-code-tab-font-size: 12px;
|
|
19
|
+
--slidev-code-tab-active-text-color: #3c3c43;
|
|
15
20
|
}
|
|
16
21
|
|
|
17
22
|
html.dark {
|
|
18
23
|
--slidev-code-background: #1b1b1b;
|
|
19
24
|
--slidev-code-foreground: #eee;
|
|
25
|
+
--slidev-code-tab-divider: #222222;
|
|
26
|
+
--slidev-code-tab-text-color: #98989f;
|
|
27
|
+
--slidev-code-tab-active-text-color: #dfdfd6;
|
|
20
28
|
}
|