Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow async engine.render in converter #540

Merged
merged 1 commit into from
Aug 14, 2023

Conversation

GuillaumeDesforges
Copy link
Contributor

Related to discussion https://github.com/orgs/marp-team/discussions/466

The whole context is async already, but the engine.render method is not treated as possibly async.
Using await here allows to use either non-async and async render method, which is helpful for custom engines.

@GuillaumeDesforges
Copy link
Contributor Author

The following marp.config.mjs works for me as expected:

import { Marp } from "@marp-team/marp-core"


async function marpMermaidPlugin(md) {
    // special render for mermaid fence code blocks
    const { fence } = md.renderer.rules
    md.renderer.rules.fence = (tokens, idx, options, env, self) => {
        const info = md.utils.unescapeAll(tokens[idx].info).trim()
        if (info) {
            const [_, lang, divOptions] = info.match(/(\w+)\s*(?:\{\s*(.+)\s*\})?/)
            if (lang == "mermaid") {
                const graphDefinition = tokens[idx].content

                // <marp-auto-scaling> is working only with Marp Core v3
                return `<p><marp-auto-scaling data-downscale-only><div class="mermaid-unprocessed">${graphDefinition}</div></marp-auto-scaling></p>`
            }
        }

        return fence.call(self, tokens, idx, options, env, self)
    }
}

class PostprocessMarpitEngine extends Marp {
    constructor(options, postprocess) {
        super(options)
        this.postprocess = postprocess
    }

    withPostprocess(postprocess) {
        this.postprocess = postprocess
        return this
    }

    async render(markdown, env = {}) {
        const { html, css, comments } = super.render(markdown, env)
        if (this.postprocess) {
            return await this.postprocess(markdown, env, html, css, comments)
        }
        return { html, css, comments }
    }
}

export default {
    engine: async (constructorOptions) =>
        new PostprocessMarpitEngine(constructorOptions)
            .use(marpMermaidPlugin)
            .withPostprocess(async (markdown, env, html, css, comments) => {
                // do things on HTML (in my case call mermaid-cli API)
                return { html, css, comments }
            }),
}

Copy link
Member

@yhatt yhatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acceptable since it does not affect the assumed return value of Marpit.prototype.render().

Warning

Marpit framework is still assuming to return the non-promise object. Remark the custom engine with returning Promise might become incompatible with other Marp/Marpit tools that strictly follow Marpit API.
https://marpit-api.marp.app/marpit#render

Marp team is still planning async render in the next-gen Marpit framework.

@yhatt yhatt merged commit 0c80836 into marp-team:main Aug 14, 2023
4 checks passed
@GuillaumeDesforges GuillaumeDesforges deleted the converter-async-render branch August 14, 2023 11:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants