hexo自動更新文章修改時間


一、問題描述

在部署完Github Action實現自動部署博客之后,存在一個問題,每次更新時,由於是雲函數部署,所有的文章的更新時間都會改變,目前只能通過為文章添加updated字段再提交才能避免這種情況。

但是每次更新文章都要手動去修改updated,這么麻煩的事情當然要交給程序去做。想過用python但是考慮到有些人可能沒有python環境,而使用hexo部署博客的人肯定都有node環境,因此采用js來完成。

二、解決方案

首先,如果你之前沒有為文章添加updated字段,需要先添加上。

1 為現有的文章添加updated字段

如果你現有文章已經有updated字段,此步驟可以跳過。

代碼參考:批量寫入文件的修改時間,原來的代碼在多次運行時,重復添加字段,我對其做了優化,重復運行也只會添加一個updated字段。

創建js文件:博客根目錄/source/_posts/writeupdatetime.js,文件內容如下

#!/usr/bin/env node
/*
批量添加修改時間
用於bolg初始化修改時間
*/

console.log('腳本開始運行..');
var fs = require("fs"); //請求文件系統
var file = "./txt"; //設置讀取和寫入的文件,當前目錄下的test文件
var RegExp=/(updated:\s*)((\d{2}(([02468][048])|([13579][26]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|([1-2][0-9])))))|(\d{2}(([02468][1235679])|([13579][01345789]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\s((([0-1][0-9])|(2?[0-3]))\:([0-5]?[0-9])((\s)|(\:([0-5]?[0-9])))))\r/g;

fs.readdir("./",function(err,files){
	var len=files.length;
	var file=null;
	for(var i=0;i<len;i++){
		file=files[i];
		//console.log("讀取文件:",file);
		if(file.indexOf(".md")>-1){
			console.log("正在處理文件:",file);
			writeFileTime(file,fs);
		}
	}
    console.log("運行完畢!");
});
/*
file:讀取時間的文件以及寫入內容的文件
fs: 文件系統
*/
function writeFileTime(file,fs){
	fs.readFile(file, 'utf8',function(err, data) { //讀取文件內容
		if (err) return console.log("讀取文件內容錯誤:",err);
		//console.log("文件"+file+"的內容:",data);
		fs.stat(file,function(err, stats) { //讀取文件信息,創建時間等
		   if (err) return console.log("讀取文件信息錯誤:",err);
			//console.log("文件"+file+"的信息:",stats);  //打印文件的信息
			//console.log("創建時間是:",stats.mtime);
			//console.log("文件的創建時間是:",getFormatDate(stats.mtime));
            var result= data.replace(RegExp,""); //替換更新時間
			result = result.replace(/categories:/g, "updated: "+getFormatDate(stats.mtime)+"\r"+"categories:");//data:替換為標准化日期
			//console.log("修改后文件內容為:",result);
			fs.writeFile(file, result, 'utf8',function(err) { //寫入新的文件內容
				if (err) return console.log("寫文件錯誤:",err);
			});
		});
	});
}

/*
 timeStr:時間,格式可為:"September 16,2016 14:15:05、
 "September 16,2016"、"2016/09/16 14:15:05"、"2016/09/16"、
 '2014-04-23T18:55:49'和毫秒
 dateSeparator:年、月、日之間的分隔符,默認為"-",
 timeSeparator:時、分、秒之間的分隔符,默認為":"
 */
function getFormatDate(timeStr, dateSeparator, timeSeparator) {
    dateSeparator = dateSeparator ? dateSeparator : "-";
    timeSeparator = timeSeparator ? timeSeparator : ":";
    var date = new Date(timeStr),
            year = date.getFullYear(),// 獲取完整的年份(4位,1970)
            month = date.getMonth(),// 獲取月份(0-11,0代表1月,用的時候記得加上1)
            day = date.getDate(),// 獲取日(1-31)
            hour = date.getHours(),// 獲取小時數(0-23)
            minute = date.getMinutes(),// 獲取分鍾數(0-59)
            seconds = date.getSeconds(),// 獲取秒數(0-59)
            Y = year + dateSeparator,
            M = ((month + 1) > 9 ? (month + 1) : ('0' + (month + 1))) + dateSeparator,
            D = (day > 9 ? day : ('0' + day)) + ' ',
            h = (hour > 9 ? hour : ('0' + hour)) + timeSeparator,
            m = (minute > 9 ? minute : ('0' + minute)) + timeSeparator,
            s = (seconds > 9 ? seconds : ('0' + seconds)),
            formatDate = Y + M + D + h + m + s;
    return formatDate;
}

博客根目錄/source/_posts/打開bash,運行代碼:

./writeupdatetime.js

代碼的運行原理是尋找categories,在categories字段上方添加updated字段,因此要確保你為每篇文章添加了categories。如果沒有添加,請自行修改源碼,將categories改成其它字段,比如tags等。

打開你的文章看一下,確保每篇文章都添加了updated

2 修改Front-matter模版

由於我之前沒有設置Front-matter模版,所以每篇文章都沒有updated字段,因此要修改該模版。

打開博客根目錄/scaffolds/post.md文件,修改添加updated字段,以我的模板為例:

title: {{ title }}
date: {{ date }}
updated: {{ date }}
tags:
  -
categories:
  -
sticky: 

以后再通過hexo new post新建文章的時候就會有updated字段了。

3 代碼實現自動更新文章修改時間

代碼參考:自動更新文章的修改時間,做了一些改動。

創建js文件:博客根目錄/source/_posts/updateFileTime.js,文件內容如下

#!/usr/bin/env node
/*
批量更新修改時間
博客自動更新文章的修改時間
*/

console.log('腳本開始運行..');
var fs = require("fs"); //請求文件系統
var file = "./txt"; //設置讀取和寫入的文件,當前目錄下的test文件
var RegExp=/(updated:\s*)((\d{2}(([02468][048])|([13579][26]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|([1-2][0-9])))))|(\d{2}(([02468][1235679])|([13579][01345789]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\s((([0-1][0-9])|(2?[0-3]))\:([0-5]?[0-9])((\s)|(\:([0-5]?[0-9])))))/g;

fs.readdir("./",function(err,files){
	var len=files.length;
	var file=null;
	for(var i=0;i<len;i++){
		file=files[i];
		//console.log("讀取文件:",file);
		if(file.indexOf(".md")>-1){
			console.log("正在處理文件:",file);
			writeFileTime(file,fs);
		}
	}
});

/*
file:讀取時間的文件以及寫入內容的文件
fs: 文件系統
*/
function writeFileTime(file,fs){
	fs.readFile(file, 'utf8',function(err, data) { //讀取文件內容
		if (err) return console.log("讀取文件內容錯誤:",err);
		//console.log("文件"+file+"的內容:",data);
		if(RegExp.test(data)){ //如果匹配到`updated`字段
			fs.stat(file,function(err, stats) { //讀取文件信息,創建時間等
				if (err) return console.log("讀取文件信息錯誤:",err);
				var updateds=data.match(RegExp);
				//console.log("updated數組:",updateds);
				if(updateds.length>1) console.log("文件"+file+"匹配到多處update字段");
				var updated=updateds[0].replace("updated: ","").replace(/-/g,"/");  //時間格式化為2018/01/29 21:33:30
				//console.log("updated:",updated);
				if(new Date(stats.mtime).getTime()-new Date(Date.parse(updated))>1000*60*5){ // 只要修改時間和文章內updated時間差大於1000毫秒*60*5=5分鍾就觸發更新
					var result= data.replace(RegExp,"updated: "+getFormatDate(stats.mtime)); //替換更新時間
					fs.writeFile(file, result, 'utf8',function(err) { //寫入新的文件內容
						if (err) return console.log("寫文件錯誤:",err);
						fs.utimes(file,new Date(stats.atime),new Date(stats.mtime),function(err){  //還原訪問時間和修改時間
							if (err) return console.log("修改時間失敗:",err);
							console.log(file,"成功更新時間");
						});
					});
				}
			});
		}	
	});
}

/*
 timeStr:時間,格式可為:"September 16,2016 14:15:05、
 "September 16,2016"、"2016/09/16 14:15:05"、"2016/09/16"、
 '2014-04-23T18:55:49'和毫秒
 dateSeparator:年、月、日之間的分隔符,默認為"-",
 timeSeparator:時、分、秒之間的分隔符,默認為":"
 */
function getFormatDate(timeStr, dateSeparator, timeSeparator) {
    dateSeparator = dateSeparator ? dateSeparator : "-";
    timeSeparator = timeSeparator ? timeSeparator : ":";
    var date = new Date(timeStr),
            year = date.getFullYear(),// 獲取完整的年份(4位,1970)
            month = date.getMonth(),// 獲取月份(0-11,0代表1月,用的時候記得加上1)
            day = date.getDate(),// 獲取日(1-31)
            hour = date.getHours(),// 獲取小時數(0-23)
            minute = date.getMinutes(),// 獲取分鍾數(0-59)
            seconds = date.getSeconds(),// 獲取秒數(0-59)
            Y = year + dateSeparator,
            M = ((month + 1) > 9 ? (month + 1) : ('0' + (month + 1))) + dateSeparator,
            D = (day > 9 ? day : ('0' + day)) + ' ',
            h = (hour > 9 ? hour : ('0' + hour)) + timeSeparator,
            m = (minute > 9 ? minute : ('0' + minute)) + timeSeparator,
            s = (seconds > 9 ? seconds : ('0' + seconds)),
            formatDate = Y + M + D + h + m + s;
    return formatDate;
}

4 shell自動運行代碼

在博客根目錄下新建update.sh文件,內容如下:

#!/bin/sh
cd source/_posts/ && ./updateFileTime.js && cd .. && cd .. && git add . && git commit -m "uptate" && git push origin master
# 如果你的分支不是master記得替換

5 修改gitignore

我們需要忽略_posts下的js文件,打開 博客根目錄/.gitignore文件,添加一條:

source/_posts/*.js

大功告成,接下來你只需要運行update.sh

./update.sh

就可以在提交代碼之前自動將更新時間寫入文章的updated字段,然后提交到遠程源碼倉庫進行自動部署了。

三、一些小問題解決

可能有些文章的更新時間改變了但是git無法跟蹤到,可以將文章從索引中刪除,然后再添加回來。博客根目錄下執行命令:

git rm --cached source/_posts/ -r

然后再運行update.sh即可。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM