nuxt-community / markdownit-module

Markdownit for Nuxt 2
MIT License
48 stars 11 forks source link

Nuxt 3 Support ? #47

Closed jyotirmaybarman closed 1 year ago

jyotirmaybarman commented 3 years ago

It is incompatible with latest nuxt 3 beta ...!!

jyotirmaybarman commented 3 years 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);
});
laurentpellet commented 2 years ago

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

jyotirmaybarman commented 2 years ago

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

laurentpellet commented 2 years ago

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>
nevotheless commented 2 years ago

@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?

jyotirmaybarman commented 2 years ago

@nevotheless Sorry for this late reply, hope you have found a solution for your issue.

nevotheless commented 2 years ago

Unfortunately not but I have found out that my issue is not tied to markdownit.

jyotirmaybarman commented 2 years ago

@nevotheless maybe there is some problem with your data fetching, maybe you should try different ways to fetch data in different lifecycle hooks.

nevotheless commented 2 years ago

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 😅

sinkaroid commented 2 years ago

Hi, Any update for this? @nuxtjs/markdownit still maintained?

khalidzamer commented 2 years ago

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 renderer const 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

/** @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

wvovaw commented 1 year ago

Add markdown renderer as a nuxt plugin:

  1. Install markdown-it: yarn add -D markdown-it @types/markdown-it
  2. Create a file in the plugins directory: plugins/markdownit.ts
  3. Paste there this code:
    
    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>
kowiste commented 1 year ago
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

mickeyvanolst commented 1 year ago

@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.

wvovaw commented 1 year ago

@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!

mickeyvanolst commented 1 year ago

@wvovaw you're a hero! Works like charm 👍

IvanWala commented 1 year ago

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,
    },
  };
});
ulysse-lacour commented 1 year ago

@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 ?

afflexux commented 1 year ago

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>
Willen17 commented 1 year ago

@wvovaw Been trying to get this to work for a while now. You're truly amazing! A million thanks!

harlan-zw commented 1 year ago

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.

ndro commented 12 months ago

@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",
xarthurx commented 6 months ago

@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?

wvovaw commented 6 months ago

@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 commented 6 months ago

@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.