我的一个强需求是: 将 ob 上管理的这些文档,发布到 web 中。
- 在发布的页面中,要解决 双向链接 的识别问题 [强需求]
- 在发布的页面中,要解决 悬浮阅读 的问题 [中强需求]
- 在发布的页面中,要解决 段落引用 的问题 [中等需求]
- 在发布的页面中,我需要有 知识关联图谱 存在 [弱需求]
由于我的 博客 渲染,采用的是 hexo 体系,因此发布问题的解决,需要结合 hexo 的生态。
hexo 解决双链问题
最简单的方案是: npm install hexo-backlink
, 项目地址
由于 社区的 hexo-backlink 不支持子路径,因此借鉴一下自己改改。
hexo 采取的插件机制,估计是用的类似于 quickjs 或者 v8 的沙盒,可由开发者自行开发插件,而 hexo 只需要把所有的插件代码组织起来,运行一遍,就能实现插件对内容的处理。沙盒技术可以参考 虚拟机随谈 #插件机制 #quickjs #js引擎
考虑到将来可能会有比较多的 hexo 的适配问题,因此希望能更全面了解 hexo 的插件能
力,可以阅读 hexo extend
不得不说,hexo 的文档写得是真的烂……
根本不知道每个阶段有什么参数,会影响什么……
最后,通过 两次 before_post_render
解决了全局变量获取的问题,虽然不怎么优雅,但算是能解决问题。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
|
function doreplace(data) { let { content, title } = data; let result = content.match(/\[\[.*?\]\]/g); if (result && result.length > 0) { result.forEach((linkName) => { let [realName, showName] = (linkName + "") .replace("[[", "") .replace("]]", "") .split("|"); let anchor = null; [realName, anchor] = realName.split("#");
let doc = hexo.locals.get(realName) console.log(doc)
if (doc) { let path = getsubpath(doc.permalink) content = content.replace( linkName, `<a href="${path}${anchor ? "#" + anchor : ""}" name="${realName}" >${showName || realName}</a>` ); } else { content = content.replace( linkName, `<a href="/notpublish/index.html" name="${realName}" >${showName || realName}</a>` ); } }); }
data.content = content; return data; }
hexo.extend.filter.register("before_post_render", function (data) { if (ignore(data)) {return}
hexo.locals.set(data.title, () => data) }, 0)
hexo.extend.filter.register("before_post_render", function (data) { if (ignore(data)) {return}
doreplace(data) }, 0)
function ignore(data) { var sourceFileName = data.source; var ext = sourceFileName.substring(sourceFileName.lastIndexOf(".")).toLowerCase(); return !data.publish || ext != '.md'; }
function getsubpath(p) { if (p.match(/^(http|https):\/\//)) { let u = new URL(p) return u.pathname } return p }
|
解决 blog 站的发布问题
方案: 采用 七牛云 的 qshell,发布到某个 bucket 下即可:
1
| qshell qupload quploadconfig.json
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| ➜ blog git:(master) ✗ cat quploadconfig.json { "src_dir" : "publish/", "bucket" : "bloglong", "key_prefix" : "", "ignore_dir" : false, "overwrite" : true, "check_exists" : false, "check_hash" : true, "check_size" : false, "rescan_local" : true, "skip_file_prefixes" : "test,demo,", "skip_path_prefixes" : "temp/", "skip_fixed_strings" : ".svn,.git,.vscode", "skip_suffixes" : ".DS_Store", "log_rotate" : 1, "log_stdout" : false, "file_type" : 0, "resumable_api_v2" : false, "resumable_api_v2_part_size" : 4194304 }
|
解决 github 发布问题
方案: 采用 docs 目录,作为 github pages 的入口。
目前可以先这样用着,之后觉得 基于分支
的发布方式更好的话,到时再调整一下就行。
解决悬浮阅读的问题
实际上,这是一个和发布本身没太多相关性的问题,甚至可以认为,这个功能通过加一个浏览器插件就能解决。
确实如此,因此通过在生成的 html 中,添加自定义的 js 引用来达到目的。代码比较粗糙,将来有更多更清晰的需求时,再进行统一改造。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| let allowSubs = ["/archives/", "/posts/", "/categories/", "/tags/"] let matchpath = window.location.pathname.match(/\/.*\//) || [] let firstPath = matchpath[0] let shouldOpen = false
if (allowSubs.includes(firstPath) && self == top) { let longiframeStyle = document.createElement("style") longiframeStyle.innerText = `.long-frame{width:500px;height:600px;border:none;position:absolute;z-index:9999;display:block;}.frame-on{display:block}` let longiframe = document.createElement("iframe") longiframe.id = "longframe" longiframe.classList.add("long-frame") let body = document.getElementsByTagName("body")[0] body.append(longiframeStyle) body.append(longiframe) runscript() }
function runscript() {
let longframe = document.getElementById("longframe"); this.document.querySelectorAll("main a").forEach(a => { a.addEventListener("mouseover", e => showInIframe(longframe, e)) }); this.document.onclick = function (e) { shouldOpen = false if (longframe.src != "") { longframe.style.height = 0 longframe.style.width = 0 longframe.style.display = "none" } }; }
function showInIframe(iframe, e) { if (shouldOpen) { return } shouldOpen = true let src = e.target.href || "" if (!src) { return } src = src.split("#")[0] if (src.trimStart().startsWith("http")) { if (window.location.host == src.replace(/^(http|https):\/\//, "").split("/")[0]) { iframe.onload = function () { if (!shouldOpen) { return } let posx = e.pageX; let posy = e.pageY; iframe.style.top = posy + 30 + "px"; iframe.style.left = posx + 50 + "px"; iframe.style.width = "500px" iframe.style.height = "600px" iframe.style.display = "block" } iframe.src = src } } };
|
现在悬浮阅读有一些不方便的地方:
- 仅有一个预览框 (无法多个预览)
- 预览框的位置和大小太死板
- 仅适用于一级结构 (层级内是关闭的)
- 内嵌页面的格式不够友好 (header 部分太长)
- 无法自定义是否开启或关闭
之后看情况解决下这些问题。【TODO】
hexo 与 ob 的目录结构组织问题
我目前的绝大多数文章,都是 技术相关 的文章,所以在写的时候,都是直接扔到一个统一的 _posts
目录下,因为这也是 hexo 直接的文章管理方式。
随着文章范围的扩展,有一些其他类型的文章独立成体系,就不太方便统一扔到一个目录下,比如 生产力建设
下有一系列 ob 的文章。
从期望来看,一个目录,就对应着一个 分类
。
从 ob 和 hexo 的职责来看,ob 负责 知识库管理
,hexo 负责 blog 渲染和发布
。
hexo 需要用到 ob 中的各种文档。 目前我的解决方式是,把原有的 hexo 下的 source
目录,软链到 ob 的根目录下。 这样的问题在于,想发布的文档,只能被拖到另一个目录下。 这是不友好的。
可以探索另一种方式,所有的文档全部放到 ob 中,把要发布的文章,统一加上一个特定的 meta 信息,要发布之前,用脚本跑一次,把相关文档 软链/复制 到对应的 hexo 目录下,然后再进行渲染和发布操作。
值得参考的文档:
归属: