From 51b43a2115a6b38bbaad67b203c2158a387b5588 Mon Sep 17 00:00:00 2001
From: Keisuke ANDO <g.kei0429@gmail.com>
Date: Tue, 27 May 2025 19:26:17 +0000
Subject: [PATCH] feat(links): added ofm option to style unresolved or broken links differently (#1992)

---
 quartz/styles/base.scss                  |   11 ++++++++++-
 quartz/plugins/transformers/ofm.ts       |   16 +++++++++++++++-
 docs/plugins/ObsidianFlavoredMarkdown.md |    1 +
 3 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/docs/plugins/ObsidianFlavoredMarkdown.md b/docs/plugins/ObsidianFlavoredMarkdown.md
index 414f743..277c772 100644
--- a/docs/plugins/ObsidianFlavoredMarkdown.md
+++ b/docs/plugins/ObsidianFlavoredMarkdown.md
@@ -23,6 +23,7 @@
 - `enableYouTubeEmbed`: If `true` (default), enables the embedding of YouTube videos and playlists using external image Markdown syntax.
 - `enableVideoEmbed`: If `true` (default), enables the embedding of video files.
 - `enableCheckbox`: If `true`, adds support for interactive checkboxes in content. Defaults to `false`.
+- `disableBrokenWikilinks`: If `true`, replaces links to non-existent notes with a dimmed, disabled link. Defaults to `false`.
 
 > [!warning]
 > Don't remove this plugin if you're using [[Obsidian compatibility|Obsidian]] to author the content!
diff --git a/quartz/plugins/transformers/ofm.ts b/quartz/plugins/transformers/ofm.ts
index ef59179..42428ae 100644
--- a/quartz/plugins/transformers/ofm.ts
+++ b/quartz/plugins/transformers/ofm.ts
@@ -41,6 +41,7 @@
   enableYouTubeEmbed: boolean
   enableVideoEmbed: boolean
   enableCheckbox: boolean
+  disableBrokenWikilinks: boolean
 }
 
 const defaultOptions: Options = {
@@ -56,6 +57,7 @@
   enableYouTubeEmbed: true,
   enableVideoEmbed: true,
   enableCheckbox: false,
+  disableBrokenWikilinks: false,
 }
 
 const calloutMapping = {
@@ -206,7 +208,7 @@
 
       return src
     },
-    markdownPlugins(_ctx) {
+    markdownPlugins(ctx) {
       const plugins: PluggableList = []
 
       // regex replacements
@@ -275,6 +277,18 @@
                   // otherwise, fall through to regular link
                 }
 
+                // treat as broken link if slug not in ctx.allSlugs
+                if (opts.disableBrokenWikilinks) {
+                  const slug = slugifyFilePath(fp as FilePath)
+                  const exists = ctx.allSlugs && ctx.allSlugs.includes(slug)
+                  if (!exists) {
+                    return {
+                      type: "html",
+                      value: `<a class=\"internal broken\">${alias ?? fp}</a>`,
+                    }
+                  }
+                }
+
                 // internal link
                 const url = fp + anchor
 
diff --git a/quartz/styles/base.scss b/quartz/styles/base.scss
index 3ed9e63..f534e37 100644
--- a/quartz/styles/base.scss
+++ b/quartz/styles/base.scss
@@ -91,7 +91,7 @@
   color: var(--secondary);
 
   &:hover {
-    color: var(--tertiary) !important;
+    color: var(--tertiary);
   }
 
   &.internal {
@@ -101,6 +101,15 @@
     border-radius: 5px;
     line-height: 1.4rem;
 
+    &.broken {
+      color: var(--secondary);
+      opacity: 0.5;
+      transition: opacity 0.2s ease;
+      &:hover {
+        opacity: 0.8;
+      }
+    }
+
     &:has(> img) {
       background-color: transparent;
       border-radius: 0;

--
Gitblit v1.10.0