博客增加闲言碎语页面


Table of Contents

主要用于记录一些短文或吐槽,这些内容不适合作为博客文章出现,该功能类似我很久之前实现过的时间轴,但上次更新时间轴已经是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

  1. 内容处理: 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));
    
  2. 资源处理: 资源应该是包括图片、音频、视频等多种类型的,目前我只处理了图片类型,这也是基于我的需求

    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等远程服务的管理

作者: honmaple
链接: https://honmaple.me/articles/2025/11/博客增加闲言碎语页面.html
版权: CC BY-NC-SA 4.0 知识共享署名-非商业性使用-相同方式共享4.0国际许可协议
wechat
alipay

加载评论