quantizor / markdown-to-jsx

🏭 The most lightweight, customizable React markdown component.
https://markdown-to-jsx.quantizor.dev/
MIT License
1.97k stars 169 forks source link

Supply original string for special case processing #541

Open henrymcl opened 7 months ago

henrymcl commented 7 months ago

We're developing a web platform for teachers to create questions. Often they'll create questions with blanks like this:

Markdown

The quick brown fox ________ (jump) over the lazy dog

Which is rendered as The quick brown fox ________ (jump) over the lazy dog on GitHub here but is rendered as The quick brown fox (jump) over the lazy dog using markdown-to-jsx (which is understandable, as there are no characters within the bold text).

I'd like to render the original text if there's no characters within the bold text. Currently I can set component overrides like this:

function Strong(props: any) {
    if (props.children.length) return <strong {...props} />;
    return <span>____</span>;
}

function Em(props: any) {
    if (props.children.length) return <em {...props} />;
    return <span>__</span>;
}

Nonetheless as the original text isn't provided as prop, we can't tell ________ from ********. How can we tell them apart?

quantizor commented 6 months ago

That ____ is emitting an <em> is actually a bug to me, it should be the plain text if there is nothing between the delimiters.

henrymcl commented 5 months ago

Here's some patch codes for underscores.

function checkIsAllUnderline(node: MarkdownToJSX.ParserResult): number | false {
    if (node.type === RuleType.text) return /^_+$/.test(node.text) ? node.text.length : false;
    if (node.type !== RuleType.textEmphasized && node.type !== RuleType.textBolded) return false;
    let count = 0;

    for (let n of node.children) {
        const c = checkIsAllUnderline(n);
        if (c) count += c;
        else return false;
    }
    return count + (node.type === RuleType.textEmphasized ? 2 : 4);
}

renderRule(next, node, renderChildren, state) {
    if (node) {
        // @ts-expect-error
        if (node.type === RuleType.gfmTask) return node.completed ? `[x]` : `[]`;
        const count = checkIsAllUnderline(node);
        if (count) {
            return Array.from({ length: count }, () => '_').join('');
        }
    }
    return next();
}

I get Cannot access ambient const enums when 'isolatedModules' is enabled. all over the place but it otherwise works for outputting _s.

henrymcl commented 3 months ago

That piece of code will generate issues like changing

**A
B
C**

to

**A
B
C__

so it isn't perfect by all means