found issue with MergeView

@marijn Hello! I’m using the latest version Merge plugin with Vue3.0, the diff function seems not working well when I use YAML or XML file. two panel with same content, but it always verdict the whole b panel was changed.


image-20230224151734042
And a crush happened when I click the revert button or type in b panel ,

here is my code

<template>
  <div ref="Cm" style="width: 100%; height: 100%"></div>
</template>

<script setup lang="ts">
import { basicSetup } from 'codemirror'
import { indentWithTab } from '@codemirror/commands'
import { MergeView } from '@codemirror/merge'
import { onMounted, onBeforeUnmount, watch } from 'vue'
import { dracula } from '@ddietr/codemirror-themes/dracula'
import { keymap } from '@codemirror/view'
import { EditorState } from '@codemirror/state'
import { json, jsonParseLinter } from '@codemirror/lang-json'
import { linter, lintGutter } from '@codemirror/lint'
import { StreamLanguage } from '@codemirror/language'
import { yaml } from '@codemirror/legacy-modes/mode/yaml'

const Cm = $ref<any>()
const props = defineProps({
  oText: {
    type: String,
    required: true,
  },
  mText: {
    type: String,
    required: true,
  },
})
let eView = $ref<MergeView>()

const initEditor = () => {
  eView = new MergeView({
    a: {
      extensions: [basicSetup, dracula, EditorState.readOnly.of(true)],
      doc: props.oText,
    },
    b: {
      extensions: [
        basicSetup,
        dracula,
        keymap.of([indentWithTab]),
        // StreamLanguage.define(yaml),
        // json(),
        // linter(jsonParseLinter()),
        // lintGutter(),
      ],
      doc: props.mText,
    },
    parent: Cm,
    revertControls: 'a-to-b',
  })
}
const getDoc = () => {
  console.log(eView?.chunks)
  return eView?.b.state.doc.toString()
}

onBeforeUnmount(() => {
  eView?.destroy()
})

onMounted(() => {
  initEditor()
})

watch([() => props.mText], () => {
  eView?.b.dispatch({ changes: { from: 0, to: eView.b.state.doc.length, insert: props.mText } })
})
watch([() => props.oText], () => {
  eView?.a.dispatch({ changes: { from: 0, to: eView.a.state.doc.length, insert: props.oText } })
})
defineExpose({ getDoc })
</script>

two problem only happened with YAML and XML, other languages are fine.
please help me resolve it.

1 Like

The merge module shouldn’t interact with the language or syntax tree at all, so I’m not sure how this can be language-related. Trying to set up a merge view with XML content doesn’t show this happening for me. Can you provide an example script?

You are right, the issue is not related with language at all. I test the issue again, and find out that It would always happen as long as the content ends with a linebreak ‘\n’.

I’m not seeing anything like this happen with content that ends with a linebreak. Please provide precise (preferably minimal) example documents needed to reproduce this.

Try this content
‘[\n {\n “targets”: [\n “192.168.56.2:8080”\n ],\n “labels”: {\n “milepost”: “K123+102”\n }\n }\n]\n’

I might know why you can’t reproduce the issue. In my code above, I init these panel with two empty string, then insert this content after request. Somehow the b panel was inserted before a, then the issue show up. You can reproduce it by adding two methods below, execute test1 after test2.

const test1 = () => {
  eView?.a.dispatch({
    changes: {
      from: 0,
      to: eView.a.state.doc.length,
      insert:
        '[\n  {\n    "targets": [\n      "192.168.56.2:8080"\n    ],\n    "labels": {\n      "milepost": "K123+102"\n    }\n  }\n]\n',
    },
  })
}
const test2 = () => {
  eView?.b.dispatch({
    changes: {
      from: 0,
      to: eView.b.state.doc.length,
      insert:
        '[\n  {\n    "targets": [\n      "192.168.56.2:8080"\n    ],\n    "labels": {\n      "milepost": "K123+102"\n    }\n  }\n]\n',
    },
  })
}

My thought was It might be caused by two chunks mixing ,that panel a was inserted, and the former chunk still remain.

But still need the linebreak at the end.

https://codesandbox.io/p/sandbox/kind-davinci-4l3ivq
made a example

That helped reproduce this. This patch should fix it.

Great work, problem solved. Thx.