pngwn / MDsveX

A markdown preprocessor for Svelte.
https://mdsvex.pngwn.io
MIT License
2.35k stars 102 forks source link

feature: support props in code fence meta #289

Open jcayzac opened 3 years ago

jcayzac commented 3 years ago

remark supports the following notation:

```js foo bar baz
var x = 1
```

In the MDAST Code node, js becomes lang and foo bar baz becomes meta.

Since MDSveX allows to swap in our own components from a layout file, it would be nice to parse the meta string as props and pass them to the component. This can be done with the following plugin for remark:

import { visit } from 'unist-util-visit'
import { parse } from 'svelte-parse'

const preserveCodeProperties = tree => {
    visit(tree, 'code', node => {
        if (node.data === undefined) node.data = {}
        const { meta, lang, data } = node

        if (data.hProperties === undefined) data.hProperties = {}
        const { hProperties } = data

        if (lang) {
            hProperties.language = lang
        }

        if (meta) {
            const properties = parse({
                value: `<Foo ${meta} />`,
                generatePositions: false,
            })
            .children[0]
            .properties
            ?.map(({name, value}) => ({...value[0], name}))

            for (const property of properties) {
                const { name, expression, value: input } = property

                // Properties with no value are just truish
                let value = '{true}'

                // Input values are passes as-is
                if (input !== undefined) value = input

                // Expressions are enclosed in curly braces
                else if (expression !== undefined) value = `{${expression.value}}`

                hProperties[name] = value
            }
        }
    })
}

export default () => preserveCodeProperties
ProQuestionAsker commented 2 years ago

@jcayzac this is a cool idea! Did you end up getting it to work?

Since there seems to be no way (currently) to add custom pre or code elements, I've been unable to get this to actually pass the props anywhere useful

jcayzac commented 2 years ago

@jcayzac this is a cool idea! Did you end up getting it to work?

I literally posted my working code in the body of the issue.