npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@type-editor/search

v0.0.3

Published

This is a refactored version of the ProseMirror's 'search' module. Original: https://github.com/ProseMirror/prosemirror-search

Downloads

179

Readme

@type-editor/search

A refactored version of ProseMirror's prosemirror-search module, providing search and replace functionality for rich text editors.

Installation

npm install @type-editor/search

Overview

This module provides a comprehensive search and replace API for ProseMirror-based editors. It includes:

  • A search plugin that manages search state and highlights matches
  • A SearchQuery class for defining search parameters (literal, regex, case-sensitive, whole-word)
  • Commands for navigating between matches and performing replacements

Styling

When using this module, you should either load the provided CSS file or define your own styles:

/* Import the provided styles */
@import '@type-editor/search/style/search.css';

/* Or define your own */
.ProseMirror-search-match {
  background-color: #ffff0054;
}
.ProseMirror-active-search-match {
  background-color: #ff6a0054;
}

Usage

Basic Setup

import { searchPlugin, SearchQuery, findNext, findPrev, replaceNext, replaceAll } from '@type-editor/search';
import { keymap } from '@type-editor/keymap';
import { EditorState } from '@type-editor/state';

const state = EditorState.create({
  schema,
  plugins: [
    searchPlugin(),
    keymap({
      'Mod-f': openSearchDialog, // Your custom handler
      'F3': findNext,
      'Shift-F3': findPrev
    })
  ]
});

Configuration Options

The searchPlugin() function accepts an optional configuration object:

searchPlugin({
  initialQuery: new SearchQuery({ search: 'hello' }),
  initialRange: { from: 0, to: 100 }
});

| Option | Type | Description | |----------------|--------------------------------|------------------------------------------------------------| | initialQuery | SearchQuery | The initial search query to use when the plugin is created | | initialRange | { from: number, to: number } | Optional range to limit the initial search scope |

Creating a Search Query

import { SearchQuery } from '@type-editor/search';

// Simple text search
const simpleQuery = new SearchQuery({ search: 'hello' });

// Case-sensitive search
const caseSensitiveQuery = new SearchQuery({
  search: 'Hello',
  caseSensitive: true
});

// Regular expression search
const regexQuery = new SearchQuery({
  search: '\\bword\\b',
  regexp: true
});

// Search and replace
const replaceQuery = new SearchQuery({
  search: 'old',
  replace: 'new'
});

// Whole word matching
const wholeWordQuery = new SearchQuery({
  search: 'the',
  wholeWord: true
});

// Regex search with capture groups
const captureQuery = new SearchQuery({
  search: '(\\w+)@(\\w+)',
  regexp: true,
  replace: '$2:$1'  // Swap the groups
});

SearchQuery Configuration

| Option | Type | Default | Description | |-----------------|------------|------------|--------------------------------------------------------------------------------| | search | string | (required) | The search string or regular expression pattern | | caseSensitive | boolean | false | Whether the search should be case-sensitive | | literal | boolean | false | When false, \n, \r, and \t are replaced with their character equivalents | | regexp | boolean | false | When true, interpret the search string as a regular expression | | replace | string | '' | The replacement text (supports $1, $& etc. for regex) | | wholeWord | boolean | false | When true, only match whole words | | filter | function | null | Optional filter to exclude certain results |

Updating the Search State

To update the search state after the plugin is initialized, you can dispatch a transaction with metadata:

import { searchPlugin, SearchQuery } from '@type-editor/search';

// Create a new query and update via plugin key
const newQuery = new SearchQuery({ search: 'new search term' });

// The plugin listens for metadata updates on the search plugin key
// See the search-plugin-key module for advanced usage

Commands

Find Commands

| Command | Description | |------------------|-------------------------------------------------------------------------------------------------| | findNext | Find the next match after the current selection and move to it. Wraps around at the end. | | findPrev | Find the previous match before the current selection and move to it. Wraps around at the start. | | findNextNoWrap | Find the next match without wrapping at document/range end. | | findPrevNoWrap | Find the previous match without wrapping at document/range start. |

Replace Commands

| Command | Description | |---------------------|---------------------------------------------------------------------------------------------------| | replaceNext | Replace the current match and move to the next one, or select the next match if none is selected. | | replaceNextNoWrap | Replace the next match without wrapping at document end. | | replaceCurrent | Replace the currently selected match and keep it selected. | | replaceAll | Replace all matches in the document or search range. |

Example: Search Dialog Integration

import {
  searchPlugin,
  SearchQuery,
  findNext,
  findPrev,
  replaceNext,
  replaceAll
} from '@type-editor/search';

// The search plugin manages state internally
// Use the provided commands to navigate and replace

function handleFindNext(view) {
  findNext(view.state, view.dispatch);
}

function handleFindPrev(view) {
  findPrev(view.state, view.dispatch);
}

function handleReplaceAll(view) {
  replaceAll(view.state, view.dispatch);
}

SearchQuery API

Properties

| Property | Type | Description | |-----------------|-----------|--------------------------------------------------------| | search | string | The search string or pattern | | caseSensitive | boolean | Whether the search is case-sensitive | | valid | boolean | Whether the query is non-empty and syntactically valid |

Methods

| Method | Returns | Description | |----------------------------------|----------------|-------------------------------------------------| | eq(other) | boolean | Compare this query to another query | | findNext(state, from?, to?) | SearchResult | Find the next occurrence in the given range | | findPrev(state, from?, to?) | SearchResult | Find the previous occurrence in the given range | | getReplacements(state, result) | Array | Get the replacement ranges for a search result |

SearchResult Interface

When a match is found, it returns a SearchResult object:

interface SearchResult {
  from: number;    // Start position of the match
  to: number;      // End position of the match
  match: RegExpMatchArray | null;  // The regex match array (only for regex queries)
}

API Reference

Exports

| Export | Type | Description | |---------------------|------------|---------------------------------------------------| | searchPlugin | function | Creates the search plugin | | search | function | Alias for searchPlugin (backward compatibility) | | SearchQuery | class | Class for defining search parameters | | findNext | Command | Find next match with wrap | | findPrev | Command | Find previous match with wrap | | findNextNoWrap | Command | Find next match without wrap | | findPrevNoWrap | Command | Find previous match without wrap | | replaceNext | Command | Replace current and find next | | replaceNextNoWrap | Command | Replace next without wrap | | replaceCurrent | Command | Replace current match | | replaceAll | Command | Replace all matches | | SearchResult | type | Interface for search match results |

License

MIT