LCOV - code coverage report
Current view: top level - src/components - CodeMirrorMixin.js (source / functions) Hit Total Coverage
Test: lcov.info Lines: 16 16 100.0 %
Date: 2025-06-29 02:18:36 Functions: 7 7 100.0 %

          Line data    Source code
       1             : // @ts-check
       2             : 
       3             : import { Compartment, EditorState } from "@codemirror/state";
       4             : import { EditorView } from "@codemirror/view";
       5             : import { basicSetup } from "./CodeMirrorMixinInit";
       6             : 
       7             : import { mixinMaker } from "../utils";
       8             : 
       9             : /**
      10             :  * @typedef {{ cm: EditorView, extensions: any }} Opts
      11             :  * @typedef {{
      12             :  *  extensions?: import("@codemirror/state").Extension[]
      13             :  * }} CodeMirrorMixinOptions
      14             :  * @typedef {import("@codemirror/state").Transaction} CodeMirrorStateTransaction
      15             :  *
      16             :  * @typedef {import("vue").ComponentOptionsMixin} ComponentOptionsMixin
      17             :  * @typedef {{ value: string }} MixinProps
      18             :  * @typedef {{ editValue: string }} MixinData
      19             :  * @typedef {{
      20             :  *      _changeFilter(tr: CodeMirrorStateTransaction): boolean,
      21             :  *      setContent(data: string): void
      22             :  * }} MixinMethods
      23             :  * @typedef { Vue & MixinMethods & MixinData } MixinInstance
      24             :  * @typedef { MixinInstance & { $options: Opts } } MixinInstanceWithOptions
      25             :  */
      26             : 
      27           1 : const theme = EditorView.theme({
      28             :   "&": {
      29             :     fontSize: "0.875rem"
      30             :   }
      31             : });
      32           1 : export const ThemeCompartment = new Compartment();
      33             : 
      34             : const CodeMirrorMixin =
      35           2 :   (/** @type {CodeMirrorMixinOptions} */options) => mixinMaker({
      36             :     name: "CodeMirrorMixin",
      37             :     model: { prop: "value", event: "edit" },
      38             :     props: {
      39             :       value: { type: String, default: "" }
      40             :     },
      41             :     /** @return {MixinData} */
      42             :     data() {
      43           8 :       return { editValue: "" };
      44             :     },
      45             :     /** @this {MixinInstanceWithOptions} */
      46             :     beforeDestroy() {
      47           8 :       this.$options.cm.destroy();
      48             :     },
      49             :     /** @this {MixinInstanceWithOptions & Readonly<MixinProps>} */
      50             :     mounted() {
      51           8 :       const ext = [ basicSetup, EditorState.changeFilter.of(this._changeFilter),
      52             :                     ThemeCompartment.of(theme) ];
      53           8 :       if (options?.extensions) {
      54           8 :         ext.push(options.extensions);
      55             :       }
      56             : 
      57           8 :       this.$options.cm = new EditorView({
      58             :         extensions: ext,
      59             :         parent: (/** @type {Element} */(this.$refs?.cm) ?? this.$el),
      60             :         doc: this.value
      61             :       });
      62             :     },
      63             :     methods: {
      64             :       /**
      65             :        * @this {MixinInstance}
      66             :        * @param {CodeMirrorStateTransaction} tr
      67             :        * @returns {boolean}
      68             :        */
      69             :       _changeFilter(tr) {
      70          29 :         this.editValue = tr.state.doc.toString();
      71          29 :         this.$emit("edit", this.editValue);
      72          29 :         return true;
      73             :       },
      74             :       /**
      75             :        * @this {MixinInstance}
      76             :        * @returns {EditorView}
      77             :        */
      78             :       getEditor() {
      79           9 :         return /** @type {MixinInstanceWithOptions} */(this).$options.cm;
      80             :       },
      81             :       /**
      82             :        * @this {MixinInstance}
      83             :        * @param {string} data
      84             :        */
      85             :       setContent(data) {
      86          16 :         const cm = /** @type {MixinInstanceWithOptions} */(this).$options.cm;
      87          16 :         if (!cm) { return; }
      88          16 :         cm.dispatch(cm.state.update({
      89             :           changes: {
      90             :             from: 0, to: cm.state.doc.length, insert: data
      91             :           }
      92             :         }));
      93             :       }
      94             :     }
      95             :   });
      96             : export default CodeMirrorMixin;

Generated by: LCOV version 1.16