Solitude 1.4.7版本开始,主题移除了内置的动态即刻短文功能。
每个人使用习惯都不一样。众口难调。对于部分用户来说,这可能是一个非常不友好的改动。

当然,如果你希望继续使用动态即刻短文,你可以通过魔改进行实现此功能。

本篇教程基于 Hexo 6.3.0 & Solitude 1.9.1 的动态即刻短文魔改教程 📝

如果没有服务器可以搭建memos,可以使用iCat自用的memos服务。

效果预览

创建数据

  • 创建并修改 [blogRoot]/source/essay/index.md 页面。
1
2
3
4
5
6
7
8
9
10
11
12
---
title: 即刻短文
date: 2024-01-16 16:15:08
type: says
cover: 'https://img.meuicat.com/banner'
desc: 封の碎碎念
leftend: '使用 即刻短文动态部署版 构建'
rightbtn: '部署项目'
rightbtnlink: /posts/d525bbc8.html
---

<!-- 页面内容 -->
  • 删减 [blogRoot]/themes/Solitude/layout/includes/inject/body.pug 文件中,第九十三至九十四行的内容。
    + 号直接删除 即是正常缩进)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    ···

if theme.aside.siteinfo.uv
carousel_swiper()
if page.type === 'says' && theme.says.enable
script.
- GLOBAL_CONFIG.lightbox && utils.lightbox(document.querySelectorAll(".bber-content-img img"));
- sco.changeTimeFormat(document.querySelectorAll('.bber-info-time time'))
+ setTimeout(() => {
+ GLOBAL_CONFIG.lazyload.enable && utils.lazyloadImg();
+ GLOBAL_CONFIG.lightbox && utils.lightbox(document.querySelectorAll(".bber-content-img img"));
+ sco.changeTimeFormat(document.querySelectorAll('.item time'));
+ sco.refreshWaterFall();
+ }, 800)
+ if is_home() && theme.says.enable && theme.says.home_mini
+ script.
+ setTimeout(() => {
+ sco.initbbtalk();
+ }, 500)
if theme.busuanzi && (theme.aside.siteinfo.uv || theme.aside.siteinfo.pv)

···
  • 删减 [blogRoot]/themes/Solitude/scripts/filter/checkThemeConfig.js 文件中,第十二至十六行的内容。
    + 号直接删除 即是正常缩进)
1
2
3
4
5
6
7
8
9
10
11
    ···

}
- if (theme.says.enable && !data.essay) {
- logger.error('\n 启用说说的情况下,必须提供 essay 数据文件!\n 请新建 essay.yaml。');
- logger.error('\n If says is enabled, essay data must be supplied! \n Please create essay.yaml.');
- process.exit(-1);
- }
if (theme.footer.randomlink && !data.links){

···
  • 删增 [blogRoot]/themes/Solitude/source/css/_page/says.styl 样式文件中,第九十五至一百六十三行的内容。
    + 号直接删除 即是正常缩进)
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
    ···

.goComment
position: absolute
top: 0
right: 0

- div
- &.bber-content
- display flex
- flex-direction initial
- flex-wrap wrap
- border-radius 12px
- width 100%
- height 100%
-
- & > section
- & > ul
- & > li
- &.item
- margin-bottom 1rem
-
- if hexo-config('says.style') == 1
- .bber-bottom
- display flex
- justify-content space-between
- width 100%
- user-select none
-
- .bber-info
- display flex
- align-items center
-
- .fa-rectangles-mixed
- margin-right 8px
-
- .bber-info-time
- color var(--efu-fontcolor)
- font-size .7rem
- background-color var(--efu-gray-op)
- padding 0 8px
- border-radius 20px
- cursor default
- display flex
- align-items center
-
- i
- margin-right 8px
- font-size 16px
-
- .datafrom
- order 2
- color var(--efu-secondtext)
- font-size .7rem
- margin-left 8px
-
- small
- font-size .7rem
-
- .bber-content-link
- display flex
- margin-left .5rem
- color var(--efu-secondtext)
- font-size .7rem
- align-items center
- background-color rgba(245, 108, 108, .13)
- padding 0 8px
- border-radius 20px
-
- &:hover
- background-color var(--efu-main)
- color var(--efu-white)
-
- i
- margin-right 3px
- font-size 16px
+ .bber-content
+ span::after
+ content ''
+ margin-right .5rem
+
+ a
+ padding 0 4px
+ box-decoration-break clone
+ -webkit-box-decoration-break clone
+ border-radius 4px
+ color rgb(245, 108, 108)
+
+ &:hover
+ color var(--efu-fontcolor)
+ background var(--efu-main)
+
+ .bber-info
+ display flex
+ align-items center
+ margin-top 4px
+
+ div
+ display flex
+ align-items center
+ margin-left .5rem
+ font-size 14px
+ color var(--efu-secondtext)
+ gap 4px
+
+ &:first-child
+ margin-left 0
+
+ i
+ font-size 14px
+
+ .bber-info-top
+ color rgba(245, 108, 108, .8)
+ gap 6px
+
+ i
+ display inline-flex
+ transform rotateZ(35deg)
+
+ .bber-loading
+ position revert !important
+ margin 0 auto
+
+ div
+ &.bber-content
+ display flex
+ flex-direction initial
+ flex-wrap wrap
+ border-radius 12px
+ width 100%
+ height 100%
+
+ & > section
+ & > ul
+ & > li
+ &.item
+ margin-bottom 1rem
+
+ if hexo-config('says.style') == 1
+ .bber-bottom
+ display flex
+ justify-content space-between
+ width 100%
+ user-select none
+
+ .bber-info
+ display flex
+ align-items center
+
+ div
+ margin-left .5rem
+
+ &:first-child
+ margin-left 0
+
+ .fa-rectangles-mixed
+ margin-right 8px
+
+ .bber-info-time,
+ .bber-info-from,
+ .bber-info-top
+ color var(--efu-fontcolor)
+ font-size .7rem
+ background-color var(--efu-gray-op)
+ padding 0 8px
+ border-radius 20px
+ cursor default
+ display flex
+ align-items center
+
+ i
+ margin-right 8px
+ font-size 16px
+
+ .bber-info-time
+ .datafrom
+ order 2
+ color var(--efu-secondtext)
+ font-size .7rem
+ margin-left 8px
+
+ small
+ font-size .7rem
+
+ .bber-content-link
+ display flex
+ margin-left .5rem
+ color rgb(103, 194, 58)
+ font-size .7rem
+ align-items center
+ background-color rgba(103, 194, 58, 0.13)
+ padding 0 8px
+ border-radius 20px
+
+ &:hover
+ background-color var(--efu-main)
+ color var(--efu-white)
+
+ i
+ margin-right 3px
+ font-size 16px
+
+ .bber-info-top
+ background-color rgba(245, 108, 108, .13)
+ color rgb(245, 108, 108)
+
+ i
+ display inline-flex
+ transform rotateZ(35deg)
+
+ .bber-reply
+ margin 0 0 0 .5rem

.count
color var(--efu-secondtext)
font-size .8rem

···
完整Stylus样式
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
if hexo-config('says.home_mini')
#bbTimeList
background var(--efu-card-bg)
border-radius 12px
display flex
white-space nowrap
overflow hidden
border var(--style-border)
transition .3s
height 50px
width 100%
justify-content space-between
user-select none
align-items center
padding .5rem 1rem

&.more-page
margin-bottom 0

if hexo-config('hometop.enable')
margin-bottom 1rem

+maxWidth1300()
if hexo-config('hometop.enable')
margin-bottom 1rem
animation slide-in .6s 0s backwards

+minWidth1300()
if hexo-config('hometop.enable')
margin-bottom .5rem
animation slide-in .6s 0s backwards
&:hover
border var(--style-border-hover)
box-shadow var(--efu-shadow-main)

+maxWidth768()
margin 0
background var(--efu-background)
border none
i.bber-logo,
i.bber-gotobb
transition .3s
cursor pointer

&:hover
opacity .8
color var(--efu-theme)

i.bber-logo
font-size 2rem
margin-right 1rem

i.bber-gotobb
font-size 16px
margin-left 1rem

if hexo-config('says.enable')
#bber
margin-top 1rem
width 100%

if hexo-config('says.style') == 2
.meta
display flex
align-items center
line-height 1.5
position relative
width 100%
margin-bottom 4px

.avatar
margin 0
width 50px
height 50px
border-radius 10px

.info
display flex
flex-direction column
margin-left 10px

span.bber_nick
color var(--efu-main)
font-size .9rem

time.bber_date
font-size 14px
opacity .6

.goComment
position: absolute
top: 0
right: 0

.bber-content
span::after
content ''
margin-right .5rem

a
padding 0 4px
box-decoration-break clone
-webkit-box-decoration-break clone
border-radius 4px
color rgb(245, 108, 108)

&:hover
color var(--efu-fontcolor)
background var(--efu-main)

.bber-info
display flex
align-items center
margin-top 4px

div
display flex
align-items center
margin-left .5rem
font-size 14px
color var(--efu-secondtext)
gap 4px

&:first-child
margin-left 0

i
font-size 14px

.bber-info-top
color rgba(245, 108, 108, .8)
gap 6px

i
display inline-flex
transform rotateZ(35deg)

.bber-loading
position revert !important
margin 0 auto

div
&.bber-content
display flex
flex-direction initial
flex-wrap wrap
border-radius 12px
width 100%
height 100%

& > section
& > ul
& > li
&.item
margin-bottom 1rem

if hexo-config('says.style') == 1
.bber-bottom
display flex
justify-content space-between
width 100%
user-select none

.bber-info
display flex
align-items center

div
margin-left .5rem

&:first-child
margin-left 0

.fa-rectangles-mixed
margin-right 8px

.bber-info-time,
.bber-info-from,
.bber-info-top
color var(--efu-fontcolor)
font-size .7rem
background-color var(--efu-gray-op)
padding 0 8px
border-radius 20px
cursor default
display flex
align-items center

i
margin-right 8px
font-size 16px

.bber-info-time
.datafrom
order 2
color var(--efu-secondtext)
font-size .7rem
margin-left 8px

small
font-size .7rem

.bber-content-link
display flex
margin-left .5rem
color rgb(103, 194, 58)
font-size .7rem
align-items center
background-color rgba(103, 194, 58, 0.13)
padding 0 8px
border-radius 20px

&:hover
background-color var(--efu-main)
color var(--efu-white)

i
margin-right 3px
font-size 16px

.bber-info-top
background-color rgba(245, 108, 108, .13)
color rgb(245, 108, 108)

i
display inline-flex
transform rotateZ(35deg)

.bber-reply
margin 0 0 0 .5rem

.count
color var(--efu-secondtext)
font-size .8rem

p
margin 0

.datafrom
i
margin-right 4px

.bber-music
width 100%
height 90px
margin .5rem 0
border-radius 8px
overflow hidden
border var(--style-border-always)
background var(--efu-secondbg)

.aplayer-lrc
display none

.aplayer
margin 0

.aplayer-info
.aplayer-music
height 23px

.aplayer-title
font-size .8rem
font-weight 700
margin 0
color var(--efu-black)

.aplayer-controller
align-items center

.aplayer-bar-wrap
padding 0

.aplayer-bar
background var(--efu-gray)
height 8px
border-radius 12px
transition .3s
overflow hidden

.aplayer-played
height 100%
border-radius 12px

.aplayer-thumb
display none

.aplayer-loaded
height 100%
border-radius 12px

&:hover
.aplayer-bar
height 12px

.aplayer-time
position initial

&.aplayer-withlrc
.aplayer-pic
height 82px
width 82px
margin 4px
border-radius 4px

.bber-video
position relative
padding 30% 50%
margin 0.5rem 0

.bber-content-img
height 100px
margin auto
margin-top 0.2rem
margin-bottom 0.3rem
margin-left 0
border-radius 12px
overflow hidden
display flex
position relative

img
margin-right 10px
object-fit cover
max-height 100%
border-radius 12px
min-height 100px
height 100px

.bber-content
.datacont
order 0
font-size .8rem
font-weight 700
color var(--efu-fontcolor)
width 100%
line-height 1.38
border-radius 12px
margin-bottom .5rem
display flex
flex-direction column
text-align justify

.timeline
ul
li
&.item
position relative
width 32%
border var(--style-border-always)
border-radius 12px
padding 1rem 1rem .5rem
transition .3s
display flex
flex-direction column
flex-wrap nowrap
justify-content space-between
align-items flex-start
background var(--efu-card-bg)
box-shadow var(--efu-shadow-border)
margin-right 2%

+maxWidth1300()
width 49%
margin-right 1%

+maxWidth768()
width 100%
margin-right 0
padding 16px 20px

hr
display flex
position relative
margin 8px 0
border 1px dashed var(--efu-theme-op)
width 100%

&:hover
border var(--style-border-hover)

ul
&.list
display flex
flex-direction row
flex-wrap wrap
justify-content space-between

li
&.item
display flex
flex-direction column
flex-wrap nowrap
align-items flex-start

#bber .bber-video video,
#bber .bber-video iframe
position absolute
width 100%
height 100%
left 0
top 0
margin 0
border-radius 8px
border var(--style-border)

#bber-tips
font-size 14px
display flex
justify-content center
margin-top 1rem
color var(--efu-secondtext)

#bber-talk
width 100%
height 25px
line-height 25px
display flex
flex-direction column

.li-style
width auto
max-width 100%
height 25px
text-align center
overflow hidden
text-overflow ellipsis
transition .3s
display flex
justify-content center
align-items center
font-weight 700
margin auto
cursor pointer
white-space nowrap

.solitude
font-size 1rem
margin-left .5rem

#bbtalk
overflow hidden
width 100%
text-overflow ellipsis
white-space nowrap

#bbTimeList
.li-style
&:hover
color var(--efu-theme)
transition .3s
  • _config.Solitude.yml 主题配置文件中,在 says 配置项中新增link。
    + 号直接删除 即是正常缩进)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 即刻短文
# talk now
# 前置要求:需配置即刻短文页面
# Pre-requirements: talk now page needs to be configured
says:
enable: true
# 主页的即刻轮播条
# Talk carousel bar on the homepage
home_mini: true
# 1:张洪heo样式 / 2:Leonus样式
# 1: Zhang Hong heo style / 2: Leonus style
style: 2
# 即刻短文仅展示前n条
# Talk short text only shows the first n
strip: 30
+ # 动态短文数据地址
+ # Dynamic short text data address
+ link: https://memos.meuicat.com/api/v1/memo?creatorId=1&tag=说说
  • 根据以下两种适配方案二选一,按需求选择。

Json适配

  • 替换 [blogRoot]/themes/Solitude/layout/includes/page/says.pug 页面所有内容。
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
include ../widgets/page/banner
if theme.says.enable
#bber
section.timeline.page-1
ul.list.waterfall
.bber-loading
img(src="https://yife68.gitee.io/icat-pic/blog/loading.svg")
script.
(async function () {
const response = await fetch('!{url_for(theme.says.link)}');
const data = await response.json();
const strip = !{theme.says.strip};
let items = [],
topitem = [],
essayTips = '',
listResult = '';

const processedData = await Promise.all(data[0].essay_list.map(async (item) => {
const formatdata = await essayFormat(item);
if (!formatdata) return null;
if (item.top) {
topitem.push(formatdata);
} else {
items.push(formatdata);
}
return formatdata;
}));

essayTips = strip === -1 || strip >= items.length ? `<div id="bber-tips">- 已展开所有短文 -</div>` : (items = items.slice(0, strip), `<div id="bber-tips">- 只展示最近 ${strip} 条短文 -</div>`);

document.getElementsByClassName('list')[0].innerHTML = topitem.concat(items).filter(item => item !== null).join('');
document.querySelector("#bber").insertAdjacentHTML("beforeend", essayTips);
})();
case theme.says.style
when 1
script.
async function essayFormat(item) {
let image = '',
video = '',
type = '';
if (item.image) item.image.map(e => image += `<img src="${e.split(' || ')[0]}" ${e.split(' || ').length > 1 ? `alt='${e.split(' || ')[1]}'` : ''} />`).join('');
let aplayer = item.aplayer ? `<div class="bber-music"><meting-js server="${item.aplayer.server}" type="song" id="${item.aplayer.id}" mutex="true" preload="none" theme="var(--efu-main)" data-lrctype="0"></meting-js></div>` : '';
if (item.video) video = item.video.player ? `<div class="bber-video"><video src="${item.video.player}" controls="controls" style="object-fit: cover;"></video></div>` : item.video.bilibili ? `<div class="bber-video"><iframe src="//player.bilibili.com/player.html?bvid=${item.video.bilibili.match(/(BV\w+)/)[1]}${item.video.autoplay ? '&autoplay=1' : '&autoplay=0'}" scrolling="no" bozrder="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe></div>` : '';
let link = item.link ? ((type = item.link.split(' || ')), `<a class="bber-content-link" href='${type[0].startsWith('/') ? type[0] : (type[0].startsWith('http') ? type[0] : 'https://' + type[0])}' title="${type.length > 1 ? type[1] : '跳转到短文指引的链接' }" target="_blank"><i class="solitude st-link-m-line"></i>链接</a>`) : '';

return `
<li class="item">
<div id="bber-content">
${item.content ? `<p class="bber-content">${item.content}</p>` : ''}
${image ? `<div class="bber-content-img">${image}</div>` : ''}
</div>
${aplayer}
${video}
<hr>
<div class="bber-bottom">
<div class="bber-info">
<div class="bber-info-time">
<i class="solitude st-calendar-todo-fill"></i>
<time class="datatime" datetime="${item.date}"></time>
</div>
${link}
${item.from ? `<div class="bber-info-from"><span>${item.from}</span></div>` : ''}
${item.top ? `<div class="bber-info-top"><i class="solitude st-thumbtack-solid"></i>置顶</div>` : ''}
</div>
${item.content ? `<a class="bber-reply goComment" onclick="sco.toTalk('${item.content}')"><i class="solitude st-chat-fill" style="font-size: 1rem;"></i></a>` : ''}
</div>
</li>`;
}
when 2
script.
async function essayFormat(item) {
let image = '',
video = '',
type = '';
if (item.image) item.image.map(e => image += `<img src="${e.split(' || ')[0]}" ${e.split(' || ').length > 1 ? `alt='${e.split(' || ')[1]}'` : ''} />`).join('');
let aplayer = item.aplayer ? `<div class="bber-music"><meting-js server="${item.aplayer.server}" type="song" id="${item.aplayer.id}" mutex="true" preload="none" theme="var(--efu-main)" data-lrctype="0"></meting-js></div>` : '';
if (item.video) video = item.video.player ? `<div class="bber-video"><video src="${item.video.player}" controls="controls" style="object-fit: cover;"></video></div>` : item.video.bilibili ? `<div class="bber-video"><iframe src="//player.bilibili.com/player.html?bvid=${item.video.bilibili.match(/(BV\w+)/)[1]}${item.video.autoplay ? '&autoplay=1' : '&autoplay=0'}" scrolling="no" bozrder="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe></div>` : '';
let link = item.link ? ((type = item.link.split(' || ')), `<a class="bber-content-link" href='${type[0].startsWith('/') ? type[0] : (type[0].startsWith('http') ? type[0] : 'https://' + type[0])}' target="_blank">${type.length > 1 ? ('@' + type[1]) : '跳转到短文指引的链接' }</a>`) : '';

return `
<li class="item">
<div class="meta">
<img class="no-lightbox nolazyload avatar" src="!{theme.aside.card.author.img}">
<div class="info">
<span class="bber_nick">#{config.author}</span>
<time class="datetime bber_date" datetime="${item.date}"></time>
</div>
${item.content ? `<a class="bber-reply goComment" onclick="sco.toTalk('${item.content}')"><i class="solitude st-chat-fill" style="font-size: 1rem;"></i></a>` : ''}
</div>
<div id="bber-content">
${item.content ? `<p class="bber-content"><span>${item.content}</span>${link}</p>` : ''}
${image ? `<div class="bber-content-img">${image}</div>` : ''}
</div>
${aplayer}
${video}
<div class="bber-bottom">
<div class="bber-info">
${item.top ? `<div class="bber-info-top"><i class="solitude st-thumbtack-solid"></i>置顶</div>` : ''}
${item.from ? `<div class="bber-info-from"><span>${item.from}</span></div>` : ''}
</div>
</div>
</li>`;
}

数据文件

  • JSON文件可参照以下格式
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
[
{
"class_name": "即刻短文",
"essay_list": [
{
"content": "园长新造型!爱死",
"date": "2023/08/01 17:12:30",
"video": {
"bilibili": "//player.bilibili.com/player.html?aid=701381935&bvid=BV1dm4y1L7vj&cid=1212026428&page=1",
"autoplay": true
}
},
{
"content": "这辈子都不想完善项目了 😭 两点了 一看才搓完三分之一..",
"date": "2023/08/01 02:02:44",
"video": {
"player": "https://meuicat.com/video/1.mp4"
}
},
{
"content": "让我看看是谁在路上都还在敲键盘 噢 原来是我自己啊..",
"date": "2023/07/31 15:54:26",
"from": "iPhone XR",
"top": true
},
{
"content": "落班 烧个排骨778~",
"date": "2023/07/26 17:55:36",
"from": "iPhone XR",
"image": [
"https://s11.ax1x.com/2023/07/26/pCjWbY4.jpg || 吃吃吃",
"https://s11.ax1x.com/2023/07/26/pCjWqfJ.jpg"
]
},
{
"content": "嘘..听歌..睡觉...",
"date": "2023/07/20 00:38:41",
"aplayer": {
"server": "netease",
"id": "1430702919"
},
"top": true
},
{
"content": "人生应该是一个轴对称的形状,最后失去的,也就是最开始拥有的。现在没人记得你的生日,有好处也有坏处,至少我是这么理解的。但无论是好还是坏,忍一忍,都会很快过去的",
"date": "2023/07/19 01:48:36",
"from": "iPhone XR",
"link": "/blog/64"
},
{
"content": "用堆AI重绘一下我最爱的头像(图一 👉 图二)",
"date": "2023/07/06 16:30:32",
"from": "iPhone XR",
"link": "/blog/61 || 堆友Ai",
"image": [
"https://img.meuicat.com/posts/2023/7/10.webp",
"https://img.meuicat.com/posts/2023/7/11.webp"
]
},
{
"content": "",
"date": "2023/06/30 08:26:22",
"aplayer": {
"server": "netease",
"id": "2009974513"
}
}
]
}
]
参数 释义 注意事项
content 【选填】说说内容 /
date 【必填】说说发布的时间 /
image 【可选】说说图片 图片的描述可在链接后以“||”分割开。如:”https://img.meuicat.com/posts/2023/7/11.webp || 亦小封”
aplayer 【可选】音乐播放器 /
aplayer.server 【必填】音乐播放器的服务器 目前仅支持填写:netease、tencent
aplayer.id 【必填】音乐ID 只能填写单曲id
video 【可选】视频 /
video.player 【选填】video视频播放器 /
video.bilibili 【选填】bilibili视频 必须是b站带BV号的视频链接
video.autoplay 【选填】bilibili视频是否自动播放 如需自动播放,请填写true
from 【可选】标识符,无实际意义 /
link 【可选】外部链接 链接描述可在链接后以“||”分割开。如:”https://meuicat.com/ || MeuiCat”

即刻Mini

  • 删减 [blogRoot]/themes/Solitude/layout/includes/widgets/home/bbTimeList.pug 文件中,第五至十七行的内容。
    + 号直接删除 即是正常缩进)
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
.bbTimeList.container#bbTimeList(class=is_home_first_page() ? '' : 'more-page')
i.bber-logo.solitude.st-bblogo(onclick=`pjax.loadUrl('/essay/')`)
.swiper-container.swiper-no-swiping.swiper-container-initialized.swiper-container-vertical.swiper-container-pointer-events#bbtalk(tabindex="-1" onclick=`pjax.loadUrl('/essay/')`)
.swiper-wrapper#bber-talk
- each item, i in site.data.essay.essay_list.slice(0, 10)
- .li-style.swiper-slide
- | #{item.content}
- if item.image
- i.solitude.st-image-fill
- else if item.aplayer
- i.solitude.st-disc-fill
- else if item.video
- i.solitude.st-video-fill
- else if item.bilibili
- i.solitude.st-bilibili-line
- else if item.link
- i.solitude.st-links
+ .li-style.bber-loading(style="text-align: center") 正在加载...
+ script.
+ (async function () {
+ const response = await fetch('!{url_for(theme.says.link)}');
+ const data = await response.json();
+ const list = data[0].essay_list.slice(0, 10).map(item => {
+ let type = item.image ? '【图片】' : item.aplayer ? '【音乐】' : item.video ? '【视频】' : '';
+ return `<div class="li-style swiper-slide">${item.content + type}</div>`
+ });
+ document.querySelector('#bber-talk').innerHTML = list.join(' ');
+ })()
i.bber-gotobb.solitude.st-right-btn-fill(title=_p('home.bbtime.text') onclick=`pjax.loadUrl('/essay/')`)
图标版Mini
1
2
3
4
5
6
7
8
9
10
11
+            .li-style.bber-loading(style="text-align: center") 正在加载...
+ script.
+ (async function () {
+ const response = await fetch('!{url_for(theme.says.link)}');
+ const data = await response.json();
+ const list = data[0].essay_list.slice(0, 10).map(item => {
+ let type = item.image ? `<i class="solitude st-image-fill"></i>` : item.aplayer ? `<i class="solitude st-disc-fill"></i>` : item.video.player ? `<i class="solitude st-video-fill"></i>` : item.video.bilibili ? `<i class="solitude st-bilibili-line"></i>` : '';
+ return `<div class="li-style swiper-slide">${item.content + type}</div>`
+ });
+ document.querySelector('#bber-talk').innerHTML = list.join(' ');
+ })()

Memos适配

  • 替换 [blogRoot]/themes/Solitude/layout/includes/page/says.pug 页面所有内容。
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
include ../widgets/page/banner
if theme.says.enable
#bber
section.timeline.page-1
ul.list.waterfall
.bber-loading
img(src="https://yife68.gitee.io/icat-pic/blog/loading.svg")
script.
(async function () {
let url = '!{url_for(theme.says.link)}';
const baseUrl = url.substring(0, url.indexOf("/", url.indexOf("//") + 2));
const response = await fetch(url);
const data = await response.json();
const strip = !{theme.says.strip};
let items = [],
topitem = [],
essayTips = '';

const processedData = await Promise.all(data.map(async (item) => {
const formatdata = await essayFormat(item,baseUrl);
if (!formatdata) return null;
if (item.content.includes('#top')) {
topitem.push(formatdata);
} else {
items.push(formatdata);
}
return formatdata;
}));

essayTips = strip === -1 || strip >= items.length ? `<div id="bber-tips">- 已展开所有短文 -</div>` : (items = items.slice(0, strip), `<div id="bber-tips">- 只展示最近 ${strip} 条短文 -</div>`);

document.getElementsByClassName('list')[0].innerHTML = topitem.concat(items).filter(item => item !== null).join('');
document.querySelector("#bber").insertAdjacentHTML("beforeend", essayTips);
})();
case theme.says.style
when 1
script.
async function essayFormat(item,baseUrl) {
const contentRegex = /#(.*?)\s|\n/g,
imageRegex = /\!\[(.*?)\]\((.*?)\)/g,
playerRegex = /{\s*player\s*(.*)\s*}/g,
linkRegex = /(?<!\!)\[(.*?)\]\((.*?)\)/g,
topRegex = /#top/g,
fromRegex = /(?<![\w\/])(?<!\{)\{([^{}\s]+)\}(?!\})(?![\w\/])/g;
let time = new Date((item.createdTs - (new Date().getTimezoneOffset() * 60)) * 1000).toISOString(),
content = item.content,
image = '',
img = content.match(imageRegex);
aplayer = content.match(/{\s*music\s*(.*?)\s*(.*?)\s*}/g),
video = content.match(playerRegex),
link = content.match(linkRegex),
type = '',
from = content.match(fromRegex);

if (item.resourceList.length) {
if (!img) img = [];
item.resourceList.forEach(e => {
if (e.externalLink) img.push(e.externalLink);
else img.push(`${baseUrl}/o/r/${e.uid}`);
});
}
if (img) image += img.map(e => `<img src="${e.replace(imageRegex, '$2')}" alt="${e.replace(imageRegex, '$1')}" />`).join('');
aplayer = aplayer ? `<div class="bber-music"><meting-js server="${aplayer[0].match(/\{\s*music\s*(.*?)\s*\d+\s*\}/)[1]}" type="song" id="${aplayer[0].match(/\d+/)[0]}" mutex="true" preload="none" theme="var(--efu-main)" data-lrctype="0"></meting-js></div>` : '';
video = video ? `<div class="bber-video"><video src="${video[0].replace(playerRegex, '$1').trim()}" controls="controls" style="object-fit: cover;"></video></div>` : content.match(/{\s*bilibili\s*(.*?)\s*}/g);
video = Array.isArray(video) ? `<div class="bber-video"><iframe src="//player.bilibili.com/player.html?bvid=${video[0].match(/(BV\w+)/)[1]}${video[0].match(/{\s*bilibili\s*(.*?)\s*true\s*}/g) ? '&autoplay=1' : '&autoplay=0'}" scrolling="no" bozrder="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe></div>` : '';
link = link ? ((type = link[0].replace(linkRegex, '$2')), `<a class="bber-content-link" href='${type.startsWith('/') ? type : (type.startsWith('http') ? type : 'https://' + type)}' title="${link[0].replace(linkRegex, '$1') ? link[0].replace(linkRegex, '$1') : '跳转到短文指引的链接' }" target="_blank"><i class="solitude st-link-m-line"></i>链接</a>`) : '';
from = from ? `<div class="bber-info-from"><span>${from[0].replace(fromRegex, '$1')}</span></div>` : '';
content = content.replace(contentRegex, '').replace(imageRegex, '').replace(/\{(.*?)\}/g, '').replace(linkRegex, '').trim();

return `
<li class="item">
<div id="bber-content">
${content ? `<p class="bber-content">${content}</p>` : ''}
${image ? `<div class="bber-content-img">${image}</div>` : ''}
</div>
${aplayer}
${video}
<hr>
<div class="bber-bottom">
<div class="bber-info">
<div class="bber-info-time">
<i class="solitude st-calendar-todo-fill"></i>
<time class="datatime" datetime="${time}"></time>
</div>
${link}
${from}
${item.content.includes('#top') ? `<div class="bber-info-top"><i class="solitude st-thumbtack-solid"></i>置顶</div>` : ''}
</div>
${content ? `<a class="bber-reply goComment" onclick="sco.toTalk('${content}')"><i class="solitude st-chat-fill" style="font-size: 1rem;"></i></a>` : ''}
</div>
</li>`;
}
when 2
script.
async function essayFormat(item,baseUrl) {
const contentRegex = /#(.*?)\s|\n/g,
imageRegex = /\!\[(.*?)\]\((.*?)\)/g,
playerRegex = /{\s*player\s*(.*)\s*}/g,
linkRegex = /(?<!\!)\[(.*?)\]\((.*?)\)/g,
topRegex = /#top/g,
fromRegex = /(?<![\w\/])(?<!\{)\{([^{}\s]+)\}(?!\})(?![\w\/])/g;
let time = new Date((item.createdTs - (new Date().getTimezoneOffset() * 60)) * 1000).toISOString(),
content = item.content,
image = '',
img = content.match(imageRegex);
aplayer = content.match(/{\s*music\s*(.*?)\s*(.*?)\s*}/g),
video = content.match(playerRegex),
link = content.match(linkRegex),
type = '',
from = content.match(fromRegex);

if (item.resourceList.length) {
if (!img) img = [];
item.resourceList.forEach(e => {
if (e.externalLink) img.push(e.externalLink);
else img.push(`${baseUrl}/o/r/${e.uid}`);
});
}
if (img) image += img.map(e => `<img src="${e.replace(imageRegex, '$2')}" alt="${e.replace(imageRegex, '$1')}" />`).join('');
aplayer = aplayer ? `<div class="bber-music"><meting-js server="${aplayer[0].match(/\{\s*music\s*(.*?)\s*\d+\s*\}/)[1]}" type="song" id="${aplayer[0].match(/\d+/)[0]}" mutex="true" preload="none" theme="var(--efu-main)" data-lrctype="0"></meting-js></div>` : '';
video = video ? `<div class="bber-video"><video src="${video[0].replace(playerRegex, '$1').trim()}" controls="controls" style="object-fit: cover;"></video></div>` : content.match(/{\s*bilibili\s*(.*?)\s*}/g);
video = Array.isArray(video) ? `<div class="bber-video"><iframe src="//player.bilibili.com/player.html?bvid=${video[0].match(/(BV\w+)/)[1]}${video[0].match(/{\s*bilibili\s*(.*?)\s*true\s*}/g) ? '&autoplay=1' : '&autoplay=0'}" scrolling="no" bozrder="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe></div>` : '';
link = link ? ((type = link[0].replace(linkRegex, '$2')), `<a class="bber-content-link" href='${type.startsWith('/') ? type : (type.startsWith('http') ? type : 'https://' + type)}' target="_blank">${link[0].replace(linkRegex, '$1') ? ('@' + link[0].replace(linkRegex, '$1')) : '跳转到短文指引的链接' }</a>`) : '';
from = from ? `<div class="bber-info-from"><i class="solitude st-hashtag-solid"></i>${from[0].replace(fromRegex, '$1')}</div>` : '';
content = content.replace(contentRegex, '').replace(imageRegex, '').replace(/\{(.*?)\}/g, '').replace(linkRegex, '').trim();

return `
<li class="item">
<div class="meta">
<img class="no-lightbox nolazyload avatar" src="!{theme.aside.card.author.img}">
<div class="info">
<span class="bber_nick">#{config.author}</span>
<time class="datetime bber_date" datetime="${time}"></time>
</div>
${content ? `<a class="bber-reply goComment" onclick="sco.toTalk('${content}')"><i class="solitude st-chat-fill" style="font-size: 1rem;"></i></a>` : ''}
</div>
<div id="bber-content">
${content ? `<p class="bber-content"><span>${content}</span>${link}</p>` : ''}
${image ? `<div class="bber-content-img">${image}</div>` : ''}
</div>
${aplayer}
${video}
<div class="bber-bottom">
<div class="bber-info">
${item.content.includes('#top') ? `<div class="bber-info-top"><i class="solitude st-thumbtack-solid"></i>置顶</div>` : ''}
${from}
</div>
</div>
</li>`;
}

数据文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#说说 {标识符} 我是内容 [我是链接](https://meuicat.com) ![](https://img.meuicat.cn/blog/8.png)
<!-- 常规写法 -->

#说说 网易云音乐 {music netease 29947420 }
#说说 腾讯音乐 {music tencent 330977131 }
<!-- 音乐写法 -->

#说说 普通视频 { player https://v.meuicat.com/video/1.mp4 }
#说说 哔哩哔哩手机视频 { bilibili https://m.bilibili.com/video/BV17T4y1A7eW }
#说说 哔哩哔哩网页视频 { bilibili https://www.bilibili.com/video/BV17T4y1A7eW/?spm_id_from=333.1007.tianma.1-3-3.click }
<!-- 视频写法 -->

#说说 #top
我是内容 ![我是图片描述](https://img.meuicat.cn/blog/8.png)![](https://img.meuicat.cn/blog/8.png)
<!-- 置顶写法 -->
参数 释义 注意事项
#标签 【必填】标签,用于区分说说 标签内前缀为#,至少需要有一个
#top 【可选】置顶,用于置顶说说。置顶的说说会排在最前面,不受数量显示限制 /
{自定义标识符} 【可选】标识符,无实际意义,选填 {}内容前后不能有空格和换行
music 【可选】音乐,写法注意规范,以空格隔开每个项。 /
music.service 【必选】music第一项数据,音乐服务商 目前仅支持填写:netease、tencent
music.id 【必选】music第二项数据,音乐id 仅可以是封面id/单曲id/歌单id
bilibili 【可选】bilibili,写法注意规范,以空格隔开每个项。 /
bilibili.link 【必选】bilibili第一项数据,bilibili视频链接 必须是b站带BV号的视频链接
bilibili.autoplay 【可选】bilibili第二项布尔值,bilibili视频是否自动播放。默认不自动播放 如需自动播放,请填写true

关于更多写法问题可以访问iCat - Memos查看

即刻Mini

  • 删减 [blogRoot]/themes/Solitude/layout/includes/widgets/home/bbTimeList.pug 文件中,第五至十七行的内容。
    + 号直接删除 即是正常缩进)
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
.bbTimeList.container#bbTimeList(class=is_home_first_page() ? '' : 'more-page')
i.bber-logo.solitude.st-bblogo(onclick=`pjax.loadUrl('/essay/')`)
.swiper-container.swiper-no-swiping.swiper-container-initialized.swiper-container-vertical.swiper-container-pointer-events#bbtalk(tabindex="-1" onclick=`pjax.loadUrl('/essay/')`)
.swiper-wrapper#bber-talk
- each item, i in site.data.essay.essay_list.slice(0, 10)
- .li-style.swiper-slide
- | #{item.content}
- if item.image
- i.solitude.st-image-fill
- else if item.aplayer
- i.solitude.st-disc-fill
- else if item.video
- i.solitude.st-video-fill
- else if item.bilibili
- i.solitude.st-bilibili-line
- else if item.link
- i.solitude.st-links
+ .li-style.bber-loading(style="text-align: center") 正在加载...
+ script.
+ (async function () {
+ const response = await fetch('!{url_for(theme.says.link)}');
+ const data = await response.json();
+ const list = data.slice(0, 10).map(item => {
+ let data = item.content,
+ content = data.replace(/#(.*?)\s|\n/g, '').replace(/\!\[(.*?)\]\((.*?)\)/g, '').replace(/\{(.*?)\}/g, '').replace(/(?<!\!)\[(.*?)\]\((.*?)\)/g, '').trim();
+ type = data.match(/\!\[(.*?)\]\((.*?)\)/g) ? '【图片】' : data.match(/{\s*music\s*(.*?)\s*(.*?)\s*}/g) ? '【音乐】' : data.match(/{\s*player\s*(.*)\s*}/g) || data.match(/{\s*bilibili\s*(.*?)\s*}/g) ? '【视频】' : '';
+ return `<div class="li-style swiper-slide">${content + type}</div>`
+ });
+ document.querySelector('#bber-talk').innerHTML = list.join(' ');
+ })()
i.bber-gotobb.solitude.st-right-btn-fill(title=_p('home.bbtime.text') onclick=`pjax.loadUrl('/essay/')`)
图标版Mini
1
2
3
4
5
6
7
8
9
10
11
12
13
+            .li-style.bber-loading(style="text-align: center") 正在加载...
+ script.
+ (async function () {
+ const response = await fetch('!{url_for(theme.says.link)}');
+ const data = await response.json();
+ const list = data.slice(0, 10).map(item => {
+ let data = item.content,
+ content = data.replace(/#(.*?)\s|\n/g, '').replace(/\!\[(.*?)\]\((.*?)\)/g, '').replace(/\{(.*?)\}/g, '').replace(/(?<!\!)\[(.*?)\]\((.*?)\)/g, '').trim();
+ type = data.match(/\!\[(.*?)\]\((.*?)\)/g) ? `<i class="solitude st-image-fill"></i>` : data.match(/{\s*music\s*(.*?)\s*(.*?)\s*}/g) ? `<i class="solitude st-disc-fill"></i>` : data.match(/{\s*player\s*(.*)\s*}/g) ? `<i class="solitude st-video-fill"></i>` : data.match(/{\s*bilibili\s*(.*?)\s*}/g) ? `<i class="solitude st-bilibili-line"></i>` : '';
+ return `<div class="li-style swiper-slide">${content + type}</div>`
+ });
+ document.querySelector('#bber-talk').innerHTML = list.join(' ');
+ })()

魔改适配

已适配Butterfly主题,具体魔改教程可前往下方文章查看。