给博客食用的预制菜(主题改造记录)

(这个页面是站长自用的,用来记录他改造博客主题的过程,防止改不回去)

(本页面会持续更新一些博客优化/美化代码)

⚠*Warning/警告*⚠
本文的某些代码仅限于Argon主题

Mimosa提醒您:在改动主题代码前一定要记得做好备份工作。

本文最后更新时间:2025.4.11

实况照片

*ATTENTION/注意*
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 来实现弹窗仅在每个浏览器只显示一次。

不需要烟花的可以把注释=🎇 弹窗逻辑=下面的for循环改成for (let i = 0; i < 0; i++) {

为了防止网站主题文件的样式预设干扰,这里把所有样式后面都加了!important权重,并且把所有变量名都起的特别长(防止重复变量名干扰)

for循环那儿可以调整烟花的个数(i < 8那儿)和每个烟花间隔的延迟;const particleCount_2025 = 45;可以调整每个烟花微粒的个数(别太多了,容易死机的);

colorList_2025这个列表是烟花微粒的随机颜色

<!--弹窗-->
<style>
    /* 弹窗 */
    .popup_modal_2025_newyear {
        display: none;
        position: fixed;
        z-index: 99999;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        background: white !important;
        padding: 20px !important;
        border-radius: 10px !important;
        text-align: center !important;
        width: 320px !important;
        box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3) !important;
    }

    .popup_modal_2025_newyear h2 {
        margin: 0 !important;
        font-size: 22px !important;
    }

    .popup_modal_2025_newyear p {
        margin: 15px 0 !important;
    }

    .popup_modal_2025_newyear button {
        margin-top: 10px !important;
        padding: 8px 20px !important;
        border: none !important;
        background-color: #007BFF !important;
        color: white !important;
        border-radius: 5px !important;
        cursor: pointer !important;
    }

    /* 烟花粒子 */
    .firework_particle_2025 {
        position: absolute !important;
        width: 6px !important;
        height: 6px !important;
        opacity: 1 !important;
        border-radius: 2px !important; 
    }
    
    .cillo_2025_text_h2 {
        color: #A52A2A !important;
    }
    
    .cillo_2025_text_p {
        color: #8B4500 !important;
    }
    
    
</style>


<!-- 弹窗 -->
<div id="modal_container_2025_happy_newyear" class="popup_modal_2025_newyear">
    <h2 class="cillo_2025_text_h2">🎉 2025 新年快乐 🎉</h2>
    <p class="cillo_2025_text_p">愿新的一年,所有的美好都如期而至,所有的期待都不负等待。</p>
    <button onclick="closePopup_2025_newyear()">确定</button>
</div>

<script>
    // === 🎆 烟花特效 ===
    function createFireworkEffect_2025(x, y) {
        const colorList_2025 = ["#FFFF00", "#7CFC00", "#33FF57", "#339FFF", "#E633FF"];
        const particleCount_2025 = 45; //每个烟花的微粒数量

        for (let i = 0; i < particleCount_2025; i++) {
            let particleElement_2025 = document.createElement("div");
            particleElement_2025.classList.add("firework_particle_2025");
            particleElement_2025.style.backgroundColor = colorList_2025[Math.floor(Math.random() * colorList_2025.length)];
            particleElement_2025.style.left = `${x}px`;
            particleElement_2025.style.top = `${y}px`;

            document.body.appendChild(particleElement_2025);

            let angle_2025 = (Math.PI * 2 * i) / particleCount_2025;
            let velocity_2025 = Math.random() * 4 + 2;
            let gravity_2025 = 0.15;
            let xVelocity_2025 = Math.cos(angle_2025) * velocity_2025;
            let yVelocity_2025 = Math.sin(angle_2025) * velocity_2025;
            let fadeOut_2025 = 1;

            let animation_2025 = setInterval(() => {
                xVelocity_2025 *= 0.98;
                yVelocity_2025 += gravity_2025;
                let newX_2025 = parseFloat(particleElement_2025.style.left) + xVelocity_2025;
                let newY_2025 = parseFloat(particleElement_2025.style.top) + yVelocity_2025;

                particleElement_2025.style.left = `${newX_2025}px`;
                particleElement_2025.style.top = `${newY_2025}px`;
                fadeOut_2025 -= 0.02;
                particleElement_2025.style.opacity = fadeOut_2025;

                if (fadeOut_2025 <= 0) {
                    clearInterval(animation_2025);
                    particleElement_2025.remove();
                }
            }, 20);
        }
    }

    //随机位置
    function randomPosition_2025() {
        return [Math.random() * window.innerWidth * 0.9, Math.random() * window.innerHeight * 0.6];
    }
    // === 🎇 弹窗逻辑 ===
    function showPopup_2025_newyear() {
        if (!localStorage.getItem("popup_2025_newyear_shown")) {
            document.getElementById("modal_container_2025_happy_newyear").style.display = "block";
    
            for (let i = 0; i < 8; i++) {
                setTimeout(() => {
                    let [x, y] = randomPosition_2025();
                    createFireworkEffect_2025(x, y);
                }, i * 650); // 每次间隔 650ms
            }
        }
    }



    function closePopup_2025_newyear() {
        document.getElementById("modal_container_2025_happy_newyear").style.display = "none";
        localStorage.setItem("popup_2025_newyear_shown", "true");
    }

    showPopup_2025_newyear();

</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&#10;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 -->

博客热力图

为博客添加热力图(仿Github贡献图) – 阿草Mimosa的小屋

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯
 ̄﹃ ̄
(/ω\)
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
(´っω・`。)
( ,,´・ω・)ノ)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•)
(ㆆᴗㆆ)
有希酱最可爱啦!(素材来自bilibili@最上川下山)
from魔女的夜宴 (Mimosa整理)
Source: github.com/k4yt3x/flowerhd
整活by Mimosa233
颜文字
周防有希
魔女
小恐龙
花!
夸夸我!