Custom gutter for specific lines only?


I’d like to create a gutter which only adds line numbering for specific lines. This code (sort of) works, but is definitely wrong, since it makes too many iterations. Is there a better way to achieve my goal? Also, what do I have to return for lines for which I don’t like to add the gutter?

Thanks in advance!

const codeLines = lineNumbers({
  formatNumber (lineNo: number, state: EditorState){
    if (lineNo > state.doc.lines)
      return lineNo;

    const line = state.doc.line(lineNo);
    let tree = syntaxTree(state);

    let Pos = offsetToPos(state.doc, line.from);
    let Offset = posToOffset(state.doc, Pos);
    let bFound = false;
    syntaxTree(transaction.state).iterate({ from:line.from,,
      enter(node) {
        if ( === "HyperMD-codeblock_HyperMD-codeblock-bg"){
            bFound = true;
            return false;

    if (bFound)
      return lineNo;
    // else return nothing???

Right, you really don’t want to be doing that much work in formatNumber (or lineMarker, for that matter). The best approach here would probably be to not use lineNumbers at all, but create a custom gutter, with markers only at the lines where you need them, and only recompute them when necessary.

And that worked perfectly! Thank you!
This is almost what I wanted. The desired effect would be this (gutter at the beginning of the selected lines):
I can achieve this by setting margin-right:-14px to the gutter I created, and setting margin-right: -24px, and padding-right: -24px to cm-gutters. This however results that I can’t click anymore at the beginning of line text above or below a codeblock, because of the applied changes. Also, I probably shouldn’t mess with cm-gutters, because it could mess up other gutters. So in this case, I can’t click anymore on “test”:

I tried also to reach my goal using a widget:

class LineNumberWidget extends WidgetType {
  constructor(private lineNumber: number) {

  toDOM(view: EditorView): HTMLElement {
    const container = document.createElement("div");
    container.classList.add("gutter-container"); = "inline";
    const span = document.createElement("div");
    span.innerText = `${this.lineNumber}`;
    return container;

This works ok, but here I can delete the linenumbers (probably because since it is not a gutter), and if a line is too long and it breaks in a newline, then the line will continue below the line number.

Is there anything I can do to achieve my goal, or the current situation is the best, which is this:

Thanks in advance!

The gutter is going to have to appear next to the content, not overlaid on it (that’s just not something the gutter plugin was written for). What is that empty margin on the left of your text? Whitespace, or padding? If padding, how about just not having it and leaving space for the gutter there?

That’s just padding, as I was trying out different things with CSS. Then it stays this way. Thank you for your help!