Path: blob/main/frontend/vue/components/CodeExercise/CodeArea.vue
3376 views
<template> <div ref="codeAreaWrapper" class="code-area" /> </template> <script lang="ts"> import { defineComponent } from 'vue-demi' import { basicSetup } from 'codemirror' import { EditorView, keymap } from '@codemirror/view' import { EditorState, StateField } from '@codemirror/state' import { defaultKeymap, indentWithTab } from '@codemirror/commands' import { python } from '@codemirror/lang-python' export default defineComponent({ name: 'CodeArea', props: { code: { type: String, required: false, default: '' } }, data () { return { editor: undefined as EditorView | undefined } }, watch: { code (newVal: string) { const editor = this.editor! as EditorView const newValAsText = editor.state.toText(newVal) if (editor.state.doc.eq(newValAsText)) { return } editor.dispatch({ changes: { from: 0, to: editor.state.doc.length, insert: newValAsText } }) } }, mounted () { const emit = this.$emit const parentHTMLElement = this.$refs.codeAreaWrapper as HTMLDivElement const docChanged = StateField.define({ create (state) { return state.sliceDoc() }, update (value, tr) { if (tr.docChanged) { const newCode = tr.state.sliceDoc() emit('codeChanged', newCode) } } }) const keyboardRun = (view: EditorView): boolean => { emit('keyboardRun', true) return true } const state = EditorState.create({ doc: this.code, extensions: [ basicSetup, python(), docChanged, keymap.of([ ...defaultKeymap, indentWithTab, { key: 'Shift-Enter', preventDefault: true, run: keyboardRun, }, ]) ] }) this.editor = new EditorView({ state, parent: parentHTMLElement }) } }) </script> <style lang="scss"> @import 'carbon-components/scss/globals/scss/spacing'; @import 'carbon-components/scss/globals/scss/typography'; @import '~/../scss/variables/colors.scss'; .code-area .cm-editor { .cm- { &scroller { background-color: $background-color-lighter; &::-webkit-scrollbar { width: 0.4rem; height: 0.4rem; } } &content { @include type-style('code-01'); padding: $spacing-08 0; min-height: 6rem; } &gutters { @include type-style('code-01'); background-color: $background-color-lighter; } &activeLine { background-color: rgba($background-color-light-2, 0.2); } &activeLineGutter { background-color: rgba($background-color-light-2, 0.5); } &line:hover { background-color: rgba($background-color-light-2, 0.5); cursor: text; } } &:hover .cm- { &gutters { background-color: $background-color-light; } } } </style>