继续优化Obsidian双链在Hugo上的效果

我发现我之前进入了一个误区,明明知道 Obsidian 上的双链格式可以使用传统的 Markdown 链接上的格式,切换成这种格式的话,在用 Hugo 生成静态页面时就可以让 Obsidian 上的双链也变成一个超链接,这时也解决了 Hugo 默认的 Markdown 渲染引擎不渲染双中括号的尴尬。

我之前觉得 Obsidian 上的双链就要使用 Wiki 链接这样的格式才显得有灵魂,就强行去各种折腾。这明显是错的,人类为何选择各式各样的工具呢?原因就在于它们能够带来便捷。所以灵魂不灵魂的都是扯蛋,应该怎么方便怎么来。

之前我的方案是利用 JavaScript 将页面上匹配正则的值里的双中括号删除,后来觉得应该也加个超链接返回对应的标签,最终的效果也能正确的执行,就是相对的多此一举了。而且我还发现在很致命的问题,由于 JavaScript 在页面加载完成后再进行替换的动作,替换后的字符比渲染前减少了,进行重新排版后就会将页面拉扯,虽然这个过程很短暂,但还是挺明显的。这个小问题居然直接触发了我的强迫症,尝试了好几个方法感觉都不太理想。例如添加一个加载动画,将内容先隐藏起来,设定一个时间值作用给加载动画的隐藏与内容页面的打开。这样就可以将因替换造成的页面拉扯给过渡过去了。但是实际测试后显然对此不是很满意,不想无缘无故给页面增加几百毫秒的加载过程。不过这期间我想到,此法若用在加载网络字体的话,体验应该不错,有空研究一下。

话说回来,既然之前的坑已经埋下了,那么现在只能想办法填了。注意的是,我在 Obsidian 上的双链都是基于标签的形式,请根据自己实际情况判断以下内容是否适合使用。

替换所有内容下已有的 Wiki 链接

判断目录下的文件是否为 Markdown 文件,如果是就读取文件里的内容并匹配对应的值进行替换。

const fs = require('fs');
const path = require('path');
const directoryPath = __dirname;

function replaceMarkdownLink(filePath) {
  if (path.extname(filePath).toLowerCase() !== '.md') {
    return;
  }

  const content = fs.readFileSync(filePath, 'utf-8');
  const replacedContent = content.replace(/\[\[(.*?)\]\]/g, '[$1]($1.md)');

  fs.writeFileSync(filePath, replacedContent, 'utf-8');
}

function processDirectory(directoryPath) {
  const files = fs.readdirSync(directoryPath);

  for (const file of files) {
    const filePath = path.join(directoryPath, file);

    if (fs.statSync(filePath).isDirectory()) {
      processDirectory(filePath);
    } else {
      replaceMarkdownLink(filePath);
    }
  }
}

processDirectory(directoryPath);

将文件保存到笔记仓库运行即可。

node replace.js

替换页面 a 标签中 href 值

这样 Obsidian 上的双链格式就会从 [[生活]] 变成 [生活](生活.md) 这样的格式,很显然,转换后的格式可以被 Hugo 正确渲染成超链接。

<a href="生活.md">生活</a>

这时需将之前的替换代码修改一下,让其输出为以下的结果。

<a href="/tags/生活" title="查看与「生活」相关的内容">生活</a>
const contentDiv = document.querySelector('.article-content');

if (contentDiv) {
    const paragraphs = contentDiv.querySelectorAll('p');

    paragraphs.forEach(p => {
        const links = p.querySelectorAll('a[href$=".md"]');

        links.forEach(link => {
            const href = link.getAttribute('href');
            const title = link.textContent;
            const newHref = href.replace('.md', '').toLowerCase();
            const newLinkHtml = `<a href="/tags/${newHref}" title="查看与「${title}」相关的内容">${title}</a>`;

            p.innerHTML = p.innerHTML.replace(link.outerHTML, newLinkHtml);
        });
    });
}

End…