一种使 Hugo 可以正确渲染类 wiki 链接、图片的方式

最近几个月,使用 obsidian 作为主要的笔记管理工具,并用 Hugo 渲染后部署到服务器。

Obisidan 的内链功能很有特色,但是 Hugo 内置的 markdown 引擎并不能正确的渲染它。这里,我写一个函数,把它引入到你使用的 Hugo 主题的 js 文件中调用,即可正确渲染 wiki 语法的内链,如 [[link]] 、[[link | desc]] 、 [[link#anchor]] 、[[#anchor]]、![[img-path | size]] 等等。

// 标识渲染 Obsidian 等 Wiki 语法的图片、链接
// 支持中文路径
$('.content, .list').each((idx, item) => {
// console.log(item.outerHTML)
// console.log(item.innerHTML)
let _innerHtml = item.innerHTML;

if(_innerHtml.indexOf('[[') > -1) {
	// console.log('>>>', _innerHtml)

	// 1. 先匹配替换图片
	// let _re = /!\[\[(\w*\/?\w+\.\w+)\|?(\d*)\]\]/
	let _re = /!\[\[(([\/\-\.\*\$\&]|\w|\s|[^\x00-\xff])*\.\w+)\s*\|?\s*(\d*)\]\]/g;
	// let _str = _innerHtml.match(_re, "$1, $3");
	// 此处默认图片链接为根引用方式,即 /assets/*
	// let _str = _innerHtml.replace(_re, '<img src="$1" alt="$1" width="$3" />');
	let _str = _innerHtml.replace(_re, '<img src="/$1" alt="$1" width="$3" />');
	// item.innerHTML = _str;

	// 2. 后匹配替换链接
	let _reLink = /\[\[(([\/\-\.\*\$\:\#]|\w|\s|[^\x00-\xff])*)\|?(([\/\-\.\*\$]|\w|\s|[^\x00-\xff])*)\]\]/g;
	// let _strLink = _str.match(_reLink);
	// let _strLink = _str.replace(_reLink, '<a href="$1">$3</a>');
	let _strLink = _str.replace(_reLink, (val) => {
		val = val.replace(/[\[\]]/g, '')
		let _arr = val.split(/\s*\|\s*/)
		let _relLink = _arr[0]
		let _desc = _arr[1] ? _arr[1] : _arr[0]

		// 检查链接描述是否包含 #锚点,形式有(我们假设当前文章名称为 test ,它有一个章节 ttt):
		// - 2.1. 孙子兵法#军争篇 - 此类可以正常识别
		// - 2.2. cpu-是如何制造出来的#18.-等级测试 - https://example.com/cpu-是如何制造出来的#18.-等级测试 ,
		//        此类锚点中包含特殊符号 `.` ,在新标签中打开,且无法正确定位到锚点
		// - 2.3 test#ttt - https://example.com/test#ttt 默认会在新标签页中打开,需要优化为在当前页面滚动
		// - 2.4  #ttt - 不能正常,会翻译为 https://example.com/#ttt ,丢失了当前页面路径
		let _idx = _desc.indexOf('#');
		if (_idx > -1) {
			// 2.4
			if (_idx == 0) {
				_relLink = location.pathname.slice(1) + _desc

			} else {
				// 2.3
				_relLink = _desc.replace('#','/#')
				
				// 2.2
				_relLink = _relLink.replace(/[\.\、]/g, '')
			}
		}

		// console.log(_arr);
		// console.log(_desc);
		// return `<a href="${_arr[0]}">${_desc}</a>`
		return `<a href="/${_relLink.replace(/\s/g, '-').toLowerCase()}">${_desc}</a>`
	// });
	});

	item.innerHTML = _strLink;
}
1 Like

放到渲染过后的静态文件里?

它依赖于 jquery ,当然可以通过简单的修改使用原生 js 实现。

可以放在如 static/renderWikiLink.js 这样的文件中,并在你所用的 Hugo 主题头文件中引用它。

哦,机智如你 :clap:

受你启发,不过不用这么麻烦。
直接修改single.html
把所有![[name]]转成name`,这样obsidian可以无缝对接。
obsidian目录作为git目录直接发布

增加:
235 ```
236 {{ $pattern := !\[\[(.*?)\]\] }}
237 {{ $replace := <img src="/img/$1" alt="$1"> }}
238 {{ $content := .Content | replaceRE $pattern $replace }}
239 {{ $content | safeHTML }}
240