UNPKG

vue-codemirror6

Version:

CodeMirror6 Component for vue2 and vue3.

310 lines (308 loc) 8.66 kB
/** * vue-codemirror6 * * @description CodeMirror6 Component for vue2 and vue3. * @author Logue <logue@hotmail.co.jp> * @copyright 2022-2026 By Masashi Yoshikawa All rights reserved. * @license MIT * @version 1.5.2 * @see {@link https://github.com/logue/vue-codemirror6} */ import { indentWithTab as e } from "@codemirror/commands"; import { indentUnit as t } from "@codemirror/language"; import { diagnosticCount as n, forceLinting as r, lintGutter as i, linter as a } from "@codemirror/lint"; import { Compartment as o, EditorSelection as s, EditorState as c, StateEffect as l } from "@codemirror/state"; import { EditorView as u, keymap as d, placeholder as f } from "@codemirror/view"; import { basicSetup as p, minimalSetup as m } from "codemirror"; import { computed as h, defineComponent as g, h as _, isVue2 as v, nextTick as y, onMounted as b, onUnmounted as x, ref as S, shallowRef as C, watch as w } from "vue-demi"; //#region src/Meta.ts var T = { version: "1.5.2", date: "2026-05-01T12:27:43.027Z" }, E = (e) => e ? Object.entries(e).reduce((e, [t, n]) => (t = t.charAt(0).toUpperCase() + t.slice(1), t = `on${t}`, { ...e, [t]: n }), {}) : {}; function D(e, t = {}, n) { if (v) return _(e, t, n); let { props: r, domProps: i, on: a, ...o } = t, s = a ? E(a) : {}; return _(e, { ...o, ...r, ...i, ...s }, n); } var O = (e) => typeof e == "function" ? e() : e ?? [], k = g({ name: "CodeMirror", model: { prop: "modelValue", event: "update:modelValue" }, props: { modelValue: { type: String, default: "" }, theme: { type: Object, default: () => ({}) }, dark: { type: Boolean, default: !1 }, basic: { type: Boolean, default: !1 }, minimal: { type: Boolean, default: !1 }, placeholder: { type: String, default: void 0 }, wrap: { type: Boolean, default: !1 }, tab: { type: Boolean, default: !1 }, indentUnit: { type: String, default: void 0 }, allowMultipleSelections: { type: Boolean, default: !1 }, tabSize: { type: Number, default: void 0 }, lineSeparator: { type: String, default: void 0 }, readonly: { type: Boolean, default: !1 }, disabled: { type: Boolean, default: !1 }, extensions: { type: Array, default: () => [] }, phrases: { type: Object, default: void 0 }, lang: { type: Object, default: void 0 }, linter: { type: Function, default: void 0 }, linterConfig: { type: Object, default: () => ({}) }, forceLinting: { type: Boolean, default: !1 }, gutter: { type: Boolean, default: !1 }, gutterConfig: { type: Object, default: void 0 }, tag: { type: String, default: "div" }, scrollIntoView: { type: Boolean, default: !0 }, preserveScrollPosition: { type: Boolean, default: !1 }, keymap: { type: Array, default: () => [] } }, emits: { "update:modelValue": (e = "") => !0, update: (e) => !0, ready: (e) => !0, focus: (e) => !0, change: (e) => !0, destroy: () => !0 }, setup(g, _) { let v = S(), T = S(g.modelValue), E = C(void 0), D = h({ get: () => E.value?.hasFocus ?? !1, set: (e) => { e && E.value && E.value.focus(); } }), O = h({ get: () => E.value?.state.selection, set: (e) => { E.value && e && E.value.dispatch({ selection: e }); } }), k = h({ get: () => E.value?.state.selection.main.head ?? 0, set: (e) => { E.value && E.value.dispatch({ selection: { anchor: e } }); } }), A = h({ get: () => E.value?.state.toJSON(), set: (e) => { E.value && e && E.value.setState(c.fromJSON(e)); } }), j = S(0), M = S(0), N = h(() => { let n = new o(), s = new o(); if (g.basic && g.minimal) throw Error("[Vue CodeMirror] Both basic and minimal cannot be specified."); let l = []; return g.keymap && g.keymap.length > 0 && (l = g.keymap), g.tab && l.push(e), [ g.basic && !g.minimal ? p : void 0, g.minimal && !g.basic ? m : void 0, u.updateListener.of((e) => { E.value && (_.emit("focus", E.value.hasFocus), j.value = E.value.state.doc?.length, !(e.changes.empty || !e.docChanged) && (g.linter && (g.forceLinting && r(E.value), M.value = g.linter(E.value).length), _.emit("update", e))); }), u.theme(g.theme, { dark: g.dark }), g.wrap ? u.lineWrapping : void 0, g.indentUnit ? t.of(g.indentUnit) : void 0, c.allowMultipleSelections.of(g.allowMultipleSelections), g.tabSize ? s.of(c.tabSize.of(g.tabSize)) : void 0, g.phrases ? c.phrases.of(g.phrases) : void 0, c.readOnly.of(g.readonly), u.editable.of(!g.disabled), g.lineSeparator ? c.lineSeparator.of(g.lineSeparator) : void 0, g.lang ? n.of(g.lang) : void 0, g.linter ? a(g.linter, g.linterConfig) : void 0, g.linter && g.gutter ? i(g.gutterConfig) : void 0, g.placeholder ? f(g.placeholder) : void 0, l.length > 0 ? d.of(l) : void 0, ...g.extensions ].filter((e) => !!e); }); w(N, (e) => E.value?.dispatch({ effects: l.reconfigure.of(e) }), { immediate: !0 }), w(() => g.modelValue, async (e) => { if (!E.value || E.value.composing || E.value.state.doc.toJSON().join(g.lineSeparator ?? "\n") === e) return; let t = !E.value.state.selection.ranges.every((t) => t.anchor < e.length && t.head < e.length), n = { from: 0, to: E.value.state.doc.length, insert: e }, r = g.preserveScrollPosition ? E.value.scrollSnapshot().map(E.value.state.changes(n)) : void 0; E.value.dispatch({ changes: n, selection: t ? { anchor: 0, head: 0 } : E.value.state.selection, scrollIntoView: g.scrollIntoView, effects: r ? [r] : void 0 }); }, { immediate: !0 }), b(async () => { if (globalThis.window === void 0 || !v.value) return; let e = T.value; v.value.childNodes[0] && (T.value !== "" && console.warn("[CodeMirror.vue] The <code-mirror> tag contains child elements that overwrite the `v-model` values."), e = v.value.childNodes[0].innerText.trim()), E.value = new u({ parent: v.value, state: c.create({ doc: e, extensions: N.value }), dispatch: (e) => { E.value && (E.value.update([e]), !(e.changes.empty || !e.docChanged) && (_.emit("update:modelValue", e.state.doc.toString()), _.emit("change", e.state))); } }), await y(), _.emit("ready", { view: E.value, state: E.value.state, container: v.value }); }), x(() => { E.value && (E.value.destroy(), _.emit("destroy")); }); let P = { editor: v, view: E, cursor: k, selection: O, focus: D, length: j, json: A, diagnosticCount: M, dom: E.value?.contentDOM, lint: () => { !g.linter || !E.value || (g.forceLinting && r(E.value), M.value = n(E.value.state)); }, forceReconfigure: () => { E.value?.dispatch({ effects: l.reconfigure.of([]) }), E.value?.dispatch({ effects: l.appendConfig.of(N.value) }); }, getRange: (e, t) => E.value?.state.sliceDoc(e, t), getLine: (e) => E.value?.state.doc.line(e + 1).text, lineCount: () => E.value?.state.doc.lines ?? 0, getCursor: () => E.value?.state.selection.main.head ?? 0, listSelections: () => E.value?.state.selection.ranges ?? [], getSelection: () => E.value ? E.value.state.sliceDoc(E.value.state.selection.main.from, E.value.state.selection.main.to) : "", getSelections: () => { let e = E.value?.state; return e ? e.selection.ranges.map((t) => e.sliceDoc(t.from, t.to)) : []; }, somethingSelected: () => E.value?.state.selection.ranges.some((e) => !e.empty) ?? !1, replaceRange: (e, t, n) => { E.value && E.value.dispatch({ changes: { from: t, to: n, insert: e } }); }, replaceSelection: (e) => { E.value && E.value.dispatch(E.value.state.replaceSelection(e)); }, setCursor: (e) => { E.value && E.value.dispatch({ selection: { anchor: e } }); }, setSelection: (e, t) => { E.value && E.value.dispatch({ selection: { anchor: e, head: t } }); }, setSelections: (e, t) => { E.value && E.value.dispatch({ selection: s.create(e, t) }); }, extendSelectionsBy: (e) => { E.value && O.value && E.value.dispatch({ selection: s.create(O.value.ranges.map((t) => t.extend(e(t)))) }); } }; return _.expose(P), P; }, render() { return D(this.$props.tag, { ref: "editor", class: "vue-codemirror" }, this.$slots.default ? D("aside", { style: "display: none;", "aria-hidden": "true" }, O(this.$slots.default)) : void 0); } }), A = (e) => { e.component("CodeMirror", k); }; //#endregion export { T as Meta, k as default, A as install };