codemirror / dev

Development repository for the CodeMirror editor project
https://codemirror.net/
Other
5.68k stars 361 forks source link

Conditionally-rendered block replace decoration breaks selection rendering and gutter #1406

Closed jsimonrichard closed 1 month ago

jsimonrichard commented 1 month ago

Describe the issue

I'm trying to create a block replace decoration that is not displayed when the editor selection includes that decoration's range so that the user can edit the text behind the decoration. However, this is causing some issues with the rendering of the selection and the gutter.

I've created an MRE: https://github.com/jsimonrichard/codemirror-block-deco-issue (I've included a CodeMirror sandbox link below as well).

As shown in the video below, It seems works at first, but as soon as you make an edit to the second or third line the line number next to the decoration disappears. If you try to edit the text behind the decoration, you can, but you can't see any of the selections you make. Selection still works (in the video I double click to select the word "Hello" and then hit backspace to delete the entire word) but it's not displayed. But, if you edit the text covered by the decoration, the line number comes back and selection works as normal.

https://github.com/user-attachments/assets/c2a792a2-b6bd-4b38-839e-b50c17ed55d7

Browser and platform

I've tested Brave, Chrome, and Firefox

Reproduction link

https://codemirror.net/try/?c=aW1wb3J0IHtiYXNpY1NldHVwLCBFZGl0b3JWaWV3fSBmcm9tICJjb2RlbWlycm9yIgppbXBvcnQge2phdmFzY3JpcHR9IGZyb20gIkBjb2RlbWlycm9yL2xhbmctamF2YXNjcmlwdCIKaW1wb3J0IHsgRWRpdG9yU3RhdGUsIFN0YXRlRmllbGQgfSBmcm9tICJAY29kZW1pcnJvci9zdGF0ZSIKaW1wb3J0IHsgRGVjb3JhdGlvbiwgV2lkZ2V0VHlwZSB9IGZyb20gIkBjb2RlbWlycm9yL3ZpZXciCgpjbGFzcyBNeVdpZGdldCBleHRlbmRzIFdpZGdldFR5cGUgewogIHRvRE9NKCkgewogICAgbGV0IGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiZGl2Iik7CiAgICBlbC5pbm5lckhUTUwgPSAiSGVsbG8gd29ybGQhIChpdCdzIGEgd2lkZ2V0KSI7CiAgICByZXR1cm4gZWw7CiAgfQp9Cgpjb25zdCBidWlsZERlY29zID0gKHN0YXRlKSA9PiB7CiAgY29uc3QgZGVjb3MgPSBbXTsKICBjb25zdCBsaW5lID0gc3RhdGUuZG9jLmxpbmUoMSk7CiAgCiAgaWYgKHN0YXRlLnNlbGVjdGlvbi5yYW5nZXNbMF0uZnJvbSA8IGxpbmUudG8pCiAgICByZXR1cm4gRGVjb3JhdGlvbi5ub25lOwoKICByZXR1cm4gRGVjb3JhdGlvbi5zZXQoWwogICAgRGVjb3JhdGlvbi5yZXBsYWNlKHsKICAgICAgd2lkZ2V0OiBuZXcgTXlXaWRnZXQoKSwKICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICBibG9jazogdHJ1ZSwKICAgIH0pLnJhbmdlKGxpbmUuZnJvbSwgbGluZS50byksCiAgXSk7Cn07CgpleHBvcnQgY29uc3QgZGVjb3NFeHRlbnNpb24gPSBTdGF0ZUZpZWxkLmRlZmluZSh7CiAgY3JlYXRlKHN0YXRlKSB7CiAgICByZXR1cm4gYnVpbGREZWNvcyhzdGF0ZSk7CiAgfSwKICB1cGRhdGUoZGVjbywgdHIpIHsKICAgIGlmICh0ci5zZWxlY3Rpb24gfHwgdHIuZG9jQ2hhbmdlZCkKICAgICAgZGVjbyA9IGJ1aWxkRGVjb3ModHIuc3RhdGUpOwogICAgcmV0dXJuIGRlY28ubWFwKHRyLmNoYW5nZXMpOwogIH0sCiAgcHJvdmlkZTogZiA9PiBFZGl0b3JWaWV3LmRlY29yYXRpb25zLmZyb20oZiksCn0pOwoKCm5ldyBFZGl0b3JWaWV3KHsKICBkb2M6ICJjb25zb2xlLmxvZygnaGVsbG8nKVxuIiwKICBleHRlbnNpb25zOiBbYmFzaWNTZXR1cCwgamF2YXNjcmlwdCgpLCBkZWNvc0V4dGVuc2lvbl0sCiAgcGFyZW50OiBkb2N1bWVudC5ib2R5Cn0pCg==

marijnh commented 1 month ago

I don't ever see the line number next to the widget. How are you getting in a state where that is displayed?

jsimonrichard commented 1 month ago

I'm not sure; I noticed that the number only appears when the decoration is on the first line and when the decoration is displayed conditionally (based on the selection). Also, when the decoration takes up two lines, neither of the bugs occur.

But you should be able to reproduce what I have using either of the examples I've provided. By "I don't ever see..." do you mean that my examples aren't working?

jsimonrichard commented 1 month ago

I don't know if this gives you any clues, but I wasn't able to reproduce the bug when using the bundled version of a library containing this logic. I'm using vite with this config:

// vite.config.js
...

export default defineConfig({
  ...
  build: {
    lib: {
      // Could also be a dictionary or array of multiple entry points
      entry: resolve(__dirname, 'lib/main.ts'),
      name: 'HyperMD',
      formats: ['es', 'cjs'],
      // the proper extensions will be added
      fileName: (format, entryName) => `${entryName}.${format}.js`,
    },
    rollupOptions: {
      external: [
        '@codemirror/state',
        '@codemirror/view',
        '@codemirror/commands',
        '@codemirror/language',
        '@codemirror/lang-markdown',
        '@codemirror/language-data',
        '@lezer/highlight',
      ],
    },
  },
});
marijnh commented 1 month ago

By "I don't ever see..." do you mean that my examples aren't working?

I mean I never see a line number next to the widget (and that is the expected behavior).

jsimonrichard commented 1 month ago

Hmm... maybe it's a browser specific thing (regardless, it's not a high priority for me; I don't need line numbers right now). Are you able to reproduce the other part of the bug?

marijnh commented 1 month ago

No, I'm not. I tried both Chrome and Firefox. Both seem to behave normally for selections and edits on the first line.

jsimonrichard commented 1 month ago

On this version of Chrome, I'm able to reproduce both bugs

Google Chrome   126.0.6478.126 (Official Build) (64-bit) 
Revision    d36ace6122e0a59570e258d82441395206d60e1c-refs/branch-heads/6478@{#1591}
OS  Linux
JavaScript  V8 12.6.228.21
User Agent  Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
Command Line    /usr/bin/google-chrome-stable --flag-switches-begin --flag-switches-end --origin-trial-disabled-features=ElementCapture
Executable Path /opt/google/chrome/google-chrome

Using this version of Firefox I'm able to reproduce both bugs, but only after adding a new line to the document (just adding a space won't do it). And the gutter number works as expected until the new line is added.

128.0 (64-bit)
Mozilla Firefox Snap for Ubuntu
canonical-002 - 1.0

Also, I was able to reproduce this on both Linux (Kubuntu 22.04.3 LTS x86_64) and Windows 11, so I doubt it's OS dependent.

While doing testing, I realized I missed a detail of this bug. When the decoration is not displayed (when the cursor is on the first line), the first gutter number is still not displayed. Except in firefox before a new line is added; then the gutter number appears/disappears as expected.

marijnh commented 1 month ago

Right, I can see it behaving weirdly that way. This was an update issue where some parts of the view state didn't get recomputed though they should, for decoration changes like that, even if the resulting block heights didn't change. Attached patch should help with that.

Can we close this or are you are of remaining problems?

jsimonrichard commented 1 month ago

I just verified---it's working for me now too.

That's all I had it. Thank you!