vue-codemirror6
Version:
CodeMirror6 Component for vue2 and vue3.
310 lines (308 loc) • 8.66 kB
JavaScript
/**
* 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 };