主要用于记录一些短文或吐槽,这些内容不适合作为博客文章出现,该功能类似我很久之前实现过的时间轴,但上次更新时间轴已经是6年前的事情了,而且时间轴所使用的后端服务还是我十年前写的一个基于
Python+Flask的博客。近几年我一直在使用 usememos 作为个人朋友圈的替代品,此次也是准备将memos利用起来,在博客内嵌入一个新的闲言碎语的页面
实现
我使用的博客系统是我自己写的 Snow静态博客生成器,所以实现也很方便。
首先添加一个新的页面 content/pages/memos.org
#+TITLE: 闲言碎语 #+PROPERTY: SLUG memos #+PROPERTY: COMMENT True #+begin_export html <div id="memos" data-src="https://memos.libforest.com"> <div class="entry-loading"> <i class="fa fa-spinner fa-spin"></i> <span>加载中...</span> </div> </div> <script type="text/javascript" src="https://s.libforest.com/static/js/marked.min.js"></script> <script type="text/javascript" src="/static/js/memos.js"></script> #+end_export
使用 data-src 设置后端 memos 的服务接口,而 memos 的开放接口是 https://{api}/api/v1/memo, 返回数据如下
{
"memos": [
{
"name": "memos/GorXqRpEUPCE3jVjY9pp8W",
"state": "NORMAL",
"createTime": "2025-11-11T08:57:38Z",
"updateTime": "2025-11-11T08:57:38Z",
"content": "测试图片",
"pinned": false,
"resources": [
{
"name": "resources/VPqiT6yFj2nBgyGsKtUWjj",
"filename": "02.png",
"type": "image/png",
"size": "1107605",
"memo": "memos/GorXqRpEUPCE3jVjY9pp8W"
}
]
}
],
"nextPageToken": "CAoQCg=="
}
使用JS请求就是
document.addEventListener("DOMContentLoaded", async () => { let dom = document.querySelector("#memos"); let api = dom.getAttribute("data-src"); if (api && api != "") { let resp = await fetch(`${api}/api/v1/memos`); let data = await resp.json(); console.log(data.memos); } });
注意:
我正在使用的memos版本在查询接口上的参数需要进行一层转换,必须使用生成的protobuf文件才行,这在单独的JS文件中不好实现,所以暂不支持添加参数查询,目前也只是显示第一页总共10条的数据,这对于我来说已经足够了,如果有需要下一页 ,可以利用返回数据里的 nextPageToken,将其作为查询参数添加到请求URL中
`${api}/api/v1/memos?page_token=${nextPageToken}`
获取到数据后就能转换成 HTML
-
内容处理: memos 的内容基于
Markdown,所以我引入了marked.js作为解析库,同时还需要对标签进行解析和渲染const memoTag = { extensions: [{ name: 'memoTag', level: 'inline', start(src) { return src.indexOf('#'); }, tokenizer(src) { const rule = /^#([^\s#]+)(\s*)/; const match = rule.exec(src); if (match) { let html = `<span class="memo-tag">#${match[1]}</span>`; if (match[2].endsWith('\n')) { html = `${html}<br />` } return { type: 'memoTag', raw: match[0], html: html }; } }, renderer(token) { return token.html; } }], }; marked.setOptions({ breaks: true, smartypants: false, }); marked.use(memoTag); console.log(marked.parse(memo.content));
-
资源处理: 资源应该是包括图片、音频、视频等多种类型的,目前我只处理了图片类型,这也是基于我的需求
function renderContent(memo) { let resources = memo.resources.map((r) => { const src = `${api}/file/${r.name}/${r.filename}?thumbnail=true`; const style = "max-height: 16rem;border-radius: 0.5rem;object-fit: contain;"; return `<a href="${src}" data-fancybox="image"><img data-src="${src}" class="lazyload" style="${style}" /></a>`; }); if (resources.length > 0) { return `<div>${marked.parse(memo.content)} <div style="display: flex;gap: 0.5rem; align-items: baseline;">${resources.join("")}</div> </div>`; } return `<div>${marked.parse(memo.content)}</div>`; }
或许可以把该功能作为 shortcodes 使用, 完整代码可以在 memos.js 查看
其它
如果需要一个 memos 客户端,可以试试我写的 红枫笔记,除了支持本地笔记外,还支持 memos、blinko等远程服务的管理
知识共享署名-非商业性使用-相同方式共享4.0国际许可协议