Add QOL addons to CodeMirror editor
This commit is contained in:
parent
415bc4e0db
commit
9d12bc7388
|
@ -0,0 +1,146 @@
|
|||
<script context="module">
|
||||
export const EditorModes = {
|
||||
JS: {
|
||||
name: "javascript",
|
||||
json: false,
|
||||
},
|
||||
JSON: {
|
||||
name: "javascript",
|
||||
json: true,
|
||||
},
|
||||
SQL: {
|
||||
name: "sql",
|
||||
},
|
||||
Handlebars: {
|
||||
name: "handlebars",
|
||||
base: "text/html",
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import CodeMirror from "components/integration/codemirror"
|
||||
import { themeStore } from "builderStore"
|
||||
import { createEventDispatcher, onMount } from "svelte"
|
||||
|
||||
export let mode = EditorModes.JS
|
||||
export let value = ""
|
||||
export let height = 300
|
||||
export let readonly = false
|
||||
export let hints = []
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
let textarea
|
||||
let editor
|
||||
|
||||
// Keep editor up to date with value
|
||||
$: editor?.setValue(value || "")
|
||||
|
||||
// Creates an instance of a code mirror editor
|
||||
async function createEditor(mode, value) {
|
||||
if (!CodeMirror || !textarea || editor) {
|
||||
return
|
||||
}
|
||||
|
||||
// Configure CM options
|
||||
const lightTheme = $themeStore.theme.includes("light")
|
||||
const options = {
|
||||
mode,
|
||||
value: value || "",
|
||||
readOnly: readonly,
|
||||
theme: lightTheme ? "default" : "tomorrow-night-eighties",
|
||||
|
||||
// Style
|
||||
lineNumbers: true,
|
||||
lineWrapping: true,
|
||||
indentWithTabs: true,
|
||||
indentUnit: 2,
|
||||
tabSize: 2,
|
||||
|
||||
// QOL addons
|
||||
extraKeys: { "Ctrl-Space": "autocomplete" },
|
||||
styleActiveLine: { nonEmpty: true },
|
||||
autoCloseBrackets: true,
|
||||
matchBrackets: true,
|
||||
}
|
||||
|
||||
// Register hints plugin if desired
|
||||
if (hints?.length) {
|
||||
CodeMirror.registerHelper("hint", "dictionaryHint", function (editor) {
|
||||
const cursor = editor.getCursor()
|
||||
return {
|
||||
list: hints,
|
||||
from: CodeMirror.Pos(cursor.line, cursor.ch),
|
||||
to: CodeMirror.Pos(cursor.line, cursor.ch),
|
||||
}
|
||||
})
|
||||
CodeMirror.commands.autocomplete = function (cm) {
|
||||
CodeMirror.showHint(cm, CodeMirror.hint.dictionaryHint)
|
||||
}
|
||||
}
|
||||
|
||||
// Construct CM instance
|
||||
editor = CodeMirror.fromTextArea(textarea, options)
|
||||
|
||||
// Use a blur handler to update the value
|
||||
editor.on("blur", instance => {
|
||||
dispatch("change", instance.getValue())
|
||||
})
|
||||
}
|
||||
|
||||
// Export a function to expose caret position
|
||||
export const getCaretPosition = () => {
|
||||
const cursor = editor.getCursor()
|
||||
return {
|
||||
start: cursor.ch,
|
||||
end: cursor.ch,
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
// Create the editor with initial value
|
||||
createEditor(mode, value)
|
||||
|
||||
// Clean up editor on unmount
|
||||
return () => {
|
||||
if (editor) {
|
||||
editor.toTextArea()
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<div style={`--code-mirror-height: ${height}px`}>
|
||||
<textarea tabindex="0" bind:this={textarea} readonly {value} />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
div :global(.CodeMirror) {
|
||||
height: var(--code-mirror-height);
|
||||
font-family: monospace;
|
||||
line-height: 1.3;
|
||||
border: var(--spectrum-alias-border-size-thin) solid;
|
||||
border-color: var(--spectrum-alias-border-color);
|
||||
overflow: hidden;
|
||||
border-radius: var(--border-radius-s);
|
||||
}
|
||||
|
||||
/* Override default active line highlight colour in dark theme */
|
||||
div
|
||||
:global(.CodeMirror-focused.cm-s-tomorrow-night-eighties
|
||||
.CodeMirror-activeline-background) {
|
||||
background: rgba(255, 255, 255, 0.075);
|
||||
}
|
||||
|
||||
/* Remove active line styling when not focused */
|
||||
div
|
||||
:global(.CodeMirror:not(.CodeMirror-focused)
|
||||
.CodeMirror-activeline-background) {
|
||||
background: unset;
|
||||
}
|
||||
|
||||
/* Add a spectrum themed border when focused */
|
||||
div :global(.CodeMirror-focused) {
|
||||
border-color: var(--spectrum-alias-border-color-mouse-focus);
|
||||
}
|
||||
</style>
|
|
@ -1,12 +1,22 @@
|
|||
import CodeMirror from "codemirror"
|
||||
import "codemirror/lib/codemirror.css"
|
||||
import "codemirror/theme/tomorrow-night-eighties.css"
|
||||
import "codemirror/addon/hint/show-hint.css"
|
||||
import "codemirror/theme/neo.css"
|
||||
|
||||
// Modes
|
||||
import "codemirror/mode/javascript/javascript"
|
||||
import "codemirror/mode/sql/sql"
|
||||
import "codemirror/mode/css/css"
|
||||
import "codemirror/mode/handlebars/handlebars"
|
||||
import "codemirror/mode/javascript/javascript"
|
||||
|
||||
// Hints
|
||||
import "codemirror/addon/hint/show-hint"
|
||||
import "codemirror/addon/hint/show-hint.css"
|
||||
|
||||
// Theming
|
||||
import "codemirror/theme/tomorrow-night-eighties.css"
|
||||
|
||||
// Functional addons
|
||||
import "codemirror/addon/selection/active-line"
|
||||
import "codemirror/addon/edit/closebrackets"
|
||||
import "codemirror/addon/edit/matchbrackets"
|
||||
|
||||
export default CodeMirror
|
||||
|
|
Loading…
Reference in New Issue