pngwn / MDsveX

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

Import markdown into svx #247

Closed janosh closed 3 years ago

janosh commented 3 years ago

Could MDsveX add support for importing markdown files into .svx files?

Would allow for deduplication in a lot of docs sites, I imagine, if you could do

<script>
  import Readme from '../readme.md'
</script>

<Readme />

## More markdown

Foo bar.
pngwn commented 3 years ago

If you allow mdsvex to handle markdown files as well in the config then this already works.

janosh commented 3 years ago

I tried that but couldn't get it to work. Which config are you referring to?

preprocess: mdsvex({ extension: `.md` })
preprocess: mdsvex({ extension: [`.md`, `.svx`] })
preprocess: mdsvex({ extensions: [`.md`, `.svx`] })

All of the above gave me

Failed to parse source for import analysis because the content contains invalid JS syntax. You may need to install appropriate plugins to handle the .md file format.

pngwn commented 3 years ago

Yeah, this would actually need to be a bundler plugin of some description for it to work. I'll put together an example, or maybe I'll just publish a rollup plugin as part of the package to make this easier.

A simple way to make it work would be to add md as an extension for the svelte compiler.

janosh commented 3 years ago

Forgot to mention, I tried that as well. Trying this with a SvelteKit site, so the config I wrote looks like this:

import adapter from '@sveltejs/adapter-static'
import { mdsvex } from 'mdsvex'
import marked from 'marked'

export default {
  extensions: [`.svelte`, `.svx`, `.md`],
  preprocess: [markdown(), mdsvex()],
  kit: {
    adapter: adapter(),

    // hydrate the <body> element in src/app.html
    target: `body`,
  },
}

function markdown() {
  return {
    name: `markdown`,
    transform(content, filename) {
      if (filename.endsWith(`.md`)) {
        content = marked(content)
        return {
          code: `export default ${JSON.stringify(content)}`,
        }
      } else return null
    },
  }
}

which throws

Unexpected block closing tag
ParseError: Unexpected block closing tag
    at error (node_modules/svelte/compiler.js:16752:20)
    at Parser$1.error (node_modules/svelte/compiler.js:16828:10)
    at mustache (node_modules/svelte/compiler.js:16352:21)
    at new Parser$1 (node_modules/svelte/compiler.js:16787:22)
    at parse$3 (node_modules/svelte/compiler.js:16919:21)
    at compile (node_modules/svelte/compiler.js:30012:18)
    at compileSvelte (node_modules/@sveltejs/vite-plugin-svelte/dist/index.js:246:48)
    at async TransformContext.transform (node_modules/@sveltejs/vite-plugin-svelte/dist/index.js:829:27)
    at async Object.transform (node_modules/vite/dist/node/chunks/dep-2c03f3f9.js:43780:30)
    at async transformRequest (node_modules/vite/dist/node/chunks/dep-2c03f3f9.js:59429:29)
pngwn commented 3 years ago

Try this:

import adapter from '@sveltejs/adapter-static'
import { mdsvex } from 'mdsvex'

export default {
  extensions: ['.svelte', '.svx', '.md'],
  preprocess: mdsvex({ extensions: ['.md', '.svx'] }),
  kit: {
    adapter: adapter(),
    target: 'body',
  },
}
janosh commented 3 years ago

That worked! Thanks a lot for your help!

Would you accept a PR that documents this feature somewhere? How about under https://mdsvex.pngwn.io/docs#extension?

Maybe this:

To import markdown files as components, add .md to both the Svelte compiler and mdsvex extensions:

// svelte.config.js
import { mdsvex } from 'mdsvex'

export default {
  extensions: ['.svelte', '.svx', '.md'],
  preprocess: mdsvex({ extensions: ['.md', '.svx'] }),
}

Then you can do

<script>
  import Readme from '../readme.md'
</script>

<Readme />
pngwn commented 3 years ago

Yes, that would be very welcome. Thank you.