Showdown: Feature Request: Default Classes for each HTML element type

Created on 12 Apr 2017  ยท  5Comments  ยท  Source: showdownjs/showdown

I have read the documentation and gone through some of the issues, it seems like with some effort it might be possible to make an extension that does the required job. But I feel it really makes sense to have this functionality within the core library.

A lot of people use css ui kits like bootstrap, semantic-ui, etc. And if we could pass a bindings map object like so:

const classBindings = {
  h1: '.ui.large.header',
  h2: '.ui.medium.header',
  ul: '.ui.list'
  li: '.ui.item'
}

const converter = new showdown.Converter({ classBindings });

const text = `
# 1st Heading
## 2nd Heading

- first item
- second item
`
return  converter.makeHtml(text);
md5-fd05a7646c6f05755d1f96d93ba041da




md5-46b074d4ce26d3a1c9a3fa4d4868a97f




md5-95d7f1b6bad9b1ddbbf4d2c0ff1c4bb6


Though if you think writing an extension for consuming this mappings object will be a very easy task, then could you please guide me on the same?

If possible I'd like to have the example added to the docs as well, like a recipe of sorts, so that other people can use it for bindings with any css ui kit of their choice.

And thanks so much for this wonderful library! ๐Ÿ˜

enhancement request

Most helpful comment

Actually it is very trivial to write such an extension. I can confirm that the one below does works as intended.

const showdown = require('showdown');

const classMap = {
  h1: 'ui large header',
  h2: 'ui medium header',
  ul: 'ui list',
  li: 'ui item'
}

const bindings = Object.keys(classMap)
  .map(key => ({
    type: 'output',
    regex: new RegExp(`<${key}>`, 'g'),
    replace: `<${key} class="${classMap[key]}">`
  }));

const conv = new showdown.Converter({
  extensions: [...bindings],
  noHeaderId: true // important to add this, else regex match doesn't work
});

const text = `
# 1st Heading
## 2nd Heading

- first item
- second item
`;

console.log(conv.makeHtml(text));
/**
โ€‹โ€‹โ€‹โ€‹โ€‹<h1 class="ui large header">1st Heading</h1>โ€‹โ€‹โ€‹โ€‹โ€‹
โ€‹โ€‹โ€‹โ€‹โ€‹<h2 class="ui medium header">2nd Heading</h2>โ€‹โ€‹โ€‹โ€‹โ€‹
โ€‹โ€‹โ€‹โ€‹โ€‹<ul class="ui list">โ€‹โ€‹โ€‹โ€‹โ€‹
โ€‹โ€‹โ€‹โ€‹โ€‹<li class="ui item">first item</li>โ€‹โ€‹โ€‹โ€‹โ€‹
โ€‹โ€‹โ€‹โ€‹โ€‹<li class="ui item">second item</li>โ€‹โ€‹โ€‹โ€‹โ€‹
โ€‹โ€‹โ€‹โ€‹โ€‹</ul>โ€‹โ€‹โ€‹โ€‹โ€‹
*/

You can close the issue, but as requested earlier, it would be useful for other people if this could be added to the documentation as a specific recipe.

All 5 comments

Actually it is very trivial to write such an extension. I can confirm that the one below does works as intended.

const showdown = require('showdown');

const classMap = {
  h1: 'ui large header',
  h2: 'ui medium header',
  ul: 'ui list',
  li: 'ui item'
}

const bindings = Object.keys(classMap)
  .map(key => ({
    type: 'output',
    regex: new RegExp(`<${key}>`, 'g'),
    replace: `<${key} class="${classMap[key]}">`
  }));

const conv = new showdown.Converter({
  extensions: [...bindings],
  noHeaderId: true // important to add this, else regex match doesn't work
});

const text = `
# 1st Heading
## 2nd Heading

- first item
- second item
`;

console.log(conv.makeHtml(text));
/**
โ€‹โ€‹โ€‹โ€‹โ€‹<h1 class="ui large header">1st Heading</h1>โ€‹โ€‹โ€‹โ€‹โ€‹
โ€‹โ€‹โ€‹โ€‹โ€‹<h2 class="ui medium header">2nd Heading</h2>โ€‹โ€‹โ€‹โ€‹โ€‹
โ€‹โ€‹โ€‹โ€‹โ€‹<ul class="ui list">โ€‹โ€‹โ€‹โ€‹โ€‹
โ€‹โ€‹โ€‹โ€‹โ€‹<li class="ui item">first item</li>โ€‹โ€‹โ€‹โ€‹โ€‹
โ€‹โ€‹โ€‹โ€‹โ€‹<li class="ui item">second item</li>โ€‹โ€‹โ€‹โ€‹โ€‹
โ€‹โ€‹โ€‹โ€‹โ€‹</ul>โ€‹โ€‹โ€‹โ€‹โ€‹
*/

You can close the issue, but as requested earlier, it would be useful for other people if this could be added to the documentation as a specific recipe.

Thank you @zusamann

It is indeed a great idea to add this to the cookbook, which I will do as soon as possible.

Added this to the wiki. https://github.com/showdownjs/showdown/wiki/Add-default-classes-for-each-HTML-element

Thank you very much for your contribution!!

Actually it is very trivial to write such an extension.

Is it though? I suppose the proposed solution doesn't take into account code blocks, whose content shouldn't be modified at all.

I suppose the proposed solution doesn't take into account code blocks, whose content shouldn't be modified at all.

While this is technically true since, per the HTML spec, code tags allow any phrasing content, showdown always html-encodes html tags inside code blocks (as per markdown's own specification).

This means that:

some text

    this is some<b>code</b>
    <span>block</span>

will be literally converted into:

<p>some text</p>
<pre><code>
this is some&lt;b&gt;code&lt;/b&gt;
&lt;span&gt;block&lt;/span&gt;
</code></pre>

the only way you can have proper html tags inside code tags is when HTML is present in the source/input:

<pre><code>
this is some<b>code</b>
<span>block</span>
</code></pre>

While the last case is perfectly fine and valid, it's a rather odd edge case.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jonaskello picture jonaskello  ยท  4Comments

geudrik picture geudrik  ยท  7Comments

BusyHe picture BusyHe  ยท  4Comments

buremba picture buremba  ยท  4Comments

qyvlik picture qyvlik  ยท  4Comments