博客上一个主题是 Initial 用了2-3年,后来更换到 Facile,目前是2.4版本,为方便以后跟随主题作者更新,根据自己的需求做了一些修改。

1、自定义CSS样式

header .navbar{border-width:0 0 1px 0;}
.post-list .post .post-title{font-size:26px;}
.sidebar section h2{font-size:14px;}
.sidebar section ul li{font-size:14px;}
.sidebar section ul li a{font-size:14px;}
.sidebar .latest-comment .media-body p{font-size:14px;}
.text-color{font-size:14px;word-wrap:break-word;word-break:break-all;}
.post-page article .post-content img:not(.logo){display:inline;}
.post-page article .post-content blockquote{border-left:4px solid #ccc;font-size:14px;color:#888;}
.archive-title{border-radius:4px;padding:18px 20px 10px;text-align:center;}
.archive-page .archives .archives-item ul li .day{text-align:right;}
.auto-color .archive-title{background:#f3f3f3;}
.light-color .archive-title{background:#f3f3f3;}
.dark-color .archive-title{background:#16161a;}
.nav-item{font-size:14px;}
.nitxt .form-control{height:calc(2.25em + .75rem + 3px);}
.nitxt .required{color:#f00;}
.text-truncate{font-size:16px;}
.table-responsive{font-size:16px;}
code{font-size:100%;padding:0 4px;}
#comments .comment-input .row div{margin-bottom:0;}
#comments .comment-input .row div.nitxt{margin-bottom:16px;}
#comments .comments-lists .comment-author .comment-reply a, #comments .comments-lists .comment-author .comment-reply i{font-size:12px;color:#888;}
#copyright-info p{font-size:.8125rem;line-height:120%;}
#copyright-info p a{font-size:.8125rem;}
footer .text-center {font-size:12px;}
@media screen and (max-width:575px) {
  .post-list .post .post-title{font-size:20px;}
  .post-page .post-title{font-size:22px;}
}
注:comment-input.php文件inputtextarea上层divclass加上:nitxt,目的为了统一输入框与验证码Captcha的高度。

2、自定义JS,实现内容里非本站链接弹出新窗口打开

<script type="text/javascript">
  const currentDomain = window.location.hostname;
  const links = document.querySelectorAll('.post-content a');
  links.forEach(el => {
    if (el.getAttribute('href').includes(currentDomain)) {
      el.removeAttribute('target');
    }
  });
</script>

3、标题和模板副标题中间加上“-”分隔

查找header.php的代码<?php if ($this->is('index')) echo $this->options->tagline; ?>,修改为:<?php if ($this->is('index')) echo ' - ' . $this->options->tagline; ?>

4、新增导航显示文章分类

查找header.php的代码<?php $this->widget('Widget_Contents_Page_List')->to($pages); ?>,在其上方加入:

<?php $this->widget('Widget_Metas_Category_List@nav')->to($category); ?>
<?php while($category->next()): ?>
<li class="nav-item<?php if ($this->is('category', $category->slug)) echo ' active'; ?>">
  <a class="nav-link" href="<?php $category->permalink(); ?>"<?php if ($this->is('category', $category->slug)) echo ' aria-current="category"'; ?>><?php $category->name(); ?></a>
</li>
<?php endwhile; ?>

5、新增分享内容页给好友或朋友圈时,显示缩微图和简介

查找header.php的代码<link rel="icon" href="<?php echo $this->options->logoUrl?$this->options->logoUrl:$this->options->siteUrl . 'favicon.ico'; ?>" type="image/x-icon">,在其上方加入:

<?php if ($this->is('post') || $this->is('page')): ?>
<?php
// 获取缩略图
$thumb = '';
// 先尝试自定义字段
if ($this->fields->thumb) {
    $thumb = $this->fields->thumb;
} 
// 再尝试自动获取第一张图片
else {
    preg_match('/<img[^>]+src=[\'"]([^\'"]+)[\'"][^>]*>/i', $this->content, $matches);
    if (!empty($matches[1])) {
        $thumb = $matches[1];
    }
}
// 处理图片路径,确保是完整URL
if (!empty($thumb)) {
    // 如果已经是完整URL(http/https或//开头),不做处理
    if (!preg_match('/^(https?:)?\/\//i', $thumb)) {
        // 不是完整URL,需要加上网站根URL
        if (strpos($thumb, '/') === 0) {
            // 以斜杠开头,是网站根目录下的绝对路径
            $thumb = rtrim($this->options->siteUrl, '/') . $thumb;
        } else {
            // 相对路径,使用网站根URL作为基础
            $thumb = rtrim($this->options->siteUrl, '/') . '/' . ltrim($thumb, '/');
        }
    }
} 
// 没有图片,使用默认
else {
    $thumb = rtrim($this->options->siteUrl, '/') . '/usr/themes/' . $this->options->theme . '/images/default.png';
}
// 获取描述
if ($this->fields->excerpt) {
    $description = $this->fields->excerpt;
} elseif ($this->description) {
    $description = $this->description;
} else {
    $description = Typecho_Common::subStr(strip_tags($this->excerpt), 0, 150, '...');
}
?>
    <meta property="og:title" content="<?php $this->title() ?>" />
    <meta property="og:type" content="article" />
    <meta property="og:url" content="<?php $this->permalink() ?>" />
    <meta property="og:image" content="<?php echo $thumb ?>" />
    <meta property="og:image:width" content="800" />
    <meta property="og:image:height" content="800" />
    <meta property="og:description" content="<?php echo htmlspecialchars($description) ?>" />
    <meta property="og:site_name" content="<?php $this->options->title() ?>" />
    <!-- Twitter -->
    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:title" content="<?php $this->title() ?>" />
    <meta name="twitter:description" content="<?php echo htmlspecialchars($description) ?>" />
    <meta name="twitter:image" content="<?php echo $thumb ?>" />
    <!-- Wechat -->
    <meta property="wechat:article:title" content="<?php $this->title() ?>" />
    <meta property="wechat:article:description" content="<?php echo htmlspecialchars(Typecho_Common::subStr(strip_tags($description), 0, 120, '...')) ?>" />
    <meta property="wechat:article:image" content="<?php echo $thumb ?>" />
<?php endif; ?>

6、屏蔽<head>部分相关的meta内容输出

查找header.php的代码<?php $this->header(); ?>,修改为:<?php $this->header('generator=&template=&pingback=&xmlrpc=&wlw=&rss1=&rss2=&atom=&social='); ?>

注:social是Typecho 1.3.0新增的。

7、右侧sidebar新增随机文章显示

helpers.php最底部新增代码如下:

function getRandomPosts($random = 5) {
    $db = Typecho_Db::get();
    $adapterName = $db->getAdapterName(); // 兼容非MySQL数据库
    if ($adapterName == 'pgsql' || $adapterName == 'Pdo_Pgsql' || $adapterName == 'Pdo_SQLite' || $adapterName == 'SQLite') {
        $order_by = 'RANDOM()';
    } else {
        $order_by = 'RAND()';
    }
    
    $sql = $db->select()->from('table.contents')
        ->where('status = ?', 'publish')
        ->where('table.contents.created <= ?', time())
        ->where('type = ?', 'post')
        ->limit($random)
        ->order($order_by);

    $result = $db->fetchAll($sql);
    if ($result) {
        foreach ($result as $val) {
            // 实例化内容组件并推入数据行
            $obj = Typecho_Widget::widget('Widget_Abstract_Contents');
            $obj->push($val);
            
            // 通过对象属性获取数据,避免数组键缺失
            $post_title = htmlspecialchars($obj->title);
            $permalink = $obj->permalink;
            
            echo '
                <li>
                    <a href="' . $permalink . '" title="' . $post_title . '">' . $post_title . '</a>
                </li>';
        }
    }
}

sidebar.php对应位置新增代码:

        <?php if ($component == '推荐阅读'): ?>
            <!--最新文章-->
            <section class="ml-xl-4 ml-lg-3 mb-5">
                <h2 class="mb-4"><?php echo $GLOBALS['t']['sidebar']['recommendPosts']; ?></h2>
                <ul aria-label="<?php echo $GLOBALS['t']['sidebar']['recommendPosts']; ?>">
<?php getRandomPosts(10);?>
                </ul>
            </section>
        <?php endif; ?>

最后在语言包,'sidebar' => array(,下面新增:'recommendPosts' => '推荐阅读',。对应的英文语言包也需要加上。

8、实现文章内容里非本站链接加上rel="nofollow"

查找post.php的这段代码:

<?php $GLOBALS['postPage'] = splitArticleContent($this->content); ?>

替换为下面的新代码:

<?php
$h=parse_url(Typecho_Widget::widget('Widget_Options')->siteUrl,PHP_URL_HOST);
$GLOBALS['postPage']=splitArticleContent(preg_replace_callback('/<a\s+([^>]*)href=["\'](.*?)["\']([^>]*)>/i',function($m)use($h){
$uH=parse_url($m[2],PHP_URL_HOST);
if($uH&&strcasecmp($uH,$h)!==0){
if(preg_match('/rel=["\'](.*?)["\']/i',$m[1],$r)){
stripos($r[1],'nofollow')===false&&$m[1]=str_replace($r[0],'rel="'.$r[1].' nofollow"',$m[1]);
}else{$m[1].=' rel="nofollow"';}
}return'<a '.$m[1].' href="'.$m[2].'"'.$m[3].'>';
},$this->content));
?>