使用 Facile 主题已经有一年多了应该,首先感谢作者的开发,目前我使用得挺好。我最近刚由 2.1.12 切换到 2.2 版本,但是图片懒加载功能似乎一直没有生效?直到我最近写了一篇包含94张图片的文章,才发现浏览体验受到了很大的影响。

我也提了一个 issue,并给出了我的解决方法, https://github.com/changbin1997/Facile/issues/12 作者回复他那边没问题,那很可能是我这边什么插件导致了 replaceImgSrc 方法不起作用,或者其他兼容性问题,但最后好在我解决了,本文就分享一下我的解决方法,并且给出我做的其他小细节定制。

图片懒加载优化

引入懒加载js文件

进入容器(或者你是宿主机直接安装就去宿主机找)找到文件 usr/themes/Facile/components/header.php

<head> 标签下引入脚本,详细如下

找到 <link rel="stylesheet" 这一行,以及 <!--自定义CSS--> 这一行,在其中插入 <script src="https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.2.2/lazysizes.min.js" async></script> 修改后如下

<link rel="stylesheet" href="<?php $this->options->themeUrl('assets/css/style-1722355012.css'); ?>" type="text/css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.2.2/lazysizes.min.js" async></script>
<!--自定义CSS-->
<?php if ($this->options->cssCode): ?>

修改 replaceImgSrc 方法

找到 usr/themes/Facile/functions.php 文件,或者直接在 typecho 后台管理页修改,也就是 控制台 -> 外观 -> 编辑当前外观 -> functions.php,具体修改如下,注释掉原本的代码,我修改的 replaceImgSrc 使用了一个 svg loading 图作为占位符(滚动可视区域内的图片尚未完全加载前的转圈圈效果

// 把图片的 src 替换为 data-src,用于图片懒加载,这是Facile 2.1.12以及2.2 版本当中的代码
//function replaceImgSrc($content) {
//    $pattern = '/<img(.*?)src(.*?)=(.*?)"(.*?)">/i';
//    $replacement = '<img$1data-src$3="$4"$5 class="load-img">';
//    return preg_replace($pattern, $replacement, $content);
// }

function replaceImgSrc($content) {
    // SVG 数据URI
    $loadingSVG = 'data:image/svg+xml;charset=UTF-8,' . rawurlencode('<svg version="1.1" id="L9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 0 0" xml:space="preserve"><path fill="#000" d="M73.438,49.25c0-13.025-10.634-23.562-23.75-23.562c-13.024,0-23.562,10.537-23.562,23.562h6.797 c0-9.276,7.489-16.765,16.765-16.765c9.276,0,16.765,7.489,16.765,16.765H73.438z"><animateTransform attributeName="transform" attributeType="XML" type="rotate" dur="1s" from="0 50 50" to="360 50 50" repeatCount="indefinite" /></path></svg>');

    $pattern = '/<img(.*?)src=["\'](.*?)["\'](.*?[^>])>/i';
    $replacement = '<img$1src="' . $loadingSVG . '" data-src="$2"$3 class="lazyload"><noscript><img$1src="$2"$3></noscript>';
    return preg_replace($pattern, $replacement, $content);
}

这个方法是在 usr/themes/Facile/post.php 的如下地方调用的,也就是主题设置中的图片懒加载功能需要打开

<?php echo $this->options->imagelazyloading == 'on'?replaceImgSrc($GLOBALS['post']['content']):$GLOBALS['post']['content']; ?>

最终我这边图片懒加载功能完美运行,你可以参考我这篇文章,一共94张图,可以很好地预览图片懒加载功能 2024年8月我的宜昌 - 重庆 - 川西小环线自驾旅行分享

给文章添加字数统计和预计阅读时间

usr/themes/Facile/functions.php 尾部追加代码,如下

// 添加文章字数统计,预计阅读用时方法
function  art_count ($cid){
    $db = Typecho_Db::get ();
    $rs = $db->fetchRow ($db->select ('table.contents.text')->from ('table.contents')->where ('table.contents.cid=?',$cid)->order ('table.contents.cid',Typecho_Db::SORT_ASC)->limit (1));
    $text = preg_replace("/[^\x{4e00}-\x{9fa5}]/u", "", $rs['text']);
    $text_num = mb_strlen($text,'UTF-8');
    $read_time = ceil($text_num/400);
    $output = '本文共' . $text_num . '个字,预计阅读时间' . $read_time  . '分钟';
    return $output;
}

然后修改 usr/themes/Facile/post.php 文件,在适当位置调用 art_count 方法,修改后如下

<span class="ml-1" title="发布日期" data-toggle="tooltip" data-placement="top">
    <i class="icon-calendar mr-2" aria-hidden="true"></i>
    <?php $this->date('Y年m月d日'); ?>
</span>
<span class="ml-2" title="作者" data-toggle="tooltip" data-placement="top">
    <i class="icon-user mr-2" aria-hidden="true"></i>
    <a rel="author" href="<?php $this->author->permalink(); ?>" class="mr-2" title="作者:<?php $this->author(); ?>">
        <?php $this->author(); ?>
    </a>
</span>
<span class="ml-2" title="阅读量" data-toggle="tooltip" data-placement="top">
    <i class="icon-eye mr-2" aria-hidden="true"></i>
    <?php echo postViews($this); ?>
</span>
<span class="ml-2" title="文章字数和阅读预计用时" data-toggle="tooltip" data-placement="top">
    <i class="icon-eye mr-2" aria-hidden="true"></i>
    <?php _e(art_count($this->cid)); ?>
</span>

页面footer底部修改

修改文件 usr/themes/Facile/components/footer.php ,我改成了如下

<footer>
    <div class="container py-3">
        <?php if ($this->options->icp): ?>
        <nav class="text-center mb-1">
            <?php $this->options->icp(); ?>
        </nav>
        <?php endif; ?>
        <nav class="text-center">
            <p>Copyright &copy;
                <?php echo "2019 - " . date('Y'); ?> by hellodk.cn | Proudly Powered by <a href="http://www.typecho.org"
                    target="_blank">Typecho</a> &amp;
                <a href="https://hellodk.cn/" target="_blank"> ❤.</a>
                Theme by
                <a class="ml-1" href="https://github.com/changbin1997/Facile" target="_blank">Facile</a>.
            </p>
            <p>
                <?php hasBeenRunningTime2(); ?>
            </p>
        </nav>
    </div>
</footer>

其中调用了一个方法 hasBeenRunningTime2,该方法定义如下,添加到 usr/themes/Facile/functions.php 尾部

// 计算网站已运行多长时间
function hasBeenRunningTime2()
{

        // 设置时区
        date_default_timezone_set('Asia/Shanghai');
        // 在下面按格式输入本站创建的时间
        $site_create_time = strtotime('2019-04-06 14:00:00'); //格式:年 月 日 时 分 秒
        $time = time() - $site_create_time;
        if (is_numeric($time)) {
                $value = array(
                        "years" => 0, "days" => 0, "hours" => 0,
                        "minutes" => 0, "seconds" => 0,
                );
                if ($time >= 31556926) {
                        $value["years"] = floor($time / 31556926);
                        $time = ($time % 31556926);
                }
                if ($time >= 86400) {
                        $value["days"] = floor($time / 86400);
                        $time = ($time % 86400);
                }
                if ($time >= 3600) {
                        $value["hours"] = floor($time / 3600);
                        $time = ($time % 3600);
                }
                if ($time >= 60) {
                        $value["minutes"] = floor($time / 60);
                        $time = ($time % 60);
                }
                $value["seconds"] = floor($time);
                echo 'Site has been running for ';
                echo '<span class="btime">' . $value['years'] . ' years ' . $value['days'] . ' days ' . $value['hours'] . ' hours.</span>';
        } else {
                echo '';
        }
}

访客添加评论时增加简单算数校验

usr/themes/Facile/functions.php 尾部追加方法,代码如下

//评论区简单算术验证,防止评论被滥用
function themeInit($comment){
    $comment = spam_protection_pre($comment, $post, $result);
}

function spam_protection_math(){
    $num1=rand(1,49);
    //数字范围,自定义修改
    $num2=rand(1,49);
    echo "验证码:<input type=\"text\" name=\"sum\" class=\"text\" value=\"\" size=\"25\" tabindex=\"4\" style=\"width:100px\" placeholder=\"$num1 + $num2 = ?\">\n";
    echo "<input type=\"hidden\" name=\"num1\" value=\"$num1\">\n";
    echo "<input type=\"hidden\" name=\"num2\" value=\"$num2\">";
}

function spam_protection_pre($comment, $post, $result){
    $sum=$_POST['sum'];
    switch($sum){
        case $_POST['num1']+$_POST['num2']:
        break;
        case null:
        throw new Typecho_Widget_Exception(_t('对不起: 请输入验证码。<a href="javascript:history.back(-1)">返回上一页</a>','评论失败'));
        break;
        default:
        throw new Typecho_Widget_Exception(_t('对不起: 验证码错误,请<a href="javascript:history.back(-1)">返回</a>重试 。','评论失败'));
    }
    return $comment;
}

然后需要修改 usr/themes/Facile/components/comment-input.php 文件,在适当位置添加对 spam_protection_math 方法的调用,修改后如下

<!--姓名输入-->
<div class="col-12 col-sm-12 col-md-6 col-lg-6 col-xl-6">
    <label for="author" class="d-block">姓名</label>
    <input type="text" class="form-control" placeholder="请输入您的姓名或昵称" name="author" id="author" value="<?php $this->remember('author'); ?>" required>
</div>
<!--邮箱地址输入-->
<div class="col-12 col-sm-12 col-md-6 col-lg-6 col-xl-6">
    <label for="mail" class="d-block">电子邮件地址(不会公开)</label>
    <input type="email" class="form-control" placeholder="请输入您的电子邮件地址" name="mail" id="mail" value="<?php $this->remember('mail'); ?>" <?php if ($this->options->commentsRequireMail): ?> required <?php endif; ?>>
</div>
<!--网站地址输入-->
<div class="col-12 col-sm-12 col-md-6 col-lg-6 col-xl-6">
    <label for="url" class="d-block">网站(选填)</label>
    <input type="url" class="form-control" placeholder="请输入您的网站或博客地址" name="url" id="url" value="<?php $this->remember('url'); ?>" <?php if ($this->options->commentsRequireURL): ?> required <?php endif; ?>>
</div>
<!--数字验证码-->
<div class="col-12 col-sm-12 col-md-6 col-lg-6 col-xl-6">
    <?php spam_protection_math(); ?>
</div>

gravatar 换源

参考了这篇文章 Gravatar 头像镜像源收集 (2024年)

主题

Facile 2.2 版本支持在主题设置中设置 gravatar 源,于是我参考上面文章,修改成了 https://cravatar.cn/avatar/ 国内源,目前 gravatar 头像加载速度很快,解决的很完美。

博客全局

顺便修改一下 Typecho 系统全局的 gravatar 源。比如在 manage-comments.php 评论管理页面就用上了这个地方定义的头像源。修改文件 config.inc.php,改成如下

// 更换头像源
define('__TYPECHO_GRAVATAR_PREFIX__', 'https://cravatar.cn/avatar/');

改后建议重启 typecho 和数据库。


好了,目前我做的一些修改就是这些。其实之前 2.1.12版本时我还做了全站字数统计放在归档页面等小细节,但是目前就这样,先不改了。

本文是给自己做的修改的详细记录,也给广大网友提供了参考。如有问题,欢迎评论。