(这个页面是站长自用的,用来记录他改造博客主题的过程,防止改不回去)
(本页面会持续更新一些博客优化/美化代码)
本文的某些代码仅限于Argon主题
—
Mimosa提醒您:在改动主题代码前一定要记得做好备份工作。
本文最后更新时间:2025.6.17
注:标题中打星号(*)的是仅限于argon使用
自用引言
Mimosa自用,放在某些作品杂谈文章的开头有奇效。如:
<style>
.fancy-quote {
position: relative;
display: block;
max-width: 80%;
margin: 2em auto;
padding: 1em 2em;
font-size: 1.6em;
line-height: 1.4;
text-align: center;
font-weight: bold;
color: #20c1dd;
}
.fancy-quote::before,
.fancy-quote::after {
position: absolute;
font-family: serif;
font-size: 1.85em;
color: #c1c3f2;
line-height: 1;
}
/* 左引号:紧贴容器的内边距起始位置 */
.fancy-quote::before {
content: "“";
inset-block-start: 0;
inset-inline-start: 0;
transform: translate(-50%, -50%);
}
/* 右引号:紧贴容器的内边距结束位置 */
.fancy-quote::after {
content: "”";
inset-block-end: 0;
inset-inline-end: 0;
transform: translate(50%, 50%);
}
</style>
<div class="fancy-quote">
<span style="color:yellow;">有朋自远方来 </span><span style="color:#20c1dd;">不亦乐乎</span>
</div>
字数统计+与文学作品字数比较
实现效果:
(这里直接用MySQL查询的)
首先,在你主题的functions.php里加上这个。
function get_site_word_count_comparison_filtered() {
global $wpdb;
// 获取所有已发布的文章
$post_ids = $wpdb->get_col("
SELECT ID FROM {$wpdb->prefix}posts
WHERE post_status = 'publish'
AND post_type IN ('post')
");
$total_words = 0;
foreach ($post_ids as $post_id) {
$content = get_post_field('post_content', $post_id);
// 剔除 Markdown 代码块 ```...```
$content = preg_replace('/```.*?```/s', '', $content);
// 剔除 HTML <pre>...</pre> 和 <code>...</code>
$content = preg_replace('/<pre.*?>.*?<\/pre>/is', '', $content);
$content = preg_replace('/<code.*?>.*?<\/code>/is', '', $content);
// 剔除行内代码(Markdown)
$content = preg_replace('/`[^`]+`/', '', $content);
// 剔除 WordPress 短代码里的代码块,如 [code]...[/code]
$content = preg_replace('/\[code\].*?\[\/code\]/is', '', $content);
// 剥离 HTML 标签
$content = strip_tags($content);
// 加总字数
$total_words += mb_strlen(trim($content));
}
$book_map = [
50000 => '《变形记》(卡夫卡)',
58000 => '《老人与海》(海明威)',
70000 => '《动物农庄》(奥威尔)',
97000 => '《鲁滨逊漂流记》(笛福)',
100000 => '《麦田里的守望者》(塞林格)',
120000 => '《月亮与六便士》(毛姆)',
140000 => '《了不起的盖茨比》(菲茨杰拉德)',
180000 => '《挪威的森林》(村上春树)',
260000 => '《百年孤独》(加西亚·马尔克斯)',
320000 => '《悲惨世界》(上册,雨果)',
360000 => '《追风筝的人》(胡赛尼)',
430000 => '《三体》(全集第一部)',
500000 => '《红楼梦》(曹雪芹)',
560000 => '《活着》(余华)+《许三多》合计',
640000 => '《哈利·波特与凤凰社》(J.K.罗琳)',
780000 => '《追忆似水年华》(普鲁斯特)',
860000 => '《指环王》(托尔金,三部曲合计)',
970000 => '《战争与和平》(托尔斯泰)',
1100000 => '《约翰·克利斯朵夫》(罗曼·罗兰)',
1500000 => '《基督山伯爵》(大仲马)+ 注释本',
1800000 => '《史记》(司马迁)',
2000000 => '《尤利西斯》+《荒原狼》(冯内古特等合集)'
];
// 找最近的一本书
$closest_diff = PHP_INT_MAX;
$closest_book = '';
foreach ($book_map as $word_count => $book_name) {
$diff = abs($total_words - $word_count);
if ($diff < $closest_diff) {
$closest_diff = $diff;
$closest_book = $book_name;
}
}
// 输出单行
return '本站文章的总字数(刨除代码)为 ' . number_format($total_words) . ' 字,已经接近 ' . $closest_book . ' 的篇幅了!';
}
(注:在 AND post_type IN
那儿是你要统计的文章类型。比如要把页面也加上就加个”post”,argon主题特有的 ‘shuoshuo’类型也可以的。
$book_map
这个变量是填写对应字数的书籍,可按需修改。)
然后,在你主题的footer.php的footer区块中(或者想要显示的任意地方)添加以下代码来运行上面的函数:
<?php echo get_site_word_count_comparison_filtered(); ?>
argon让文章头图变暗增加标题可读性*
就是给封面图加个灰色遮罩,以防白色标题看不清
在style.css里插入:
/* 1. 让 post-header 成为定位容器 */
.post-header {
position: relative;
}
/* 2. 在容器之上添加遮罩 */
.post-header::before {
content: "";
position: absolute;
inset: 0; /* 相当于 top:0; right:0; bottom:0; left:0; */
background: rgba(0, 0, 0, 0.4); /* 半透明黑色遮罩,可根据需要调节透明度或改成渐变 */
z-index: 1; /* 遮罩在图片之上,但在文字之下 */
pointer-events: none; /* 保证下方链接依旧可点 */
}
/* 3. 确保文字内容在遮罩之上 */
.post-header .post-header-text-container {
position: relative;
z-index: 2;
}
argon短代码*
argon主题自带了许多有趣的短代码。在写长文章的时候需要添加短代码(简码)区块,然后在区块中添加短代码;但发表说说类型的短文时直接同文本一样 输入短代码即可。
[checkbox checked="false"]未完成[/checkbox]
[checkbox checked="true"]已完成[/checkbox]
[label]我是标签[/label]
[label]我是标签*2[/label]
[progressbar progress="50"]50%[/progressbar]
[progressbar progress="100"]100%[/progressbar]
[alert]我是提示[/alert]
[admonition]我是警告[/admonition]
[collapse title="折叠区块标题"]我是折叠区块[/collapse]
[github author="bigbulen" project="" /]
[spoiler]隐藏文本(高斯模糊)[/spoiler]
实现效果:
我是标签
我是标签*2
实况照片
iOS的实况照片实质上就是一张静态图片与heic视频格式的结合。
这里引用Apple Developer的livephotoskit.js (官方使用文档:LivePhotosKit JS | Apple Developer Documentation)来实现。
若需展示动态图片,需将鼠标悬浮至图片左上角的
LIVE
图案上。示例:
(源代码参考» WordPress 古腾堡编辑器增加 live 实况图预览模块 – 漫川笔记,由于源代码有一点bug,Mimosa对其进行二次修改:优化了编辑页面的图片展示以及展示图片路径、展示实况图片的自适应大小)
step.1
在主题的functions.php中,在<?php
后插入以下代码(注:必须在php标签内插入,没有php标签的自己建一个,因为这是php代码):
// 实况图片
function enqueue_livephotoskit_script() {
wp_enqueue_script('livephotoskit-js', 'https://source.loneapex.cn/js/livephotoskit.js', array(), null, true);
}
add_action('wp_enqueue_scripts', 'enqueue_livephotoskit_script');
function register_custom_live_photos_block() {
wp_register_script(
'custom-live-photos-block',
get_template_directory_uri() . '/block.js',
array('wp-blocks', 'wp-element', 'wp-editor', 'wp-components', 'wp-i18n'),
filemtime(get_template_directory() . '/block.js')
);
register_block_type('custom/live-photos-block', array(
'editor_script' => 'custom-live-photos-block',
'render_callback' => 'render_custom_live_photos_block'
));
}
add_action('init', 'register_custom_live_photos_block');
function render_custom_live_photos_block($attributes) {
if (!isset($attributes['photoURL']) || !isset($attributes['videoURL'])) {
return '';
}
$width = '100%';
$height = '300px'; // Example fixed height, adjust as necessary
return sprintf(
'<div class="live-photo-wrapper" style="width:%s; height:%s; position:relative;">
<div data-live-photo data-photo-src="%s" data-video-src="%s" style="width:100%%; height:100%%;"></div>
</div>',
esc_attr($width),
esc_attr($height),
esc_url($attributes['photoURL']),
esc_url($attributes['videoURL'])
);
}
step.2
在博客主题的根目录(与functions.php同级目录)建一个block.js
文件
(function (blocks, editor, element, components) {
var el = element.createElement;
var MediaUpload = editor.MediaUpload;
var InspectorControls = editor.InspectorControls;
var TextControl = components.TextControl;
blocks.registerBlockType('custom/live-photos-block', {
title: 'Live Photos Block',
icon: 'camera',
category: 'media',
attributes: {
photoURL: {
type: 'string',
default: ''
},
videoURL: {
type: 'string',
default: ''
},
width: {
type: 'number',
default: 400
},
height: {
type: 'number',
default: 300
}
},
edit: function (props) {
var attributes = props.attributes;
var setAttributes = props.setAttributes;
return el(
'div',
{ className: props.className },
el('p', {}, '选择图片和视频:'),
el(
MediaUpload,
{
onSelect: function (media) {
setAttributes({ photoURL: media.url });
},
allowedTypes: 'image',
render: function (obj) {
var fileName = '';
if (attributes.photoURL) {
// 从 URL 中提取文件名
fileName = attributes.photoURL.split('/').pop();
}
return el(
components.Button,
{
className: 'button button-large',
onClick: obj.open
},
attributes.photoURL ? fileName : '选择图片'
);
}
}
),
el(
MediaUpload,
{
onSelect: function (media) {
setAttributes({ videoURL: media.url });
},
allowedTypes: 'video',
render: function (obj) {
var fileNam1e = '';
if (attributes.videoURL) {
// 从 URL 中提取文件名
fileName1 = attributes.videoURL.split('/').pop();
}
return el(
components.Button,
{
className: 'button button-large',
onClick: obj.open
},
attributes.videoURL ? fileName1 : '选择视频'
);
}
}
),
el(InspectorControls, {},
el(TextControl, {
label: '宽度(px)',
value: attributes.width,
onChange: function (value) {
setAttributes({ width: parseInt(value, 10) || 0 });
}
}),
el(TextControl, {
label: '高度(px)',
value: attributes.height,
onChange: function (value) {
setAttributes({ height: parseInt(value, 10) || 0 });
}
})
)
);
},
save: function () {
// 后台通过 PHP 渲染,前端保存为空
return null;
}
});
}(
window.wp.blocks,
window.wp.editor,
window.wp.element,
window.wp.components
));
step.3
在写文章的时候应该会出现如图所示的区块,把iOS的实况照片转换成视频格式,然后分别上传图片和视频即可
文章中插入音乐播放器
<link rel="stylesheet" href="https://loneapex.cn/extra-js/Aplayer/APlayer.min.css">
<script src="https://loneapex.cn/extra-js/Aplayer/APlayer.min.js"></script>
<script src="https://loneapex.cn/extra-js/Aplayer/Meting.min.js"></script>
<meting-js
server="netease"
type="song"
id="761626"
fixed="false"
mini="false"
order="list"
loop="all"
preload="false"
list-folded="true"
></meting-js>
这里引用的是aplayer播放器+meting获取网易云音乐
参数:
- id=’外链播放器id’,必须参数(比如网易云音乐播放单曲就填写该音乐id,歌单填写歌单的id,皆可通过网易云音乐的分享链接查看具体id)
- type=[song=单曲, playlist=歌单, album=专辑, search=搜索结果, artist=艺术家],必须参数
- server=[netease=网易云音乐, tencent=QQ音乐, kugou=酷狗音乐, xiami=虾米音乐, baidu=百度音乐],必须参数
- fixed=启用固定模式,固定在左下角,默认false
- mini=在页面左下角启用迷你模式,默认false(不启用的话就是上面的效果)
- preload=[none,metadata,auto] (预加载)
- mutex=[互斥锁,默认true],默认false
- order=[random=随机播放,list=列表播放]
- loop=[all=全部循环, one=循环一次 ,none=不循环]
- volume=[音量,默认0.7]
- lrc-type=[歌词类型,默认0]
- list-folded=[列表是否折叠,默认false]
- list-max-height=列表最大高度,默认340px
- storage-name=本地存储存储密钥,用于存储播放器设置,默认metingjs
节日弹窗(已弃用)
差不多这个效果
由于每次打开网站都会显示这玩意而过于繁琐,我用 JavaScript 和 localStorage 来实现弹窗仅在每个浏览器只显示一次。
<!-- 弹窗样式 -->
<style>
.popup_modal {
display: none;
position: fixed;
z-index: 99999;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background: white;
padding: 20px;
border-radius: 10px;
text-align: center;
width: 320px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
}
.popup_modal h2 {
margin: 0;
font-size: 22px;
color: #A52A2A;
}
.popup_modal p {
margin: 15px 0;
color: #8B4500;
}
.popup_modal button {
margin-top: 10px;
padding: 8px 20px;
border: none;
background-color: #007BFF;
color: white;
border-radius: 5px;
cursor: pointer;
}
</style>
<!-- 弹窗结构 -->
<style>
.popup_modal {
display: none;
position: fixed;
z-index: 99999;
left: 50%;
top: 50%;
transform: translate(-50%, -50%) scale(0.8);
background: #272822 !important;
padding: 20px;
border-radius: 10px;
text-align: center;
width: 320px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
opacity: 0;
transition: opacity 0.3s ease, transform 0.3s ease;
}
.popup_modal.show {
display: block;
opacity: 1;
transform: translate(-50%, -50%) scale(1);
}
.popup_modal.hide {
opacity: 0;
transform: translate(-50%, -50%) scale(0.8);
}
.popup_modal h2 {
margin: 0;
font-size: 22px;
color: #A52A2A;
}
.popup_modal small {
display: block;
margin-top: 8px;
color: #ccc;
}
.popup_modal button {
margin-top: 10px;
padding: 8px 20px;
border: none;
background-color: #007BFF;
color: white;
border-radius: 5px;
cursor: pointer;
}
</style>
<div id="modal" class="popup_modal">
<h2>Mimosa酱去哪了呢?</h2>
<p>他正在享受暑假,请允许他善意地摸鱼吧。</p>
<small>(但是本站并没有停更哦?!)</small>
<button id="closeBtn">原来如此</button>
</div>
<script>
const modal = document.getElementById('modal');
const closeBtn = document.getElementById('closeBtn');
const storageKey = 'popup_2025_newyear_shown';
closeBtn.addEventListener('click', () => {
modal.classList.remove('show');
modal.classList.add('hide');
setTimeout(() => {
modal.style.display = 'none';
localStorage.setItem(storageKey, 'true');
}, 300); // 延迟隐藏,确保动画完成
});
window.addEventListener('DOMContentLoaded', () => {
if (!localStorage.getItem(storageKey)) {
modal.style.display = 'block'; // 先显示出来才能触发过渡动画
requestAnimationFrame(() => {
modal.classList.add('show');
});
}
});
</script>
过年灯笼
详情见这篇文章:给博客挂上赛博灯笼吧 – 阿草Mimosa的小屋
(注:这东西用window.onload
加载,小心别与其他代码冲突。window.onload
的特性是其语句仅能执行一次。若有若干window.onload
代码块,仅执行第一个window.onload
。(我曾经踩过的大坑))
悼念色
为了表示悼念,使整个网站变为黑白色调的。在额外CSS的最底部添加下列代码即可:
/*网站黑白色(悼念)*/
html {
filter: grayscale(100%);
-webkit-filter: grayscale(100%);
-moz-filter: grayscale(100%);
-ms-filter: grayscale(100%);
-o-filter: grayscale(100%);
filter: url("data:image/svg+xml;utf8,#grayscale");
filter:progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);
-webkit-filter: grayscale(1);
}
站内邮件发送内容*
functions.php 1432行 直接找注释//发送评论通知邮件
就行
归档页面添加说说短文章*
详见Argon主题:文章归档页面添加说说类型 – 阿草Mimosa的小屋
讨论区给多个特定邮箱添加标识*
(为了便于管理,我基于argon主题管理页面设置的)
在setting.php最后头(但不是最后)添加
//讨论区 「朋友」标识 号代替邮箱输入
argon_update_option_allow_tags('friend_mail_sign');
然后,去前面(出现很多tr和td、th标签的地方)加上这些:
<tr><th class="subtitle"><h2><?php _e('讨论区朋友标识', 'argon');?></h2></th></tr>
<tr><th class="subtitle" colspan="2"><h2><?php _e('讨论区朋友标识', 'argon');?></h2></th></tr>
<tr>
<th scope="row">
<label><?php _e('邮箱列表(每行一个)', 'argon');?></label>
</th>
<td>
<textarea
name="friend_mail_sign"
rows="5"
cols="50"
placeholder="example1@qq.com example2@gmail.com"
><?php echo htmlspecialchars(get_option('friend_mail_sign')); ?></textarea>
<p class="description"><?php _e('每行输入一个需要显示「朋友」标识的邮箱', 'argon');?></p>
</td>
</tr>
这样是为了在主题后台管理页面输入邮箱,然后让前端获取就行了。
所以,打开functions.php文件,找到//评论样式格式化
注释(我的在1077行)
在博主标识后面添加
<?php
$friendEmails = explode("\n", get_option('friend_mail_sign', ''));
$friendEmails = array_map('trim', $friendEmails); // 去除首尾空格
$friendEmails = array_filter($friendEmails); // 过滤空行
if (in_array($comment->comment_author_email, $friendEmails)) {
echo '<span class="badge badge-warning">' . __('朋友', 'argon') . '</span>';
}
?>
然后往下找,找到//评论样式格式化 (说说预览界面)
注释,我们也要把说说预览给打上标签,过程和代码同上。
首页文章只显示人工摘要,而非截取文字*
首页显示文章摘要可以更好地让读者了解文章内容。
但是,argon主题的文章摘要功能开启后,若没有为文章添加人工摘要,则会自动截取文章的前部分文章作为摘要,这样的效果只会很丑,且无实际意义。
因此,修改主题代码:若有人工摘要则显示,若无人工摘要则不显示。
记得在 argon主题选项 的 「文章内容预览截取字数」 填上数字
在 网站根目录/wp-content/themes/argon/template-parts中 找到content-preview-1.php
(其中有多个content-preview.php,经过Mimosa实测只改动第一个即可实现效果)
将
<?php if ($trim_words_count > 0){ ?>
<div class="post-content">
<?php
if (get_option("argon_hide_shortcode_in_preview") == 'true'){
$preview = wp_trim_words(do_shortcode(get_the_content('...')), $trim_words_count);
}else{
$preview = wp_trim_words(get_the_content('...'), $trim_words_count);
}
if (post_password_required()){
$preview = __("这篇文章受密码保护,输入密码才能阅读", 'argon');
}
if ($preview == ""){
$preview = __("这篇文章没有摘要", 'argon');
}
if ($post -> post_excerpt){
$preview = $post -> post_excerpt;
}
echo $preview;
?>
</div>
<?php
}
?>
替换为
<?php
$preview = '';
if ($post -> post_excerpt){
$preview = $post -> post_excerpt;
}elseif (post_password_required()){
$preview = __("这篇文章受密码保护,输入密码才能阅读", 'argon');
}
if (!empty($preview)){
?>
<div class="post-content">
<?php
if (get_option("argon_hide_shortcode_in_preview") == 'true'){
echo do_shortcode($preview);
}else{
echo $preview;
}
?>
</div>
<?php } ?>
即可。
文内外跳转 (文章锚点)*
(理论适用于h1-h6标签 仅适用于Argon)
添加至footer.php即可:转自Bensz
<!-- 标题自动锚点: Start -->
<script>
window.addEventListener('load', function() {
// 构建标题文本与 Argon ID 的映射表
const headers = document.querySelectorAll('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]');
const textToIdMap = new Map();
headers.forEach(header => {
const id = header.id;
const text = header.textContent.trim();
textToIdMap.set(text, id); // 标题文本 -> ID 映射
});
// 替换页面中的基于文本的锚点链接
const links = document.querySelectorAll('a[href^="#"]');
links.forEach(link => {
const targetText = decodeURIComponent(link.getAttribute('href').slice(1)); // 获取锚点文本
if (textToIdMap.has(targetText)) {
link.setAttribute('href', `#${textToIdMap.get(targetText)}`); // 替换为 Argon 的 ID
}
});
//文外跳转
if (window.location.hash) {
const hash = window.location.hash.slice(1); // 去掉 #
let targetElement;
// 优先检查哈希值是否是一个有效的 ID
targetElement = document.getElementById(hash);
if (!targetElement) {
// 如果哈希值是标题文本,检查映射表
const decodedHash = decodeURIComponent(hash); // 解码哈希值
if (textToIdMap.has(decodedHash)) {
const targetId = textToIdMap.get(decodedHash); // 获取对应的 ID
targetElement = document.getElementById(targetId); // 查找对应 ID 的元素
}
// 替换图片的 src 属性
const lazyImages = document.querySelectorAll('img.lazyload[data-original]');
lazyImages.forEach(img => {
img.src = img.getAttribute('data-original'); // 直接替换为真正的图片链接
});
}
// 如果找到了目标元素,滚动到该元素
if (targetElement) {
targetElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
}
});
</script>
<!-- 标题自动锚点: End -->
这层楼是补充说明用的,请勿回复。
1.字数统计那里 是已经刨除代码的字数了(如果加上代码的话总字数直接翻了四倍😶🌫️,水分过多了),如果想要显示代码的字数可以把那些剔除代码块的限制语句都给删了。
2.音乐播放器那里 请不要直接引用该代码。loneapex.cn已开启防跨域(cros),直接引用的话meting-js脚本加载不出来。loneapex.cn不是cdn,因此请引用自己的APlayer.js和meting.js资源。
请问顶部菜单栏你是如何调整的?只是调整了字体么?
是的,这是原版的菜单栏