X Tutup
The Wayback Machine - https://web.archive.org/web/20220323002117/https://github.com/unifiedjs/unified/discussions/162
Skip to content

Having troubles creating a plugin to manipulate a markdown syntax tree #162

Answered by ChristianMurphy
kvietcong asked this question in Q&A
Having troubles creating a plugin to manipulate a markdown syntax tree #162
Sep 25, 2021 · 1 answers · 3 replies

Hi I'm working with Next.JS right now and as apart of the static generation, I wanted to parse out some markdown. However, I wanted to do something special with the mermaid code blocks and so I'm trying to manipulate them. However, it seems that when I try running this code, the tree is not impacted and it seems the calling stops at the first level. Only "Is this even called?" and the options are logged. It seems like the transformer isn't even run. I have also tried using regular functions but that didn't help. Thanks for any help!

Current Code

const remarkFixMermaid = options => {
    console.log("Is this even called?");
    console.log(options);
    return ast => {
        console.log("IS THIS EVEN CALLED");
        visit(ast, "code", node => {
            console.log("HIIIIIII YOU MADE IT", node)
            if (node.lang === "mermaid") {
                node.type = "mermaid";
            }
            return node;
        });
    }
}

const test = unified()
        .use(remarkParse)
        .use(remarkFixMermaid, {test: "test"})
        .parse(testInput);
Example input of test
const testInput = `
# Hi there
This is a test

\`\`\`mermaid
graph TD;
A ==> B
\`\`\`
`;

Example output of test
{
    "type": "root",
    "children": [
        {
            "type": "heading",
            "depth": 1,
            "children": [
                {
                    "type": "text",
                    "value": "Hi there",
                    "position": {
                        "start": {
                            "line": 2,
                            "column": 3,
                            "offset": 3
                        },
                        "end": {
                            "line": 2,
                            "column": 11,
                            "offset": 11
                        }
                    }
                }
            ],
            "position": {
                "start": {
                    "line": 2,
                    "column": 1,
                    "offset": 1
                },
                "end": {
                    "line": 2,
                    "column": 11,
                    "offset": 11
                }
            }
        },
        {
            "type": "paragraph",
            "children": [
                {
                    "type": "text",
                    "value": "This is a test",
                    "position": {
                        "start": {
                            "line": 3,
                            "column": 1,
                            "offset": 12
                        },
                        "end": {
                            "line": 3,
                            "column": 15,
                            "offset": 26
                        }
                    }
                }
            ],
            "position": {
                "start": {
                    "line": 3,
                    "column": 1,
                    "offset": 12
                },
                "end": {
                    "line": 3,
                    "column": 15,
                    "offset": 26
                }
            }
        },
        {
            "type": "code",
            "lang": "mermaid",
            "meta": null,
            "value": "    graph TD;\n        A ==> B",
            "position": {
                "start": {
                    "line": 5,
                    "column": 1,
                    "offset": 28
                },
                "end": {
                    "line": 8,
                    "column": 4,
                    "offset": 72
                }
            }
        }
    ],
    "position": {
        "start": {
            "line": 1,
            "column": 1,
            "offset": 0
        },
        "end": {
            "line": 9,
            "column": 1,
            "offset": 73
        }
    }
}

@kvietcong sorry you ran into a spot of trouble.
Some context on the different ways to call unified:

| ........................ process ........................... |
| .......... parse ... | ... run ... | ... stringify ..........|

          +--------+                     +----------+
Input ->- | Parser | ->- Syntax Tree ->- | Compiler | ->- Output
          +--------+          |          +----------+
                              X
                              |
                       +--------------+
                       | Transformers |
                       +--------------+

source: https://github.com/unifiedjs/unified#description

unified.parse will generate a syntax tree, but do…

Replies

1 suggested answer
·
3 replies

@kvietcong sorry you ran into a spot of trouble.
Some context on the different ways to call unified:

| ........................ process ........................... |
| .......... parse ... | ... run ... | ... stringify ..........|

          +--------+                     +----------+
Input ->- | Parser | ->- Syntax Tree ->- | Compiler | ->- Output
          +--------+          |          +----------+
                              X
                              |
                       +--------------+
                       | Transformers |
                       +--------------+

source: https://github.com/unifiedjs/unified#description

unified.parse will generate a syntax tree, but does not run plugins/transformers.
If you want to do so, use something like:

const remarkFixMermaid = options => {
    return ast => {
        visit(ast, "code", node => {
            if (node.lang === "mermaid") {
                node.type = "mermaid";
            }
            return node;
        });
    }
}

const ast = unified()
        .use(remarkParse)
        .parse(testInput);

const transformedAst = unified()
        .use(remarkFixMermaid, {test: "test"})
        .run(ast);

console.log(transformedAst);

or, an equivalent solution like:

const remarkFixMermaid = options => {
    return ast => {
        visit(ast, "code", node => {
            if (node.lang === "mermaid") {
                node.type = "mermaid";
            }
            return node;
        });
    }
}

const pipeline = unified()
        .use(remarkParse)
        .use(remarkFixMermaid, {test: "test"})

const ast = pipeline.parse(testInput);

const transformedAst = pipeline.run(ast);

console.log(transformedAst);
3 replies
@kvietcong

Thanks for the help! I had a question about plugins then. They seem to manipulate the tree like my plugin does but I can chain them together. Is there any way I could modify my code to be like that? Like I'm using remark-highlight and that seems to be doing something similar to me but for all code blocks.

@ChristianMurphy

but I can chain them together

Yep, plugins can be chained together.
Transformer plugins run in the order you .use() them.

Is there any way I could modify my code to be like that?

It already can be chained with other plugins.
Is there something more specific you are interested in?
The guides at https://unifiedjs.com/learn/ may offer some additional context and recipes.

@kvietcong

Ah I see. So the problem was that I was using parse. I could use my plugin like any other if I had done something like process. Thank you for your help!

Answer selected by kvietcong
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
🗄 area/interface
2 participants
X Tutup