adding class with keyboard event

Hello,

I’m trying to make a block of code blinking by adding a class when I press mod-e keyboard shortcut.
To make this I’m trying to follow the Decoration example from here :
https://codemirror.net/6/examples/decoration/

First of all, the example for me is super complicated to understand and so, adapt(not the fault of the example, more because is to advanced for me).

So my question is simple, is there an easy way to add a class to the text by giving a range? With dispatch for instance?

If no I will share my code, but I’m sure is really not correct, awfull and messy so I will do that only if following the example is the only way to achieve that.

Thank you very much everyone

Guillaume

I achieve to do it by following the example… Here is the code, don’t know if there is a simple way to do it.

      const addBlink = StateEffect.define()

      const blinkField = StateField.define({
        create() {
          return Decoration.none
        },
        update(blinks, tr) {
          blinks = blinks.map(tr.changes)
          for (let e of tr.effects) if (e.is(addBlink)) {
            blinks = blinks.update({
              add: [blinkMark.range(e.value.from, e.value.to)]
            })
          }
          return blinks
        },
        provide: f => EditorView.decorations.from(f)
      })

      const blinkMark = Decoration.mark({class: "cm-blink"})

      const underlineTheme = EditorView.baseTheme({
        ".cm-blink": {  animationName: 'blink',
                        animationDuration: '1s',
                        borderRadius:'2.5px',
                      }
      })


      const blink = (view, start, end) => {
        let effects = [addBlink.of({from:start, to:end})]
          console.log(effects);
        if (!effects.length) return false

        if (!view.state.field(blinkField, false))
          effects.push(StateEffect.appendConfig.of([blinkField,
                                                    underlineTheme]))
        view.dispatch({effects})
        return true
      }


      const keyMaps = keymap.of([{
        key: "Mod-e",
        preventDefault: true,
        run: ()=>{
         // here I have a bunch of code that compute where start and end the expression regarding the cursor position
            blink(this.view, start, end)
                

        }
      }])

Now the class is added to the html element after event jeyboard, and that’s great. But I would need, to make the feature more clean and stable, to remove this class after a while (1.5sec). Do you think that in this kind of setup this is possible?

Thank you very much for your help

Guillaume

You could associate an ID with each mark, and set a timeout that fires a transaction that removes the mark with the given ID when you initially add it.

thank you for the hint, by following the reference, I attached an id like this:

      const blinkMark = Decoration.mark(
        {
          class: "cm-blink",
          attributes: {id: "blink"}
        })

But then I don’t get which kind of transaction I should do to : "removes the mark with the given ID ". Could you please give me an hint on that? Step by step I’m starting to get more familiar with the reference, but it’s still a bit complicated so, sorry if my questions looks a bit silly…

The idea is to put the id in the spec object, and use a state effect that filters out decorations with a given id from your decoration set.

thank you very much for helping me in this adventure.
I also noticed that in this part of the documentation : CodeMirror 5 to 6 Migration Guide
in the “Marked Text” part there is an example were they filter some marks, maybe I could try to follow this method also?