Search code examples
cssangulartypescriptcodemirrorngx-codemirror

CodeMirror Line-Break doesn't add line number - Angular


I'm using code mirror from ngx-codemirror. I want to split the line when it fits to the width of the parent. I have found some solutions to split the like using,

lineWrapping: true

and in styles

.CodeMirror-wrap pre {
  word-break: break-word;
}

Using this I was able to split the line but I need to show the line number too. The line number is not shown for the line that was just split. This is the stackblitz link to my issue : code-mirror-line-break-issue

Screenshot : enter image description here

Please help me with this.


Solution

  • This is not feasible using Code Mirror options, as this is something that is a bit counter intuitive that is rarely (ever?) wanted.

    Like I said in my comment, say 2 persons discussing on a phone/web chat about a piece of code/json. They will not see the same thing when one mentions a line number to the other if they have different windows/screen sizes

    Solution

    As a hack, you can create your own elements representing line numbers and place them over the default line numbers.

    Here is the stackblitz demo

    Note: This a a very basic example. If you change code mirror settings (font size, gutters,...), you might need to tweak the css or do more calculation based on these settings.

    component.html

    <div class='codeMirrorContainer'>
      <ngx-codemirror
          #codeMirror
          [options]="codeMirrorOptions"
          [(ngModel)]="codeObj"
        ></ngx-codemirror>
    
    <ul class='lineContainer' [style.top.px]="-topPosition">
      <li [style.width.px]='lineWidth' *ngFor="let line of lines">{{line}}</li>
    </ul>
    </div>
    

    component.css

    li
    {
      height: 19px;
      list-style: none;
    }
    
    .codeMirrorContainer
    {
      position:relative;
      overflow: hidden;
    }
    
    .lineContainer
    {
      position:absolute;
      top:0;
      left:0;
      margin: 0;
        padding: 5px 0 0 0;
      text-align: center;
      
    }
    
    ::ng-deep .CodeMirror-linenumber
    {
      visibility: hidden; /* Hides default line numbers */
    }
    

    component.ts

    export class AppComponent
    {
    
    
      @ViewChild('codeMirror') codeMirrorCmpt: CodemirrorComponent;
    
      private lineHeight: number;
      public lineWidth;
    
      public topPosition: number;
      public lines = [];
    
      codeMirrorOptions: any = ....;
      codeObj :any = ...;
    
      constructor(private cdr: ChangeDetectorRef)
      {
      }
    
    
    
      ngAfterViewInit()
      {
        this.codeMirrorCmpt.codeMirror.on('refresh', () => this.refreshLines());
        this.codeMirrorCmpt.codeMirror.on('scroll', () => this.refreshLines());
        setTimeout(() => this.refreshLines(), 500)
    
      }
    
    
      refreshLines()
      {
        let editor = this.codeMirrorCmpt.codeMirror;
        let height = editor.doc.height;
        this.lineHeight = editor.display.cachedTextHeight ? editor.display.cachedTextHeight : this.lineHeight;
        if (!this.lineHeight)
        {
          return;
        }
        let nbLines = Math.round(height / this.lineHeight);
        this.lines = Array(nbLines).fill(0).map((v, idx) => idx + 1);
        this.lineWidth = editor.display.lineNumWidth;
        this.topPosition = document.querySelector('.CodeMirror-scroll').scrollTop;
        this.cdr.detectChanges();
    
      }
    
    
    }