Skip to content

lorb-studio/ghost-highlight

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Lorb.studio

@lorb/ghost-highlight

Highlight text without touching the DOM.

Zero DOM mutation. Uses the Custom Highlight API — highlights are a rendering layer, not DOM nodes. No wrappers, no broken selectors, no killed event handlers.

Full CSS control. Background color, text color, underlines, text shadows, custom animations — anything CSS ::highlight() supports.

Live. Highlights follow DOM changes automatically. Content updates? Highlights re-apply on their own.

import { search } from '@lorb/ghost-highlight';

search('keyword');
// Every instance of "keyword" on the page is now highlighted.
// The DOM is untouched.

Install

npm install @lorb/ghost-highlight

What you can do

Search and highlight text

import { search, clear } from '@lorb/ghost-highlight';

search('error');              // highlight all matches
search('warning', {           // with custom color
  style: { backgroundColor: 'rgba(255, 200, 0, 0.3)' },
});
clear();                      // remove all highlights

Style highlights with full CSS

Beyond background color — use text color, underlines, text shadows, and decorations.

search('deprecated', {
  style: {
    backgroundColor: 'rgba(255, 0, 0, 0.1)',
    color: '#ff4444',
    textDecoration: 'line-through red',
  },
});

search('important', {
  style: {
    textShadow: '0 0 8px gold',
    backgroundColor: 'rgba(255, 215, 0, 0.2)',
  },
});

Animate highlights

Three built-in animation presets, or define your own keyframes.

// Built-in presets: fade-in, pulse, sweep
search('new', {
  style: {
    backgroundColor: 'gold',
    animation: { preset: 'pulse', iterations: 3 },
  },
});

// Custom keyframes — anything CSS animation supports
search('alert', {
  style: {
    animation: {
      keyframes: '@keyframes glow { 0% { background-color: transparent } 50% { background-color: red } 100% { background-color: transparent } }',
      duration: '1s',
      easing: 'ease-in-out',
      iterations: 'infinite',
    },
  },
});

Multiple highlight groups that overlap

Different groups stack visually. Priority controls which renders on top.

import { search, createGroup, clear } from '@lorb/ghost-highlight';

// Built-in presets with priority levels
search('error message', { preset: 'error' });    // priority 2 (top)
search('network', { preset: 'warning' });          // priority 1
search('response', { preset: 'info' });            // priority 0 (bottom)

clear('error');   // clear one group
clear();          // clear all

Highlight specific ranges

For precise control — highlight exact positions, not just text matches.

import { highlight } from '@lorb/ghost-highlight';

const range = new Range();
range.setStart(textNode, 10);
range.setEnd(textNode, 25);

highlight(range, 'selection', {
  backgroundColor: 'rgba(0, 120, 255, 0.3)',
});

Live-update when content changes

Highlights automatically re-apply when the DOM mutates.

import { search, observe } from '@lorb/ghost-highlight';

observe();          // start watching
search('keyword');  // highlights persist through content updates

// Dynamic content? SPA navigation? Editor changes?
// Highlights follow automatically.

Check what's highlighted at a position

import { getGroupsAt } from '@lorb/ghost-highlight';

const groups = getGroupsAt(textNode, 5);
// Returns array of group names at that cursor position
// Useful for context menus, inspectors, or tooltips

Browser support

Uses the Custom Highlight API — zero DOM mutation. Supported in Chrome 105+, Edge 105+, Safari 17.2+, Firefox 132+.

In older browsers, falls back to <span> wrapping (DOM mutation, with a console warning). Use isSupported() to check which mode is active.

API

Export Description
search(query, options?) Highlight all text matches. Returns match count
highlight(range, group?, style?) Highlight a specific Range
clear(group?) Clear one or all groups
createGroup(name, options?) Pre-configure a highlight group with styles and priority
observe(root?, debounceMs?) Auto-update highlights on DOM changes
getGroupsAt(node, offset) Query which groups exist at a position
isSupported() Check for Custom Highlight API support

Built-in presets: search, error, warning, info, selection Animation presets: fade-in, pulse, sweep

License

𖦹 MIT — Lorb.studio

Releases

No releases published

Packages

 
 
 

Contributors