codemirror-editor-vue3

repository·main·Indexed 42 days ago

https://github.com/rennzhang/codemirror-editor-vue3

A Vue 3 wrapper for the CodeMirror 5 editor providing a component-based interface for code editing. Version 2.8.0 supports v-model:value binding, standard CodeMirror 5 configuration via the options prop, and specialized log modes (log and fclog) with helper functions. It includes support for syntax highlighting, linting for js and json, and a Merge Mode for side-by-side diffing.

Tokens
13.5K
Snippets
37
Records
40
Agent score
52%

What's inside codemirror-editor-vue3

  1. Obtain the CodeMirror editor instance via events

    main

    You can retrieve the CodeMirror Editor instance directly through the @ready and @change component events. This is often cleaner than using refs if you only need the instance when specific editor actions occur.

    • @ready: Emits the Editor instance once the editor is initialized.
    • @change: Emits the current value (string) and the Editor instance whenever the content changes.
    <template>
      <Codemirror
        v-model:value="code"
        :options="cmOptions"
        @ready="onReady"
        @change="onChange"
      />
    </template>
    
    <script lang="ts">
    import { ref } from "vue";
    import Codemirror from "codemirror-editor-vue3";
    import type { Editor, EditorConfiguration } from "codemirror";
    
    export default {
      components: { Codemirror },
      setup() {
        const code = ref(`const ary = []`);
        const cminstance = ref<Editor>();
    
        const cmOptions: EditorConfiguration = {
          mode: "javascript",
        };
    
        // The 'ready' event provides the Editor instance directly
        const onReady = (cm: Editor) => {
          cminstance.value = cm;
          cminstance.value?.focus();
        };
    
        // The 'change' event provides the new value and the Editor instance
        const onChange = (value: string, cm: Editor) => {
          cminstance.value = cm;
          cminstance.value?.focus();
        };
    
        return {
          code,
          cmOptions,
          onReady,
          onChange,
        };
      },
    };
    </script>
  2. Use Merge Mode in Codemirror

    main

    Merge Mode allows for side-by-side diffing and merging of code. The codemirror-editor-vue3 component handles the necessary diff-match-patch dependencies automatically.

    To use Merge Mode, pass the merge prop to the <Codemirror /> component and configure the cmOptions object with the following relevant keys:

    • value: The current content of the editor.
    • orig: The original content to compare against.
    • origLeft: (Optional) The content for the left side of the diff.
    • connect: The connection method (e.g., 'align').
    • mode: The language mode (e.g., 'text/html').
    • collapseIdentical: Boolean to toggle collapsing identical lines.
    • highlightDifferences: Boolean to toggle difference highlighting.

    Note: You must manually import the language pattern and style files required for your specific mode (e.g., codemirror/mode/htmlmixed/htmlmixed.js).

    <template>
      <Codemirror merge :options="cmOptions" :height="400" @change="onChange" />
    </template>
    
    <script lang="ts">
    import { ref, defineComponent, reactive } from "vue";
    import { MergeView } from "codemirror/addon/merge/merge";
    import type { Editor } from "codemirror";
    import Codemirror from "codemirror-editor-vue3";
    
    // You must import the language mode manually
    import "codemirror/mode/htmlmixed/htmlmixed.js";
    
    export default defineComponent({
      components: {
        Codemirror,
      },
      setup() {
        const code = ref(`<div>Content</div>`);
        const orig2 = ref(`<div>Old Content</div>`);
    
        const onChange = (val: string, cm: any) => {
          // cm is an instance of MergeView
          const cmMerge = cm as MergeView;
          // Access the underlying editor instance via .editor()
          const cminstance: Editor = cmMerge.editor();
          console.log(cminstance.getValue());
        };
    
        const cmOptions = reactive({
          value: code,
          orig: orig2,
          connect: "align",
          mode: "text/html",
          lineNumbers: true,
          collapseIdentical: false,
          highlightDifferences: true,
        });
    
        return { onChange, cmOptions };
      },
    });
    </script>
  3. Register Codemirror as a global component

    main

    You can register the component globally using the InstallCodeMirror plugin.

    Warning: Global registration is not recommended because it may prevent template type prompts from working correctly in your IDE.

    By default, the component name is Codemirror. You can customize this name by passing an options object to app.use().

    import { createApp } from "vue";
    import App from "./App.vue";
    import { InstallCodeMirror } from "codemirror-editor-vue3";
    
    const app = createApp(App);
    
    // Default name: <Codemirror />
    app.use(InstallCodeMirror);
    
    // Custom name: <customName />
    // app.use(InstallCodeMirror, { componentName: "customName" });
    
    app.mount("#app");
  4. Create and use a custom theme

    main

    You can create custom themes for the CodeMirror editor by defining CSS styles and applying the theme name via the onReady event.

    To implement a custom theme:

    1. Define CSS Styles: Create CSS rules using the .cm-s-[theme-name].CodeMirror selector. It is recommended to use CSS variables for colors to simplify maintenance.
    2. Apply the Theme: Use the onReady callback to call cm.setOption('theme', 'your-theme-name').

    Important: The theme name you pass to setOption must match the suffix used in your CSS class (e.g., if your CSS class is .cm-s-my-theme.CodeMirror, your theme name is my-theme).

    <template>
      <Codemirror
        :options="cmOptions"
        @ready="onReady"
        v-model:value="code"
      />
    </template>
    
    <script lang="ts">
    import { defineComponent, ref } from "vue";
    import { Editor } from "codemirror";
    import Codemirror from "codemirror-editor-vue3";
    
    export default defineComponent({
      components: { Codemirror },
      setup() {
        const code = ref("// your code");
        const cmOptions = { mode: "javascript", lineNumbers: true };
    
        const onReady = (cm: Editor) => {
          // 'ctp-mocha' matches the CSS class .cm-s-ctp-mocha
          cm.setOption("theme", "ctp-mocha");
        };
    
        return { code, cmOptions, onReady };
      },
    });
    </script>
    
    <style>
    /* Define the theme using the .cm-s-[name] pattern */
    .cm-s-ctp-mocha.CodeMirror {
      --primary-bg: #1e1e2e;
      --fg: #cdd6f4;
    }
    
    .cm-s-ctp-mocha.CodeMirror, 
    .cm-s-ctp-mocha .CodeMirror-gutters {
      background-color: var(--primary-bg);
      color: var(--fg);
    }
    
    /* Syntax highlighting example */
    .cm-s-ctp-mocha span.cm-keyword {
      color: #f38ba8;
    }
    </style>
  5. Enable TypeScript support for codemirror-editor-vue3

    main

    To use TypeScript with codemirror-editor-vue3, you must ensure your project is configured for TypeScript and install the @types/codemirror package to provide type definitions for the underlying CodeMirror instance and its configuration. It is also recommended to use the Volar extension in your IDE for improved template type checking and prompts.

    npm install @types/codemirror -D
    # or
    yarn add @types/codemirror
    # or
    pnpm i @types/codemirror -D
  6. Use Codemirror in Vue 3 components

    main

    To use the editor, import Codemirror and use it in your template. You can bind the editor content using v-model:value and pass configuration via the :options prop.

    To enable syntax highlighting, you must manually import the specific Codemirror mode (e.g., import "codemirror/mode/javascript/javascript.js").

    Key Features:

    • v-model:value: Two-way binding for the editor content.
    • :options: An object of type EditorConfiguration for Codemirror settings.
    • Events: Supports @change, @input, and @ready.
    • Ref Access: Use a template ref to access the component instance for methods like .refresh(), .resize(), and .destroy().
    <template>
      <Codemirror
        v-model:value="code"
        :options="cmOptions"
        border
        ref="cmRef"
        height="400"
        width="600"
        @change="onChange"
        @input="onInput"
        @ready="onReady"
      />
    </template>
    
    <script lang="ts" setup>
    import { ref, onMounted, onUnmounted } from "vue";
    import "codemirror/mode/javascript/javascript.js";
    import Codemirror from "codemirror-editor-vue3";
    import type { CmComponentRef } from "codemirror-editor-vue3";
    import type { Editor, EditorConfiguration } from "codemirror";
    
    const code = ref("var i = 0;");
    const cmRef = ref<CmComponentRef>();
    const cmOptions: EditorConfiguration = {
      mode: "text/javascript",
    };
    
    const onChange = (val: string, cm: Editor) => {
      console.log(val, cm.getValue());
    };
    
    const onInput = (val: string) => {
      console.log(val);
    };
    
    const onReady = (cm: Editor) => {
      cm.focus();
    };
    
    onMounted(() => {
      // Example: Refreshing the editor instance
      cmRef.value?.refresh();
      // Example: Resizing the editor
      cmRef.value?.resize(300, 200);
    });
    
    onUnmounted(() => {
      // Cleanup
      cmRef.value?.destroy();
    });
    </script>
  7. Obtain the CodeMirror editor instance via component ref

    main

    To perform direct operations on the editor content (such as select, insert, or collapse), you can access the underlying CodeMirror Editor instance through the component's ref.

    Important: Because the editor instance is initialized asynchronously, you must access cmComponentRef.value.cminstance within the onMounted lifecycle hook or inside a nextTick callback to ensure the instance is available.

    <template>
      <Codemirror
        ref="cmComponentRef"
        v-model:value="code"
        :options="cmOptions"
      />
    </template>
    
    <script lang="ts">
    import { ref, onMounted, nextTick } from "vue";
    import Codemirror, { CmComponentRef } from "codemirror-editor-vue3";
    import type { Editor, EditorConfiguration } from "codemirror";
    
    export default {
      components: { Codemirror },
      setup() {
        const code = ref(`const ary = []`);
        const cmComponentRef = ref<CmComponentRef>(null);
        const cminstance = ref<Editor>();
    
        const cmOptions: EditorConfiguration = {
          mode: "javascript",
        };
    
        onMounted(() => {
          // Access the cminstance property from the component ref
          cminstance.value = cmComponentRef.value?.cminstance;
          cminstance.value?.focus();
        });
    
        // Alternatively, use nextTick
        nextTick(() => {
          cminstance.value = cmComponentRef.value?.cminstance;
          cminstance.value?.focus();
        });
    
        return { cmComponentRef, code, cmOptions };
      },
    };
    </script>
  8. Install codemirror-editor-vue3

    main

    Install the codemirror-editor-vue3 package along with codemirror version 5.

    If you are using TypeScript, you must also install the @types/codemirror type definitions as a development dependency.

    # npm
    npm install codemirror-editor-vue3 codemirror@^5 -S
    npm install @types/codemirror -D
    
    # yarn
    yarn add codemirror-editor-vue3 codemirror@">=5.64.0 <6"
    yarn add @types/codemirror
    
    # pnpm
    pnpm i codemirror-editor-vue3 codemirror@^5 -S
    pnpm i @types/codemirror -D
  9. Use Custom Log Mode (`mode: "fclog"`)

    main

    Custom log mode (fclog) is designed for logs that include both a timestamp and an output type automatically. This mode uses the createLog helper function instead of createLogMark.

    To enable this mode, set mode: "fclog" in your cmOptions object.

    <template>
      <Codemirror v-model:value="code" :options="cmOptions" border :height="400" />
    </template>
    
    <script>
    import { ref, defineComponent } from "vue";
    import Codemirror, { createLinkMark, createLog, createTitle } from "codemirror-editor-vue3";
    
    export default defineComponent({
      components: { Codemirror },
      setup() {
        const code = ref(`Complete log download address: ${createLinkMark({
          href: "/logDownload",
          download: "",
          target: "_blank",
        })}
    
    ${createTitle("Logs with time nodes and output types")}
    ${createLog("info content", "info")}
    ${createLog("warning content", "warning")}
    ${createLog("error content", "error")}
    `);
        const cmOptions = {
          mode: "fclog",
          theme: "default",
        };
        return { code, cmOptions };
      },
    });
    </script>
  10. Perform code syntax checking (linting)

    main

    The codemirror-editor-vue3 component supports code syntax checking (linting) for specific languages, such as js and json. This allows the editor to highlight syntax errors or warnings directly within the editor interface.

    Note: The specific implementation details for linting depend on the underlying CodeMirror extensions being passed to the component. The documentation indicates that js and json are currently supported use cases for this feature.

  11. Use Simple Log Mode (`mode: "log"`)

    main

    Simple log mode is used for displaying logs where you manually flag specific lines with an output type (info, warning, or error). In this mode, words starting with a capital letter are shown in red by default. You use helper functions like createLogMark to inject log metadata into your text string.

    To enable this mode, set mode: "log" in your cmOptions object.

    <template>
      <Codemirror v-model:value="code" :options="cmOptions" border :height="400" />
    </template>
    
    <script>
    import { ref, defineComponent } from "vue";
    import Codemirror, { createLinkMark, createLogMark, createTitle } from "codemirror-editor-vue3";
    
    export default defineComponent({
      components: { Codemirror },
      setup() {
        const code = ref(`Complete log download address: ${createLinkMark({
          href: "/logDownload",
          download: "",
          target: "_blank",
        })}
    ${createTitle("You can mark the output type of each log row")}
    ${createLogMark("2021-08-26 15:07:09: job is success", "info")}
    ${createLogMark("2021-08-26 15:07:09: job is success", "warning")}
    ${createLogMark("2021-08-26 15:07:09: job is error", "error")}
    `);
        const cmOptions = {
          mode: "log",
          theme: "default",
        };
        return { code, cmOptions };
      },
    });
    </script>
  12. Configure language modes in Codemirror

    main

    To enable syntax highlighting for a specific language, you must perform two steps:

    1. Import the language pack: Import the corresponding JavaScript file from the codemirror/mode/... directory.
    2. Set the mode option: Pass the language identifier string to the mode property within the options object passed to the <Codemirror> component.

    Supported language modes follow the CodeMirror 5 specification. For a full list of available modes, refer to the CodeMirror 5 mode index.

    <template>
      <Codemirror v-model:value="code" :options="cmOptions" />
    </template>
    
    <script setup>
    import { ref } from "vue";
    import Codemirror from "codemirror-editor-vue3";
    // 1. Import the language pack
    import "codemirror/mode/javascript/javascript.js";
    
    const code = ref("var i = 0;");
    
    // 2. Set the mode in options
    const cmOptions = {
      mode: "text/javascript",
    };
    </script>