showdown icon indicating copy to clipboard operation
showdown copied to clipboard

Support for "reddit" flavor markdown

Open DenverCoder1 opened this issue 3 years ago • 0 comments

Reddit has some markdown differences and it would be nice to automatically be able to convert Reddit markdown to HTML for displaying on web pages.

Most important differences are the superscript and table syntax.

Other features would be nice but not necessary.

Reddit-specific extensions

  • Superscript — Reddit has its own syntax (^text, ^(multiple words)) Nesting is supported (one^two^three)

  • Strikethrough — Reddit's syntax is different from the GFM extension (~~strikethrough~~) (Works already when strikethrough: true is set)

  • Spoilertext — Spoilertext (>!spoiler!<) is Reddit-specific. (Can be ignored as I don't think there is standard HTML for this?) Possibly a class (eg. <span class='md-spoiler-text'>) can be used for allowing custom styling and scripts?

  • Redditlinks and userlinks — Names of subreddits and Reddit users, prefixed with /r/, r/, /u/, and u/, are automatically linked. (Not critical, but would be a cool addition) Would be similar to GitHub mention support.

  • Rich text media — Reddit supports submissions containing images, videos, and gifs, and these are encoded into the Markdown with a customized inline image syntax. This feature is only supported by the Fancy Pants editor — the syntax would be prohibitively difficult to write manually at present. (Probably not worth implementing?)

Other differences

  • Tables — Tables on reddit can have only a single dash for alignment, for example:
| **Normal** | **Center** | **Left** | **Right** |
|-|:-:|:-|-:|
| A | B | C | D |

Currently with showdown, this only becomes a table when center is written as :--:, right as --: and left as :-- or --.

| **Normal** | **Center** | **Left** | **Right** |
|--|:--:|:--|--:|
| A | B | C | D |
  • > with no space currently does not create blockquotes or support other markdown
>#Header 1
>##Header 2
>###Header 3
>####Header 4
>#####Header 5
>######Header 6

Expected: image Actual: image

  • Lists should order starting from 1
7. Item 1
2. Item 2
5. Item 3

Expected: image Actual: image

  • Bullets on same line as ordered list number
1. Ordered list item 1
2. * Bullet 1 in list item 2
    * Bullet 2 in list item 2
3. List item 3

Expected: image Actual: image


See reference: https://www.reddit.com/wiki/markdown


Current workaround

(This only solves part of the issues)

const mdConverter = new showdown.Converter({
    tables: true,
    simplifiedAutoLink: true,
    literalMidWordUnderscores: true,
    strikethrough: true,
    ghCodeBlocks: true,
    disableForced4SpacesIndentedSublists: true,
});
function redditPostToHTML(original) {
    // fix Reddit tables to have at least two dashes per cell in the alignment row
    let body = original.replace(/(?<=^\s*|\|\s*)(:?)-(:?)(?=\s*\|[-|\s:]*$)/gm, "$1--$2");
    // convert superscripts in the form "^(some text)" or "^text" to <sup>text</sup>
    const multiwordSuperscriptRegex = /\^\((.+?)\)/gm;
    while (multiwordSuperscriptRegex.test(body)) {
        body = body.replace(multiwordSuperscriptRegex, "<sup>$1</sup>");
    }
    const superscriptRegex = /\^(\S+)/gm;
    while (superscriptRegex.test(body)) {
        body = body.replace(superscriptRegex, "<sup>$1</sup>");
    }
    // convert user and subreddit mentions to links (can be /u/, /r/, u/, or r/)
    body = body.replace(/(?<=^|[^\w\/])(\/?)([ur]\/\w+)/gm, "[$1$2](/$2)");
    // add spaces after '>' to keep blockquotes (if it has '>!' ignore since that is spoilertext)
    body = body.replace(/^((?:&gt;|>)+)(?=[^!\s])/gm, function (match, p1) {
        return p1.replace(/&gt;/g, ">") + " ";
    });
    // convert markdown to HTML
    let html = mdConverter.makeHtml(body);
    // convert Reddit spoilertext
    return html.replace(
        /(?<=^|\s|>)&gt;!(.+?)!&lt;(?=$|\s|<)/gm,
        "<span class='md-spoiler-text' title='Reveal spoiler'>$1</span>"
    );
}

DenverCoder1 avatar Jul 15 '22 19:07 DenverCoder1