Search code examples
javascriptcssmonaco-editor

Shift the underline to the right


Following this question of marking a position between 2 characters, somebody suggested to use decoration of Monaco Editor. I tried the following code in the playground.

(* JavaScript: *)

var editor = monaco.editor.create(document.getElementById('container'), {
    value: "fg(23,)",
    language: 'javascript'
});

var decorations = editor.deltaDecorations(
    [],
    [
        {
            range: new monaco.Range(1, 6, 1, 7),
            options: { inlineClassName: 'myInlineDecoration' }
        }
    ]
);

(* CSS: *)

.myInlineDecoration {
    text-decoration: underline;
    text-decoration-style: wavy;
    text-decoration-color: red;
}

And it returned this output:

enter image description here

However,

  1. It seems that the underline returned by text-decoration-style: wavy is "more wavy" than normal underlines we often see in an editor like the yellow underlines here.

  2. It would be ideal if the underline could be shifted by 0.5 character to the right, then the position between , and ) will be underlined.

Does anyone know how to achieve this (probably by CSS)?


Solution

  • Building on @Roberto's answer, you could use the following CSS to insert content after .myInlineDecoration, set the content itself to transparent and adding an underline to it (which is visible):

    .myInlineDecoration {
       text-decoration: none; 
       position: relative; 
     }   
    
    .myInlineDecoration:after {
        text-decoration: underline;
        text-decoration-color: red;
        text-decoration-style: wavy;
        position: absolute;
        height: 1px;
        margin: 0 5px; /* adjust to move left and right */
        content: 'x';
        color: rgba(0, 0, 0, 0);
        left: 0;
        bottom: 13px; /* adjust to move up and down */
    }
    

    The Javascript is as follows:

    var editor = monaco.editor.create(document.getElementById('container'), {
        value: "fg(23,)\ngh(45,)",
        language: 'javascript'
    });
    
    var decorations = editor.deltaDecorations(
        [],
        [
            {
                range: new monaco.Range(1, 6, 1, 7),
                options: { inlineClassName: 'myInlineDecoration' }
            },
            {
                range: new monaco.Range(2, 3, 2, 4),
                options: { inlineClassName: 'myInlineDecoration' }
            }
        ]
    );
    

    I'm not convinced it's the best solution (feels quite hacky using CSS rather than relying on Monaco - but then I'm not sure how to do it solely in Monaco)