<nuxt-link> in markdown

delucis
8
delucis
commented 2 years ago

I’m using the markdown-it module, and wanted to see if it would be possible to render links as <nuxt-link> tags.

markdown html
[About](/about) <nuxt-link to="/about">About</nuxt-link>

I managed to do that by setting md.renderer.rules for link_open and link_close, which produces HTML including <nuxt-link> tags, but when rendered using v-html, Vue/Nuxt doesn’t pick up any included components.

Where would I have to do the markdown rendering in order for those to be processed properly? Or is there an existing solution?

1
zash80
10
zash80
commented a year ago

I think I ran into the same issue. Having links in markdown that should end up as proper <nuxt-link>. Is there anyone having a solution?
@delucis, can you share your code so i can see how far you got? Thanks, M.

0
delucis
8
delucis
commented a year ago

Hi @zash80 I tried the following on my markdown component:

props: {
  markdown: String
},
computed: {
  renderedMd: function () {
    if (!this.markdown) return undefined
    this.$md.renderer.rules.link_open = function (tokens, idx, options, env, slf) {
      var token = tokens[idx]
      token.attrs = token.attrs.map(attr => {
        if (attr[0] === 'href') attr[0] = 'to'
        return attr
      })
      return '<nuxt-link' + slf.renderAttrs(token) + '>'
    }
    this.$md.renderer.rules.link_close = function () { return '</nuxt-link>' }
    return this.$md.render(this.markdown)
  }
}

This renders markdown links as <nuxt-link> instead of <a> and switches the href attribute to be to. That’s all fine, but rendering the resulting string using v-html won’t compile the contained <nuxt-link> elements. I would be interested if you find a solution!

0
zash80
10
zash80
commented a year ago

Hi @delucis, thanks for sharing your code. With that and with this post I found a working solution.

<template>
  <div>
    <component :is="renderedMd"></component>
  </div>
</template>

<script>
export default {
  props: {
    markdown: String
  },
  computed: {
    renderedMd: function () {
      let rawTemplate = '<div />'
      if (this.markdown) {
        this.$md.renderer.rules.link_open = function (tokens, idx, options, env, slf) {
          var token = tokens[idx]
          token.attrs = token.attrs.map(attr => {
            if (attr[0] === 'href') attr[0] = 'to'
            return attr
          })
          return '<nuxt-link' + slf.renderAttrs(token) + '>'
        }
        this.$md.renderer.rules.link_close = function () { return '</nuxt-link>' }
        rawTemplate = this.$md.render(this.markdown)
      }
      return {
        name: 'DynamicComponent',
        template: rawTemplate
      }
    }
  }
}
</script>

Furthermore I had to add some webpack config into nuxt.config.js build > extend section (see also this)

config.resolve.alias['vue'] = 'vue/dist/vue.js'

Hope that helps!

2
delucis
8
delucis
commented a year ago

Awesome! Thanks for sharing — I got it working in no time.

Wish there was a way to avoid using the full Vue library as it adds ~75kb to my build, which seems a lot for some markdown rendering, but I can’t figure out any other way (i.e. the console warning before aliasing vue suggests “pre-compiling render functions,” but I don’t how that can be done).

0
Atinux
24.6k
Atinux
commented a year ago

If you guys are interested, this is how we do it on Nuxt.js documentation website: https://github.com/nuxt/nuxtjs.org/blob/master/components/HtmlParser.vue

We bind every link to catch the click event, and if it's a relative link, we simply use $router.push :)

1
delucis
8
delucis
commented a year ago

Thanks @Atinux that’s a much cleaner solution!

0
ManUtopiK
10
ManUtopiK
commented 6 months ago

@Atinux Your solution works well, but with some regressions.
Vue-router add the classes router-link-active and router-link-exact-active if the link match the current route.
But especially, nuxt 2.4 bring prefetching, which is not provided by this HtmlParser component.
Is there a way to use nuxt-router or vue-router fonctions directly to parse links?

0
Atinux
24.6k
Atinux
commented 6 months ago

Great suggestion @ManUtopiK

I am working on the new Markdown parser that will transform to JSON, so we could directly use <nuxt-link> instead of parsing the <a> elements :)

0
martinrisseeuw
3
martinrisseeuw
commented 2 months ago

Great suggestion @ManUtopiK

I am working on the new Markdown parser that will transform to JSON, so we could directly use <nuxt-link> instead of parsing the <a> elements :)

Is this something that's still being worked on? Or should I give it a go to implement the solution you guys are currently using for the Nuxt documentation? :)

0
Informations
QuestionUnresolved
#c106 - Created 2 years ago