UNPKG

vue-codemirror6

Version:

CodeMirror6 Component for vue2 and vue3.

471 lines (469 loc) 13.2 kB
/** * vue-codemirror6 * * @description CodeMirror6 Component for vue2 and vue3. * @author Logue <logue@hotmail.co.jp> * @copyright 2022-2025 By Masashi Yoshikawa All rights reserved. * @license MIT * @version 1.3.12 * @see {@link https://github.com/logue/vue-codemirror6} */ import { indentWithTab as W } from "@codemirror/commands"; import { indentUnit as G } from "@codemirror/language"; import { linter as P, lintGutter as Z, forceLinting as b, diagnosticCount as k } from "@codemirror/lint"; import { EditorState as s, Compartment as w, StateEffect as y, EditorSelection as C } from "@codemirror/state"; import { EditorView as c, keymap as q, placeholder as H } from "@codemirror/view"; import { basicSetup as K, minimalSetup as Q } from "codemirror"; import { isVue2 as X, h as O, defineComponent as Y, ref as v, shallowRef as ee, computed as r, watch as V, onMounted as te, nextTick as ae, onUnmounted as ne } from "vue-demi"; const me = { version: "1.3.12", date: "2025-03-31T11:10:32.144Z" }, le = (e) => e ? Object.entries(e).reduce((i, [l, u]) => (l = l.charAt(0).toUpperCase() + l.slice(1), l = `on${l}`, { ...i, [l]: u }), {}) : {}; function B(e, i = {}, l) { if (X) return O(e, i, l); const { props: u, domProps: t, on: d, ...f } = i, m = d ? le(d) : {}; return O( e, { ...f, ...u, ...t, ...m }, l ); } const ie = (e) => typeof e == "function" ? e() : e; var oe = Y({ /** Component Name */ name: "CodeMirror", /** Model Definition */ model: { prop: "modelValue", event: "update:modelValue" }, /** Props Definition */ props: { /** Model value */ modelValue: { type: String, default: "" }, /** * Theme * * @see {@link https://codemirror.net/docs/ref/#view.EditorView^theme} */ theme: { type: Object, default: () => ({}) }, /** Dark Mode */ dark: { type: Boolean, default: !1 }, /** * Use Basic Setup * * @see {@link https://codemirror.net/docs/ref/#codemirror.basicSetup} */ basic: { type: Boolean, default: !1 }, /** * Use Minimal Setup (The basic setting has priority.) * * @see {@link https://codemirror.net/docs/ref/#codemirror.minimalSetup} */ minimal: { type: Boolean, default: !1 }, /** * Placeholder * * @see {@link https://codemirror.net/docs/ref/#view.placeholder} */ placeholder: { type: String, default: void 0 }, /** * Line wrapping * * An extension that enables line wrapping in the editor (by setting CSS white-space to pre-wrap in the content). * * @see {@link https://codemirror.net/docs/ref/#view.EditorView%5ElineWrapping} */ wrap: { type: Boolean, default: !1 }, /** * Allow tab key indent. * * @see {@link https://codemirror.net/examples/tab/} */ tab: { type: Boolean, default: !1 }, /** * Tab character */ indentUnit: { type: String, default: void 0 }, /** * Allow Multiple Selection. * * @see {@link https://codemirror.net/docs/ref/#state.EditorState^allowMultipleSelections} */ allowMultipleSelections: { type: Boolean, default: !1 }, /** * Tab size * * @see {@link https://codemirror.net/docs/ref/#state.EditorState^tabSize} */ tabSize: { type: Number, default: void 0 }, /** * Set line break (separetor) char. * * @see {@link https://codemirror.net/docs/ref/#state.EditorState^lineSeparator} */ lineSeparator: { type: String, default: void 0 }, /** * Readonly * * @see {@link https://codemirror.net/docs/ref/#state.EditorState^readOnly} */ readonly: { type: Boolean, default: !1 }, /** * Disable input. * * This is the reversed value of the CodeMirror editable. * Similar to `readonly`, but setting this value to true disables dragging. * * @see {@link https://codemirror.net/docs/ref/#view.EditorView^editable} */ disabled: { type: Boolean, default: !1 }, /** * Additional Extension * * @see {@link https://codemirror.net/docs/ref/#state.Extension} */ extensions: { type: Array, default: () => [] }, /** * Language Phreses * * @see {@link https://codemirror.net/examples/translate/} */ phrases: { type: Object, default: () => { } }, /** * CodeMirror Language * * @see {@link https://codemirror.net/docs/ref/#language} */ lang: { type: Object, default: () => { } }, /** * CodeMirror Linter * * @see {@link https://codemirror.net/docs/ref/#lint.linter} */ linter: { type: Function, default: void 0 }, /** * Linter Config * * @see {@link https://codemirror.net/docs/ref/#lint.linter^config} */ linterConfig: { type: Object, default: () => ({}) }, /** * Forces any linters configured to run when the editor is idle to run right away. * * @see {@link https://codemirror.net/docs/ref/#lint.forceLinting} */ forceLinting: { type: Boolean, default: !1 }, /** * Show Linter Gutter * * An area to 🔴 the lines with errors will be displayed. * This feature is not enabled if `linter` is not specified. * * @see {@link https://codemirror.net/docs/ref/#lint.lintGutter} */ gutter: { type: Boolean, default: !1 }, /** * Gutter Config * * @see {@link https://codemirror.net/docs/ref/#lint.lintGutter^config} */ gutterConfig: { type: Object, default: () => { } }, /** * Using tag */ tag: { type: String, default: "div" }, /** * Allows an external update to scroll the form. * @see {@link https://codemirror.net/docs/ref/#state.TransactionSpec.scrollIntoView} */ scrollIntoView: { type: Boolean, default: !0 } }, /** Emits */ emits: { /** Model Update */ "update:modelValue": (e = "") => !0, /** CodeMirror ViewUpdate */ update: (e) => !0, /** CodeMirror onReady */ ready: (e) => !0, /** CodeMirror onFocus */ focus: (e) => !0, /** State Changed */ change: (e) => !0, /** CodeMirror onDestroy */ destroy: () => !0 }, /** * Setup * * @param props - Props * @param context - Context */ setup(e, i) { const l = v(), u = v(e.modelValue), t = ee(new c()), d = r({ get: () => t.value.hasFocus, set: (a) => { a && t.value.focus(); } }), f = r({ get: () => t.value.state.selection, set: (a) => t.value.dispatch({ selection: a }) }), m = r({ get: () => t.value.state.selection.main.head, set: (a) => t.value.dispatch({ selection: { anchor: a } }) }), M = r( { get: () => t.value.state.toJSON(), set: (a) => t.value.setState(s.fromJSON(a)) } ), S = v(0), h = v(0), g = r(() => { const a = new w(), n = new w(); if (e.basic && e.minimal) throw "[Vue CodeMirror] Both basic and minimal cannot be specified."; return [ // Toggle basic setup e.basic && !e.minimal ? K : void 0, // Toggle minimal setup e.minimal && !e.basic ? Q : void 0, // ViewUpdate event listener c.updateListener.of((o) => { i.emit("focus", t.value.hasFocus), S.value = t.value.state.doc?.length, !(o.changes.empty || !o.docChanged) && (e.linter && (e.forceLinting && b(t.value), h.value = e.linter(t.value).length), i.emit("update", o)); }), // Toggle light/dark mode. c.theme(e.theme, { dark: e.dark }), // Toggle line wrapping e.wrap ? c.lineWrapping : void 0, // Indent with tab e.tab ? q.of([W]) : void 0, // Tab character e.indentUnit ? G.of(e.indentUnit) : void 0, // Allow Multiple Selections s.allowMultipleSelections.of(e.allowMultipleSelections), // Indent tab size e.tabSize ? n.of(s.tabSize.of(e.tabSize)) : void 0, // locale settings e.phrases ? s.phrases.of(e.phrases) : void 0, // Readonly option s.readOnly.of(e.readonly), // Editable option c.editable.of(!e.disabled), // Set Line break char e.lineSeparator ? s.lineSeparator.of(e.lineSeparator) : void 0, // Lang e.lang ? a.of(e.lang) : void 0, // Append Linter settings e.linter ? P(e.linter, e.linterConfig) : void 0, // Show 🔴 to error line when linter enabled. e.linter && e.gutter ? Z(e.gutterConfig) : void 0, // Placeholder e.placeholder ? H(e.placeholder) : void 0, // Append Extensions ...e.extensions ].filter((o) => !!o); }); V( g, (a) => { t.value?.dispatch({ effects: y.reconfigure.of(a) }); }, { immediate: !0 } ), V( () => e.modelValue, async (a) => { if (t.value.composing || // IME fix t.value.state.doc.toJSON().join(e.lineSeparator ?? ` `) === a) return; const n = !t.value.state.selection.ranges.every( (o) => o.anchor < a.length && o.head < a.length ); t.value.dispatch({ changes: { from: 0, to: t.value.state.doc.length, insert: a }, selection: n ? { anchor: 0, head: 0 } : t.value.state.selection, scrollIntoView: e.scrollIntoView }); }, { immediate: !0 } ), te(async () => { let a = u.value; l.value && (l.value.childNodes[0] && (u.value !== "" && console.warn( "[CodeMirror.vue] The <code-mirror> tag contains child elements that overwrite the `v-model` values." ), a = l.value.childNodes[0].innerText.trim()), t.value = new c({ parent: l.value, state: s.create({ doc: a, extensions: g.value }), dispatch: (n) => { t.value.update([n]), !(n.changes.empty || !n.docChanged) && (i.emit("update:modelValue", n.state.doc.toString() ?? ""), i.emit("change", n.state)); } }), await ae(), i.emit("ready", { view: t.value, state: t.value.state, container: l.value })); }), ne(() => { t.value.destroy(), i.emit("destroy"); }); const $ = () => { !e.linter || !t.value || (e.forceLinting && b(t.value), h.value = k(t.value.state)); }, j = () => { t.value?.dispatch({ effects: y.reconfigure.of([]) }), t.value?.dispatch({ effects: y.appendConfig.of(g.value) }); }, x = (a, n) => t.value.state.sliceDoc(a, n), _ = (a) => t.value.state.doc.line(a + 1).text, L = () => t.value.state.doc.lines, N = () => t.value.state.selection.main.head, U = () => { let a; return (a = t.value.state.selection.ranges) !== null && a !== void 0 ? a : []; }, z = () => { let a; return (a = t.value.state.sliceDoc( t.value.state.selection.main.from, t.value.state.selection.main.to )) !== null && a !== void 0 ? a : ""; }, R = () => { const a = t.value.state; return a ? a.selection.ranges.map( (n) => a.sliceDoc(n.from, n.to) ) : []; }, T = () => t.value.state.selection.ranges.some( (a) => !a.empty ), D = (a, n, o) => t.value.dispatch({ changes: { from: n, to: o, insert: a } }), E = (a) => t.value.dispatch(t.value.state.replaceSelection(a)), F = (a) => t.value.dispatch({ selection: { anchor: a } }), I = (a, n) => t.value.dispatch({ selection: { anchor: a, head: n } }), J = (a, n) => t.value.dispatch({ selection: C.create(a, n) }), A = (a) => t.value.dispatch({ selection: C.create( f.value.ranges.map((n) => n.extend(a(n))) ) }), p = { editor: l, view: t, cursor: m, selection: f, focus: d, length: S, json: M, diagnosticCount: h, dom: t.value.contentDOM, lint: $, forceReconfigure: j, // Bellow is CodeMirror5's function getRange: x, getLine: _, lineCount: L, getCursor: N, listSelections: U, getSelection: z, getSelections: R, somethingSelected: T, replaceRange: D, replaceSelection: E, setCursor: F, setSelection: I, setSelections: J, extendSelectionsBy: A }; return i.expose(p), p; }, render() { return B( this.$props.tag, { ref: "editor", class: "vue-codemirror" }, this.$slots.default ? ( // Hide original content B( "aside", { style: "display: none;", "aria-hidden": "true" }, ie(this.$slots.default) ) ) : void 0 ); } }); const he = (e) => e.component("CodeMirror", oe); export { me as Meta, oe as default, he as install };