MurhafSousli / ngx-highlightjs

Angular syntax highlighting module

Home Page:https://ngx-highlight.netlify.app/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Allow usage outside [highlight] with `class="language-html`

muuvmuuv opened this issue · comments

Feature Description

Hey, I would like to use hightlight.js outside the [highlight] implementation in some cases. We have a code component as a wrapper for plain code (/wo hightlighting) and with highlighting and line-numbers (with ngx-highlightjs).

Unfortunately, I can only have highlighting when used as an import of the component, but not with ng-content. If ngx-hightlightjs exposed highlightjs to the window object, I could use the default implementation of class="language-html.

Sure, I would need to add those languages myself, but I would have more control and could use it elsewhere.

An alternative would be a new directive which allows ng-content inside <code>. So I could do something like this:

<pre><code [highlight]="code" [lineNumbers]="lineNumbers"><ng-content></ng-content></code></pre>

So it would always prefer the contents of "code" but if undefined use the default contents of <code>.

This is not possible with the directive, because if the code is set as the content of the element, it will be replaced with the highlighted code and when the line number is activated, it will also cause the content to change. therefore, the directive will no longer be able to react on content change

But what if I don't need content change functionallity like in a User Interface guideline where I just want to display the code of a component we use? Would like to get highlightjs for this content too without putting everything in TS variables.

This works, thanks! Anyway, a simpler API would be cool:

  @ViewChild('plain', { static: false })
  readonly plain: ElementRef<HTMLElement>

  constructor(
    private cdr: ChangeDetectorRef,
    @Inject(HIGHLIGHT_OPTIONS) private hljsOptions: HighlightOptions,
    private hljsService: HighlightJS,
    private renderer: Renderer2
  ) {}

  ngAfterViewInit(): void {
    if (!this.code) {
      this.highlightNgContent()
    }
  }

  private highlightNgContent(): void {
    const text = this.plain.nativeElement.textContent || ''
    const languages = Object.keys(this.hljsOptions.languages || {})

    this.hljsService.highlightAuto(text, languages).subscribe((response) => {
      this.setHighlightedHtml(response)

      if (this.lineNumbers) {
        this.addLineNumbers()
      }
    })
  }

  private setHighlightedHtml(response: HighlightResult): void {
    animationFrameScheduler.schedule(() => {
      this.renderer.addClass(this.plain.nativeElement, 'language-' + response.language)
      this.renderer.setAttribute(
        this.plain.nativeElement,
        'data-relevance',
        String(response.relevance)
      )
      this.renderer.setProperty(this.plain.nativeElement, 'innerHTML', response.value)
    })
  }

  private addLineNumbers(): void {
    animationFrameScheduler.schedule(() => {
      firstValueFrom(this.hljsService.lineNumbersBlock(this.plain.nativeElement))
      this.renderer.addClass(this.plain.nativeElement, 'hljs-line-numbers')
    })
  }

EDIT: updated with line-numbers