HexoMemos相册接入Memos实现自动更新
SerMs更新记录
本教程基于anzhiyu二改,如果是小白建议先按照鱼佬文档教程搭建好基本页面在看此教程
初衷:
更新相册为了更方便一点,按照鱼的主题教程来搭建的目前只支持手动在 album.yml
文件中更新照片数据
更新完之后还需要 在编译 、 在提交博客到仓库,为了方便更新相册数据因此接入Memos,省去在博客中操作的繁琐步骤
让页面看起来更顺我心意,看不顺眼那就魔改一下下吧~
- 这里在详细说明一下关于
album_list
的问题,在鱼佬的相册页面配置教程中,有一个album_list
和一个url
属性,
当album_list
和url
同时存在的时候,会将url
中的数据覆盖掉album_list
中的数据,所以我觉得要么就都展示,要么就严谨一点做个断言处理,如果url存在链接地址,将会直接忽略album_list
这个只是一个小问题,可以忽略,但是作为强迫症患者的我受不了一点…到时候在做修改吧
效果预览
前提说明
修改步骤
修改main.js
文件地址 themes/anzhiyu/source/js/main.js
,搜代码justified-gallery 圖庫排版
,改动较多建议直接全部复制替换这个方法
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
|
const runJustifiedGallery = function (ele) { const htmlStr = arr => { let str = ""; const replaceDq = str => str.replace(/"/g, """); arr.forEach(i => { const alt = i.alt ? `alt="${replaceDq(i.alt)}"` : ""; const title = i.title ? `title="${replaceDq(i.title)}"` : ""; const dateTime = i.date ? `${new Date(i.date).toISOString()}` : ""; const address = i.address ? i.address : ""; const galleryItem = ` <div class="fj-gallery-item" id="serms-fj-gallery-item"> ${address ? `<div class="tag-address">${address}</div>` : ""} <img src="${i.url}" ${alt + title} class="card_cover"> <div class="serms-album-info-time"> <time class="datatime" datatime=${i.date} style="display: inline;">${i.date}</time> </div> </div> `; str += galleryItem; });
return str; };
const lazyloadFn = (i, arr, limit) => { const loadItem = Number(limit); const arrLength = arr.length; if (arrLength > loadItem) i.insertAdjacentHTML("beforeend", htmlStr(arr.splice(0, loadItem))); else { i.insertAdjacentHTML("beforeend", htmlStr(arr)); i.classList.remove("lazyload"); } window.lazyLoadInstance && window.lazyLoadInstance.update(); return arrLength > loadItem ? loadItem : arrLength; };
function imageInfo(input) { const lines = input.split('\n').filter(line => line.trim() !== ''); const result = [];
lines.forEach(line => { const regex = /\!\[(.*?)\]\((.*?)\)/; const match = line.match(regex); if (match) { const [, titlePart, url] = match; const [, date, address, title] = titlePart.trim().match(/(\d{4}-\d{2}-\d{2})\s(.*?)\s(.*)/); const infoObject = { "url": url.trim(), "address": address.trim(), "date": date.trim(), "title": title.trim(), }; result.push(infoObject); } });
return result; }
const fetchUrl = async url => { try { const [dUrl, mUrl] = url.split("https://").slice(1); const [dUrlResponse, mUrlResponse] = await Promise.all([ fetch(`https://${dUrl}`), fetch(`https://${mUrl}`) ]); if (!dUrlResponse.ok || !mUrlResponse.ok) { throw new Error('Network response was not ok'); } const [dUrlData, mUrlData] = await Promise.all([ dUrlResponse.json(), mUrlResponse.json() ]); const mUrlArryData = imageInfo(mUrlData[0].content); return mUrlArryData.concat(dUrlData); } catch (error) { console.error('Error occurred:', error); return []; } }; const runJustifiedGallery = (item, arr) => { const limit = item.getAttribute("data-limit") ?? arr.length; if (!item.classList.contains("lazyload") || arr.length < limit) { item.innerHTML = htmlStr(arr); item.nextElementSibling.style.display = "none"; } else { if (!item.classList.contains("btn_album_detail_lazyload") || item.classList.contains("page_img_lazyload")) { lazyloadFn(item, arr, limit); const clickBtnFn = () => { const lastItemLength = lazyloadFn(item, arr, limit); fjGallery( item, "appendImages", item.querySelectorAll(`.fj-gallery-item:nth-last-child(-n+${lastItemLength})`) ); anzhiyu.loadLightbox(item.querySelectorAll("img")); if (lastItemLength < Number(limit)) { observer.unobserve(item.nextElementSibling); } };
const observer = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { setTimeout(clickBtnFn(), 100); } }); }); observer.observe(item.nextElementSibling); } else { lazyloadFn(item, arr, limit); const clickBtnFn = () => { const lastItemLength = lazyloadFn(item, arr, limit); fjGallery( item, "appendImages", item.querySelectorAll(`.fj-gallery-item:nth-last-child(-n+${lastItemLength})`) ); anzhiyu.loadLightbox(item.querySelectorAll("img")); lastItemLength < limit && item.nextElementSibling.removeEventListener("click", clickBtnFn); }; item.nextElementSibling.addEventListener("click", clickBtnFn); } }
anzhiyu.initJustifiedGallery(item); anzhiyu.loadLightbox(item.querySelectorAll("img")); window.lazyLoadInstance && window.lazyLoadInstance.update(); };
const addJustifiedGallery = () => { ele.forEach(item => { item.classList.contains("url") ? fetchUrl(item.textContent).then(res => { runJustifiedGallery(item, res); }) : runJustifiedGallery(item, JSON.parse(item.textContent)); }); };
if (window.fjGallery) { addJustifiedGallery(); return; }
getCSS(`${GLOBAL_CONFIG.source.justifiedGallery.css}`); getScript(`${GLOBAL_CONFIG.source.justifiedGallery.js}`).then(addJustifiedGallery); };
|
修改album_detail.css
文件地址 themes/anzhiyu/source/css/_extra/album/album_detail.css
,新增以下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| .fj-gallery-item > .serms-album-info-time{ display: flex; position: absolute; left: 8px; bottom: 10px; padding: 4px 6px; border-radius: 8px; background: var(--anzhiyu-black-op); font-size: 12px; color: var(--anzhiyu-white); transition: 0.3s; z-index: 1; user-select: none; } #serms-fj-gallery-item:hover { cursor: pointer; z-index: 2; transform: scale(1.5) translateZ(0); filter: saturate(1.2) contrast(1); }
|
修改album_detail.pug
文件地址 themes/anzhiyu/layout/includes/page/album_detail.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
| 可在此文件中搜全局搜 else if type == 2 请不要复制这行到代码中 else if type == 2 .type-gallery - const rowHeight = i.rowHeight != "undefined" ? i.rowHeight : 220 - const limit = i.limit != "undefined" ? i.limit : 10 - const lazyload = i.lazyload != "undefined" ? i.lazyload : true - const lazyloadClass = lazyload == true ? "lazyload" : ""; - const btn = i.btnLazyload != "undefined" ? i.btnLazyload : false - const btnLazyloadClass = btn == true ? " btn_album_detail_lazyload" : ""; - const imgType = i.url ? " url" : " data"; - let dataStr = [] - const durl = i.url ?? false + - const murl = i.murl ?? false each item, index in i.album_list each iten, indey in item.image - let obj = {} - obj.url = iten - obj.alt = item.content - obj.title = item.content - obj.address = item.address - obj.date = item.date - dataStr.push(obj) .gallery .fj-gallery(data-rowHeight=rowHeight data-limit=limit class=`${lazyloadClass + btnLazyloadClass + imgType}`) if durl span.gallery-data=durl else span.gallery-data=JSON.stringify(dataStr) + if murl + span.gallery-data=murl if btn button.gallery-load-more span=_p('load_more') i.anzhiyufont.anzhiyu-icon-arrow-down else #album_detail_gallery_load_more
|
最后在album.yml添加murl即可
文件地址 source/_data/album.yml
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
| - class_name: 世界各地夕阳与风景 path_name: /wordScenery type: 2 description: 因为到不了世界各地,所以请网友们发来了各地的夕阳与风景🌇。 cover: https://bu.dusays.com/2023/10/09/6523a7789ed31.jpg top_background: https://jsd.onmicrosoft.cn/gh/Ser-MingShao/HexoPublicStaiciImg/serms/202303271231748.jpg rowHeight: 260 limit: 10 lazyload: false btnLazyload: false url: https://img.serms.top/static/js/wordScenery.json + murl: https://memos.serms.top/api/v1/memo?creatorId=1&tag=wordScenery (这里添加你自己的memos地址) top_link: /album top_btn_text: 返回 album_list: - date: 2022/10/26 01:00:00 content: 湘潭的一角。 address: 湖南湘潭 from: 再吃一口就减肥 image: - https://bu.dusays.com/2023/04/09/64329399db122.webp - date: 2022-10-25 content: 洛阳暴雨后的天空。 address: 河南洛阳 from: SerMs image: - https://bu.dusays.com/2023/04/09/64329399db122.webp - https://bu.dusays.com/2023/04/09/64329399db2e1.webp
|
memos演示
我这里是有三个细分相册,所以创建memostag
的时候根据细分相册名称来定义的,这里没有强制性要求,自己自定义即可
书写格式如上,将你的memosApi放入album.yaml文件中,在上文中有说明
如果不想让图片在memos上展示,可以使用Markdown中代码块的写法,一样适用