pngwn / MDsveX

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

Image Size #611

Open ariefsn opened 3 months ago

ariefsn commented 3 months ago

Hi, Is it possible to customize the image size width/height?

Thanks, 🙏🏻

PeppeL-G commented 3 months ago

What do you mean? That MDsveX would automatically scale the image files when building the project? Or do you simply want to add width and height attributes to the <img> element the markdown syntax ![Alt text](Image url) is mapped to? Or what do you mean?

ariefsn commented 3 months ago

What do you mean? That MDsveX would automatically scale the image files when building the project? Or do you simply want to add width and height attributes to the <img> element the markdown syntax ![Alt text](Image url) is mapped to? Or what do you mean?

Yes, right now I use the <img> to set w/h, just wondering if can set it with the markdown syntax. Or need to use <img> directly?

PeppeL-G commented 3 months ago

MDsveX is built on Unified, which uses remark for parsing Markdown, which in turn supports CommonMark. CommonMark does not support setting the image width/height in Markdown, so using HTML directly is the easiest way to go.

However, adding support for what you want is not very hard using the remark-directive plugin to support general Markdown text directives, and then you also add your own plugin to instruct Markdown how these text directives should be mapped to HTML.

To turn this:

Hi there!

How are you? Here's an image: :img[the-urlx100x200].

Nice, right?

Into this:

<p>Hi there!</p>
<p>How are you? Here's an image: <img src="the-url" width="100" height="200">.</p>
<p>Nice, right?</p>

You can use the plugin (and also remark-directive) shown below:

import { unified } from 'unified'
import remarkParse from 'remark-parse'
import rehypeStringify from 'rehype-stringify'
import { visit } from 'unist-util-visit'
import remarkDirective from 'remark-directive'
import remarkRehype from 'remark-rehype'

const doc = `
Hi there!

How are you? Here's an image: :img[the-urlx100x200].

Nice, right?
`

// This plugin turns :img[SRCxWIDTHxHEIGHT] into <img src="SRC" width="WIDTH" height="HEIGHT">
function myImgPlugin() {

    /**
     * @param {import('mdast').Root} tree
     *   Tree.
     * @param {import('vfile').VFile} file
     *   File.
     * @returns {undefined}
     *   Nothing.
     */
    return (tree, file) => {

        visit(tree, function (node){

            if(node.type === 'textDirective'){

                if(node.name !== 'img'){
                    return
                }

                // Create the data property if no
                // previous plugin has created it.
                node.data = node.data ?? {}

                // Read out the data.
                const text = node.children[0].value // "SRCxWIDTHxHEIGHT"
                const [src, width, height] = text.split('x')

                // Tell markdown how to map this text directive to HTML.
                node.data.hName = 'img'
                node.data.hProperties = {
                    src,
                    width,
                    height,
                }

                // <img> is a void element, so it should not have any children.
                node.children = []

            }

        })

    }

}

const file = await unified()
    .use(remarkParse)
    .use(remarkDirective)
    .use(myImgPlugin)
    .use(remarkRehype)
    .use(rehypeStringify)
    .process(doc)

console.log(String(file))

Just remember: