gatsby-digital-garden
gatsby-digital-garden copied to clipboard
Support relative filepaths/links in `gatsby-transformer-markdown-references`
In my setup (not fully working yet), my notes live in the content/
directory, and within that I have some sub-directories. Obsidian, Logseq, etc support linking to those notes with [[sub_dir/note_name]]
syntax.
The issue is that gatsby-transformer-markdown-references
seems to assume either a flat file hierarchy, or a root dir of the project root (e.g. siblings to index.js
or any entrypoint), computing inbound references fails when the link is coming from a file whose contextual ID is sub_dir/note_name
.
To replicate:
- Set up
gatsby-transformer-markdown-references
, and have Remark or Mdx usecontent/
as the FS source dir - Create a note
my-topic.md
incontent/
- Create another note at
content/blog/2022-10-10-my-blog-post.md
- (Optional, I think): Set up Gatsby to publish notes from the
content/blog/
directory at/blog/YYYY/MM/note-name
- Check
outboundReferences
oncontent/blog/2022-10-10-my-blog-post.md
--you should seemy-topic.md
correctly linked - Check
inboundReferences
onmy-topic.md
--there are no references to links coming fromblog/2022-10-10-my-blog-post.md
or its URL pattern either
Looking at compute-inbounds.ts
, it looks to me like adding something like this might handle links based on paths relative to a content/
or notes/
directory:
diff --git a/packages/gatsby-transformer-markdown-references/src/compute-inbounds.ts b/packages/gatsby-transformer-markdown-references/src/compute-inbounds.ts
index 2acde5c..08521b3 100644
--- a/packages/gatsby-transformer-markdown-references/src/compute-inbounds.ts
+++ b/packages/gatsby-transformer-markdown-references/src/compute-inbounds.ts
@@ -1,4 +1,4 @@
-import { basename, extname } from "path";
+import { basename, extname, format as formatPath } from "path";
import { Node } from "gatsby";
import { nonNullable } from "./non-nullable";
import {
@@ -33,6 +33,24 @@ function hasChildInArrayExcept(
let currentGeneration: Promise<boolean> | undefined;
+// For contexts where you transform nodes so that their URLs or titles do not match
+// their filesystem reference.
+//
+// For example, blog/2022-10-01-post.md is published at /2022/10/post, but you want to link to it using its filesystem
+// ref of [[blog/2022-10-01-post]]
+const isRelativeNameMatch = (title, path) => {
+ if (typeof path !== "string")
+ return false
+
+ const relativePath = relative(__dirname, path)
+ const extension = extname(relativePath)
+
+ const reference = relativePath.replace(extension, '')
+
+ return reference === title
+}
+
+
export async function generateData(cache: any, getNode: Function) {
if (currentGeneration) {
return currentGeneration;
@@ -55,7 +73,8 @@ export async function generateData(cache: any, getNode: Function) {
) === title) ||
(typeof x.node.absolutePath === "string" &&
basename(x.node.absolutePath, extname(x.node.absolutePath)) ===
- title)
+ title) ||
+ (isRelativeNameMatch(title, x.node.fileAbsolutePath))
);
}
I've run this locally (I originally wrote this in the JS file installed in node_modules/
in my project), and it's working in my case. Dump of my GraphQL query result:
{
"data": {
"allMdx": {
"edges": [
{
"node": {
"fields": {
"title": "Intro"
},
"fileAbsolutePath": "/Users/me/src/plamo-site/content/intro.md",
"outboundReferences": [],
"inboundReferences": [
{
"fields": {
"title": "Test",
"path": "/2022/10/test"
},
"fileAbsolutePath": "/Users/me/src/plamo-site/content/blog/2022-10-01-test.md"
}
]
}
},
{
"node": {
"fields": {
"title": "Test"
},
"fileAbsolutePath": "/Users/me/src/plamo-site/content/blog/2022-10-01-test.md",
"outboundReferences": [
{
"fields": {
"title": "Intro"
}
}
],
"inboundReferences": []
}
}
]
}
},
"extensions": {}
}
If this is sufficient to open up into a PR, I'm happy to do so, but I haven't written any tests and I'm not sure of any other considerations you might have, so proposing as an issue first.
Also, this so far only handles inbound refs, but similar work would I think be needed to handle and create the outbound refs.
Context
I'm migrating an old Jekyll blog and merging it with my Obsidian notes. The file => URL naming convention and transformation from Jekyll in this case is ./_posts/YYYY-MM-DD-blog-post-title.md
=> https://DOMAIN/blog/YYYY/MM/blog-post-title
.
Most notes are flat in the content/
directory in the Gatsby project root, so linking from them isn't an issue. Similarly
I could go and rename all the old blog post files to content/blog/YYYY/MM/blog-post-title.md
, but it's much harder to manage and review old posts if they're scattered across tons of date-based folders. The date string is meaningful when it's all lined up in a single _posts/
or content/blog
folder, but a nightmare when there are directories obfuscating the content that's there.