This commit is contained in:
2024-07-30 21:41:51 +08:00
commit 192ef21b12
574 changed files with 70686 additions and 0 deletions

View File

@@ -0,0 +1,116 @@
/**
* AnZhiYu
* for aside archives
*/
"use strict";
hexo.extend.helper.register("aside_archives", function (options = {}) {
const { config } = this;
const archiveDir = config.archive_dir;
const { timezone } = config;
const lang = toMomentLocale(this.page.lang || this.page.language || config.language);
let { format } = options;
const type = options.type || "monthly";
const { transform } = options;
const showCount = Object.prototype.hasOwnProperty.call(options, "show_count") ? options.show_count : true;
const order = options.order || -1;
const compareFunc =
type === "monthly"
? (yearA, monthA, yearB, monthB) => yearA === yearB && monthA === monthB
: (yearA, monthA, yearB, monthB) => yearA === yearB;
const limit = options.limit;
let result = "";
if (!format) {
format = type === "monthly" ? "MMMM YYYY" : "YYYY";
}
const posts = this.site.posts.sort("date", order);
if (!posts.length) return result;
const data = [];
let length = 0;
posts.forEach(post => {
// Clone the date object to avoid pollution
let date = post.date.clone();
if (timezone) date = date.tz(timezone);
const year = date.year();
const month = date.month() + 1;
const lastData = data[length - 1];
if (!lastData || !compareFunc(lastData.year, lastData.month, year, month)) {
if (lang) date = date.locale(lang);
const name = date.format(format);
length = data.push({
name,
year,
month,
count: 1,
});
} else {
lastData.count++;
}
});
const link = item => {
let url = `${archiveDir}/${item.year}/`;
if (type === "monthly") {
if (item.month < 10) url += "0";
url += `${item.month}/`;
}
return this.url_for(url);
};
const len = data.length;
const Judge = limit === 0 ? len : Math.min(len, limit);
result += `<div class="item-headline"><i class="anzhiyufont anzhiyu-icon-archive"></i><span>${this._p(
"aside.card_archives"
)}</span>`;
if (len > Judge) {
result += `<a class="card-more-btn" href="${this.url_for(archiveDir)}/" title="${this._p("aside.more_button")}">
<i class="anzhiyufont anzhiyu-icon-angle-right"></i></a>`;
}
result += '</div><ul class="card-archive-list">';
for (let i = 0; i < Judge; i++) {
const item = data[i];
result += '<li class="card-archive-list-item">';
result += `<a class="card-archive-list-link" href="${link(item)}">`;
result += '<span class="card-archive-list-date">';
result += transform ? transform(item.name) : item.name;
result += "</span>";
if (showCount) {
result += `<div class="card-archive-list-count-group"><span class="card-archive-list-count">${item.count}</span><span>篇</span></div>`;
}
result += "</a>";
result += "</li>";
}
result += "</ul>";
return result;
});
const toMomentLocale = function (lang) {
if (lang === undefined) {
return undefined;
}
// moment.locale('') equals moment.locale('en')
// moment.locale(null) equals moment.locale('en')
if (!lang || lang === "en" || lang === "default") {
return "en";
}
return lang.toLowerCase().replace("_", "-");
};

View File

@@ -0,0 +1,99 @@
/**
* AnZhiYu
* for aside categories
*/
'use strict'
hexo.extend.helper.register('aside_categories', function (categories, options) {
if (!options && (!categories || !Object.prototype.hasOwnProperty.call(categories, 'length'))
) {
options = categories
categories = this.site.categories
}
if (!categories || !categories.length) return ''
options = options || {}
const { config } = this
const showCount = Object.prototype.hasOwnProperty.call(options, 'show_count')
? options.show_count
: true
const depth = options.depth ? parseInt(options.depth, 10) : 0
const orderby = options.orderby || 'name'
const order = options.order || 1
const categoryDir = this.url_for(config.category_dir)
const limit = options.limit === 0 ? categories.length : options.limit
const isExpand = options.expand !== 'none'
const expandClass = isExpand && options.expand === true ? 'expand' : ''
const buttonLabel = this._p('aside.more_button')
const prepareQuery = (parent) => {
const query = {}
if (parent) { query.parent = parent } else { query.parent = { $exists: false } }
return categories.find(query).sort(orderby, order).filter((cat) => cat.length)
}
let expandBtn = ''
const hierarchicalList = (t, level, parent, topparent = true) => {
let result = ''
const isTopParent = topparent
if (t > 0) {
prepareQuery(parent).forEach((cat, i) => {
if (t > 0) {
t = t - 1
let child
if (!depth || level + 1 < depth) {
const childList = hierarchicalList(t, level + 1, cat._id, false)
child = childList[0]
t = childList[1]
}
const parentClass = isExpand && isTopParent && child ? 'parent' : ''
result += `<li class="card-category-list-item ${parentClass}">`
result += `<a class="card-category-list-link" href="${this.url_for(cat.path)}">`
result += `<span class="card-category-list-name">${cat.name}</span>`
if (showCount) {
result += `<span class="card-category-list-count">${cat.length}</span>`
}
if (isExpand && isTopParent && child) {
expandBtn = ' expandBtn'
result += `<i class="anzhiyufont anzhiyu-icon-caret-left ${expandClass}"></i>`
}
result += '</a>'
if (child) {
result += `<ul class="card-category-list child">${child}</ul>`
}
result += '</li>'
}
})
}
return [result, t]
}
const list = hierarchicalList(limit, 0)
const moreButton = function () {
if (categories.length <= limit) return ''
const moreHtml = `<a class="card-more-btn" href="${categoryDir}/" title="${buttonLabel}">
<i class="anzhiyufont anzhiyu-icon-angle-right"></i></a>`
return moreHtml
}
return `<div class="item-headline">
<i class="anzhiyufont anzhiyu-icon-folder-open"></i>
<span>${this._p('aside.card_categories')}</span>
${moreButton()}
</div>
<ul class="card-category-list${expandBtn}" id="aside-cat-list">
${list[0]}
</ul>`
})

View File

@@ -0,0 +1,13 @@
hexo.extend.helper.register("catalog_list", function (type) {
let html = ``;
hexo.locals.get(type).map(function (item) {
html += `
<div class="catalog-list-item" id="/${item.path}">
<a href="/${item.path}">
${item.name}
</a>
</div>
`;
});
return html;
});

View File

@@ -0,0 +1,58 @@
hexo.extend.helper.register('getArchiveLength', function () {
const { archive_generator: archiveGenerator } = hexo.config
if (archiveGenerator && archiveGenerator.enable === false) return this.site.posts.length
const { yearly, monthly, daily } = archiveGenerator
const { year, month, day } = this.page
if (yearly === false || !year) return this.site.posts.length
const posts = this.site.posts.sort('date')
const compareFunc = (type, y1, m1, d1, y2, m2, d2) => {
switch (type) {
case 'year':
return y1 === y2
case 'month':
return y1 === y2 && m1 === m2
case 'day':
return y1 === y2 && m1 === m2 && d1 === d2
default:
return false
}
}
const generateDateObj = (type) => {
return posts.reduce((dateObj, post) => {
const date = post.date.clone()
const year = date.year()
const month = date.month() + 1
const day = date.date()
const lastData = dateObj[dateObj.length - 1]
if (!lastData || !compareFunc(type, lastData.year, lastData.month, lastData.day, year, month, day)) {
const name = type === 'year' ? year : type === 'month' ? `${year}-${month}` : `${year}-${month}-${day}`
dateObj.push({
name,
year,
month,
day,
count: 1
})
} else {
lastData.count++
}
return dateObj
}, [])
}
const data = this.fragment_cache('createArchiveObj', () => {
const dateObjs = []
if (yearly) dateObjs.push(...generateDateObj('year'))
if (monthly) dateObjs.push(...generateDateObj('month'))
if (daily) dateObjs.push(...generateDateObj('day'))
return dateObjs
})
const name = month ? (day ? `${year}-${month}-${day}` : `${year}-${month}`) : year
return data.find(item => item.name === name).count
})

View File

@@ -0,0 +1,4 @@
hexo.extend.helper.register("get_version", function () {
const { version } = require("../../package.json");
return version;
});

View File

@@ -0,0 +1,190 @@
/**
* Butterfly
* inject js to head
*/
"use strict";
hexo.extend.helper.register("inject_head_js", function () {
const { darkmode, aside } = this.theme;
const start = darkmode.start || 6;
const end = darkmode.end || 18;
const { theme_color } = hexo.theme.config;
const themeColorLight = (theme_color && theme_color.enable && theme_color.meta_theme_color_light) || "#ffffff";
const themeColorDark = (theme_color && theme_color.enable && theme_color.meta_theme_color_dark) || "#0d0d0d";
const createLocalStore = () => {
return `
win.saveToLocal = {
set: (key, value, ttl) => {
if (ttl === 0) return
const now = Date.now()
const expiry = now + ttl * 86400000
const item = {
value,
expiry
}
localStorage.setItem(key, JSON.stringify(item))
},
get: key => {
const itemStr = localStorage.getItem(key)
if (!itemStr) {
return undefined
}
const item = JSON.parse(itemStr)
const now = Date.now()
if (now > item.expiry) {
localStorage.removeItem(key)
return undefined
}
return item.value
}
}
`;
};
// https://stackoverflow.com/questions/16839698/jquery-getscript-alternative-in-native-javascript
const createGetScript = () => {
return `
win.getScript = (url, attr = {}) => new Promise((resolve, reject) => {
const script = document.createElement('script')
script.src = url
script.async = true
script.onerror = reject
script.onload = script.onreadystatechange = function() {
const loadState = this.readyState
if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
script.onload = script.onreadystatechange = null
resolve()
}
Object.keys(attr).forEach(key => {
script.setAttribute(key, attr[key])
})
document.head.appendChild(script)
})
`;
};
const createGetCSS = () => {
return `
win.getCSS = (url, id = false) => new Promise((resolve, reject) => {
const link = document.createElement('link')
link.rel = 'stylesheet'
link.href = url
if (id) link.id = id
link.onerror = reject
link.onload = link.onreadystatechange = function() {
const loadState = this.readyState
if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
link.onload = link.onreadystatechange = null
resolve()
}
document.head.appendChild(link)
})
`;
};
const createDarkmodeJs = () => {
if (!darkmode.enable) return "";
let darkmodeJs = `
win.activateDarkMode = () => {
document.documentElement.setAttribute('data-theme', 'dark')
if (document.querySelector('meta[name="theme-color"]') !== null) {
document.querySelector('meta[name="theme-color"]').setAttribute('content', '${themeColorDark}')
}
}
win.activateLightMode = () => {
document.documentElement.setAttribute('data-theme', 'light')
if (document.querySelector('meta[name="theme-color"]') !== null) {
document.querySelector('meta[name="theme-color"]').setAttribute('content', '${themeColorLight}')
}
}
const t = saveToLocal.get('theme')
`;
const autoChangeMode = darkmode.autoChangeMode;
if (autoChangeMode === 1) {
darkmodeJs += `
const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches
const isLightMode = window.matchMedia('(prefers-color-scheme: light)').matches
const isNotSpecified = window.matchMedia('(prefers-color-scheme: no-preference)').matches
const hasNoSupport = !isDarkMode && !isLightMode && !isNotSpecified
if (t === undefined) {
if (isLightMode) activateLightMode()
else if (isDarkMode) activateDarkMode()
else if (isNotSpecified || hasNoSupport) {
const now = new Date()
const hour = now.getHours()
const isNight = hour <= ${start} || hour >= ${end}
isNight ? activateDarkMode() : activateLightMode()
}
window.matchMedia('(prefers-color-scheme: dark)').addListener(e => {
if (saveToLocal.get('theme') === undefined) {
e.matches ? activateDarkMode() : activateLightMode()
}
})
} else if (t === 'light') activateLightMode()
else activateDarkMode()
`;
} else if (autoChangeMode === 2) {
darkmodeJs += `
const now = new Date()
const hour = now.getHours()
const isNight = hour <= ${start} || hour >= ${end}
if (t === undefined) isNight ? activateDarkMode() : activateLightMode()
else if (t === 'light') activateLightMode()
else activateDarkMode()
`;
} else {
darkmodeJs += `
if (t === 'dark') activateDarkMode()
else if (t === 'light') activateLightMode()
`;
}
return darkmodeJs;
};
const createAsideStatus = () => {
if (!aside.enable || !aside.button) return "";
return `
const asideStatus = saveToLocal.get('aside-status')
if (asideStatus !== undefined) {
if (asideStatus === 'hide') {
document.documentElement.classList.add('hide-aside')
} else {
document.documentElement.classList.remove('hide-aside')
}
}
`;
};
const createDetectApple = () => {
return `
const detectApple = () => {
if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
document.documentElement.classList.add('apple')
}
}
detectApple()
`;
};
return `<script>(win=>{${
createLocalStore() +
createGetScript() +
createGetCSS() +
createDarkmodeJs() +
createAsideStatus() +
createDetectApple()
}})(window)</script>`;
});

View File

@@ -0,0 +1,149 @@
/**
* AnZhiYu
* @example
* page_description()
* cloudTags(source, minfontsize, maxfontsize, limit)
*/
"use strict";
const { stripHTML, escapeHTML, prettyUrls } = require("hexo-util");
const crypto = require("crypto");
hexo.extend.helper.register('page_description', function () {
const { config, page } = this
let description = page.description || page.content || page.title || config.description
if (description) {
description = escapeHTML(stripHTML(description).substring(0, 150)
.trim()
).replace(/\n/g, ' ')
return description
}
})
hexo.extend.helper.register("get_page_fill_description", function () {
const { config, page } = this;
let description = page.content || page.description || page.title || config.description;
if (description) {
// 使用正则表达式匹配 h1-h6 标签中的文本内容
const regex = /<h[1-6][^>]*>(.*?)<\/h[1-6]>/g;
const headings = [];
let match;
while ((match = regex.exec(description))) {
headings.push(match[0]);
}
const contents = headings.map(heading => {
// 去掉 a 标签及其内容
const text = heading.replace(/<a[^>]*>.*?<\/a>/g, "");
// 去除特殊符号 &,:,; 等
return text.replace(/<\/?[^>]+>|&|:|;|quot;||,|“|”|"|'|#/g, "");
});
// 排除 div.post-ai-description 元素中的内容
const excludedDivRegex = /<div[^>]*class="?post-ai-description"?.*?>[\s\S]*?<\/div>/gi;
description = description.replace(excludedDivRegex, "");
description = escapeHTML(stripHTML(description).trim())
.replace(/\n/g, " ")
.replace(/[^\u4e00-\u9fa5]/gi, "");
return contents.join(", ") + description;
}
});
hexo.extend.helper.register("cloudTags", function (options = {}) {
const env = this;
let source = options.source;
const minfontsize = options.minfontsize;
const maxfontsize = options.maxfontsize;
const limit = options.limit;
const unit = options.unit || "px";
const colorful = options.color || false;
const highlightTags = options.highlightTags || [];
let result = "";
if (limit > 0) {
source = source.limit(limit);
}
const sizes = [];
source.sort("length").forEach(tag => {
const { length } = tag;
if (sizes.includes(length)) return;
sizes.push(length);
});
const length = sizes.length - 1;
source.sort("name").forEach(tag => {
const ratio = length ? sizes.indexOf(tag.length) / length : 0;
const size = minfontsize + (maxfontsize - minfontsize) * ratio;
let style = `font-size: ${parseFloat(size.toFixed(2))}${unit};`;
if (colorful) {
const color =
"rgb(" +
Math.floor(Math.random() * 201) +
", " +
Math.floor(Math.random() * 201) +
", " +
Math.floor(Math.random() * 201) +
")"; // 0,0,0 -> 200,200,200
style += ` color: ${color};`;
}
const matchingTag = highlightTags.find(highlightTag => highlightTag === tag.name);
if (matchingTag) {
style += ` font-weight: 500; color: var(--anzhiyu-lighttext)`;
}
result += `<a href="${env.url_for(tag.path)}" style="${style}">${tag.name}<sup>${tag.length}</sup></a>`;
});
return result;
});
hexo.extend.helper.register("urlNoIndex", function (url = null) {
return prettyUrls(url || this.url, { trailing_index: false, trailing_html: false });
});
hexo.extend.helper.register("md5", function (path) {
return crypto
.createHash("md5")
.update(decodeURI(this.url_for(path)))
.digest("hex");
});
hexo.extend.helper.register('injectHtml', function (data) {
if (!data) return ''
return data.join('')
})
hexo.extend.helper.register("findArchivesTitle", function (page, menu, date) {
if (page.year) {
const dateStr = page.month ? `${page.year}-${page.month}` : `${page.year}`;
const date_format = page.month ? hexo.theme.config.aside.card_archives.format : "YYYY";
return date(dateStr, date_format);
}
const defaultTitle = this._p("page.archives");
if (!menu) return defaultTitle;
const loop = m => {
for (const key in m) {
if (typeof m[key] === "object") {
loop(m[key]);
}
if (/\/archives\//.test(m[key])) {
return key;
}
}
};
return loop(menu) || defaultTitle;
});
hexo.extend.helper.register('isImgOrUrl', function (path) {
const imgTestReg = /\.(png|jpe?g|gif|svg|webp)(\?.*)?$/i
return path.indexOf('//') !== -1 || imgTestReg.test(path)
})

View File

@@ -0,0 +1,86 @@
hexo.extend.generator.register("random", function (locals) {
const config = hexo.config.random || {};
const themeConfig = hexo.theme.config;
const pjaxEn = themeConfig.pjax.enable;
const randomNumberFriend = themeConfig.footer.list.randomFriends || 0;
const posts = [];
const link = locals.data.link || [];
for (const post of locals.posts.data) {
if (post.random !== false) posts.push(post.path);
}
const link_list = [];
link.forEach(element => {
element.link_list.forEach(link_list_item => {
link_list.push(link_list_item);
});
});
let result = `var posts=${JSON.stringify(
posts
)};function toRandomPost(){
${pjaxEn ? "pjax.loadUrl('/'+posts[Math.floor(Math.random() * posts.length)]);" : "window.location.href='/'+posts[Math.floor(Math.random() * posts.length)];"}
};`;
if (themeConfig.footer.list.enable && randomNumberFriend > 0) {
result += `var friend_link_list=${JSON.stringify(link_list)};
var refreshNum = 1;
function friendChainRandomTransmission() {
const randomIndex = Math.floor(Math.random() * friend_link_list.length);
const { name, link } = friend_link_list.splice(randomIndex, 1)[0];
Snackbar.show({
text:
"点击前往按钮进入随机一个友链,不保证跳转网站的安全性和可用性。本次随机到的是本站友链:「" + name + "」",
duration: 8000,
pos: "top-center",
actionText: "前往",
onActionClick: function (element) {
element.style.opacity = 0;
window.open(link, "_blank");
},
});
}
function addFriendLinksInFooter() {
var footerRandomFriendsBtn = document.getElementById("footer-random-friends-btn");
if(!footerRandomFriendsBtn) return;
footerRandomFriendsBtn.style.opacity = "0.2";
footerRandomFriendsBtn.style.transitionDuration = "0.3s";
footerRandomFriendsBtn.style.transform = "rotate(" + 360 * refreshNum++ + "deg)";
const finalLinkList = [];
let count = 0;
while (friend_link_list.length && count < ${randomNumberFriend}) {
const randomIndex = Math.floor(Math.random() * friend_link_list.length);
const { name, link, avatar } = friend_link_list.splice(randomIndex, 1)[0];
finalLinkList.push({
name,
link,
avatar,
});
count++;
}
let html = finalLinkList
.map(({ name, link }) => {
const returnInfo = "<a class='footer-item' href='" + link + "' target='_blank' rel='noopener nofollow'>" + name + "</a>"
return returnInfo;
})
.join("");
html += "<a class='footer-item' href='/link/'>更多</a>";
document.getElementById("friend-links-in-footer").innerHTML = html;
setTimeout(()=>{
footerRandomFriendsBtn.style.opacity = "1";
}, 300)
};`;
}
return {
path: config.path || "anzhiyu/random.js",
data: result,
};
});

View File

@@ -0,0 +1,102 @@
/**
* AnZhiYu
* Related Posts
* According the tag
*/
"use strict";
hexo.extend.helper.register("related_posts", function (currentPost, allPosts) {
let relatedPosts = [];
currentPost.tags.forEach(function (tag) {
allPosts.forEach(function (post) {
if (isTagRelated(tag.name, post.tags)) {
const relatedPost = {
title: post.title,
path: post.path,
cover: post.cover,
randomcover: post.randomcover,
weight: 1,
updated: post.updated,
created: post.date,
};
const index = findItem(relatedPosts, "path", post.path);
if (index !== -1) {
relatedPosts[index].weight += 1;
} else {
if (currentPost.path !== post.path) {
relatedPosts.push(relatedPost);
}
}
}
});
});
if (relatedPosts.length === 0) {
return "";
}
let result = "";
const hexoConfig = hexo.config;
const config = hexo.theme.config;
const limitNum = config.related_post.limit || 6;
const dateType = config.related_post.date_type || "created";
const headlineLang = this._p("post.recommend");
relatedPosts = relatedPosts.sort(compare("weight"));
if (relatedPosts.length > 0) {
result += '<div class="relatedPosts">';
result += `<div class="headline"><i class="anzhiyufont anzhiyu-icon-thumbs-up fa-fw" style="font-size: 1.5rem; margin-right: 4px"></i><span>${headlineLang}</span></div>`;
result += '<div class="relatedPosts-list">';
for (let i = 0; i < Math.min(relatedPosts.length, limitNum); i++) {
const cover = relatedPosts[i].cover === false ? relatedPosts[i].randomcover : relatedPosts[i].cover;
const title = this.escape_html(relatedPosts[i].title);
result += `<div><a href="${this.url_for(relatedPosts[i].path)}" title="${title}">`;
result += `<img class="cover" src="${this.url_for(cover)}" alt="cover">`;
if (dateType === "created") {
result += `<div class="content is-center"><div class="date"><i class="anzhiyufont anzhiyu-icon-calendar-days fa-fw"></i> ${this.date(
relatedPosts[i].created,
hexoConfig.date_format
)}</div>`;
} else {
result += `<div class="content is-center"><div class="date"><i class="anzhiyufont anzhiyu-icon-history fa-fw"></i> ${this.date(
relatedPosts[i].updated,
hexoConfig.date_format
)}</div>`;
}
result += `<div class="title">${title}</div>`;
result += "</div></a></div>";
}
result += "</div></div>";
return result;
}
});
function isTagRelated(tagName, TBDtags) {
let result = false;
TBDtags.forEach(function (tag) {
if (tagName === tag.name) {
result = true;
}
});
return result;
}
function findItem(arrayToSearch, attr, val) {
for (let i = 0; i < arrayToSearch.length; i++) {
if (arrayToSearch[i][attr] === val) {
return i;
}
}
return -1;
}
function compare(attr) {
return function (a, b) {
const val1 = a[attr];
const val2 = b[attr];
return val2 - val1;
};
}

View File

@@ -0,0 +1,65 @@
hexo.extend.helper.register("sort_attr_post", function (type) {
// 获取所有文章
var posts_list = hexo.locals.get("posts").data;
var swiper_list = [];
var top_group_list = [];
// 判断是否开启swiper
const swiper_enable = hexo.theme.config.home_top.swiper.enable;
const targetLength = swiper_enable ? 4 : 6;
// 若文章的front_matter内设置了index和描述则将其放到swiper_list内
for (var item of posts_list) {
if (item.swiper_index) {
swiper_list.push(item);
}
if (item.top_group_index) {
top_group_list.push(item);
}
}
// 对swiper_list进行处理使其按照index大小进行排序
function sortNumber(a, b) {
return a.swiper_index - b.swiper_index;
}
// 对top_group_list进行处理使其按照index大小进行排序
function sortNumberGroupList(a, b) {
return a.top_group_index - b.top_group_index;
}
swiper_list = swiper_list.sort(sortNumber);
top_group_list = top_group_list.sort(sortNumberGroupList);
// 排序反转,使得数字越大越靠前
swiper_list = swiper_list.reverse();
top_group_list = top_group_list.reverse();
// 当top_group_list长度小于目标长度时使用最新的可用文章来补足到目标长度
if (top_group_list.length < targetLength) {
const newPosts = posts_list
.filter(item => !top_group_list.includes(item))
.slice(0, targetLength - top_group_list.length);
top_group_list = [...top_group_list, ...newPosts];
}
// 当swiper_list长度小于目标长度时使用最新的可用文章来补足到目标长度
if (swiper_list.length < targetLength) {
const newPosts = posts_list.filter(item => !swiper_list.includes(item)).slice(0, targetLength - swiper_list.length);
swiper_list = [...swiper_list, ...newPosts];
}
// 当top_group_list或swiper_list的长度大于目标长度时使用最新的可用文章来替换已经添加的文章
if (top_group_list.length > targetLength) {
const newPosts = posts_list
.filter(item => !top_group_list.slice(0, targetLength).includes(item))
.slice(0, top_group_list.length - targetLength);
top_group_list = [...top_group_list.slice(0, targetLength), ...newPosts];
}
if (swiper_list.length > targetLength) {
const newPosts = posts_list
.filter(item => !swiper_list.slice(0, targetLength).includes(item))
.slice(0, swiper_list.length - targetLength);
swiper_list = [...swiper_list.slice(0, targetLength), ...newPosts];
}
if (type === "swiper_list") {
return swiper_list;
} else if (type === "top_group_list") {
return top_group_list;
}
});

View File

@@ -0,0 +1,26 @@
hexo.extend.helper.register('tags_page_list', function (type) {
const tags = hexo.locals.get(type);
// Manually sort tags based on the length of tag names
const sortedTags = tags.reduce((acc, tag) => {
const index = acc.findIndex((t) => t.length < tag.length);
if (index === -1) {
acc.push(tag);
} else {
acc.splice(index, 0, tag);
}
return acc;
}, []);
let html = ``;
sortedTags.forEach(function (item) {
html += `
<a href="/${item.path}" id="/${item.path}">
<span class="tags-punctuation">#</span>${item.name}
<span class="tagsPageCount">${item.length}</span>
</a>
`;
});
return html;
});

View File

@@ -0,0 +1,18 @@
hexo.extend.helper.register("getAnimalIcon", function (year) {
var index = parseInt(year) % 12;
var icon = {
0: "anzhiyu-colorful-icon-monkey",
1: "anzhiyu-colorful-icon-rooster",
2: "anzhiyu-colorful-icon-dog",
3: "anzhiyu-colorful-icon-boar",
4: "anzhiyu-colorful-icon-rat",
5: "anzhiyu-colorful-icon-ox",
6: "anzhiyu-colorful-icon-tiger",
7: "anzhiyu-colorful-icon-rabbit",
8: "anzhiyu-colorful-icon-dragon",
9: "anzhiyu-colorful-icon-snake",
10: "anzhiyu-colorful-icon-horse",
11: "anzhiyu-colorful-icon-goat",
};
return icon[index];
});