Giter Club home page Giter Club logo

psyche's Introduction

๐Ÿง  psyche

psyche is a drop-in solution for searching documentation, inspired by Algolia's DocSearch.

  • It looks and feels awesome to use.
  • Searching is fast, accurate and typo-tolerate.
  • It can be included in any static or server-generated documentation website.
  • It doubles as a keyboard-navigable sitemap.
  • It makes registering site-wide, platform-dependent hotkeys simple.
  • It's mobile-friendly.
  • It supports both light and dark modes.

Check out the notion-enhancer documentation for a live demo.

Warning: psyche is built specifically for searching documentation. It is not built for implementation into other interfaces (e.g. eCommerce) or use with custom data schemes.

Getting started

Generating an index

The psyche client requires a pre-generated index of results to search. This should be an array of Result records (see types.d.ts). Indexes are provided to the client programmatically, but should take the form of an unformatted/minified .json file.

Indexers are plugins/middleware that crawl a site and generate an index, either during a build process or on-the-fly if the site is dynamically served.

Indexers for some documentation generators are provided below. If your generator of choice is not yet supported, either open a feature request or write your own and open a pull request.

Add the following to your _config.ts file:

import psyche from 'https://deno.land/x/psyche/indexers/lume.ts';

site.use(psyche());

The indexer can be configured by providing a LumeConfig object as the first argument of the psyche() call (see types.d.ts).

By default:

  • The index will be output to /search.json.
  • Pages without data.section or where data.draft = true will be ignored.
  • Pages will be grouped by data.section_order & sorted by data.order.
  • Page titles are accessed from data.title.
  • Page sections are accessed from data.section.
  • Headings, code blocks, paragraphs and lists within an <article></article> element in a page are indexed according to semantic HTML. Other elements (e.g. <blockquote></blockquote>) are treated as paragraphs. This works best with markdown output.

Read the page data and/or shared data pages of Lume's documentation to see how to set these properties.

Including the client

The psyche client is written in TypeScript. You can either directly import it if your site's assets will be bundled by e.g. ESBuild, or import the pre-transpiled and minified JavaScript build.

import psyche from 'https://deno.land/x/psyche/client/mod.ts';
// or
import psyche from 'https://deno.land/x/psyche/client/psyche.min.mjs';

The psyche default export is a function that when provided with a ClientConfig object (see types.d.ts) will return a ClientInstance (see types.d.ts).

Calling .register() on a client instance will insert the component into the document and listen for hotkey presses. The component can then be opened either by calling .open() or by pressing CTRL/โŒ˜ + K.

E.g.

const searchInstance = psyche({
  theme: { scrollbarStyle: 'square' },
  index: await fetch('/search.json').then((res) => res.json()),
});
searchInstance.register();
searchInstance.open();

Registering hotkeys

To add a hotkey to the list in the search modal, add it to the hotkeys array of psyche's ClientConfig object (see types.d.ts).

For platform-dependent hotkeys, the named export platformModifier will be equivalent to the โŒ˜ key on MacOS or the CTRL key on other platforms.

To handle hotkeys, provide a ClientHotkey object (see types.d.ts) to the named export registerHotkey. This is a KeyboardEvent partial with a few additional properties:

  • the platformModifier property is equivalent to metaKey on MacOS or ctrlKey on other platforms.
  • the onkeydown property will be called when the key combination is pressed down, passed the triggered KeyboardEvent as its first argument.
  • the onkeyup property will be called when the key combination is released, passed the triggered KeyboardEvent as its first argument.

E.g.

import psyche, {
  registerHotkey,
  platformModifier,
} from 'https://deno.land/x/psyche/client/psyche.min.mjs';

registerHotkey({
  key: 'l',
  platformModifier: true,
  shiftKey: true,
  onkeydown: (event) => {
    event.preventDefault();
    toggleTheme();
  },
});

const searchInstance = psyche({
  hotkeys: [{ kbd: `${platformModifier} + SHIFT + L`, label: 'to toggle theme' }],
});
searchInstance.register();

Changes to this project are recorded in the CHANGELOG.

This project is licensed under the MIT License.

To support future development of this project, please consider sponsoring the author.

psyche's People

Contributors

dragonwocky avatar imgbotapp avatar oscarotero avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

psyche's Issues

Url value from Lume

Hi, see that you use this code to get the urls of the pages:

psyche/indexers/lume.ts

Lines 65 to 67 in 53f44fd

const url = page.dest.path.endsWith("/index")
? page.dest.path.slice(0, -"index".length)
: page.dest.path;

In Lume, all pages have a url value with the public url, so you could do simply:

const url = page.data.url;

But it could happen that the site is published in a subdirectory (like https://example.com/blog/) so all urls should prepend the /blog subdirectory. A more strong way to get the url is:

const url = site.url(page.data.url);

site.url() returns the final url of any path, prepending subdirectories if needed.

It doesn't work on Safari

Hi.
I just realized that the widget doesn't work on Safari. On open it I see this:

imaxe

This is the error I got:

imaxe

Order results by relevance

Hi.
Is it possible to order the results by relevance? For instance, right now when I search markdown I have the following result:
image

The first results are pages from "Getting started" or other pages with the word "markdown" in the content. And the page of the markdown plugin is way down in the results list. I think a page having this word in the title should be more relevant than a page with this word in the content. So I'd like to propose a way rank the results by relevance. For example:

  • If the term is in the title, it has 1.
  • If the term in in the main description, it has 0.5.
  • If the term is in a paragraph, it has 0.2.

This allows to order the page by rank and opens the door to implement in the future more advanced ranking features, like define different weights for different properties, or if the word is repeat, or is at the begining of the content, etc.

Custom styling

Hi.
As I can see, this component use a style tag in the shadow root to apply styles and use themes to apply colors and fonts.
I recommend to use CSS ::part() pseudo selector for more flexibility and maintainability.

You can see an example of this in the oom-components/searcher web component:

This would make more easy to apply styles on different media queries, light/dark themes, etc. For example:

psyche-search::part(input) {
    border-color: var(--primary-color);
}

And it allows to combine a base theme in the shadow DOM that can be overrided by outside css.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.