Skip to content

Commit 9d264e0

Browse files
feat(snippets): use codemirror for screenshot (#321)
1 parent a44ebd2 commit 9d264e0

1 file changed

Lines changed: 83 additions & 48 deletions

File tree

src/renderer/components/screenshot/TheScreenshot.vue

Lines changed: 83 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@
9191
</g>
9292
</svg>
9393
</div>
94-
<div v-html="renderer" />
94+
<div ref="editorRef" />
9595
</div>
9696
</div>
9797
<div class="transparent" />
@@ -107,14 +107,14 @@
107107

108108
<script setup lang="ts">
109109
import { useAppStore } from '@/store/app'
110-
import hljs from 'highlight.js'
111110
import interact from 'interactjs'
112111
import { computed, onMounted, ref, watch } from 'vue'
113-
import { useHljsTheme } from '@/composable'
114112
import { store, track, i18n } from '@/electron'
115113
import { useSnippetStore } from '@/store/snippets'
116114
import { useMagicKeys } from '@vueuse/core'
117115
import domToImage from 'dom-to-image'
116+
import CodeMirror from 'codemirror'
117+
import { getThemeName } from '../editor/themes'
118118
119119
const GUTTER_RIGHT_OFFSET = 10
120120
const GUTTER_WIDTH = 8
@@ -136,13 +136,13 @@ const { escape } = useMagicKeys()
136136
const frameRef = ref<HTMLElement>()
137137
const snippetRef = ref<HTMLElement>()
138138
const gutterRef = ref<HTMLElement>()
139+
const editorRef = ref<HTMLElement>()
139140
140141
const gutterWidth = ref(GUTTER_WIDTH + 'px')
141142
const offsetGutterRight = ref(GUTTER_RIGHT_OFFSET + 'px')
142143
143144
const forceRefresh = ref()
144145
145-
const font = computed(() => appStore.editor.fontFamily)
146146
const frameWidthC = computed(() => appStore.screenshot.width + 'px')
147147
const transparentOpacity = computed(() =>
148148
appStore.isLightTheme ? '75%' : '10%'
@@ -156,13 +156,10 @@ const colorBgStyle = computed(() => {
156156
backgroundImage: `linear-gradient(45deg, ${appStore.screenshot.gradient[0]}, ${appStore.screenshot.gradient[1]})`
157157
}
158158
})
159+
const fontSize = computed(() => appStore.editor.fontSize + 'px')
160+
const fontFamily = computed(() => appStore.editor.fontFamily)
159161
160-
const renderer = computed(() => {
161-
const language = hljs.getLanguage(props.lang) ? props.lang : 'plaintext'
162-
return `<pre><code class="language-${props.lang} hljs">${
163-
hljs.highlight(props.snippet, { language }).value
164-
}</code></pre>`
165-
})
162+
let editor: CodeMirror.Editor
166163
167164
const height = computed(() => {
168165
// eslint-disable-next-line no-unused-expressions
@@ -176,10 +173,61 @@ const height = computed(() => {
176173
return window.innerHeight - result + 'px'
177174
})
178175
176+
const setValue = (value: string) => {
177+
if (!editor) return
178+
179+
const cursor = editor.getCursor()
180+
editor.setValue(value)
181+
182+
if (cursor) editor.setCursor(cursor)
183+
}
184+
185+
const setLang = (lang: string) => {
186+
if (!editor) return
187+
editor.setOption('mode', lang)
188+
}
189+
190+
const setTheme = (theme: string) => {
191+
if (!editor) return
192+
editor.setOption('theme', theme)
193+
}
194+
179195
const init = () => {
180-
hljs.registerAliases('apache_conf', { languageName: 'apache' })
181-
hljs.registerAliases('c_cpp', { languageName: 'cpp' })
182-
hljs.registerAliases('graphqlschema', { languageName: 'graphql' })
196+
editor = CodeMirror(editorRef.value!, {
197+
value: props.snippet,
198+
mode: props.lang,
199+
theme: appStore.screenshot.darkMode
200+
? getThemeName('dark:material')
201+
: getThemeName('light:github'),
202+
lineNumbers: false,
203+
tabSize: appStore.editor.tabSize,
204+
scrollbarStyle: 'null',
205+
readOnly: true
206+
})
207+
208+
interact(frameRef.value!).resizable({
209+
allowFrom: gutterRef.value!,
210+
onmove: e => {
211+
const { pageX } = e
212+
const gutterOffset = GUTTER_RIGHT_OFFSET + GUTTER_WIDTH / 2
213+
const width = Math.floor(
214+
pageX -
215+
appStore.sizes.sidebar -
216+
appStore.sizes.snippetList +
217+
gutterOffset
218+
)
219+
220+
appStore.screenshot.width = width
221+
222+
if (width < MIN_WIDTH) {
223+
appStore.screenshot.width = 520
224+
}
225+
226+
if (width > MAX_WIDTH) {
227+
appStore.screenshot.width = 920
228+
}
229+
}
230+
})
183231
}
184232
185233
const onSaveScreenshot = async (type: 'png' | 'svg' = 'png') => {
@@ -205,12 +253,11 @@ watch(
205253
() => appStore.screenshot.darkMode,
206254
v => {
207255
if (v) {
208-
useHljsTheme('dark')
256+
setTheme(getThemeName('dark:material')!)
209257
} else {
210-
useHljsTheme('light')
258+
setTheme(getThemeName('light:github')!)
211259
}
212-
},
213-
{ immediate: true }
260+
}
214261
)
215262
216263
watch(
@@ -225,56 +272,41 @@ watch(escape, () => {
225272
snippetStore.isScreenshotPreview = false
226273
})
227274
228-
onMounted(() => {
229-
interact(frameRef.value!).resizable({
230-
allowFrom: gutterRef.value!,
231-
onmove: e => {
232-
const { pageX } = e
233-
const gutterOffset = GUTTER_RIGHT_OFFSET + GUTTER_WIDTH / 2
234-
const width = Math.floor(
235-
pageX -
236-
appStore.sizes.sidebar -
237-
appStore.sizes.snippetList +
238-
gutterOffset
239-
)
240-
241-
appStore.screenshot.width = width
242-
243-
if (width < MIN_WIDTH) {
244-
appStore.screenshot.width = 520
245-
}
275+
watch(
276+
() => props.snippet,
277+
v => setValue(v)
278+
)
279+
watch(
280+
() => props.lang,
281+
v => setLang(v)
282+
)
246283
247-
if (width > MAX_WIDTH) {
248-
appStore.screenshot.width = 920
249-
}
250-
}
251-
})
284+
onMounted(() => {
285+
init()
252286
})
253287
254288
window.addEventListener('resize', () => {
255289
forceRefresh.value = Math.random()
256290
})
257-
258-
init()
259291
</script>
260292

261293
<style lang="scss" scoped>
262294
.snippet-screenshot {
263295
--color-bg-transparent: hsla(0, 0%, v-bind(transparentOpacity));
264296
265-
:deep(code) {
266-
font-family: v-bind(font) !important;
267-
}
268297
:deep(pre) {
269298
white-space: pre-wrap;
270299
font-size: 12px;
271300
}
272-
:deep(code) {
273-
padding: 0;
274-
}
275301
:deep(.ps) {
276302
height: v-bind(height);
277303
}
304+
:deep(.CodeMirror) {
305+
height: 100%;
306+
font-size: v-bind(fontSize);
307+
font-family: v-bind(fontFamily);
308+
line-height: calc(v-bind(fontSize) * 1.5);
309+
}
278310
.tools {
279311
display: flex;
280312
justify-content: space-between;
@@ -348,6 +380,9 @@ init()
348380
border-radius: 12px;
349381
background-color: v-bind(colorBodyBg);
350382
user-select: none;
383+
.window-controls {
384+
margin-bottom: var(--spacing-xs);
385+
}
351386
}
352387
}
353388
</style>

0 commit comments

Comments
 (0)