question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Is it possible to use router-links with vue-markdown?

See original GitHub issue

Obviously the following code

[contact us](/contact)

gets translated into

<a href="/contact">contact us</a>

Without vue-markdown I could write

<router-link to="/contact">contact us</router-link>

which will use client side routing instead of reloading the page. Is this possible to use this concept with vue-markdown?

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:10
  • Comments:6

github_iconTop GitHub Comments

5reactions
soualidcommented, Apr 21, 2021

Another (hacky) way I’m not proud of, but hey… it works!

document.querySelectorAll('#yourElement a').forEach(a => {
  a.addEventListener('click', (e) => {
    e.preventDefault()
    this.$router.push({ path: a.attributes.href.value })
  })
})
4reactions
insightcodercommented, Oct 2, 2020

Sure. Like I said, I had to jump through some hoops, so open to simplifying things. Ideally these features could be incorporated into vue-markdown.

Markdown

This is my md file. 

<div id="image">
</div>

[normal link](http://www.google.com)

[vue link]{/my/app/route}

Component Usage


<markdown :source="source">
  <template v-slot:image>
       <img src="/my/img"/>
  </template>
</markdown>

Component Code

<template>
  <div>
    <vue-markdown
      v-bind="$attrs"
      :toc="true"
      :breaks="true"
      :linkify="false"
      :toc-anchor-link-space="true"
      toc-anchor-link-symbol="¶"
      :prerender="prerender"
    >
      <slot></slot>
    </vue-markdown>
    <div  v-for="(i,s) in $slots" :key="s" :ref="s">
      <slot :name="s" v-if="slotsInserted">
      </slot>
    </div>

    <router-link v-for="(link) in internalLinks"
      :to="link.to" 
      :key="link.id" 
      :ref="link.id">{{ link.text }}</router-link>

  </div>
</template>

<script lang="ts">
import { CreateElement } from 'vue';
import { Vue, Component } from "vue-property-decorator";
import VueMarkdown from "vue-markdown";
import router from '@/router'; 

interface InternalLink {
  id: string;
  to: string;
  text: string;
}

/**
 * Component that wraps the <vue-markdown> component. 
 * 
 * This currently offers two main features:
 * 
 * 1) Allows for using named slots to inject vue code
 * into the markdown.  To do this, in the .md file create 
 * a div/span with a certain id.  Then create a slot with a name
 * that matches the id.  This will be injected into that placeholder
 * div/span. 
 * 
 * 2) Adds support for internal links using router-link. 
 * Adds preprocessor for syntax [text]{internal-url}.  Notice
 * the curly braces instead of the parentheses.
 */
@Component({
  components: {
    VueMarkdown
  }
})
export default class Markdown extends Vue {
  public numSlots = this.$slots.length;
  public slotsInserted = false;
  public internalLinks: InternalLink[] = [];
  public prerendered = false;

  public mounted() {
    this.insertSlotContentIntoMarkdown();
  } 

  public updated() {
    this.insertInternalLinksIntoMarkdown();
  }

  /**
   * Insert all slots content
   * into dom elements with id of slot name.
   */
  public insertSlotContentIntoMarkdown() {
    for(var slotName in this.$slots) {
      if(slotName == null) {
        continue;
      }
      var slot = (this.$refs[slotName] as Element[])[0];
      var parent = this.$el.querySelector(`#${slotName}`);
      if(slot !== null && parent !== null) {
        parent.appendChild(slot);
      } else {
        console.error(`Markdown mapping error for id/slot "${slotName}"`);
      }
    }
    this.slotsInserted = true;
  }

  /**
   * Insert all internal router-links
   * into dom elements with id.
   */
  public insertInternalLinksIntoMarkdown() {
    for(var link of this.internalLinks) {
      var routerLink = (this.$refs[link.id] as any[])[0];
      if (routerLink == null) {
        continue;
      }
      var parent = this.$el.querySelector(`#${link.id}`);
      if(routerLink !== null && parent !== null) {
        parent.appendChild(routerLink.$el);
      } else {
        console.error(`Markdown mapping error for id/slot "${link.id}"`);
      }
    }
    this.slotsInserted = true;
  }  

  public prerender(content: string): string {
    // substitute "internal" links ({text}(url) with div placeholder
    // for slots.
    const regex = /\[(.*?)\]\{(.*?)\}/g;
    var match;
    let internalLinks: InternalLink[] = [];
    while ((match = regex.exec(content)) !== null) {
      let to = match[2];
      let text = match[1]
      let id = `internal-link-${internalLinks.length}`;
      internalLinks.push({ id, to, text });
      let replacement = `<span id="${id}"></span>`;
      content = content.replace(match[0], replacement);
    } 
    if (!this.prerendered) {
      this.internalLinks = internalLinks;
      this.prerendered = true;
    }
    return content;
  }

}

</script>

Read more comments on GitHub >

github_iconTop Results From Across the Web

vue-router : Creating a router-link with <a> - Stack Overflow
In my Vue SPA, I use vue-router with history mode. One of the components is vue-showdown. The vue-showdown generates HTML code dynamically.
Read more >
Need help replacing archor/<a> tags with <router-link> in ...
I've managed to use <router-link> s and Vue Router for seamless navigation elsewhere throughtout the website. Is it possible to convert the ...
Read more >
How To Navigate Between Views with Vue Router
The first thing to do is import the Vue Router library. You actually don't need to access everything in this library in order...
Read more >
Extending Vue Router Links in Vue 3 - Vue School Blog
The <router-link> tag is a great tool for navigating between different pages of your Vue application but it is not the tool to...
Read more >
Working with Routes in Vue.js - Raymond Camden
The official router for Vue.js is vue-router. It supports what I described above as well as more complex routing, for example, nested routes ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found