Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nuxt 3 Support ? #47

Closed
therealzaybee opened this issue Oct 31, 2021 · 25 comments
Closed

Nuxt 3 Support ? #47

therealzaybee opened this issue Oct 31, 2021 · 25 comments

Comments

@therealzaybee
Copy link

therealzaybee commented Oct 31, 2021

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

@therealzaybee
Copy link
Author

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
Copy link

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

@therealzaybee
Copy link
Author

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
Copy link

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
Copy link

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

@therealzaybee
Copy link
Author

therealzaybee commented Jul 5, 2022

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

@nevotheless
Copy link

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

@therealzaybee
Copy link
Author

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

@nevotheless
Copy link

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
Copy link

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

@khalidzamer
Copy link

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

  • install package npm install -D @tailwindcss/typography
  • update tailwind.config
/** @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
Copy link

wvovaw commented Dec 10, 2022

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,
    },
  };
});
  1. In template:
<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
Copy link

kowiste commented Feb 1, 2023

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
Copy link

mickeyvanolst commented Mar 3, 2023

@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
Copy link

wvovaw commented Mar 3, 2023

@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 [email protected] version and since then markdown-it worked perfectly.

P.S. I just upgraded my nuxt version to [email protected] 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
Copy link

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

@IvanWala
Copy link

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
Copy link

@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
Copy link

afflexux commented Aug 31, 2023

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
Copy link

Willen17 commented Sep 7, 2023

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

@harlan-zw
Copy link
Contributor

Thanks for the solutions, everyone! I'm going to track Nuxt 3 support here: #67

I've linked the solution in here as an alternative.

@harlan-zw harlan-zw closed this as not planned Won't fix, can't repro, duplicate, stale Sep 11, 2023
@ndro
Copy link

ndro commented Nov 21, 2023

@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
Copy link

@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 [email protected] version and since then markdown-it worked perfectly.

P.S. I just upgraded my nuxt version to [email protected] 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
Copy link

wvovaw commented May 14, 2024

@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
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests