From 51b43a2115a6b38bbaad67b203c2158a387b5588 Mon Sep 17 00:00:00 2001 From: Keisuke ANDO Date: Wed, 28 May 2025 04:26:17 +0900 Subject: [PATCH] feat(links): added ofm option to style unresolved or broken links differently (#1992) * feat: add option to disable broken wikilinks * fix(style): update hover color for broken links and introduce new class * feat: add "disableBrokenWikilinks" option to ObsidianFlavoredMarkdown --- docs/plugins/ObsidianFlavoredMarkdown.md | 1 + quartz/plugins/transformers/ofm.ts | 16 +++++++++++++++- quartz/styles/base.scss | 11 ++++++++++- 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 @@ This plugin accepts the following configuration options: - `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 @@ export interface Options { enableYouTubeEmbed: boolean enableVideoEmbed: boolean enableCheckbox: boolean + disableBrokenWikilinks: boolean } const defaultOptions: Options = { @@ -56,6 +57,7 @@ const defaultOptions: Options = { enableYouTubeEmbed: true, enableVideoEmbed: true, enableCheckbox: false, + disableBrokenWikilinks: false, } const calloutMapping = { @@ -206,7 +208,7 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin> return src }, - markdownPlugins(_ctx) { + markdownPlugins(ctx) { const plugins: PluggableList = [] // regex replacements @@ -275,6 +277,18 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin> // 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: `${alias ?? fp}`, + } + } + } + // 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 @@ a { color: var(--secondary); &:hover { - color: var(--tertiary) !important; + color: var(--tertiary); } &.internal { @@ -101,6 +101,15 @@ a { 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;