fix theme...
This commit is contained in:
116
themes/anzhiyu/scripts/helpers/aside_archives.js
Normal file
116
themes/anzhiyu/scripts/helpers/aside_archives.js
Normal 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("_", "-");
|
||||
};
|
||||
99
themes/anzhiyu/scripts/helpers/aside_categories.js
Normal file
99
themes/anzhiyu/scripts/helpers/aside_categories.js
Normal 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>`
|
||||
})
|
||||
13
themes/anzhiyu/scripts/helpers/catalog_list.js
Normal file
13
themes/anzhiyu/scripts/helpers/catalog_list.js
Normal 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;
|
||||
});
|
||||
58
themes/anzhiyu/scripts/helpers/findArchiveLength.js
Normal file
58
themes/anzhiyu/scripts/helpers/findArchiveLength.js
Normal 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
|
||||
})
|
||||
4
themes/anzhiyu/scripts/helpers/get_version.js
Normal file
4
themes/anzhiyu/scripts/helpers/get_version.js
Normal file
@@ -0,0 +1,4 @@
|
||||
hexo.extend.helper.register("get_version", function () {
|
||||
const { version } = require("../../package.json");
|
||||
return version;
|
||||
});
|
||||
190
themes/anzhiyu/scripts/helpers/inject_head_js.js
Normal file
190
themes/anzhiyu/scripts/helpers/inject_head_js.js
Normal 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>`;
|
||||
});
|
||||
149
themes/anzhiyu/scripts/helpers/page.js
Normal file
149
themes/anzhiyu/scripts/helpers/page.js
Normal 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)
|
||||
})
|
||||
86
themes/anzhiyu/scripts/helpers/random.js
Normal file
86
themes/anzhiyu/scripts/helpers/random.js
Normal 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,
|
||||
};
|
||||
});
|
||||
102
themes/anzhiyu/scripts/helpers/related_post.js
Normal file
102
themes/anzhiyu/scripts/helpers/related_post.js
Normal 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;
|
||||
};
|
||||
}
|
||||
65
themes/anzhiyu/scripts/helpers/sort_attr_post.js
Normal file
65
themes/anzhiyu/scripts/helpers/sort_attr_post.js
Normal 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;
|
||||
}
|
||||
});
|
||||
26
themes/anzhiyu/scripts/helpers/tags_page_list.js
Normal file
26
themes/anzhiyu/scripts/helpers/tags_page_list.js
Normal 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;
|
||||
});
|
||||
18
themes/anzhiyu/scripts/helpers/year.js
Normal file
18
themes/anzhiyu/scripts/helpers/year.js
Normal 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];
|
||||
});
|
||||
Reference in New Issue
Block a user