Closed jyotirmaybarman closed 1 year ago
Got it working by creating this plugin.
import { defineNuxtPlugin } from '#app';
import hljs from 'highlight.js';
import mdit from 'markdown-it';
import sub from 'markdown-it-sub';
import sup from 'markdown-it-sup';
import fn from 'markdown-it-footnote';
import emo from 'markdown-it-emoji';
import def from 'markdown-it-deflist';
import ins from 'markdown-it-ins';
import container from 'markdown-it-container';
const markdownit = new mdit({
html: true,
xhtmlOut: false,
breaks: false,
langPrefix: 'language-',
linkify: true,
typographer: true,
quotes: '“”‘’',
highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return '<pre class="hljs"><code>' +
hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
'</code></pre>';
} catch (error) {console.log(error)}
}
return '<pre class="hljs"><code>' + mdit.utils.escapeHtml(str) + '</code></pre>';
}
})
.use(sub)
.use(sup)
.use(fn)
.use(emo)
.use(def)
.use(ins)
.use(container,'codeblock',{marker:'@'});
markdownit.linkify.set({ fuzzyEmail: false });
export default defineNuxtPlugin(nuxtApp => {
nuxtApp.provide('mdit',markdownit);
});
Hello,
Can you provide a way to use the plugin in a .vue file ? I've created a file markdownit.client.ts in /plugins and $md doesnot seems to work
[Vue warn]: Property "$md" was accessed during render but is not defined on instance. Cannot read property 'render' of undefined
You can access it by useNuxtApp().$md
For a working example you may look here...!!
https://github.com/jyotirmaybarman/nuxt3-tailwind-pinia/blob/main/components/MarkdownEditor.vue
Work for me ! The plugin file should be a javascript file (and not a *.ts file as I was doing)
Below, a working sample with an API call to strapi4 in nuxt3 API call is a GET on a Page Entity which has some markdown in data.attributes.contenu
<template>
<div>
<main class="content">
<div
v-if="page.data.id"
id="editor"
v-html="nuxtApp.$mdit.render(page.data.attributes.contenu)"
/>
</main>
</div>
</template>
<script lang="ts" setup>
import type { Strapi4Response } from "@nuxtjs/strapi";
const props = defineProps(["IDPage"]);
const { findOne } = useStrapi4();
const nuxtApp = useNuxtApp()
const page = await findOne<Strapi4Response<Page>>("pages", props.IDPage);
</script>
@jyotirmaybarman Thanks for providing the plugin. It's works fine for me, except on page reload it weirdly instantly vanishes for some reason do you may have any pointers where i could look at?
@nevotheless Sorry for this late reply, hope you have found a solution for your issue.
Unfortunately not but I have found out that my issue is not tied to markdownit.
@nevotheless maybe there is some problem with your data fetching, maybe you should try different ways to fetch data in different lifecycle hooks.
ty for the advice, i came to the same conclusion but i didn't really fiddle with it ever since. It demotivated me too much 😅
Hi, Any update for this? @nuxtjs/markdownit still maintained?
The solution that worked for me in Nuxt 3 RC
1- install package npm install markdown-it
2- within your Vue Single File component ref your markdown
a- add to the script
import md from "markdown-it";
b- in the script, create a rendererconst renderer = md();
3- in the component template, use it in a dev like
<div
class="max-w-2xl mx-auto p-4"
v-html="renderer.render(articleContent)"
></div>
define articleContent
is the markdown you want to render using a data fetching method
const articleContent = await $fetch('/api/blog/' + slug);
thats it, no edits to nuxt.config required it works
in this example, the class is using tailwind; if you use tailwind, you can also use the typography plugin, which is recommended
npm install -D @tailwindcss/typography
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./components/**/*.{js,vue,ts}",
"./layouts/**/*.vue",
"./pages/**/*.vue",
"./plugins/**/*.{js,ts}",
],
plugins: [
require('@tailwindcss/typography'),
],
}
credits: Mounir Younes
Add markdown renderer as a nuxt plugin:
yarn add -D markdown-it @types/markdown-it
plugins/markdownit.ts
import md from "markdown-it";
export default defineNuxtPlugin(() => { const renderer = md(); return { provide: { mdRenderer: renderer, }, }; });
4. In template:
```vue
<script setup lang="ts">
const markdownString = "# Markdwon-it in Nuxt3"
</script>
<template>
...
<section
class="prose prose-gray text-sm"
v-html="$mdRenderer.render(markdownString)"
/>
...
</template>
import md from "markdown-it"; export default defineNuxtPlugin(() => { const renderer = md(); return { provide: { mdRenderer: renderer, }, }; });
Hi I try your answer and get this
Expected 1 arguments, but got 0.ts(2554) module.d.ts(22, 35): An argument for 'moduleOptions' was not provided.
md need to pass some configuration,,, do you know what I should use?
Thanks
@wvovaw are you using a specific version of markdown-it ? When I add it to my modules in nuxt config upon running dev I get the error that @types/markdown-it nuxt module should be a function
and nuxt won't run.
@mickeyvanolst @Kowiste
Here is what I have in the Package.json:
"@types/markdown-it": "^12.2.3",
"markdown-it": "^13.0.1",
"nuxt": "3.1.0",
Markdown-it package and its declarations package hasn't been updating for ~10 months so I'm up to date. I started the project from nuxt@3.0.0 version and since then markdown-it worked perfectly.
P.S. I just upgraded my nuxt version to nuxt@3.2.3 and everything is still ok.
Here is the code snippet from the project:
// @/plugins/markdownit.ts
import md from "markdown-it";
export default defineNuxtPlugin(() => {
const renderer = md();
return {
provide: {
mdRenderer: renderer,
},
};
});
<!-- @/components/strapi_components/blocks/RichText.vue -->
<script lang="ts" setup>
const props = defineProps({
block: {
type: Object,
required: true,
},
});
onBeforeMount(() => {
!["content"].every((propName) => props.block.hasOwnProperty(propName))
? console.error(`RichText.vue has not pass the block property validation`)
: null;
});
</script>
<template>
<div class="container mx-auto grid place-content-center">
<div
class="prose-xl border border-gray-300 prose-blue prose-pre:bg-zinc-300 prose-pre:text-gray-800 text-sm m-5 p-5 bg-gray-100 shadow-xl rounded-2xl"
v-html="$mdRenderer.render(block.content)"
/>
</div>
</template>
There's no need to register the plugin, nuxt does it for you.
When I add it to my modules in nuxt config
Do not do that because markdown-it package is not a nuxt module. Just install the package, create a plugin file, provide md().renderer and that's it!
@wvovaw you're a hero! Works like charm 👍
Thanks @wvovaw
It put this here, probably someone need target="_blank" or other attributes:
import md from "markdown-it";
import markdownItAttrs from "markdown-it-attrs";
export default defineNuxtPlugin(() => {
const renderer = md();
renderer.use(markdownItAttrs)
return {
provide: {
mdRenderer: renderer,
},
};
});
@wvovaw super elegant solution doesn't work for me, inside RichText component I have this weird typescript error :
Property '$mdRenderer' does not exist on type '{ $: ComponentInternalInstance; $data: {}; $props: { style?: unknown; key?: string | number | symbol | undefined; ref?: VNodeRef | undefined; ref_for?: boolean | undefined; ... 8 more ...; readonly block: Record<...>; }; ... 10 more ...; $watch<T extends string | ((...args: any) => any)>(source: T, cb: T extends (.....'.ts(2339)
And in browser : Cannot read properties of undefined (reading 'render')
Would anyone be able to point me in the right direction on what have I done wrong ?
Thanks @wvovaw, this is much cleaner than what I had been using.
This is how I got working syntax highlighting if anyone else lands at this page.
yarn add markdown-it-highlightjs
// @/plugins/markdownit.ts
import md from 'markdown-it'
import markdownItHighlightjs from 'markdown-it-highlightjs'
export default defineNuxtPlugin(() => {
const renderer = md()
renderer.use(markdownItHighlightjs)
return {
provide: {
mdRenderer: renderer,
},
}
})
<template>
...
</template>
<script setup>
import hljs from 'highlight.js'
import 'highlight.js/styles/nord.css'
onMounted(() => {
hljs.highlightAll()
})
</script>
@wvovaw Been trying to get this to work for a while now. You're truly amazing! A million thanks!
Thanks for the solutions, everyone! I'm going to track Nuxt 3 support here: https://github.com/nuxt-community/markdownit-module/issues/67
I've linked the solution in here as an alternative.
@wvovaw Thanks for the solution, it still work for my nuxt project version:
"nuxt": "^3.8.0",
and current version of markdown-it
"@types/markdown-it": "^13.0.7",
"markdown-it": "^13.0.2",
@mickeyvanolst @Kowiste
Here is what I have in the Package.json:
"@types/markdown-it": "^12.2.3", "markdown-it": "^13.0.1", "nuxt": "3.1.0",
Markdown-it package and its declarations package hasn't been updating for ~10 months so I'm up to date. I started the project from nuxt@3.0.0 version and since then markdown-it worked perfectly.
P.S. I just upgraded my nuxt version to nuxt@3.2.3 and everything is still ok.
Here is the code snippet from the project:
// @/plugins/markdownit.ts import md from "markdown-it"; export default defineNuxtPlugin(() => { const renderer = md(); return { provide: { mdRenderer: renderer, }, }; });
<!-- @/components/strapi_components/blocks/RichText.vue --> <script lang="ts" setup> const props = defineProps({ block: { type: Object, required: true, }, }); onBeforeMount(() => { !["content"].every((propName) => props.block.hasOwnProperty(propName)) ? console.error(`RichText.vue has not pass the block property validation`) : null; }); </script> <template> <div class="container mx-auto grid place-content-center"> <div class="prose-xl border border-gray-300 prose-blue prose-pre:bg-zinc-300 prose-pre:text-gray-800 text-sm m-5 p-5 bg-gray-100 shadow-xl rounded-2xl" v-html="$mdRenderer.render(block.content)" /> </div> </template>
There's no need to register the plugin, nuxt does it for you.
When I add it to my modules in nuxt config
Do not do that because markdown-it package is not a nuxt module. Just install the package, create a plugin file, provide md().renderer and that's it!
May I ask how to add plugins to markdown-it
? -- the chained .use(xxx).use(xxx)
thing?
@xarthurx I'm not sure, but try this
// @/plugins/markdownit.ts
import md from "markdown-it";
import { plugin } from "some-markdown-it-plugin";
export default defineNuxtPlugin(() => {
const renderer = md().use(plugin);
return {
provide: {
mdRenderer: renderer,
},
};
});
BTW I'd recommend you to go with nuxt content for now for markdown powered websites.
@xarthurx I'm not sure, but try this
// @/plugins/markdownit.ts import md from "markdown-it"; import { plugin } from "some-markdown-it-plugin"; export default defineNuxtPlugin(() => { const renderer = md().use(plugin); return { provide: { mdRenderer: renderer, }, }; });
BTW I'd recommend you to go with nuxt content for now for markdown powered websites.
I tried, very hard. But the system is not mature when I need some plugins to do a bit of customized stuff... There're not a lot of documentation about customizing it, so I decided to come back to markdown-it.
It is incompatible with latest nuxt 3 beta ...!!