分享两个Hexo小工具
分享两个我自己用的 Hexo 小工具,其实就是两个 Nodejs 小脚本。
1. 网站字数统计
现在用的这个主题没有全站字数统计功能,于是自己写了一个脚本来实现。
其实原理很简单,就是获取 source/_posts
目录下的所有 .md
文件,然后统计每个文件中的文字数,最后将总文字数替换到 source/js/wordcount.js
文件中。
就是每次提交前要记得执行。
sitewordcount.js
内容如下:
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
| const fs = require('fs'); const path = require('path'); const TurndownService = require('turndown'); const turndownService = new TurndownService();
const postsDir = path.join(__dirname, 'source', '_posts'); let totalWordCount = 0;
function countWordsInFile(file) { const content = fs.readFileSync(file, 'utf-8'); const separatorIndex = content.indexOf('---', 3); const text = content.substring(separatorIndex + 3).trim(); const characters = text.length; return characters; }
function traversePostsDir(dir) { const files = fs.readdirSync(dir);
for (const file of files) { const filePath = path.join(dir, file); const stat = fs.statSync(filePath);
if (stat.isDirectory()) { traversePostsDir(filePath); } else if (stat.isFile() && file.endsWith('.md')) { const wordCount = countWordsInFile(filePath); console.log(`${file}: ${wordCount} words`); totalWordCount += wordCount; } } }
traversePostsDir(postsDir);
const wordcountFilePath = path.join(__dirname, 'source', 'js', 'wordcount.js'); let wordcountContent = fs.readFileSync(wordcountFilePath, 'utf-8'); wordcountContent = wordcountContent.replace(/var\s+siteWordCount\s+=\s+\d+;/, `var siteWordCount = ${totalWordCount};`); fs.writeFileSync(wordcountFilePath, wordcountContent);
console.log(`全站总字数: ${totalWordCount}`);
|
wordcount.js
是另一个脚本,运行在前端,负责把总字数显示到网站底部。
这里我不但用它显示总字数,同时每篇文章的字数和预计阅读时间也在此实现。
每次执行 node sitewordcount.js
之后,wordcount.js
的第一行内容就会变化。
wordcount.js
内容如下:
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
| var siteWordCount = 221051;
document.getElementById("sitewordcount").innerHTML="<p style=\"text-align:center\">全站共 " + siteWordCount + " 个字.</p>"
var articleElement = document.querySelector('article.md-text.content.post');
if (articleElement) { var pElements = articleElement.querySelectorAll('p:not(.article-footer p)');
var wordCount = 0; for (var i = 0; i < pElements.length; i++) { var pElement = pElements[i]; wordCount += countWords(pElement.textContent); }
var readingTime = (wordCount / 700).toFixed(1);
var blockquoteElement = document.createElement('blockquote');
var pElement = document.createElement('p'); pElement.innerHTML = '本文共 ' + wordCount + ' 个字,阅读本文大概需要 ' + readingTime + ' 分钟。';
blockquoteElement.appendChild(pElement);
var firstH1Element = articleElement.querySelector('h1');
if (firstH1Element) { articleElement.insertBefore(blockquoteElement, firstH1Element.nextSibling); } else { articleElement.insertBefore(blockquoteElement, articleElement.firstChild); } } else { console.log('<article class="md-text content post"> 元素不存在'); }
function countWords(text) { var cleanedText = text.replace(/\s+/g, '');
var wordCount = cleanedText.length;
return wordCount; }
|
2. 创建文章时自动创建文件夹
每次创建文章后,都需要手动创建一个用于存放图片的文件夹。
我的习惯是文件夹名字用英文,所以每次都是要先翻译,再创建,有点麻烦,所以想一步到位。
create.js
脚本如下:
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
| const { execSync } = require('child_process'); const fs = require('fs'); const path = require('path'); const axios = require('axios');
const CONFIG = { TRANSLATE_API: 'http://192.168.6.126:5000/translate', HEXO_PATH: path.join(__dirname), ASSETS_DIR: path.join(__dirname, 'source', 'assets') };
async function translate(text, source = 'zh', target = 'en') { try { const response = await axios.post( CONFIG.TRANSLATE_API, `q=${encodeURIComponent(text)}&source=${source}&target=${target}&format=text&alternatives=3`, { headers: { 'accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded' } } );
if (!response.data?.translatedText) { throw new Error('未收到有效翻译结果'); } return response.data.translatedText; } catch (error) { throw new Error(`翻译失败: ${error.response?.data?.error_msg || error.message}`); } }
function createAssetFolder(folderName) { const folderPath = path.join(CONFIG.ASSETS_DIR, folderName); if (!fs.existsSync(folderPath)) { fs.mkdirSync(folderPath, { recursive: true }); console.log(`✅ 资源文件夹创建成功: ${folderPath}`); } else { console.log(`ℹ️ 资源文件夹已存在: ${folderPath}`); } }
async function main() { const chineseTitle = process.argv[2]; if (!chineseTitle) { console.log('❌ 请提供文章标题,示例: node script.js "文章标题"'); process.exit(1); }
try { const englishTitle = await translate(chineseTitle); const folderName = englishTitle .toLowerCase() .replace(/[^\w\s]/gi, '') .replace(/\s+/g, '-');
console.log('⏳ 创建Hexo文章中...'); execSync(`hexo new post "${chineseTitle}"`, { cwd: CONFIG.HEXO_PATH, stdio: 'inherit' });
createAssetFolder(folderName);
console.log('\n🎉 操作完成!'); console.log(`📝 英文标题: ${englishTitle}`); console.log(`📁 资源目录: ${path.join(CONFIG.ASSETS_DIR, folderName)}`);
} catch (error) { console.error(`❌ 发生错误: ${error.message}`); process.exit(1); } }
main();
|
执行 node create.js "文章标题"
即可。
原理也很简单,先调用 Hexo 命令创建文章,再调用翻译接口,根据返回结果创建文件夹即可。
这里翻译服务我调用的是我本地部署的 LibreTranslate,很简单,使用 docker 部署即可。
也可以改成其他翻译 api,让 AI 修改代码即可。