在MAC上搭建HEXO博客指南
记录搭建全过程
安装环境配置
1. node.js
这一步需要调整,使用 Node.js 的版本管理工具 nvm 来安装 Node.js,这样会避免权限问题。
安装nvm
在终端中运行以下命令来安装nvm
使用 curl 安装方法
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
使用 wget 安装方法
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
安装完成后,需要将 nvm 加载到当前的终端会话中。关闭并重新打开终端,或者运行以下命令来加载 nvm。
source ~/.nvm/nvm.sh
我目前只能通过命令加载
如果你使用的是 zsh 作为你的 shell,将上面的命令替换为:
source ~/.nvm/nvm.sh --no-use
验证 nvm 安装,运行以下命令验证 nvm 是否已经安装成功:
nvm --version
安装 Vue.js
nvm install stable # 使用 nvm 安装最新稳定版 Node.js
nvm use stable # 使用刚刚安装的 Node.js 版本
# 或者如果你使用的是 n,可以运行以下命令:
# n latest
# n use latest
npm install -g @vue/cli
2. 安装git
(在终端输入git查询语句会自动弹出安装提醒)
3. 核验语句
node -v
Git -v
Npm -v
安装HEXO
npm install -g hexo
hexo -v
创建博客文件夹
hexo init Blog
我是先创建的,在把整个文件夹内容挪到文稿目录下面后,再进行下面操作
cd /Users/star/Documents/Blog
npm install
输入下面语句,核验是否搭建成功了
Hexo s
关联Github
添加ssh key 到github
检查SSH keys是否存在Github
执行如下命令,检查SSH keys是否存在。如果有文件id_rsa.pub或id_dsa.pub,则直接进入步骤1.3将SSH key添加到Github中,否则进入下一步生成SSH key。
ls -al ~/.ssh
生成新的ssh key
ssh-keygen -t rsa -C "w2388619506@163.com"
将ssh key添加到Github中
Find前往文件夹~/.ssh/id_rsa.pub打开id_rsa.pub文件,里面的信息即为SSH key,将这些信息复制到Github的Add SSH key页面即可。
进入Github –> Settings –> SSH keys –> add SSH key:
Title里任意添一个标题,将复制的内容粘贴到Key里,点击下方Add key绿色按钮即可。
重要‼️
每次启动终端后,都需要使用命令行加载nvm
source ~/.nvm/nvm.sh
博客配置文件修改
插件安装
- 要将hexo部署到GitHub
npm install hexo-deployer-git --save # 安装部署插件
- 短链接
npm install hexo-abbrlink --save
- 本地搜索
npm install hexo-generator-searchdb
站点配置文件
- GitHub同步设置
# Deployment
## Docs: https://hexo.io/docs/one-command-deployment
deploy:
type: git
repo: git@github.com:Star0time/Star0time.github.io.git
branch: master
相同的部分做替换
- 短链接配置
修改config.yml文件中的永久链接设置:
permalink: posts/:abbrlink/
# 或者
permalink: posts/:abbrlink.html
# abbrlink 配置
abbrlink:
alg: crc32 # 支持 crc16(默认)和 crc32
rep: hex # 支持 dec(默认)和 hex
drafts: false # 是否处理草稿:(true) 处理,(false) 不处理,默认为 false
# 自动根据目录树生成分类
# depth: 所需生成的目录树最大深度,应大于 0
auto_category:
enable: true # 默认启用
depth: # 默认 3
over_write: false
auto_title: false # 启用自动标题功能,能根据路径自动填充标题
auto_date: false # 启用自动日期功能,能根据当前时间自动填充日期
force: false # 启用强制模式,在此模式下,插件会忽略缓存,对每篇已有缩略名的文章重新计算。这只会更新缩略名,不会更新其他前端变量。
- 本地搜索
search:
path: search.xml
field: post
content: true
format: html
- 代码块高亮-联合主题设置
syntax_highlighter: prismjs
文章内容按照更新时间排序
# Home page setting
# path: Root path for your blogs index page. (default = '')
# per_page: Posts displayed per page. (0 = disable pagination)
# order_by: Posts order. (Order by date descending by default)
index_generator:
path: ''
per_page: 10
order_by: -updated
# Archive generator
archive_generator:
per_page: 10
yearly: true
monthly: true
order_by: -updated
主题配置文件
安装主题-next
git clone https://github.com/next-theme/hexo-theme-next themes/next
更新
cd themes/next
git pull
启用本地搜索
NexT配置文件
# Local search
# Dependencies: https://github.com/next-theme/hexo-generator-searchdb
local_search:
enable: true
# Show top n results per article, show all results by setting to -1
top_n_per_article: 1
# Unescape html strings to the readable one.
unescape: false
# Preload the search data when the page loads.
preload: false
去除底部的”由 Hexo & NexT 强力驱动”
# Powered by Hexo & NexT
powered: false
代码块高亮-联合站点配置
codeblock:
# Code Highlight theme
# All available themes: https://theme-next.js.org/highlight/
theme:
light: default
dark: stackoverflow-dark
prism:
light: prism-tomorrow
dark: prism-tomorrow
侧边栏靠右展示
sidebar:
# Sidebar position. Available values: left | right
position: right
侧边栏隐藏
设置侧栏显示的时机,修改 Sidebar display 的值,支持的选项有:
post- 默认行为,在文章页面(拥有目录列表)时显示always- 在所有页面中都显示hide- 在所有页面中都隐藏(可以手动展开)remove- 完全移除
sidebar:
display: hide
添加代码复制按钮
配置copy_button字段:
copy_button:
enable: true
# Available values: default | flat | mac
style: mac
# Fold code block
fold:
enable: true
height: 500
返回顶部
back2top:
enable: true
# Back to top in sidebar.
sidebar: false
# Scroll percent label in b2t button.
scrollpercent: true
上下篇文章导航按照更新时间排序
1. 修改主题配置文件 _config.yml
确保已开启文章导航:
post_navigation:
enabled: true
# 添加或修改这一行
order_by: updated # 可选: updated, date, title
2. 在Hexo根目录创建脚本
在博客根目录的 scripts/ 文件夹(如果没有就创建一个)中创建 custom-nav.js:
'use strict';
hexo.extend.filter.register('template_locals', function(locals) {
if (locals.page && locals.page.layout === 'post') {
// 获取所有文章按更新时间排序
const posts = locals.site.posts.sort('updated', -1).toArray();
const currentIndex = posts.findIndex(post =>
post._id === locals.page._id ||
(post.title === locals.page.title && post.date === locals.page.date)
);
if (currentIndex !== -1) {
// 设置上一篇和下一篇
locals.page.prev = currentIndex > 0 ? posts[currentIndex - 1] : null;
locals.page.next = currentIndex < posts.length - 1 ? posts[currentIndex + 1] : null;
}
}
return locals;
});
文章内容分栏设计(针对股票)
- 在博客根目录/source/_data文件夹内新建styles.styl文件,内容如下
// 媒体分栏布局 - 通用样式
// 覆盖主题的默认图片样式
.media-split-layout .image-container img {
margin-bottom: 0 !important;
}
// 主布局容器 - 基础样式
.media-split-layout {
display: flex;
align-items: stretch;
gap: 20px;
margin: 40px 0;
position: relative;
}
// 图片容器 - 共用样式
.image-container {
flex: 0 0 80%;
background: white;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
margin-bottom: 0 !important;
}
.image-container img {
width: auto;
height: 100%;
max-width: 100%;
max-height: 100%;
object-fit: contain;
object-position: center;
border-radius: 8px;
margin: 0 !important;
display: block;
}
// 文字容器 - 共用样式
.text-container {
flex: 0 0 20%;
position: relative;
background: white;
border-radius: 8px;
box-shadow: 0 3px 10px rgba(0,0,0,0.05);
overflow: hidden;
margin-bottom: 0 !important;
}
// 文字块 - 共用样式
.text-block {
position: absolute;
left: 0;
right: 0;
padding: 15px;
border-bottom: 1px solid #f0f0f0;
transition: background 0.3s ease;
overflow: auto; /* 改为auto,允许滚动 */
box-sizing: border-box;
}
.text-block:last-child {
border-bottom: none;
}
.text-block:hover {
background: #f8fafc;
}
.text-block h5 {
margin: 0 0 8px 0;
color: #333;
font-weight: 600;
line-height: 1.2;
}
.text-block p {
margin: 0;
line-height: 1.5;
color: #666;
/* 移除行数限制,允许完整显示 */
display: block;
overflow: visible;
white-space: normal;
}
// ========== 4块布局样式 ==========
.media-split-layout-4 {
min-height: 500px;
}
.media-split-layout-4 .text-block {
height: 25%; /* 100% ÷ 4 */
}
.media-split-layout-4 .text-block h5 {
font-size: 15px;
}
.media-split-layout-4 .text-block p {
font-size: 13px;
}
// ========== 6块布局样式 ==========
.media-split-layout-6 {
min-height: 600px;
}
.media-split-layout-6 .text-block {
height: 16.6667%; /* 100% ÷ 6 */
}
.media-split-layout-6 .text-block h5 {
font-size: 14px;
}
.media-split-layout-6 .text-block p {
font-size: 12px;
/* 移除行数限制 */
}
// ========== 响应式设计 ==========
@media (max-width: 768px) {
.media-split-layout {
flex-direction: column;
min-height: auto !important;
}
.image-container,
.text-container {
flex: 0 0 100% !important;
width: 100%;
}
.image-container {
height: 300px;
}
.text-container {
height: auto;
min-height: 300px;
}
.text-block {
position: relative !important;
top: 0 !important;
height: auto !important;
min-height: 80px;
overflow: visible; /* 移动端不需要滚动 */
}
// 移动端调整文字大小
.media-split-layout-4 .text-block {
padding: 12px;
}
.media-split-layout-4 .text-block h5 {
font-size: 14px;
margin-bottom: 6px;
}
.media-split-layout-4 .text-block p {
font-size: 12px;
line-height: 1.4;
}
.media-split-layout-6 .text-block {
padding: 10px;
}
.media-split-layout-6 .text-block h5 {
font-size: 13px;
margin-bottom: 4px;
}
.media-split-layout-6 .text-block p {
font-size: 11px;
line-height: 1.3;
}
}
找到主题设置文件 博客根目录/themes/next/_config.yml,
找到 custom_file_path,
新增一条 style: source/_data/styles.styl
新增文章布局:6块文章布局
<div class="media-split-layout media-split-layout-6">
<div class="image-container">
<img src="/images/图片2.jpg" alt="示例图片">
</div>
<div class="text-container">
<div class="text-block" style="top: 0%; height: 16.6667%;">
<h5 id="section-1">标题1</h5>
<p>内容1</p>
</div>
<div class="text-block" style="top: 16.6667%; height: 16.6667%;">
<h5 id="section-2">标题2</h5>
<p>内容2</p>
</div>
<div class="text-block" style="top: 33.3333%; height: 16.6667%;">
<h5 id="section-3">标题3</h5>
<p>内容3</p>
</div>
<div class="text-block" style="top: 50%; height: 16.6667%;">
<h5 id="section-4">标题4</h5>
<p>内容4</p>
</div>
<div class="text-block" style="top: 66.6667%; height: 16.6667%;">
<h5 id="section-5">标题5</h5>
<p>内容5</p>
</div>
<div class="text-block" style="top: 83.3333%; height: 16.6667%;">
<h5 id="section-6">标题6</h5>
<p>内容6</p>
</div>
</div>
</div>
- 新增文章布局:4块文章布局
<div class="media-split-layout media-split-layout-4">
<div class="image-container">
<img src="/images/图片1.jpg" alt="示例图片">
</div>
<div class="text-container">
<div class="text-block" style="top: 0%; height: 25%;">
<h5 id="section-1">标题1</h5>
<p>内容1</p>
</div>
<div class="text-block" style="top: 25%; height: 25%;">
<h5 id="section-2">标题2</h5>
<p>内容2</p>
</div>
<div class="text-block" style="top: 50%; height: 25%;">
<h5 id="section-3">标题3</h5>
<p>内容3</p>
</div>
<div class="text-block" style="top: 75%; height: 25%;">
<h5 id="section-4">标题4</h5>
<p>内容4</p>
</div>
</div>
</div>
代码块字号小1.5号
在styles.styl文件内,新增以下代码:
// ========== 代码字体大小调整(小1.5号) ==========
// 基准字体大小假设为16px,小1.5号约为13.5px (0.84em)
// 1. 行内代码(小1.5号)
code:not(pre code) {
font-size: 0.84em !important; // 小1.5号
padding: 0.15em 0.3em !important;
background-color: rgba(127, 127, 127, 0.05) !important;
border-radius: 2px !important;
border: 1px solid rgba(127, 127, 127, 0.08) !important;
}
// 2. 代码块(小1.5号)
pre, pre code {
font-size: 0.88em !important; // 小1.5号,比行内代码稍大一点
line-height: 1.7 !important; // 增加行高以提高可读性
}
// 3. 代码块容器
.highlight, figure.highlight {
font-size: 0.88em !important;
}
// 4. 高亮代码区域
.highlight pre, .highlight code {
font-size: 0.88em !important;
}
// 5. Prism.js 样式(如果使用)
pre[class*="language-"], code[class*="language-"] {
font-size: 0.88em !important;
}
// 6. 行号调整
.gutter pre {
font-size: 0.82em !important; // 行号更小一点
color: #888 !important;
text-align: right !important;
padding-right: 8px !important;
}
// 7. 表格内的代码(更小一些)
table code {
font-size: 0.78em !important;
}
// 8. 列表和引用块内的代码
li code, blockquote code {
font-size: 0.8em !important;
}
// 9. 标题内的代码(保持相对大小)
h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
font-size: 0.85em !important;
}
// 10. 移动设备适配
@media (max-width: 767px) {
code:not(pre code) {
font-size: 0.78em !important;
}
pre, pre code {
font-size: 0.82em !important;
}
.gutter pre {
font-size: 0.76em !important;
}
}
在 themes/next/_config.yml 中确保以下配置:
codeblock:
# Code Highlight theme
# All available themes: https://theme-next.js.org/highlight/
theme:
light: default
dark: stackoverflow-dark
prism:
light: prism-tomorrow
dark: prism-tomorrow
# Add copy button on codeblock
copy_button:
enable: true
# Available values: default | flat | mac
style: mac
# Fold code block
fold:
enable: true
height: 500
# Display language name
language: false
# 添加字体大小配置(如果不存在,添加以下内容)
font_size:
# 正常代码块
normal: 14px
# 移动设备
mobile: 13px
# 行高调整(可选,使小字体更易读)
line_height: 1.7
新增顶部导航
这是最可靠的方法,因为主题文件是纯HTML/模板文件,可以直接使用模板语法。
步骤1:修改Next主题的文章模板
找到并修改 themes/next/layout/_macro/post.njk 文件:
在 文章标题和内容之间 添加以下代码(在适当的位置):
njk
{# 添加简洁顶部导航 #}
{% if not is_index and theme.post_navigation and (post.prev or post.next) %}
{% set prev = post.prev if theme.post_navigation === 'right' else post.next %}
{% set next = post.next if theme.post_navigation === 'right' else post.prev %}
<nav class="simple-top-nav" style="margin: 20px 0 25px 0; padding: 0; border-top: 1px solid #eee; border-bottom: 1px solid #eee;">
<div style="display: flex; justify-content: space-between; align-items: center; padding: 10px 0; font-size: 13px;">
{% if prev %}
<div style="flex: 1;">
<a href="{{ url_for(prev.path) }}" rel="prev" style="color: #666; text-decoration: none; display: inline-flex; align-items: center; padding: 5px 10px; border-radius: 4px; transition: all 0.2s ease;">
<span style="margin-right: 5px;">←</span>
<span style="max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
{{ prev.title or __('post.untitled') }}
</span>
</a>
</div>
{% endif %}
<div style="flex: 0 0 auto; padding: 0 15px; color: #999; font-size: 12px;">
{% if prev and next %}|{% endif %}
</div>
{% if next %}
<div style="flex: 1; text-align: right;">
<a href="{{ url_for(next.path) }}" rel="next" style="color: #666; text-decoration: none; display: inline-flex; align-items: center; padding: 5px 10px; border-radius: 4px; transition: all 0.2s ease;">
<span style="max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
{{ next.title or __('post.untitled') }}
</span>
<span style="margin-left: 5px;">→</span>
</a>
</div>
{% endif %}
</div>
</nav>
<style>
/* 简洁悬停效果 */
.simple-top-nav a:hover {
color: #0078e7 !important;
background-color: #f5f5f5 !important;
}
/* 移动端适配 */
@media (max-width: 768px) {
.simple-top-nav a span {
max-width: 150px !important;
}
.simple-top-nav div[style*="flex: 0 0 auto"] {
padding: 0 8px !important;
}
}
@media (max-width: 480px) {
.simple-top-nav a span {
max-width: 120px !important;
}
}
</style>
{% endif %}
步骤2:具体位置参考
在你的 post.njk 文件中找到这个位置:
njk
{# 文章标题部分 #}
<header class="post-header">
<!-- 标题代码 -->
</header>
{# ========== 在这里添加上面的导航代码 ========== #}
{# 文章内容部分 #}
<div class="post-body" itemprop="articleBody">
<!-- 文章内容 -->
</div>
当点击锚点链接跳转到页面上的某个元素(比如 #market-position)时,该元素会出现在视口的顶部边缘,但标题被页面的固定头部(如导航栏)遮挡,导致需要向上滚动才能看到完整的标题。
在styles.styl文件内,新增以下代码:
/* 所有带有 id 的元素在成为滚动目标时,顶部留出 80px 空白 */
[id] {
scroll-margin-top: 80px;
}
阅读全文增加圆角效果
在styles.styl文件内,新增以下代码
/* 阅读全文增加圆角效果*/
.btn {
border-radius: 10px;
}