Skip to content

Commit

Permalink
feat(snippets): use codemirror for screenshot (#321)
Browse files Browse the repository at this point in the history
  • Loading branch information
antonreshetov authored Jan 7, 2023
1 parent a44ebd2 commit 9d264e0
Showing 1 changed file with 83 additions and 48 deletions.
131 changes: 83 additions & 48 deletions src/renderer/components/screenshot/TheScreenshot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
</g>
</svg>
</div>
<div v-html="renderer" />
<div ref="editorRef" />
</div>
</div>
<div class="transparent" />
Expand All @@ -107,14 +107,14 @@

<script setup lang="ts">
import { useAppStore } from '@/store/app'
import hljs from 'highlight.js'
import interact from 'interactjs'
import { computed, onMounted, ref, watch } from 'vue'
import { useHljsTheme } from '@/composable'
import { store, track, i18n } from '@/electron'
import { useSnippetStore } from '@/store/snippets'
import { useMagicKeys } from '@vueuse/core'
import domToImage from 'dom-to-image'
import CodeMirror from 'codemirror'
import { getThemeName } from '../editor/themes'
const GUTTER_RIGHT_OFFSET = 10
const GUTTER_WIDTH = 8
Expand All @@ -136,13 +136,13 @@ const { escape } = useMagicKeys()
const frameRef = ref<HTMLElement>()
const snippetRef = ref<HTMLElement>()
const gutterRef = ref<HTMLElement>()
const editorRef = ref<HTMLElement>()
const gutterWidth = ref(GUTTER_WIDTH + 'px')
const offsetGutterRight = ref(GUTTER_RIGHT_OFFSET + 'px')
const forceRefresh = ref()
const font = computed(() => appStore.editor.fontFamily)
const frameWidthC = computed(() => appStore.screenshot.width + 'px')
const transparentOpacity = computed(() =>
appStore.isLightTheme ? '75%' : '10%'
Expand All @@ -156,13 +156,10 @@ const colorBgStyle = computed(() => {
backgroundImage: `linear-gradient(45deg, ${appStore.screenshot.gradient[0]}, ${appStore.screenshot.gradient[1]})`
}
})
const fontSize = computed(() => appStore.editor.fontSize + 'px')
const fontFamily = computed(() => appStore.editor.fontFamily)
const renderer = computed(() => {
const language = hljs.getLanguage(props.lang) ? props.lang : 'plaintext'
return `<pre><code class="language-${props.lang} hljs">${
hljs.highlight(props.snippet, { language }).value
}</code></pre>`
})
let editor: CodeMirror.Editor
const height = computed(() => {
// eslint-disable-next-line no-unused-expressions
Expand All @@ -176,10 +173,61 @@ const height = computed(() => {
return window.innerHeight - result + 'px'
})
const setValue = (value: string) => {
if (!editor) return
const cursor = editor.getCursor()
editor.setValue(value)
if (cursor) editor.setCursor(cursor)
}
const setLang = (lang: string) => {
if (!editor) return
editor.setOption('mode', lang)
}
const setTheme = (theme: string) => {
if (!editor) return
editor.setOption('theme', theme)
}
const init = () => {
hljs.registerAliases('apache_conf', { languageName: 'apache' })
hljs.registerAliases('c_cpp', { languageName: 'cpp' })
hljs.registerAliases('graphqlschema', { languageName: 'graphql' })
editor = CodeMirror(editorRef.value!, {
value: props.snippet,
mode: props.lang,
theme: appStore.screenshot.darkMode
? getThemeName('dark:material')
: getThemeName('light:github'),
lineNumbers: false,
tabSize: appStore.editor.tabSize,
scrollbarStyle: 'null',
readOnly: true
})
interact(frameRef.value!).resizable({
allowFrom: gutterRef.value!,
onmove: e => {
const { pageX } = e
const gutterOffset = GUTTER_RIGHT_OFFSET + GUTTER_WIDTH / 2
const width = Math.floor(
pageX -
appStore.sizes.sidebar -
appStore.sizes.snippetList +
gutterOffset
)
appStore.screenshot.width = width
if (width < MIN_WIDTH) {
appStore.screenshot.width = 520
}
if (width > MAX_WIDTH) {
appStore.screenshot.width = 920
}
}
})
}
const onSaveScreenshot = async (type: 'png' | 'svg' = 'png') => {
Expand All @@ -205,12 +253,11 @@ watch(
() => appStore.screenshot.darkMode,
v => {
if (v) {
useHljsTheme('dark')
setTheme(getThemeName('dark:material')!)
} else {
useHljsTheme('light')
setTheme(getThemeName('light:github')!)
}
},
{ immediate: true }
}
)
watch(
Expand All @@ -225,56 +272,41 @@ watch(escape, () => {
snippetStore.isScreenshotPreview = false
})
onMounted(() => {
interact(frameRef.value!).resizable({
allowFrom: gutterRef.value!,
onmove: e => {
const { pageX } = e
const gutterOffset = GUTTER_RIGHT_OFFSET + GUTTER_WIDTH / 2
const width = Math.floor(
pageX -
appStore.sizes.sidebar -
appStore.sizes.snippetList +
gutterOffset
)
appStore.screenshot.width = width
if (width < MIN_WIDTH) {
appStore.screenshot.width = 520
}
watch(
() => props.snippet,
v => setValue(v)
)
watch(
() => props.lang,
v => setLang(v)
)
if (width > MAX_WIDTH) {
appStore.screenshot.width = 920
}
}
})
onMounted(() => {
init()
})
window.addEventListener('resize', () => {
forceRefresh.value = Math.random()
})
init()
</script>

<style lang="scss" scoped>
.snippet-screenshot {
--color-bg-transparent: hsla(0, 0%, v-bind(transparentOpacity));
:deep(code) {
font-family: v-bind(font) !important;
}
:deep(pre) {
white-space: pre-wrap;
font-size: 12px;
}
:deep(code) {
padding: 0;
}
:deep(.ps) {
height: v-bind(height);
}
:deep(.CodeMirror) {
height: 100%;
font-size: v-bind(fontSize);
font-family: v-bind(fontFamily);
line-height: calc(v-bind(fontSize) * 1.5);
}
.tools {
display: flex;
justify-content: space-between;
Expand Down Expand Up @@ -348,6 +380,9 @@ init()
border-radius: 12px;
background-color: v-bind(colorBodyBg);
user-select: none;
.window-controls {
margin-bottom: var(--spacing-xs);
}
}
}
</style>

0 comments on commit 9d264e0

Please sign in to comment.