Open henriette-einstein opened 2 years ago
I love the idea, but in order for the links to work we need to know the route associated by it, for this template we know that one page = one document but that may not be the case for all websites using Nuxt Content.
Have you tried https://github.com/landakram/remark-wiki-link ?
@Atinux side-note: I noticed that https://content.nuxtjs.org/api/configuration#markdown does a 302 redirect to https://content.nuxtjs.org/api/v1/getting-started/configuration#markdown with a "Page not found" message.
Should be fixed for the redirection thanks @sig9
@henriette-einstein
For Obsidian wiki-links with Absolute paths, you should follow these steps
visit
s text
node in tree
and using simple regex, grab the href
and alt text
of the link, and create a new html
type node. One benefit of using own plugin is to add custom classes to such node, which can be used in the next step to grab such internal links.md-a
or whatever, and create that component in components/content
folder.href
accordingly.
href
to fetch the article, how will the Content Module know where to find it relative to the source folder?href
contains /
, that article does not have a unique name, so Obsidian must have added entire path info as the href
. And, if the href
doesn't contain /
, then, it's a unique article.where
query, you can use either path
or slug
respectively to match it with href
and fetch the article._path
in the Template as the href
of the link. This syntax is (as far as I could see) not supported by nuxt content. I could do some preprocessing to convert that syntax to the standard markdown syntax. But that would not work if I use the content-directory directly as the root folder for the Obsidian vault.
By these steps,
dev
folder.@ManasMadrecha
Thanks a lot for that information. I tried to implement a custom remark plugin as you described and configured it in Nuxt-config. The plugin is super-simple:
import { visit } from 'unist-util-visit'
// The RegEx to match WikiLinks
const wikiRegex = /\[\[.*?\]\]/g
export default function remarkWikilink () {
function transformer (ast) {
visit(ast, 'text', node => {
if (wikiRegex.test(node.value)) {
const newValue = node.value.replace(wikiRegex, match => {
return (
'<w-link to="">' +
match.substring(1, match.length - 1) +
'</w-link>'
)
})
Object.assign(node, { type: 'html', value: newValue })
}
})
}
return transformer
}
The returned value is just a test here. However, the plugin is never invoked. Instead
# Wikilink Test
[[Link to Page|Link Text]]
is rendered as
<span><span>Link to Page|Link Text</span></span>
If I use a different REGEX and a different input text, I can see that the plugin is involved. The plugin configuration therefore seems to work correctly.
It looks like double square brackets are somehow treated before they arrive in the plugin.
I will try to fiddle with the remark-wikilinks plugin, even though I have not seen a possibility to change the resulting tag-name in this plugin.
@henriette-einstein
Unless some other plugin is also installed that treats the [[
as start of link, it will remain as text only. So, some other plugin must be treating it first, before your plugin. Try your custom plugin, by removing remark-wikilink plugin, or even remark-mdc plugin (enabled by default).
Also, did you register it correctly inside nuxt.config.js
, i.e., inside remark and not rehype?
Then, the [[...
will just be normal text
node. And since you are visiting text
node inside your plugin, it will work fine.
EDIT: Hey, try converting your plugin to a rehype plugin, instead of remark, and then try. So, visit the text
there, and don't replace the node. Rather in the end, instead of using type:html
, use type:element, tagName: w-link, properties: {className: ['internal']}
and Object.assign this to the node.
You can change the tagName of links even with remark-wikilink plugin, by having a custom rehype plugin. I think that plugin adds some classes like internal
to the a
links, so inside your own rehype plugin, you can visit such element
with tagName
as a
and with node.properties.className
containing internal
, and then inside the visitor
function, just change the node.tagName
to md-a
.
@ManasMadrecha
Thanks for your support! I have a minimal nuxt.config.js
:
export default defineNuxtConfig({
modules: ['@nuxt/content'],
content: {
markdown: {
remarkPlugins: ['remark-wikilink']
}
}
})
I have not configured any other plugin, therefore the behavior must be included in Nuxt-Standard.
I have already found another solution using a Nitro plugin.
Create a file wikilinkPlugin.ts in the directory server/plugins
. My initial version is
// The RegEx to match WikiLinks
const wikiREGEX = /\[\[.*?\]\]/g
// The Regex for the file part of a Wikilink
const fileREGEX = /(?<=\[\[).*?(?=(\]|\|))/;
// The Regex for the optional title part of a Wikilink
const titleREGEX = /(?<=\|).*(?=]])/;
function transformLinks (text: string): string {
let theLinks = text.match(wikiREGEX);
let linksFound = []
if (theLinks) {
for (var theLink of theLinks) {
console.log(theLink)
let theLinkRef = theLink.match(fileREGEX);
if (theLinkRef) {
let theTitle = theLink.match(titleREGEX);
let newLink = `<m-a href="${theLinkRef[0]}">`+ theTitle?theTitle[0]:theLinkRef[0] + '</m-a>'
linksFound.push(
{
'oldText': theLink,
'newText': newLink
}
)
}
}
}
for(var i of linksFound) {
text = text.replace(i.oldText,i.newText)
}
return text;
}
export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook('content:file:beforeParse', (file) => {
if (file._id.endsWith('.md')) {
file.body = transformLinks(file.body)
}
})
})
and configure the plugin in 'nuxt.config.js`.
import { defineNuxtConfig } from 'nuxt'
export default defineNuxtConfig({
modules: ['@nuxt/content'],
nitro: {
plugins: ['~/server/plugins/wikilinkPlugin.ts']
}
})
The code is still incomplete. Local links and transclusions are not handled to name only the problems I can see by now. But it may be a start.
For some reason I don't understand, the final HTML will contain additional whitespace I did not produce. This may be a more complicated issue.
<m-a href="Text"> Text </m-a>
instead of
<m-a href="Text">Text</m-a>
@henriette-einstein OMG, you have complicated it so much 😂
mdc
Well, the issue lies with mdc
.
So, this in markdown
becomes
So, previously your remark plugin was not working, because you were visiting text
node. While because of mdc
, in the ast
, the Obsidian links or embeds no more remain inside a text
node; each [
becomes a span
. That's the way mdc
works.
With it disabled, now, your remark plugin will work, and you don't need nitro-plugin
.
Note: If you don't want to disable mdc
, you will have to visit span
and not text
node.
Also, Note: You shouldn't use the Nitro Plugin for modifying the text into links, because in that, the body
is entire contents of the file. I guess that will even modify the Regex Matches inside code
nodes. Rather, using remark
to visit only text
or specific span element
ensures Regex Matches are as intended.
Here is the my code (with mdc
disabled):
Note:
md
files.mdc
enabled, will have to modify the Code drastically. So, better to disable mdc
for the time being.With my Code, the above markdown will become this
Note: After you create the actual components, these tags will be replaced with the whatever tags you use in the template
of those components.
Inside, nuxt.config.js
,
import { defineNuxtConfig } from 'nuxt'
// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
modules: ['@nuxt/content'],
content: {
markdown: {
remarkPlugins: ['remark-obsidian-links'],
mdc: false
},
}
})
The next file is plugins/markdown/remark-obsidian-links/index.js
The next file is plugins/markdown/remark-obsidian-links/package.json
{
"name": "remark-obsidian-links",
"version": "1.0.0",
"type": "module",
"main": "index.js",
"author": {"name": "ManasMadrecha", "url": "https://manas.madrecha.com"},
"dependencies": {
"unist-util-visit": "4.1.0"
}
}
Install it in app's package.json
"dependencies": {
"remark-obsidian-links": "file:./plugins/markdown/remark-obsidian-links"
},
"devDependencies": {
"@nuxt/content": "^2.0.0",
"nuxt": "^3.0.0-rc.4"
}
@ManasMadrecha Thanks a lot for your guidance and solutions! I'll now write and refine the components to see how that works.
After that, I'll try to implement a backlink component. Hope I don't have to bother you again then.
I would like to use Nuxt Content to generate HTML form Obsidian files (see https://www.obsidian.md). Obsidian uses the Wikilink syntax to reference files.
e.g. [[anotherfile]] references the file "anotherfile.md" in the current directory.
This syntax is (as far as I could see) not supported by nuxt content. I could do some preprocessing to convert that syntax to the standard markdown syntax. But that would not work if I use the content-directory directly as the root folder for the Obsidian vault.
Therefore it would be great if you could provide a remark plugin and a configuration example that handles that.