jfcere/ngx-markdown

Make independent renderer

liron-navon opened this issue · 4 comments

In my use case I wish to have the following:

<markdown>{{md1}}</markdown>
<markdown>{{md2}}</markdown>

But I wish each to render differently, therefore apply a different renderer, it's currently not possible, I would like to suggest the following API:

<markdown [renderer]="renderer1">{{md1}}</markdown>
<markdown [renderer]="renderer2">{{md2}}</markdown>

@liron-navon you are right, it is not possible right now using MarkdownComponent but renderer is exposed by MarkdownService if you need this right now it could be used as a workaround.

@jfcere What do you mean? the service is a single instance, so I can only set one renderer at a time right?

You would have to pass renderer options every time, might not be ideal but passing markedOptions to MarkdownService.compile function won't override options in the service.

Would look something like the code below... from the top of my mind, it might need adjustments and it looks so boilerplate.

Don't get me wrong this is something I'm going to improve but right now this is the only workaround I can think of with the code in place.

example.component.html
<markdown [innerHTML]="compiled"></markdown>
example.component.ts
public compiled: string;

constructor(private markdownService: MarkdownService) { }

ngOnInit() {
  // custom renderer
  const myRenderer = new MarkedRenderer()
  myRenderer.heading = (text: string, level: number) => {
      const escapedText = text.toLowerCase().replace(/[^\w]+/g, '-');
      return '<h' + level + '>' +
               '<a name="' + escapedText + '" class="anchor" href="#' + escapedText + '">' +
                 '<span class="header-link"></span>' +
               '</a>' + text +
             '</h' + level + '>';
    };

  // construct markedOptions using actual MarkdownService options + custom renderer
  const markedOptions = {
    ...this.markdownService.options,
    renderer: myRenderer,
  };

  // markdown to compile
  const markdown = '### Markdown Title Example';
  const decodeHtml = true;

  // compile markdown using constructed markedOptions
  this.compiled = this.markdownService.compile(markdown, decodeHtml, markedOptions);
}

Hello, I tried using this method to create a separate renderer. For me the custom renderer works but when adding compiled back to <markdown [innerHTML]="compiled"> the root compiler still overrides what I changed. In this case I tried to remove the p tag but it still adds it back.

const myRenderer = new MarkedRenderer()
myRenderer.paragraph = function(text) {
  return text + '\n';
};

// construct markedOptions using actual MarkdownService options + custom renderer
const markedOptions = {
  ...this.markdownService.options,
  renderer: myRenderer,
};

// markdown to compile
const markdown = this.data;
const decodeHtml = true;

// compile markdown using constructed markedOptions
this.compiled = this.markdownService.compile(markdown, decodeHtml, false, markedOptions);