惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

大猫的无限游戏
大猫的无限游戏
Security Archives - TechRepublic
Security Archives - TechRepublic
T
Threat Research - Cisco Blogs
A
Arctic Wolf
S
Securelist
O
OpenAI News
T
Threatpost
Forbes - Security
Forbes - Security
N
News and Events Feed by Topic
S
Secure Thoughts
H
Heimdal Security Blog
S
Security Affairs
P
Privacy International News Feed
C
Cisco Blogs
C
CERT Recently Published Vulnerability Notes
Cyberwarzone
Cyberwarzone
N
News and Events Feed by Topic
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Palo Alto Networks Blog
S
Security @ Cisco Blogs
Hacker News - Newest:
Hacker News - Newest: "LLM"
博客园 - 三生石上(FineUI控件)
月光博客
月光博客
T
Tailwind CSS Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Hacker News: Ask HN
Hacker News: Ask HN
T
Troy Hunt's Blog
S
SegmentFault 最新的问题
腾讯CDC
V
Visual Studio Blog
Last Week in AI
Last Week in AI
H
Hacker News: Front Page
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Project Zero
Project Zero
WordPress大学
WordPress大学
NISL@THU
NISL@THU
博客园 - 【当耐特】
博客园 - Franky
Webroot Blog
Webroot Blog
博客园_首页
T
Tenable Blog
雷峰网
雷峰网
Google Online Security Blog
Google Online Security Blog
阮一峰的网络日志
阮一峰的网络日志
V2EX - 技术
V2EX - 技术
Recent Commits to openclaw:main
Recent Commits to openclaw:main
L
Lohrmann on Cybersecurity
The Hacker News
The Hacker News

Example blog

Ghost routing explained with routes.yaml examples — routes, collections & taxonomies Ghost redirects explained with practical redirects.yaml examples How to Serve JSON or XML Data in Ghost How to Change Your Default Post Template in Ghost Ghost Custom Theme Settings How to add Google Fonts to Ghost Themes How to Configure Ghost with Mailgun Ghost Theme Structure & Organization How to Make Custom Templates in Ghost Themes How to Install Ghost CMS via Ghost-CLI How to Add Syntax Highlighting to Ghost The best Ghost CMS hosting platforms Ghost 6.0 — Social Web and Native Ghost Analytics Ghost CMS Social web beta, email 2FA and more author social links How to keep custom design settings when updating your Ghost theme How to use the public preview card in Ghost How to add members-specific sections in Ghost How to customize the default content CTA in Ghost How to build a custom homepage in Ghost An overview of Ghost editor cards and and how they work Ghost CMS News: One-time payments & collecting sales tax How to customize the private site access template in Ghost How to add custom fonts in Ghost themes Ghost CMS News: Additional payment methods & internal linking How to use Code Injection in Ghost How to set meta data of your custom routes & collections in Ghost Ghost CMS News: TK reminders, ActivityPub and improvements How to format dates and use the date helper in Ghost Ghost CMS internationalization, custom fonts & spam protection Understanding and optimizing post and page settings in Ghost CMS Trigger the Ghost Portal popup based on page scroll progress How to Deploy Your Ghost Theme with GitHub Actions How to create a custom recommendations page for your Ghost CMS theme Ghost CMS News: New editor, refreshed settings & recommendations Ghost CMS News: Source - the new default theme and native image editing How to Add Different Logos for Dark & Light Themes in Ghost Upgrade to Node v18 for Ghost CMS & common errors Ghost Snippets: Adding Schema markup in Ghost How to add a scroll-based progress bar to your Ghost CMS site How to Create a Custom Navigation Template in Ghost How to Segment Subscribers with Member Labels in Ghost The best way to create a contact page in Ghost How to Use the Ghost Subscription Forms in Your Theme & Posts How to update your Ghost site URL when self-hosting Ghost CMS News: Signup cards and better landing pages How to Add Breadcrumbs to Your Ghost Theme How to integrate the Applause Button into your Ghost theme How to Hide a Post From the Home Page in Ghost CMS Ghost CMS block and contentFor helper overview & tips How to add Image Lightbox to Ghost Themes Ghost CMS News: Signup form embed, new editor and bulk actions. Biron Themes becomes Bright Themes 🎉 How to Audit & Test a Ghost Theme How to Create Related Posts Section in Ghost How to Use Ghost Filter Expressions Ghost CMS newsletter settings and post analytics How to Update Your Ghost Theme When We Release New Versions Ghost CMS News: Automatic list cleaning & email troubleshooting How to Create a Featured Post Slider in Ghost How to Add Reading Time to Ghost Blog Posts How to Create a Post Archive for Your Ghost Theme Ghost CMS Price Helper Overview & Tips Self-Hosted Ghost CMS with DigitalOcean Ghost CMS News: Member Growth Sources & Audience Feedback How to Open External Links in a New Tab in Ghost How to Integrate Google Analytics with Ghost Ghost CMS News: History Log & Newsletter Analytics How to Automatically Add Member Labels From Referral Traffic in Ghost? Ghost CMS News: Free trials & email notifications Ghost CMS Match Helper Usage & Tips Ghost CMS News: Native Comments Ghost CMS News: Ghost Explore & Premium Newsletter Previews Ghost Snippets: Custom Progress Cards & Steps Ghost CMS News: Native Search The Best Ghost CMS Search Plugins & Libraries Ghost Snippets: Custom Stylish Tables How to Add a Scroll Top & Progress Indicator Button in Ghost Ghost Snippets: Accordions How to Add Tag Dropdown to Your Ghost Theme Ghost 5.0 released 🎉 Ghost Snippets: Custom Subscribe Forms Ghost Snippets: Custom Alert Boxes How to Show Post or Newsletter Issue Number in Ghost How to Self-Host Google Fonts in Ghost CMS Ghost CMS News: Membership, Tiers & Activity Feed Custom Pages in Ghost CMS Themes Ghost CMS News: Offers and Discounts & New Cards Ghost CMS News: Membership tiers, email CTA & filters Ghost CMS News: Grammarly Support & Feature Image Captions. Ghost CMS News: Improved Member Accounts & Personalized Newsletter. Ghost 4.0 Launched With Native Newsletters & Membership Ghost CMS News: Cancellation Feedback & Newsletter Stats. Ghost CMS News: Improved Member Dashboard & Sidebar Views. Ghost CMS News: Google Pay support, email newsletters & secondary navigation Ghost CMS News: Member Support, Portal & Content Snippets. Ghost CMS News: Referral Programs & Responsive Images. Ghost Themes as Progressive Web Apps Ghost 3.0 is here with brand new features Ghost 2.0 is here with new features How to Add Search to Ghost Using ghostHunter
Ghost CMS Search Using Fuse.js
Bright Themes · 2022-01-28 · via Example blog

Search is becoming more popular than ever, consumers have become so accustomed to searching for information that providing a search function is really important.

Ghost doesn't come with a search function by default, so adding a search box to your Ghost site can offer the following benefits:

  • Boost Conversions: By making it easier for visitors to find what they’re looking for, thus creating a positive user experience.
  • Improve SEO: A positive user experience will lead to more time spent on your website, which can help search engines like Google to consider your website to be relevant and high-quality.
  • Build Loyalty: By providing an easy way to find relevant information faster, users are more likely to return again.

A good search function is therefore just as important for a professional website as the underlying CMS or design.

We have previously talked about different search options for Ghost, and now we are going into specifics about the Fuse.js library.

Fuse.js library

Fuse.js is a powerful, lightweight fuzzy-search library, with zero dependencies.

The advantage of Fuse.js is that you don’t need to set up a dedicated backend just for the search function. Another advantage is its simplicity and performance.

It's ideal for client-side fuzzy searching of small to moderately large data sets without a dedicated backend, which is the case for most Ghost CMS websites.

Basic Options

Fuse comes with some basic options:

  • isCaseSensitive - indicates whether comparisons should be case sensitive.
  • includeScore - whether the score should be included in the result set.
  • includeMatches - whether the matches should be included in the result set
  • minMatchCharLength - only the matches whose length exceeds this value will be returned.
  • shouldSort - whether to sort the result list, by score.
  • findAllMatches - when true, the matching function will continue to the end of a search pattern even if a perfect match has already been located in the string.
  • keys - list of keys that will be searched.

Fuzzy matching options

You can also adjust the fuzzy matching options which will change how the search behaves and how the search score is built:

  • location - determines approximately wherein the text is the pattern expected to be found.
  • threshold - at what point does the matching algorithm give up.
  • distance - determines how close the match must be to the fuzzy location
  • ignoreLocation - when true, the search will ignore location and distance, so it won't matter where in the string the pattern appears.

For more details and a complete overview of options check out the official documentation.

Fuse.js in Ghost Themes

If you want to integrate Fuse in your Ghost Theme you can either integrate the script into the theme workflow or simply add the <script> tag using a CDN, for example:

<script src="https://cdn.jsdelivr.net/npm/fuse.js/dist/fuse.js"></script>

After this, we should have Fuse.js available globally. For more information check out the official installation guide. Next, we need to feed Fuse with data, meaning we have to fetch all posts that will be the base for the library to perform the search on. For this, you need to create a custom integration, from the integrations screen in Ghost Admin. Copy the API URL and Content API Key as these will be needed to fetch the posts.

Setup Content API

As mentioned before, you need the Ghost Content API to fetch all posts. If your Ghost theme workflow doesn't include the Content API library you can add it with a <script> tag, just like the fuse library.

<script src="https://unpkg.com/@tryghost/content-api@1.5.16/umd/content-api.min.js"></script>

Warning

Important to note that in the above script we are linking to version 1.5.16 of the Content API library (here is the latest version)

Here is the snippet for initializing the Content API (add your actual URL and Key):

const api = new GhostContentAPI({
  url: 'your_api_url',
  key: 'your_content_api_key',
  version: 'v4',
});

Fetch Posts & Setup Fuse.js

Now that we have both the Fuse and the Content API available, we can fetch the posts and set up the search library with the data:

// setup basic options & variable
const fuseOptions = {
  keys: [{ name: 'title' }],
};

let fuseSearch = '';

// fetch posts
api.posts
  .browse({ limit: 'all', include: 'tags,authors' })
  .then((posts) => {
    fuseSearch = new Fuse(posts, fuseOptions);
  })
  .catch((err) => {
    console.error(err);
  });

In the fuseOptions keys in this example we will search the post titles, but you can further extend it to other fields as well.

Fetching the posts, we set the limit to all and also include tags and authors. You can additionally specify the fields to be fetched (if you want to avoid loading all of them).

Finally, the fuseSearch is initialized passing the posts (data) and the fuseOptions.

Markup & Search event

As for any search, you need at least an input field, so now we will create a minimal HTML for this to work, this includes an input field and a container for the results:

<label> Search: <input class="js-fuse-search" /> </label>
<div class="js-fuse-results bg-acc-1 p-lg"></div>

We also have to add the event handling for the input field:

// script for handling the search when the input changes
document.querySelector('.js-fuse-search').onkeyup = (e) => {
  e.preventDefault();
  const results = fuseSearch.search(e.target.value, { limit: 10 });
  document.querySelector('.js-fuse-results').innerHTML = '';
  results.forEach((result) => {
    document.querySelector(
      '.js-fuse-results',
    ).innerHTML += `<h6>${result.item.title}</h6>`;
  });
};

The event handler (when a user releases a key) includes triggering the search fuseSearch.search which returns a list of posts based on the input value (e.target.value). The final step is adding the results to our container.

That's it, the search should be working.

Additional settings & adjustments

Of course, there is much more fine-tuning you could do, here is some to consider:

  • adjust the fuseOptions if necessary, for example, the keys. You could potentially add other fields to search, for example: tags , and custom_excerpt.
  • specify the fields when fetching posts with the Ghost Content API to avoid loading all fields when it's not necessary
  • to include other data besides post title adjust the markup, the result.item should contain all fields of a post, so you can also show the date, tags, author, or anything else. And of course, you can add CSS to change how it looks.

Complete code & Demo

To make everything easier here is the complete code including all scripts and markup, you can simply paste this into an HTML card in a post/page and change the your_api_url and your_content_api_key with your own integration value.

<!-- Fuse & Content API library -->
<script src="https://unpkg.com/@tryghost/content-api@1.5.16/umd/content-api.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/fuse.js/dist/fuse.js"></script>

<!-- Input field & container for result -->
<label> Search: <input class="js-fuse-search" /> </label>
<div class="js-fuse-results bg-acc-1 p-lg"></div>

<!-- Input Event handling & search -->
<script>
  document.querySelector('.js-fuse-search').onkeyup = (e) => {
    e.preventDefault();
    const results = fuseSearch.search(e.target.value, { limit: 10 });
    document.querySelector('.js-fuse-results').innerHTML = '';
    results.forEach((result) => {
      document.querySelector(
        '.js-fuse-results',
      ).innerHTML += `<h6>${result.item.title}</h6>`;
    });
  };
</script>

<!-- Initialize Content API & Fuse -->
<script>
  const fuseOptions = {
    keys: [{ name: 'title' }],
  };

  let fuseSearch = '';

  window.onload = () => {
    // setup Content API
    const api = new GhostContentAPI({
      url: 'your_api_url',
      key: 'your_content_api_key',
      version: 'v4',
    });

    // fetch posts
    api.posts
      .browse({ limit: 'all', include: 'tags,authors' })
      .then((posts) => {
        // Initialize Fuse
        fuseSearch = new Fuse(posts, fuseOptions);
      })
      .catch((err) => {
        console.error(err);
      });
  };
</script>

And here is a working demo of this setup in the Nikko theme, also the Nikko search is implemented with Fuse including some fine-tuning, to test that, go to the Nikko demo and press the search icon in the header.