并非所有想表达或分享的东西都适合写成长文,“即刻短文”可以避免博客短文章过多造成的整站文章质量下降。
最近由于未知原因,域名半寄,Artitalk 用不了了。无意间看到 即刻短文静态部署版 ,遂准备尝试。
实际上先前以多次尝试,又应种种原因不了了之。本次成功,记以备忘。本文所述已按照自用情况进行一定的修改,效果与别人的版本有出入,请慎重使用。
为书写方便,下文如无其他说明,则默认 Hexo 项目根目录为【Blogroot】
。测试使用 Butterfly 主题,其他主题未尝试。
创建数据 进入【Blogroot】/source/_data
目录,创建essay.yml
,其中数据示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 - class_name: 即刻短文 essay_list: - content: test date: 2024 /3/30 - content: test date: 2024 /3/5 - content: 链接示例 date: 2024 /1/25 link: https://info.cern.ch/ - content: 发布者名称 date: 2023 /10/23 08 :00:00 from: Author - content: 图片测试 date: 2022 /10/23 10 :00:00 image: - https://api.vvhan.com/api/bing - content: ThreeJs API 真多丫 date: 2022 /10/19 - content: 歌曲推荐 date: 2022 /09/25 aplayer: server: netease id: 3949477
参数:
参数
备选值/类型
释义
class_name
String
标识符,无实际意义
essay_list
Array
【必选】即刻短文数据列表
essay_list.content
String
必选】短文 文字内容
essay_list.date
Time
【必选】发布时间 格式建议为2022/10/10 00:00:00
essay_list.image
Array
片内容,可填写多张图片
essay_list.from
String
来源,也可以是任何标识
essay_list.link
String
外部链接
essay_list.aplayer
Array
单曲音乐,需 aplayer 支持
essay_list.aplayer.server
String
【essay_list.aplayer 后必选】音乐服务器
essay_list.aplayer.id
String
【essay_list.aplayer 后必选】单曲 id
创建单页 进入【Blogroot】/source
,新建文件夹essay
并在该文件夹下创建index.md
(此处文件夹名称可自定义,之后访问路径需与此相同),在该文件中写入:
1 2 3 4 5 6 7 --- title: 即刻短文 comments: true aside: false top_img: /img/essay_ top_img.png type: essay ---
创建 DOM 文件 进入【Blogroot】/themes/butterfly/layout/includes/page
目录,创建essay.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 #essay_page #bber section.timeline.page-1 ul#waterfall.list each i in site.data.essay each item, index in i.essay_list if index < 30 li.bber-item .bber-content p.datacont= item.content if item.image .bber-container-img each iten, indey in item.image a.bber-content-img(href=item.image[indey], target="_blank", data-fancybox="gallery", data-caption="") img(src=item.image[indey]) .bber-content-noimg if item.aplayer .bber-music .aplayer.no-destroy(data-id=item.aplayer.id data-server=item.aplayer.server data-type="song" data-order="list" data-preload="none" data-autoplay="false" data-mutex="true" data-theme='var(--blogessay-main)') hr .bber-bottom .bber-info .bber-info-time - var datedata = new Date(item.date).toISOString() i.far.fa-clock time.datatime(datetime= item.date)= datedata if item.link a.bber-content-link(target="_blank", title="跳转到短文指引的链接", href=item.link, rel="external nofollow") i.fas.fa-link | 链接 if item.from .bber-info-from i.fas.fa-fire span=item.from .bber-reply(onclick="anzhiyu.commentText(" + `'${item.content}'` + ")") i.fa-solid.fa-message #bber-tips(style='color: var(--blogessay-secondtext);') | - 只展示最近 30 条短文 -
修改文件 在【Blogroot】/themes/butterfly/layout
中找到page.pug
并编辑(上下无关代码已省去):
1 2 3 4 5 6 7 case page.type + when 'essay' + include includes/page/essay.pug when 'tags' include includes/page/tags.pug when 'categories' include includes/page/categories.pug
CSS 与 JS CSS 在【Blogroot】/source/css
目录下创建essay.css
,编辑写入:
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 :root { --blogessay-theme-op : #4259ef23 ; --blogessay-gray-op : #9999992b ; --blogessay-theme-top : var (--blogessay-theme); --blogessay-white : #fff ; --blogessay-white-op : rgba (255 , 255 , 255 , 0.2 ); --blogessay-gray : #999999 ; --blogessay-main : var (--blogessay-theme); --blogessay-main-op : var (--blogessay-theme-op); --blogessay-shadow-border : 0 8px 16px -4px #2c2d300c ; --blogessay-style-border : 1px solid var (--blogessay-card-border); --blogessay-style-border-hover : 1px solid var (--blogessay-main); --blogessay-style-border-avatar : 4px solid var (--blogessay-background); } [data-theme="light" ] { --blogessay-theme : #3b70fc ; --blogessay-theme-deep : #1856fb ; --blogessay-theme-op : #4259ef23 ; --blogessay-fontcolor : #363636 ; --blogessay-background : #f7f9feCC ; --blogessay-secondbg : #f1f3f8 ; --blogessay-card-bg : #ffffff ; --blogessay-card-border : #e3e8f7 ; } [data-theme="dark" ] { --blogessay-theme : #0084ff ; --blogessay-theme-deep : #0076e5 ; --blogessay-theme-op : #0084ff23 ; --blogessay-fontcolor : #f7f7fa ; --blogessay-background : #18171d00 ; --blogessay-secondbg : #30343f ; --blogessay-card-bg : #000000 ; --blogessay-card-border : #42444a ; } #page :has (#essay_page ) { border : 0 ; box-shadow : none !important ; padding : 0 !important ; background : transparent !important ; } #page :has (#essay_page ) .page-title { display : none; } #web_bg ~ .page :has (#essay_page ) { background : var (--blogessay-background); } #bber .bber-container-img { display : flex; align-items : center; justify-content : space-around; width : 100% ; flex-wrap : wrap; margin-bottom : 0.3rem ; } #bber .bber-container-img .bber-content-noimg { width : calc (100% / 4 - 5px ); } #bber .bber-content-img img { object-fit : cover; max-height : 100% ; border-radius : 12px ; } #bber .bber-content-img { height : 100px ; border-radius : 12px ; overflow : hidden; display : flex; position : relative; width : calc (100% / 4 - 5px ); margin-bottom : 10px ; } #bber .bber-content .datacont { order : 0 ; font-size : 0.8rem ; font-weight : 700 ; color : var (--blogessay-fontcolor); width : 100% ; line-height : 1.38 ; border-radius : 12px ; margin-bottom : 0.5rem ; display : flex; flex-direction : column; text-align : justify; } #bber p { margin : 0px ; } #bber div .bber-content { display : flex; flex-flow : wrap; border-radius : 12px ; width : 100% ; height : 100% ; } #bber .timeline ul li .bber-item { position : relative; width : 32% ; border : var (--blogessay-style-border-always); border-radius : 12px ; padding : 1rem 1rem 0.5rem ; transition : all 0.3s ease 0s ; display : flex; flex-flow : column nowrap; justify-content : space-between; align-items : flex-start; background : var (--blogessay-card-bg); box-shadow : var (--blogessay-shadow-border); margin-right : 2% ; } #bber .timeline #waterfall .show { opacity : 1 ; } #bber .timeline #waterfall { opacity : 0 ; transition : all 0.3s ease 0s ; } #bber ul .list { display : flex; flex-flow : row wrap; justify-content : space-between; } #bber { margin-top : 1rem ; width : 100% ; } #bber > section > ul > li .bber-item { margin-bottom : 1rem ; } #bber-tips { font-size : 14px ; display : flex; justify-content : center; margin-top : 1rem ; } #bber .timeline ul li .bber-item hr { display : flex; position : relative; margin : 8px 0px ; border : 1px dashed var (--blogessay-theme-op); width : 100% ; } #bber .bber-info { display : flex; align-items : center; } #bber > section > ul > li > div .bber-info-time ,#bber > section > ul > li > div .bber-info-from { color : var (--blogessay-fontcolor); font-size : 0.7rem ; background-color : var (--blogessay-gray-op); padding : 0px 8px ; border-radius : 20px ; cursor : default; display : flex; align-items : center; } #bber .bber-info .far .fa-clock { margin-right : 4px ; } #bber > section > ul > li > div .bber-info-from span ,#bber > section > ul > li > div .bber-info-from { margin-left : 4px ; } #bber .bber-bottom { display : flex; justify-content : space-between; width : 100% ; margin-top : 10px ; } #bber .bber-bottom .bber-reply { cursor : pointer; } #bber .timeline ul li .bber-item :hover { border : var (--blogessay-style-border-hover); } #bber .bber-content-link { display : flex; margin-left : 0.5rem ; font-size : 0.7rem ; align-items : center; background-color : rgba (245 , 108 , 108 , 0.13 ); color : rgb (245 , 108 , 108 ); padding : 0px 8px ; border-radius : 20px ; } #bber .bber-content-link i { margin-right : 3px ; } #bber .bber-content-link :hover { background-color : var (--blogessay-main); color : var (--blogessay-white); } #bber .bber-music { width : 100% ; height : 90px ; margin : 0.5rem 0 ; border-radius : 8px ; overflow : hidden; border : var (--blogessay-style-border-always); background : var (--blogessay-secondbg); } #bber .aplayer { margin : 0 ; } #bber .aplayer .aplayer-withlrc .aplayer-pic { height : 82px ; width : 82px ; margin : 4px ; border-radius : 4px ; } .bber-music .aplayer .aplayer-withlrc .aplayer-info { padding : 5px 7px 0 ; } #bber .aplayer .aplayer-info .aplayer-music { height : 23px ; } #bber .aplayer .aplayer-info .aplayer-music .aplayer-title { font-size : 0.8rem ; font-weight : 700 ; margin : 0 ; color : var (--blogessay-fontcolor); } #bber .aplayer .aplayer-info .aplayer-controller { align-items : center; } #bber .aplayer .aplayer-info .aplayer-controller .aplayer-bar-wrap { padding : 0 ; } #bber .aplayer .aplayer-info .aplayer-controller .aplayer-time { position : initial; } #bber .aplayer .aplayer-info .aplayer-controller .aplayer-bar-wrap .aplayer-bar { background : var (--blogessay-gray); height : 8px ; border-radius : 12px ; transition : 0.3s ; overflow : hidden; } #bber .aplayer .aplayer-info .aplayer-controller .aplayer-bar-wrap .aplayer-bar .aplayer-loaded { height : 100% ; border-radius : 12px ; } #bber .aplayer .aplayer-info .aplayer-controller .aplayer-bar-wrap .aplayer-bar .aplayer-played { height : 100% ; border-radius : 12px ; } #bber .aplayer .aplayer-info .aplayer-controller .aplayer-bar-wrap .aplayer-bar .aplayer-played .aplayer-thumb { display : none; } #bber .aplayer .aplayer-info .aplayer-controller .aplayer-time { position : initial; } @media screen and (max-width : 1300px ) { #bber .timeline ul li .bber-item { width : 49% ; margin-right : 1% ; } } @media screen and (max-width : 768px ) { #bber .timeline ul li .bber-item { width : 100% ; margin-right : 0px ; } } [data-theme="dark" ] #bber .bber-music .aplayer ,[data-theme="dark" ] #bber .aplayer .aplayer-lrc :before ,[data-theme="dark" ] #bber .aplayer .aplayer-lrc :after { background : var (--blogessay-card-bg); color : var (--blogessay-fontcolor); } #bber .aplayer .aplayer-lrc p { color : var (--blogessay-fontcolor); }
核心 JS 在【Blogroot】/source/js
目录下创建essay.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 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 var percentFlag = false ; function essayScroll ( ) { let a = document .documentElement .scrollTop || window .pageYOffset ; const waterfallResult = a % document .documentElement .clientHeight ; result <= 99 || (result = 99 ); if ( !percentFlag && waterfallResult + 100 >= document .documentElement .clientHeight && document .querySelector ("#waterfall" ) ) { setTimeout (() => { waterfall ("#waterfall" ); }, 500 ); } else { setTimeout (() => { document .querySelector ("#waterfall" ) && waterfall ("#waterfall" ); }, 500 ); } const r = window .scrollY + document .documentElement .clientHeight ; let p = document .getElementById ("post-comment" ) || document .getElementById ("footer" ); (p.offsetTop + p.offsetHeight / 2 < r || 90 < result) && (percentFlag = true ); } function replaceAll (e, n, t ) { return e.split (n).join (t); } var blogessay = { diffDate : function (d, more = false ) { const dateNow = new Date (); const datePost = new Date (d); const dateDiff = dateNow.getTime () - datePost.getTime (); const minute = 1000 * 60 ; const hour = minute * 60 ; const day = hour * 24 ; const month = day * 30 ; let result; const suffix = GLOBAL_CONFIG .date_suffix || {}; const daySuffix = suffix.day || '天前' ; const hourSuffix = suffix.hour || '小时前' ; const minSuffix = suffix.hour || '分钟前' ; if (more) { const monthCount = dateDiff / month; const dayCount = dateDiff / day; const hourCount = dateDiff / hour; const minuteCount = dateDiff / minute; if (monthCount >= 1 ) { result = datePost.toLocaleDateString ().replace (/\//g , "-" ); } else if (dayCount >= 1 ) { result = parseInt (dayCount) + " " + daySuffix; } else if (hourCount >= 1 ) { result = parseInt (hourCount) + " " + hourSuffix; } else if (minuteCount >= 1 ) { result = parseInt (minuteCount) + " " + minSuffix; } else { result = suffix.just ; } } else { result = parseInt (dateDiff / day); } return result; }, changeTimeInEssay : function ( ) { document .querySelector ("#bber" ) && document .querySelectorAll ("#bber time" ).forEach (function (e ) { var t = e, datetime = t.getAttribute ("datetime" ); (t.innerText = blogessay.diffDate (datetime, true )), (t.style .display = "inline" ); }); }, reflashEssayWaterFall : function ( ) { document .querySelector ("#waterfall" ) && setTimeout (function ( ) { waterfall ("#waterfall" ); document .getElementById ("waterfall" ).classList .add ("show" ); }, 500 ); }, commentText : function (e ) { if (e == "undefined" || e == "null" ) e = "好棒!" ; var n = document .getElementsByClassName ("el-textarea__inner" )[0 ], t = document .createEvent ("HTMLEvents" ); if (!n) return ; t.initEvent ("input" , !0 , !0 ); var o = replaceAll (e, "\n" , "\n> " ); (n.value = "> " + o + "\n\n" ), n.dispatchEvent (t); var i = document .querySelector ("#post-comment" ).offsetTop ; window .scrollTo (0 , i - 80 ), n.focus (), n.setSelectionRange (-1 , -1 ), document .getElementById ("comment-tips" ) && document .getElementById ("comment-tips" ).classList .add ("show" ); }, }; blogessay.changeTimeInEssay (); blogessay.reflashEssayWaterFall ();
若直接按照 即刻短文(瀑布流)部署方案 提供的custom.js
可能会出现essay.yml
中date
日期距今不足 30 日导致页面渲染出错的问题。对于那个文件,折中方案可以这样:
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 var blogessay = { diffDate: function (d, more = false) { const dateNow = new Date(); const datePost = new Date(d); const dateDiff = dateNow.getTime() - datePost.getTime(); const minute = 1000 * 60; const hour = minute * 60; const day = hour * 24; const month = day * 30; let result; + const monthCount = dateDiff / month; + const dayCount = dateDiff / day; + const hourCount = dateDiff / hour; + const minuteCount = dateDiff / minute; if (more) { const monthCount = dateDiff / month; const dayCount = dateDiff / day; const hourCount = dateDiff / hour; const minuteCount = dateDiff / minute; if (monthCount >= 1) { result = datePost.toLocaleDateString().replace(/\//g, "-"); } else if (dayCount >= 1) { - result = parseInt(dayCount) + " " + GLOBAL_CONFIG.date_suffix.day; + result = parseInt(dayCount) + " " + daySuffix; } else if (hourCount >= 1) { - result = parseInt(hourCount) + " " + GLOBAL_CONFIG.date_suffix.hour; + result = parseInt(hourCount) + " " + hourSuffix; } else if (minuteCount >= 1) { - result = parseInt(minuteCount) + " " + GLOBAL_CONFIG.date_suffix.min; + result = parseInt(minuteCount) + " " + minSuffix; } else { - result = GLOBAL_CONFIG.date_suffix.just; + result = suffix.just; } } else { result = parseInt(dateDiff / day); } return result; },
waterfall.js 在【Blogroot】/source/js
目录下创建waterfall.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 function waterfall (a ) { function b (a, b ) { var c = window .getComputedStyle (b); return parseFloat (c["margin" + a]) || 0 ; } function c (a ) { return a + "px" ; } function d (a ) { return parseFloat (a.style .top ); } function e (a ) { return parseFloat (a.style .left ); } function f (a ) { return a.clientWidth ; } function g (a ) { return a.clientHeight ; } function h (a ) { return d (a) + g (a) + b ("Bottom" , a); } function i (a ) { return e (a) + f (a) + b ("Right" , a); } function j (a ) { a = a.sort (function (a, b ) { return h (a) === h (b) ? e (b) - e (a) : h (b) - h (a); }); } function k (b ) { f (a) != t && (b.target .removeEventListener (b.type , arguments .callee ), waterfall (a)); } "string" == typeof a && (a = document .querySelector (a)); var l = [].map .call (a.children , function (a ) { return (a.style .position = "absolute" ), a; }); a.style .position = "relative" ; var m = []; l.length && ((l[0 ].style .top = "0px" ), (l[0 ].style .left = c (b ("Left" , l[0 ]))), m.push (l[0 ])); for (var n = 1 ; n < l.length ; n++) { var o = l[n - 1 ], p = l[n], q = i (o) + f (p) <= f (a); if (!q) break ; (p.style .top = o.style .top ), (p.style .left = c (i (o) + b ("Left" , p))), m.push (p); } for (; n < l.length ; n++) { j (m); var p = l[n], r = m.pop (); (p.style .top = c (h (r) + b ("Top" , p))), (p.style .left = c (e (r))), m.push (p); } j (m); var s = m[0 ]; a.style .height = c (h (s) + b ("Bottom" , s)); var t = f (a); window .addEventListener ? window .addEventListener ("resize" , k) : (document .body .onresize = k); }
之后编辑根目录下_config.butterfly.yml
文件,在inject:
将这三个文件引入:
1 2 3 4 5 6 7 8 9 10 inject: head: - <link rel="stylesheet" href="/css/essay.css"/> bottom: - <script async data-pjax src="/js/essay.js"></script> - <script async data-pjax src="/js/waterfall.js"></script>
之后执行 Hexo 三连即可生效。
参考:
https://blog.zhheo.com/p/557c9e72.html https://blog.anheyu.com/posts/c248.html https://meuicat.com/blog/67/index.html