Shuoshuo Feature#
Shuoshuo (θ―΄θ―΄) is a short-status/microblog page type added in Butterfly v5.0. It renders items from a YAML/JSON data source β not from regular Hexo posts β through a custom build-time processing pipeline that makes them behave like posts (Markdown, tag plugin support, timezone correction) without actually being Hexo posts.
Data Sources#
Shuoshuo items come from one of two mutually exclusive sources :
| Source | How it works |
|---|---|
Local (source/_data/shuoshuo.yml) | Processed at build time by the shuoshuoFN helper; serialized into a <script type="application/json"> tag |
Remote (shuoshuo_url: <url> in page front-matter) | Fetched client-side at runtime via fetch(); skips server-side rendering pipeline |
The local path is the only one that goes through Hexo's content rendering pipeline. Remote data is displayed as-is (no server-side Markdown rendering).
Item Schema#
Each item supports the following fields :
| Field | Required | Notes |
|---|---|---|
date | β | YYYY-MM-DD HH:mm:ss |
content | β | Markdown or HTML |
author | β | Falls back to config.author |
avatar | β | Falls back to theme.avatar.img |
key | β | Unique string; required to show per-item comment button |
tags | β | Array of tag strings |
Rendering Pipeline (shuoshuoFN helper)#
The core logic lives in the shuoshuoFN helper in scripts/helpers/page.js. For each local item, it runs four steps in order:
1. Timezone Correction#
Hexo treats all times as UTC. The helper uses moment-timezone to convert each item.date to the site's configured timezone before any rendering .
2. Mock Post Object + before_post_render#
To enable Hexo tag plugins and markdown preprocessors (e.g., syntax highlighters, code fence wrappers), the helper constructs a minimal mock post object β { content: item.content } β and passes it synchronously through all registered before_post_render filters :
const mockPost = { content: item.content }
hexo.execFilterSync('before_post_render', mockPost, { context: hexo })
item.content = mockPost.content
This is the key compatibility shim: plugins that transform post content (e.g., wrapping code blocks in <hexoPostRenderCodeBlock> elements) operate on this mock object just as they would on a real post.
3. Code Block Protection + Tag Plugin Rendering#
Before running tag plugins, the helper extracts any <hexoPostRenderCodeBlock> segments into a side-array and replaces them with <!--CODEBLOCK_N--> placeholders. This prevents the Nunjucks tag renderer from mangling pre-processed code . Tag plugins are then rendered via hexo.extend.tag.env.renderString(); errors are silently swallowed to allow graceful fallback.
4. Markdown Rendering + Placeholder Restoration#
The content is passed through hexo.render.renderSync({ engine: 'markdown' }), then code block placeholders are restored from the side-array .
Pipeline Diagram#
Template & Client-Side Rendering#
The Pug template layout/includes/page/shuoshuo.pug calls shuoshuoFN at build time and embeds the result as JSON :
- const localDate = page.shuoshuo_url ? [] : shuoshuoFN(site.data.shuoshuo, page)
script(type='application/json' id='shuoshuo-data')!= safeJSON(localDate)
Client-side JavaScript (loadShuoshuo) then reads this JSON (or fetches from shuoshuo_url), sorts by date, applies the limit filter, and renders items with pagination β 8 items per page by default .
Lazyload support for images is applied client-side when theme.lazyload.field === 'site' . A shuoshuo:rendered DOM event fires after each page render , useful for third-party integrations.
Known Limitations & Notes#
- Official docs state tag plugins and math formulas are not supported . The code does call
execFilterSync('before_post_render')andtag.env.renderString(), but errors are silently ignored β so tag plugins may partially work, with no guarantee. - Remote
shuoshuo_urlbypasses all server-side rendering; content must be pre-rendered HTML or plain Markdown displayed verbatim. - Comments require a unique
keyfield per item. Per-item comment sections are injected dynamically viaaddCommentToShuoshuo(); each click destroys the previous comment widget and mounts a new one. - PJAX cleanup: The template registers a
pjax:sendlistener to remove the.shuoshuo-navigationelement on navigation, preventing DOM leaks .
Key Files#
| File | Purpose |
|---|---|
scripts/helpers/page.js | shuoshuoFN helper β full rendering pipeline |
layout/includes/page/shuoshuo.pug | Template, JSON embedding, client-side pagination & comments |
source/_data/shuoshuo.yml | Local data file (user-created) |
| Official docs β Theme Pages | Setup guide, field reference |