nuxt / content

The file-based CMS for your Nuxt application, powered by Markdown and Vue components.
https://content.nuxt.com
MIT License
3.07k stars 622 forks source link

V2: Show backlinks, outgoing links like Obsidian or new VS Code #1084

Open ManasMadrecha opened 2 years ago

ManasMadrecha commented 2 years ago

Is your feature request related to a problem? Please describe

To be able to quickly know which all pages link to the current page. Also to know to which all pages the current page links.

Describe the solution you'd like

  1. Add a JSON of backlinks, outgoing links, etc. in the document frontmatter
  2. We can use them to display anywhere along side the body of the content; similar to TOC.
  3. Maybe, with such frontmatter data, someone can create a local Graph of the current page (similar to Obsidian)

Describe alternatives you've considered

  1. For Outgoing links, create a custom remark plugin to scan the contents for links, and add such a list of links as an array in the frontmatter. This is easy.
    • Currently, I use this technique in Content V1 to scan all the images in the markdown body, and add an array of such images in frontmatter, and submit it into Sitemap. (similar to Yoast SEO plugin for WordPress)
    • So, for links too, it may work.
  2. For Backlinks, don't know. So, it would be great if Content module added such data into the file's frontmatter.

Additional context

EDIT: If this feature is ever implemented, the backlinks should work even if the links are in WikiLinks format (similar to Obsidian or Markdown Memo plugin of VS code or Foam plugin)

atinux commented 2 years ago

I really like this idea!

vandermerwed commented 1 year ago

Would it be possible to do this using Hooks/Transforms?

ManasMadrecha commented 1 year ago

@vandermerwed Outgoing links can be added into the frontmatter either inside an own remark plugin or inside the after parse hook.

Backlinks, don't know. Content Module needs to scan all the files' aforementioned outgoingLinks key, and figure out which page links to current page.

vandermerwed commented 1 year ago

Thanks for the info @ManasMadrecha!

Ended up with the following solution for now. Not perfect, but it'll do for now 👍🏼

server\plugins\outgoing-links.ts

import { visit } from 'unist-util-visit'

export default defineNitroPlugin((nitroApp) => {
    nitroApp.hooks.hook('content:file:afterParse', (file) => {
        if (file._id.endsWith('.md')) {
            visit(file.body, (n: any) => n.tag === 'a', (node) => {

                if (file.outgoingLinks === undefined) file.outgoingLinks = [];

                file.outgoingLinks.push({
                    _to: node.props.href,
                    _title: node.children.find((c: any) => c.type === "text")?.value,
                    node
                });

            })
        }
    })
})

example.vue

<script setup>
  const { path } = useRoute()

  const { data } = await useAsyncData(async () => queryContent().where({ _path: { $ne: path } }).find());

  const backlinks = data.value?.filter(({ outgoingLinks }) => outgoingLinks?.some(({ _to }) => _to === path));
</script>
ManasMadrecha commented 1 year ago

@vandermerwed That's nice. One suggestion, inside the hook, check and only push internal links (own app's) into outgoingLinks and not external links as well (i.e., those starting withhttp).

While the example component is good, it will be time consuming to fetch all the thousands of posts, and filter them. Maybe Content Module itself can implement the backlinks key in each file's frontmatter. Until then, good solution 👌🏻

vandermerwed commented 1 year ago

One suggestion, inside the hook, check and only push internal links (own app's) into outgoingLinks and not external links as well (i.e., those starting withhttp).

Ah yeah, thanks good suggestion 👌🏼

Maybe Content Module itself can implement the backlinks key in each file's frontmatter.

I'm quite new to Nuxt and the Content Module, is there maybe documentation that you can point me to on how to do this?