创造

改造 Typecho

by Cheng, 2024-06-02


服务器配置比较低,运行 WordPress 越来越吃力了,上个月把站点转移到 Typecho 了,为了让 Typecho 变得更为好用,进行了若干改造。

登录

针对登录写了一个 Cloudflare Turnstile 的插件 typecho-plugin-turnstile

为什么选择 Turnstile 而不是 Google reCAPTCHA 呢?因为 Turnstile 不像 reCAPTCHA 那样恶心人,动不动弹一堆图片让识别。

Turnstile 仅需一个简单的免费代码片段,即可向网站访问者提供零挫败感、无 CAPTCHA 的 Web 体验。此外,Turnstile 可以阻止滥用并确认访问者的真实性,但不会有任何 CAPTCHA 给用户造成的数据隐私担忧或糟糕体验。

启用插件之后,配置好 Site KeySecret Key 就可以在登录的时候显示 Turnstile 的验证模块了。

cloudflare-turnstile.png

搜索

Typecho 的搜索功能不太好用,实现即时搜索比较麻烦。要是能集成 Algolia 就好了。

要集成 Algolia 需要进行两部分工作,第一部分是数据的提交,即将数据结构化地提交到 Algolia。第二部分就是在主题中集成 Algolia 的搜索:InstantSearch.js 或者 Autocomplete

数据提交

Typecho 没有原生的 RESTful API 也不像 WordPress 内置 Cron 功能。考虑到部署等原因,用 Rust 实现了一个将 Tyepcho 的文章同步到 Algolia 的应用:typecho-algolia。填写好配置,运行程序就可以建立 Algolia 的 index。

algolia-dataset.png

同时,程序还会自动对数据进行配置。
algolia-dataset-setting.png

要想及时提交数据,可以通过 Cron 定时运行程序。

*/5 * * * * cd /path/to/the/app && ./sync > /dev/null

搜索实现

Instant Search

const search = instantsearch({
  indexName: 'typecho_posts',
  searchClient,
  insights: true,


  searchFunction(helper) {
    const $hits = $('#hits');
    const $pagination = $('#pagination');

    if (helper.state.query === '') {
      $hits.empty();
      $pagination.empty();
    } else {
      $hits.show();
      $pagination.show();

      helper.search();
    }
  },
});

search.addWidgets([
  searchBox({
    container: '#searchbox',
  }),
  hits({
    container: '#hits',
    templates: {
      item: (hit, { html, components }) => html`
          <a href="/${hit.slug}.html" style="text-decoration: none">
            <h1>${components.Highlight({ hit, highlightedTagName: 'mark', attribute: 'title' })}</h1>
            <p>${components.Snippet({ hit, highlightedTagName: 'mark', attribute: 'text' })}</p>
          </a>
      `,
    },
  }),
  configure({
    hitsPerPage: 5,
    attributesToSnippet: ['text:25'],
  }),
  pagination({
    container: '#pagination',
  }),
]);

search.start();

Autocomplete

autocomplete({
  container: '#search',
  placeholder: '请输入关键字',
  insights: true,
  getSources({ query }) {
    return [
      {
        sourceId: 'post',
        getItems() {
          return getAlgoliaResults({
            searchClient,
            queries: [
              {
                indexName: 'typecho_posts',
                query,
                params: {
                  hitsPerPage: 5,
                  attributesToSnippet: ['title:10', 'text:35'],
                  snippetEllipsisText: '…',
                },
              },
            ],
          });
        },
        templates: {
          item({ item, components, html }) {
            return html`
                <a style="text-decoration: none" title="${item.title}" href="/${item.slug}.html">
                    <div class="aa-ItemWrapper">
                        <div class="aa-ItemContent">
                            <div class="aa-ItemContentBody">
                                <div class="aa-ItemContentTitle">
                                    ${components.Highlight({
                                        hit: item,
                                        attribute: 'title',
                                    })}
                                </div>
                                <div class="aa-ItemContentDescription">
                                    ${components.Snippet({
                                        hit: item,
                                        attribute: 'text',
                                    })}
                                </div>
                            </div>
                        </div>
                    </div>
                </a>
            `;
          },
        },
      },
    ];
  },
});

效果

404 页面

404-search.png

头部弹窗搜索

header-search-modal.png

一些探索

获取所有分类

$this->category$this->categories 获取的分类数据跟当前页面是强关联的,要想获取数据库中的所有分类,可以通过以下方式。

<?php $db = Typecho_Db::get(); ?>
<?php $categories = $db->fetchAll($db->select()->from('table.metas')->where('type = ?', 'category')) ?>

未完待续~

RustPHPTypechoAlgoliaCloudflare Turnstile

作者: Cheng

2025 © typecho & elise & Cheng