Compare commits

5 Commits
Author SHA1 Message Date
sookie c4e47fe9fa 安全加固:升级依赖消除高危漏洞,修复构建兼容性问题
【主项目依赖升级】
- hexo 6.x → 8.1.2:移除 swig-templates、swig-extras、旧版 cheerio、
  hexo-fs/hexo-util 等大量漏洞依赖链,解决 critical/high 级别漏洞
- hexo-renderer-marked 5.x → 7.0.1:修复 dompurify XSS 漏洞(GHSA-hpcv)
- gulp 4.x → 5.0.1:修复 vinyl-fs、glob/glob-stream、chokidar、
  braces 等 high 级漏洞链
- hexo-generator-sitemap 2.2.0 → 3.0.1:同步升级

【替换高危依赖】
- gulp-htmlmin 替换为 gulp-html-minifier-terser@7.1.0:
  gulp-htmlmin 依赖的 html-minifier 存在 ReDoS 高危漏洞且无修复版本,
  改用其维护分支 html-minifier-terser,API 完全兼容
- optimist 替换为 minimist@1.2.8(devDependency):
  optimist 捆绑的 minimist@<=0.2.3 存在 prototype pollution critical 漏洞,
  直接使用修复版 minimist 替代

【移除无修复版本的高危包】
- 移除 hexo-generator-baidu-sitemap(无维护更新,内部捆绑 hexo@4.x
  导致一系列 critical 漏洞),在 scripts/generator.js 中实现等效的
  自定义 Baidu Sitemap 生成器替代,功能与原包完全一致

【npm overrides 修复传递依赖漏洞】
- 添加 overrides: { ejs: "^6.0.1" }:
  hexo-renderer-ejs@2.x 依赖 ejs@3.x,ejs@3.x 存在 SSTI critical 漏洞
  且引入 jake → filelist → minimatch → brace-expansion 漏洞链;
  ejs@6.x 已无 jake 依赖,critical 漏洞全部消除

【yilia 主题依赖升级】
- @babel/core 7.26.x → 7.29.7:修复 Arbitrary File Read 漏洞
- @babel/plugin-transform-runtime / @babel/preset-env 同步升级至 7.29.x
- postcss 8.5.3 → 8.5.25:修复 XSS 及路径遍历漏洞
- 移除 clean-webpack-plugin(依赖链含 brace-expansion 高危漏洞),
  改用 webpack 5 内置 output.clean 实现等效的增量清理功能
- 添加 overrides: { brace-expansion: "5.0.9" } 修复剩余传递依赖漏洞

【构建兼容性修复】
- scripts/generator.js 新增 jsfiddle tag 注册:
  hexo@8 移除了内置 {% jsfiddle %} tag 导致构建 FATAL,
  重新实现该 tag 保持原有 iframe 嵌入行为
- gulpfile.js generate 任务错误处理修正:
  原代码在 hexo FATAL 时调用 hexo.exit(err) 但不向 gulp 抛出异常,
  导致 series 继续执行后续任务(compressHtml 因 public/ 不存在而报错),
  修改为在 hexo 退出后重新 throw err 确保 gulp 正确感知失败

【修复结果】
- 主项目:56 个漏洞(8 低危、14 中危、25 高危、9 严重)→ 0 个漏洞
- yilia 主题:8 个漏洞 → 1 个低危
  (剩余 1 个为 vue@2.x ReDoS,仅影响构建时自身模板解析,
  修复需整体迁移到 Vue 3 重写主题,暂不处理)
2026-07-31 20:38:04 +08:00
sookieandClaude Opus 4.6 a4ce7274cd 清理 CSS 浏览器前缀,使用现代标准属性
- _mixin.less: 移除 -ms-transition
- _reset.less: 使用标准 text-size-adjust 和 appearance
- share.less: 移除 -moz-inline-stack 和 zoom:1 hack
- tooltip.less: 移除 -webkit-transform 前缀

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 23:26:57 +08:00
sookie a2d1b2cc49 Revert "升级 Vue 2 到 Vue 3"
This reverts commit fb1cbbada4.
2026-03-24 23:06:58 +08:00
sookie 173e870a73 Revert "修改ref使用"
This reverts commit 6c8ac211ae.
2026-03-24 23:06:54 +08:00
sookie 6c8ac211ae 修改ref使用 2026-03-24 23:00:58 +08:00
15 changed files with 7535 additions and 4258 deletions
-1
View File
@@ -1,7 +1,6 @@
.DS_Store .DS_Store
Thumbs.db Thumbs.db
db.json db.json
package-lock.json
*.log *.log
node_modules/ node_modules/
public/ public/
+4 -5
View File
@@ -1,14 +1,12 @@
const gulp = require('gulp'), const gulp = require('gulp'),
htmlmin = require('gulp-htmlmin'), // html压缩组件 htmlmin = require('gulp-html-minifier-terser'), // html压缩组件
htmlclean = require('gulp-htmlclean'), // html清理组件 htmlclean = require('gulp-htmlclean'), // html清理组件
plumber = require('gulp-plumber'), // 容错组件(发生错误不跳出任务,并报出错误内容) plumber = require('gulp-plumber'), // 容错组件(发生错误不跳出任务,并报出错误内容)
Hexo = require('hexo'), Hexo = require('hexo'),
log = require('fancy-log') // gulp的日志输出 log = require('fancy-log') // gulp的日志输出
// 程序执行的传参 // 程序执行的传参
const argv = require('optimist') const argv = require('minimist')(process.argv.slice(2))
.describe('deployPath', '静态化后发布的目录')
.argv
const hexo = new Hexo(process.cwd(), {}) const hexo = new Hexo(process.cwd(), {})
@@ -20,7 +18,8 @@ gulp.task('generate', async function() {
await hexo.call('generate', { watch: false }) await hexo.call('generate', { watch: false })
return hexo.exit() return hexo.exit()
} catch (err) { } catch (err) {
return hexo.exit(err) await hexo.exit(err)
throw err // 让 gulp series 感知到失败并终止后续任务
} }
}) })
+5543
View File
File diff suppressed because it is too large Load Diff
+12 -10
View File
@@ -3,33 +3,35 @@
"version": "1.1.0", "version": "1.1.0",
"private": true, "private": true,
"hexo": { "hexo": {
"version": "6.0.0" "version": "8.1.2"
}, },
"scripts": { "scripts": {
"dev": "hexo server", "dev": "hexo server",
"build": "gulp" "build": "gulp"
}, },
"dependencies": { "dependencies": {
"hexo": "^6.0.0", "hexo": "^8.1.2",
"hexo-generator-archive": "^1.0.0", "hexo-generator-archive": "^1.0.0",
"hexo-generator-baidu-sitemap": "^0.1.9",
"hexo-generator-category": "^1.0.0", "hexo-generator-category": "^1.0.0",
"hexo-generator-feed": "^3.0.0", "hexo-generator-feed": "^3.0.0",
"hexo-generator-index": "^2.0.0", "hexo-generator-index": "^2.0.0",
"hexo-generator-json-content": "^4.2.3", "hexo-generator-json-content": "^4.2.3",
"hexo-generator-sitemap": "^2.2.0", "hexo-generator-sitemap": "^3.0.1",
"hexo-generator-tag": "^1.0.0", "hexo-generator-tag": "^1.0.0",
"hexo-renderer-ejs": "^2.0.0", "hexo-renderer-ejs": "^2.0.0",
"hexo-renderer-marked": "^5.0.0", "hexo-renderer-marked": "^7.0.1",
"hexo-server": "^3.0.0", "hexo-server": "^3.0.0",
"hexo-wordcount": "^6.0.1" "hexo-wordcount": "^6.0.1"
}, },
"devDependencies": { "devDependencies": {
"gulp": "^4.0.2", "gulp": "^5.0.1",
"gulp-htmlclean": "^2.7.22", "gulp-htmlclean": "^2.7.22",
"gulp-htmlmin": "^5.0.1", "gulp-html-minifier-terser": "^7.1.0",
"gulp-plumber": "^1.2.1", "gulp-plumber": "^1.2.1",
"nunjucks": "^3.2.3", "minimist": "^1.2.8",
"optimist": "^0.6.1" "nunjucks": "^3.2.3"
},
"overrides": {
"ejs": "^6.0.1"
} }
} }
+47
View File
@@ -2,6 +2,16 @@ const nunjucks = require('nunjucks')
const path = require('path') const path = require('path')
const fs = require('fs') const fs = require('fs')
// hexo@8 移除了内置 jsfiddle tag,在此重新注册
hexo.extend.tag.register('jsfiddle', function(args) {
const shortcode = args[0]
const tabs = args[1] || 'js,resources,html,css,result'
const skin = args[2] || 'light'
const width = args[3] || '100%'
const height = args[4] || '300'
return `<iframe style="width: ${width}; height: ${height}px" src="//jsfiddle.net/${shortcode}/embedded/${tabs}/?skin=${skin}" allowfullscreen="allowfullscreen" frameborder="0"></iframe>`
})
const env = new nunjucks.configure({ autoescape: false }) const env = new nunjucks.configure({ autoescape: false })
env.addFilter('noControlChars', function(str) { env.addFilter('noControlChars', function(str) {
return str && str.replace(/[\x00-\x1F\x7F]/g, '') return str && str.replace(/[\x00-\x1F\x7F]/g, '')
@@ -31,4 +41,41 @@ hexo.extend.generator.register('xml', function(locals){
path: 'articles.xml', path: 'articles.xml',
data: xmlData data: xmlData
} }
})
// 自定义 Baidu Sitemap 生成器(替代已废弃的 hexo-generator-baidu-sitemap
hexo.extend.generator.register('baidusitemap', function(locals) {
const config = hexo.config.baidusitemap || {}
const outputPath = config.path || 'baidusitemap.xml'
const posts = locals.posts.toArray().filter(function(post) { return !post.draft })
const pages = locals.pages.toArray()
const allItems = posts.concat(pages).sort(function(a, b) {
const dateA = (a.updated || a.date)
const dateB = (b.updated || b.date)
return dateB - dateA
})
const lines = [
'<?xml version="1.0" encoding="UTF-8"?>',
'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'
]
allItems.forEach(function(item) {
const dateObj = item.updated || item.date
const dateStr = dateObj && dateObj.format
? dateObj.format('YYYY-MM-DD')
: new Date(dateObj).toISOString().split('T')[0]
lines.push(' <url>')
lines.push(' <loc>' + item.permalink + '</loc>')
lines.push(' <lastmod>' + dateStr + '</lastmod>')
lines.push(' </url>')
})
lines.push('</urlset>')
return {
path: outputPath,
data: lines.join('\n')
}
}) })
+1 -1
View File
@@ -60,7 +60,7 @@
</div> </div>
<ul class="search-ul"> <ul class="search-ul">
<li class="search-li" v-for="(item,index) in items" :key="index" v-show="!item.isHide"> <li class="search-li" v-for="(item,index) in items" :key="index" v-show="!item.isHide">
<a :href="urlformat(item.path)" class="search-title"><i class="icon icon-quote-left"></i> <a :href="item.path|urlformat" class="search-title"><i class="icon icon-quote-left"></i>
<span v-text="item.title"></span> <span v-text="item.title"></span>
</a> </a>
<p class="search-time" v-if="item.date"> <p class="search-time" v-if="item.date">
+154 -568
View File
File diff suppressed because it is too large Load Diff
+8 -6
View File
@@ -23,26 +23,28 @@
"photoswipe": "^4.1.3", "photoswipe": "^4.1.3",
"qrious": "^4.0.2", "qrious": "^4.0.2",
"scrollreveal": "^4.0.9", "scrollreveal": "^4.0.9",
"vue": "^3.5.14" "vue": "^2.7.16"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.26.0", "@babel/core": "^7.29.7",
"@babel/plugin-transform-runtime": "^7.25.9", "@babel/plugin-transform-runtime": "^7.29.0",
"@babel/preset-env": "^7.26.0", "@babel/preset-env": "^7.29.0",
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
"babel-loader": "^9.2.1", "babel-loader": "^9.2.1",
"clean-webpack-plugin": "^4.0.0",
"css-loader": "^7.1.2", "css-loader": "^7.1.2",
"html-webpack-plugin": "^5.6.3", "html-webpack-plugin": "^5.6.3",
"less": "^4.2.2", "less": "^4.2.2",
"less-loader": "^12.2.0", "less-loader": "^12.2.0",
"mini-css-extract-plugin": "^2.9.2", "mini-css-extract-plugin": "^2.9.2",
"postcss": "^8.5.3", "postcss": "^8.5.25",
"postcss-loader": "^8.1.1", "postcss-loader": "^8.1.1",
"terser-webpack-plugin": "^5.3.11", "terser-webpack-plugin": "^5.3.11",
"webpack": "^5.97.1", "webpack": "^5.97.1",
"webpack-cli": "^5.1.4" "webpack-cli": "^5.1.4"
}, },
"overrides": {
"brace-expansion": "5.0.9"
},
"browserslist": [ "browserslist": [
"> 1%", "> 1%",
"last 2 versions", "last 2 versions",
@@ -285,13 +285,11 @@
// trans // trans
.trans() { .trans() {
transition: all 0.2s ease-in; transition: all 0.2s ease-in;
-ms-transition: all 0.2s ease-in;
} }
// trans8 // trans8
.trans8() { .trans8() {
transition: all 0.8s ease-in; transition: all 0.8s ease-in;
-ms-transition: all 0.8s ease-in;
} }
// display-flex // display-flex
+4 -5
View File
@@ -12,8 +12,7 @@
// 1. Prevent mobile text size adjust after orientation change, without disabling user zoom. // 1. Prevent mobile text size adjust after orientation change, without disabling user zoom.
// 2. Remove the gray background color from tap, default value is inherit // 2. Remove the gray background color from tap, default value is inherit
html { html {
-ms-text-size-adjust: 100%; // 1 text-size-adjust: 100%; // 1
-webkit-text-size-adjust: 100%; // 1
-webkit-tap-highlight-color: transparent; // 2 -webkit-tap-highlight-color: transparent; // 2
height: 100%; height: 100%;
} }
@@ -188,7 +187,7 @@ button,
html input[type="button"], html input[type="button"],
input[type="reset"], input[type="reset"],
input[type="submit"] { input[type="submit"] {
-webkit-appearance: button; // 1 appearance: button; // 1
cursor: pointer; // 2 cursor: pointer; // 2
} }
@@ -226,14 +225,14 @@ input[type="number"]::-webkit-outer-spin-button {
// 1. Address `appearance` set to `searchfield` in Safari and Chrome. // 1. Address `appearance` set to `searchfield` in Safari and Chrome.
// 2. Address `box-sizing` set to `border-box` in Safari and Chrome. // 2. Address `box-sizing` set to `border-box` in Safari and Chrome.
input[type="search"] { input[type="search"] {
-webkit-appearance: textfield; // 1 appearance: textfield; // 1
box-sizing: content-box; // 2 box-sizing: content-box; // 2
} }
// Remove inner padding and search cancel button in Safari and Chrome on OS X. // Remove inner padding and search cancel button in Safari and Chrome on OS X.
input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration { input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none; appearance: none;
} }
// Define consistent border, margin, and padding. // Define consistent border, margin, and padding.
-2
View File
@@ -13,10 +13,8 @@
a { a {
border: 1px solid @colorBorder; border: 1px solid @colorBorder;
border-radius: 50%; border-radius: 50%;
display: -moz-inline-stack;
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
zoom: 1;
margin: 10px; margin: 10px;
transition: 0.3s; transition: 0.3s;
text-align: center; text-align: center;
-1
View File
@@ -112,7 +112,6 @@
bottom: 100%; bottom: 100%;
left: 50%; left: 50%;
pointer-events: none; pointer-events: none;
-webkit-transform: translateX(-50%);
transform: translateX(-50%); transform: translateX(-50%);
} }
+112 -97
View File
@@ -1,56 +1,49 @@
import http from './request' import http from './request'
import { createApp } from 'vue' import Vue from 'vue/dist/vue.esm'
import waifuTips from '../config/waifu-tip.json' import waifuTips from '../config/waifu-tip.json'
function setScrollZero() { function setScrollZero() {
document.querySelectorAll('.tools-section').forEach(em => { let $sct = document.querySelectorAll('.tools-section')
Array.prototype.forEach.call($sct, (em) => {
em.scrollTop = 0 em.scrollTop = 0
}) })
} }
function urlformat(str) {
return (window.themeConfig && window.themeConfig.root) ? window.themeConfig.root + str : '/' + str
}
var waifuTipTimer = null, fullTextSearchTimer = null var waifuTipTimer = null, fullTextSearchTimer = null
const vm = new Vue({
const vm = createApp({ el: '#container',
data() { data: {
return { isCtnShow: false,
isCtnShow: false, isShow: undefined,
isShow: undefined, items: [],
items: [], innerArchive: false,
innerArchive: false, friends: false,
friends: false, aboutme: false,
aboutme: false, showTags: false,
showTags: false, showCategories: false,
showCategories: false, search: null,
search: null, searchItems: [],
searchItems: [], fullTextSearch: {
fullTextSearch: { pageNum: 1,
pageNum: 1, limit: 10,
limit: 10, isLoading: false,
isLoading: false, tip: undefined,
tip: undefined, hasMore: false
hasMore: false },
}, fullTextSearchWords: null,
fullTextSearchWords: null, fullTextSearchItems: [],
fullTextSearchItems: [], waifu: {
waifu: { tip: null, // 提示语文字
tip: null, // 提示语文字 tipOpacity: 0, // 提示语框透明度
tipOpacity: 0, // 提示语框透明度 showTools: false // 显示工具栏
showTools: false // 显示工具栏 },
}, themeConfig: window.themeConfig
themeConfig: window.themeConfig
}
}, },
methods: { methods: {
urlformat, stop (event) {
stop(event) {
event.stopPropagation() event.stopPropagation()
}, },
openSlider(event, type, isMobile) { openSlider (event, type, isMobile) {
if (isMobile && this.isShow) { if(isMobile && this.isShow) {
this.hideSlider() this.hideSlider()
return return
} }
@@ -63,32 +56,32 @@ const vm = createApp({
this.isCtnShow = true this.isCtnShow = true
setScrollZero() setScrollZero()
}, },
hideSlider() { hideSlider () {
if (this.isShow) { if (this.isShow) {
this.isShow = false this.isShow = false
setTimeout(() => { this.isCtnShow = false }, 300) setTimeout(() => {this.isCtnShow = false}, 300)
} }
}, },
linkMouseover(name) { linkMouseover(name) {
if (name === 'waifu' && waifuTipTimer) return if(name === 'waifu' && waifuTipTimer) return
this.showMessage(waifuTips.mouseover[name], 3000) this.showMessage(waifuTips.mouseover[name], 3000)
}, },
toolsClick(name) { toolsClick(name) {
this.showMessage(waifuTips.click[name]) this.showMessage(waifuTips.click[name])
if (name in waifuTools) { if(name in waifuTools) {
waifuTools[name].call(this) waifuTools[name].call(this)
} }
}, },
addSearchItem(query, type = 'title') { addSearchItem(query, type='title') {
if (query) { if(query) {
query = query.trim() query = query.trim()
} }
// 如果已存在相同的查询条件, 则不加入 // 如果已存在相同的查询条件, 则不加入
const isExist = this.searchItems.some(searchItem => { var isExist = Array.prototype.some.call(this.searchItems, searchItem => {
return searchItem.query === query && searchItem.type === type return searchItem.query === query && searchItem.type === type
}) })
if (!isExist && query) { if(!isExist && query) {
this.searchItems.push({ query, type }) this.searchItems.push({query, type})
} }
this.search = null this.search = null
}, },
@@ -98,18 +91,18 @@ const vm = createApp({
this.$refs.mask.classList.add('in') this.$refs.mask.classList.add('in')
}, },
loadSearchResult() { loadSearchResult() {
this.fullTextSearch.pageNum++ this.fullTextSearch.pageNum ++
this.fullTextSearch.isLoading = true this.fullTextSearch.isLoading = true
this.fullTextSearch.tip = undefined this.fullTextSearch.tip = undefined
const params = { let params = {
pageNum: this.fullTextSearch.pageNum, pageNum: this.fullTextSearch.pageNum,
limit: this.fullTextSearch.limit, limit: this.fullTextSearch.limit,
words: this.fullTextSearchWords words: this.fullTextSearchWords
} }
http.get('/api/v2/common/search', { params }).then(res => { http.get('/api/v2/common/search', {params}).then(res => {
this.fullTextSearch.isLoading = false this.fullTextSearch.isLoading = false
fullTextSearchTimer = null fullTextSearchTimer = null
if (!Array.isArray(res.list) || !res.list.length) { if(!Array.isArray(res.list) || !res.list.length) {
this.fullTextSearch.tip = '未搜索到匹配文章' this.fullTextSearch.tip = '未搜索到匹配文章'
} else { } else {
this.fullTextSearchItems.push(...res.list) this.fullTextSearchItems.push(...res.list)
@@ -122,53 +115,62 @@ const vm = createApp({
}) })
}, },
searchKeydown(event) { searchKeydown(event) {
if (event.keyCode == 13) { // 回车键 if(event.keyCode == 13){ // 回车键
this.addSearchItem(this.search) this.addSearchItem(this.search)
} else if (event.keyCode == 8 && !this.search) { // 退格键 } else if(event.keyCode == 8 && !this.search) { // 退格键
this.searchItems.pop() this.searchItems.pop()
} }
}, },
showMessage(text, time) { showMessage (text, time) {
if (!text) return if(!text) return
if (Array.isArray(text)) text = text[Math.floor(Math.random() * text.length + 1) - 1] if(Array.isArray(text)) text = text[Math.floor(Math.random() * text.length + 1)-1]
this.waifu.tip = text this.waifu.tip = text
this.waifu.tipOpacity = 1 this.waifu.tipOpacity = 1
if (waifuTipTimer) { if(waifuTipTimer) {
clearTimeout(waifuTipTimer) clearTimeout(waifuTipTimer)
waifuTipTimer = null waifuTipTimer = null
} }
waifuTipTimer = setTimeout(() => { waifuTipTimer = setTimeout(()=>{
this.waifu.tipOpacity = 0 this.waifu.tipOpacity = 0
waifuTipTimer = null waifuTipTimer = null
}, time || 5000) }, time || 5000)
}
},
filters: {
urlformat (str) {
return (window.themeConfig && window.themeConfig.root) ? window.themeConfig.root + str : '/' + str
} }
}, },
watch: { watch: {
searchItems(newVal) { searchItems (newVal, oldVal) {
if (newVal && newVal.length) { if(newVal && newVal.length) {
handleSearch.call(this, newVal) handleSearch.call(this, newVal)
} else { } else {
this.items.forEach(item => { item.isHide = false }) this.items.forEach(function(item){
item.isHide = false
})
} }
}, },
fullTextSearchWords(newVal) { fullTextSearchWords (newVal, oldVal) {
this.fullTextSearch.hasMore = false this.fullTextSearch.hasMore = false
this.fullTextSearchItems.isLoading = false this.fullTextSearchItems.isLoading = false
this.fullTextSearch.tip = undefined this.fullTextSearch.tip = undefined
this.fullTextSearchItems.splice(0, this.fullTextSearchItems.length) this.fullTextSearchItems.splice(0, this.fullTextSearchItems.length)
if (fullTextSearchTimer) { if(fullTextSearchTimer) {
clearTimeout(fullTextSearchTimer) clearTimeout(fullTextSearchTimer)
fullTextSearchTimer = null fullTextSearchTimer = null
} }
if (!newVal) return if(!newVal) {
return
}
this.fullTextSearch.pageNum = 0 this.fullTextSearch.pageNum = 0
fullTextSearchTimer = setTimeout(this.loadSearchResult.bind(this), 500) fullTextSearchTimer = setTimeout(this.loadSearchResult.bind(this), 500)
} }
}, },
mounted() { mounted () {
fetch(window.themeConfig.root + 'content.json').then(res => res.json()).then(resJson => { fetch(window.themeConfig.root + 'content.json').then(res => res.json()).then(resJson=>{
this.items = resJson this.items = resJson
}).catch(() => { }).catch(err => {
console.warn('加载文章列表失败') console.warn('加载文章列表失败')
}) })
welcomeMessage().then(msg => { welcomeMessage().then(msg => {
@@ -177,39 +179,44 @@ const vm = createApp({
document.addEventListener('copy', () => { document.addEventListener('copy', () => {
this.showMessage('你都复制了些什么呀,转载要记得加上出处哦') this.showMessage('你都复制了些什么呀,转载要记得加上出处哦')
}) })
const hideModal = () => { // 隐藏模态框
document.querySelectorAll('.page-modal').forEach(modal => { let hideModal = (function() {
let modals = document.querySelectorAll('.page-modal')
Array.prototype.forEach.call(modals, modal => {
modal.classList.remove('in') modal.classList.remove('in')
}) })
this.$refs.mask.classList.remove('in') this.$refs.mask.classList.remove('in')
} }).bind(this)
// 隐藏模态框
this.$refs.mask.addEventListener('click', hideModal) this.$refs.mask.addEventListener('click', hideModal)
document.querySelectorAll('.js-modal-close').forEach(modalClose => { Array.prototype.forEach.call(document.querySelectorAll('.js-modal-close'), modalClose => {
modalClose.addEventListener('click', hideModal) modalClose.addEventListener('click', hideModal)
}) })
}, },
created() { created() {
// 夜间模式 // 夜间模式
const night = localStorage.getItem('night') let night = localStorage.getItem('night')
if (night === 'true') { try {
document.querySelector('body').classList.add('night') if(night && eval(night)) document.querySelector('body').classList.add('night')
} } catch (e){}
} }
}).mount('#container') })
function handleSearch(searchItems) { function handleSearch(searchItems) {
this.items.forEach(articleItem => { this.items.forEach(articleItem => {
articleItem.isHide = !searchItems.every(searchItem => { articleItem.isHide = !Array.prototype.every.call(searchItems, searchItem => {
switch (searchItem.type) { switch(searchItem.type) {
case 'title': case 'title':
return articleItem.title.toLowerCase().indexOf(searchItem.query.toLowerCase()) !== -1 return articleItem.title.toLowerCase().indexOf(searchItem.query.toLowerCase()) !== -1
case 'tag': case 'tag' :
return articleItem.tags.some(tag => tag.name === searchItem.query) return Array.prototype.some.call(articleItem.tags, tag => {
case 'category': return tag.name === searchItem.query
return articleItem.categories.some(category => category.name === searchItem.query) })
case 'date': case 'category' :
return articleItem.date && (articleItem.date.substr(0, 7) === searchItem.query) return Array.prototype.some.call(articleItem.categories, category => {
return category.name === searchItem.query
})
case 'date' :
return articleItem.date && ( articleItem.date.substr(0,7) === searchItem.query )
} }
}) })
}) })
@@ -219,14 +226,22 @@ async function welcomeMessage() {
let now = new Date().getHours() let now = new Date().getHours()
return http.get('/api/v2/common/config/waifu_tip').then(textTimes => { return http.get('/api/v2/common/config/waifu_tip').then(textTimes => {
let text = null let text = null
textTimes.sort((a, b) => a.start - b.start) Array.prototype.sort.call(textTimes, (item1, item2) => {
textTimes.forEach(textTime => { if(item1.start>item2.start) {
if (now > textTime.start && now <= textTime.end) { return 1
} else if(item1.start<item2.start) {
return -1
} else {
return 0
}
})
Array.prototype.forEach.call(textTimes, textTime => {
if(now > textTime.start && now <= textTime.end) {
text = textTime.text text = textTime.text
} }
}) })
if (!text) { if(!text) {
text = textTimes[textTimes.length - 1].text text = textTimes[textTimes.length-1].text
} }
return text return text
}) })
@@ -256,12 +271,12 @@ const waifuTools = {
}, },
'tools.chart'() { 'tools.chart'() {
// 一言 // 一言
http.get('/api/v2/common/hitokoto', { params: { format: 'json' } }).then(res => { http.get('/api/v2/common/hitokoto', { params: {format: 'json'} }).then(res => {
this.showMessage(res.hitokoto + (res.from ? `  ——${res.from}` : '')) this.showMessage(res.hitokoto + (res.from?`  ——${res.from}`:''))
}) })
}, },
'tools.search'() { 'tools.search'() {
// 打开全文检索Modal // 打开全文检索Modal
vm.openFullTextSearch() vm.openFullTextSearch()
} }
} }
+2 -7
View File
@@ -1,7 +1,6 @@
const TerserPlugin = require('terser-webpack-plugin') const TerserPlugin = require('terser-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin') const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin') const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const htmlPluginConfig = { const htmlPluginConfig = {
@@ -32,7 +31,8 @@ module.exports = function(env, argv) {
output: { output: {
publicPath: '/', publicPath: '/',
path: __dirname + '/source', path: __dirname + '/source',
filename: isProd ? 'js/[name].[chunkhash].js' : 'js/[name].js' filename: isProd ? 'js/[name].[chunkhash].js' : 'js/[name].js',
clean: isProd ? { keep: (asset) => !/^(js|css|fonts|images)\//.test(asset) } : false
}, },
module: { module: {
rules: [{ rules: [{
@@ -69,11 +69,6 @@ module.exports = function(env, argv) {
template: './source-src/template/css.html', template: './source-src/template/css.html',
filename: '../layout/_partial/css.ejs' filename: '../layout/_partial/css.ejs'
}, htmlPluginConfig)), }, htmlPluginConfig)),
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: ['js/*','css/*','fonts/*','images/*'],
verbose: true,
dry: false,
}),
new MiniCssExtractPlugin({ new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash:6].css' filename: 'css/[name].[contenthash:6].css'
}) })
+1648 -3553
View File
File diff suppressed because it is too large Load Diff