0

I'm trying to write a custom plugin for underline support ( with ~the underlined text~ syntax ) in react-markdown ( remark ) and the problem is the result uses div tag instead of ins.

here is the plugin:

const UNDERLINE_REGEX = /~(.*)~/g;

const extractPosition = (string, start, end) => {
    const startLine = string.slice(0, start).split("\n");
    const endLine = string.slice(0, end).split("\n");

    return {
        start: {
            line: startLine.length,
            column: startLine[startLine.length - 1].length + 1,
        },
        end: {
            line: endLine.length,
            column: endLine[endLine.length - 1].length + 1,
        },
    };
};

const extractText = (string, start, end) => ({
    type: "text",
    value: string.slice(start, end),
    position: extractPosition(string, start, end),
});

const underlinePlugin = () => {
    function transformer(tree) {
        console.log(tree);
        visit(tree, "text", (node, position, parent) => {
            const definition = [];
            let lastIndex = 0;

            const matches = node.value.matchAll(UNDERLINE_REGEX);

            for (const match of matches) {
                const value = match[1];
                const type = "underline";
                const tagName = "ins";

                if (match.index !== lastIndex) {
                    definition.push(
                        extractText(node.value, lastIndex, match.index)
                    );
                }

                definition.push({
                    type,
                    tagName,
                    children: [
                        extractText(
                            node.value,
                            match.index + 1, // 1 is start ~
                            match.index + value.length + 1 // 1 is start ~
                        ),
                    ],
                    position: extractPosition(
                        node.value,
                        match.index,
                        match.index + value.length + 2 // 2 is start and end ~
                    ),
                });

                lastIndex = match.index + value.length + 2; // 2 is start and end ~
            }

            if (lastIndex !== node.value.length) {
                const text = extractText(
                    node.value,
                    lastIndex,
                    node.value.length
                );
                definition.push(text);
            }

            const last = parent.children.slice(position + 1);
            parent.children = parent.children.slice(0, position);
            parent.children = parent.children.concat(definition);
            parent.children = parent.children.concat(last);
        });
    }

    return transformer;
};

Here is the Markdown usage:

<ReactMarkdown
        remarkPlugins={[plugin]}
        components={{
            ins: ({ value }) => <ins>{value}</ins>,
            underline: ({ value }) => <ins>{value}</ins>,
        }}>
        ~Hello~, **world**!
    </ReactMarkdown>

And here is the result

I used type: 'underline', type: 'ins', tagName: 'underline', 'tagName: 'ins', but none of them works. I don't know what am I doing wrong here.

Thank you for your time :)

James Z
  • 12,209
  • 10
  • 24
  • 44
amdigbari
  • 21
  • 3

1 Answers1

0

The remark markdown processor supports the CommonMark specification which does not include support for ins or del tags. The react-markdown component is, presumably, subject to the CommonMark limitation (Why no underline?).

ScottWelker
  • 1,701
  • 17
  • 30