Docs/Search Matching API
Universal Developer

Search Matching API

API documentation for the CoreBox search matching system, including pinyin matching, fuzzy search, and highlighting

Search Matching API

Overview

The CoreBox search system provides powerful matching capabilities:

  • Pinyin Matching: Search fanyi to match translate
  • Initial Abbreviations: Search fy to match translate
  • Fuzzy Matching: Typo-tolerant search, e.g., helol matches hello
  • Highlighting: Highlight matched portions in search results

Introduction

Search matching combines Feature metadata, keywords, and clipboard inputs to drive ranking and highlights in CoreBox.

Search Tokens

Plugin Features automatically generate search tokens upon registration, including:

  • Original name (lowercase)
  • Full pinyin
  • Pinyin initials
  • Keywords
  • Command values

Custom Keywords

Add keywords to Features in manifest.json to enhance search matching:

EXAMPLE.JSON
{
  "features": [
    {
      "id": "translate",
      "name": "translate",
      "desc": "Translate selected text",
      "keywords": ["translate", "translation", "fanyi", "fy"]
    }
  ]
}

Match Types & Priority

The search engine matches in the following priority order:

PriorityMatch TypeScore RangeDescription
1Exact1000Title exactly matches query
2Prefix800-900Title starts with query
3Token600-950Pinyin/initials/keyword match
4Contains600-700Title contains query
5Description400Query found in description
6Fuzzy0-500Typo-tolerant match

Highlighting

Search results include a matchResult field for UI highlighting:

EXAMPLE.TYPESCRIPT
interface MatchRange {
  start: number  // Start position
  end: number    // End position (exclusive)
}

// In TuffItem.meta.extension
interface FeatureExtension {
  matchResult?: MatchRange[]
  searchTokens?: string[]
}

Using Highlighting in Renderer

The BoxItem component automatically handles matchResult highlighting:

EXAMPLE.VUE
<h5
  class="text-sm font-semibold truncate"
  v-html="getHighlightedHTML(
    render.basic?.title || '',
    props.item.meta?.extension?.matchResult
  )"
/>

The getHighlightedHTML function wraps matched regions in <span> tags:

EXAMPLE.TYPESCRIPT
function getHighlightedHTML(
  text: string,
  matchedIndices?: MatchRange[],
  opts?: {
    className?: string   // Highlight CSS class
    base?: 0 | 1        // Index base
    inclusiveEnd?: boolean
  }
): string

Using Search Matching in Plugins

Using matchFeature Function

The matchFeature function from @talex-touch/utils/search enables custom search:

EXAMPLE.TYPESCRIPT
import { matchFeature } from '@talex-touch/utils/search'

const result = matchFeature({
  title: 'translate',
  desc: 'Translate selected text',
  searchTokens: ['translate', 'fanyi', 'fy', 'translate'],
  query: 'fanyi',
  enableFuzzy: true
})

if (result.matched) {
  console.log('Match type:', result.matchType)
  console.log('Match score:', result.score)
  console.log('Highlight ranges:', result.matchRanges)
}

FeatureMatchResult Interface

EXAMPLE.TYPESCRIPT
interface FeatureMatchResult {
  /** Whether matched */
  matched: boolean
  /** Match score (0-1000) */
  score: number
  /** Match type */
  matchType: 'exact' | 'token' | 'prefix' | 'contains' | 'fuzzy' | 'none'
  /** Highlight ranges */
  matchRanges: MatchRange[]
  /** Matched token (for debugging) */
  matchedToken?: string
}

Fuzzy Matching API

fuzzyMatch Function

For typo-tolerant search:

EXAMPLE.TYPESCRIPT
import { fuzzyMatch, indicesToRanges } from '@talex-touch/utils/search'

const result = fuzzyMatch('hello', 'helol', 2)

if (result.matched) {
  console.log('Score:', result.score)
  console.log('Matched indices:', result.matchedIndices)
  
  // Convert to highlight ranges
  const ranges = indicesToRanges(result.matchedIndices)
}

FuzzyMatchResult Interface

EXAMPLE.TYPESCRIPT
interface FuzzyMatchResult {
  /** Whether matched */
  matched: boolean
  /** Match score (0-1) */
  score: number
  /** Array of matched character indices */
  matchedIndices: number[]
}

Command Matching

The Feature commands field is used for precise trigger matching:

EXAMPLE.JSON
{
  "features": [
    {
      "id": "search-web",
      "name": "Search Web",
      "commands": [
        { "type": "over" },
        { "type": "match", "value": ["g ", "google "] },
        { "type": "contain", "value": "search" },
        { "type": "regex", "value": "^s\\s+" }
      ]
    }
  ]
}

Command types:

TypeDescriptionExample
overAlways matchShows in empty search results
matchPrefix matchg hello matches g
containContains matchI want to search matches search
regexRegex matchs hello matches ^s\\s+

Clipboard State Sync

Search queries include current clipboard state:

EXAMPLE.TYPESCRIPT
interface TuffQuery {
  text: string
  inputs?: TuffQueryInput[]
}

interface TuffQueryInput {
  type: TuffInputType  // 'text' | 'image' | 'files' | 'html'
  content: string
  thumbnail?: string
  rawContent?: string
  metadata?: Record<string, unknown>
}

Declaring Accepted Input Types

Declare acceptedInputTypes in Features to receive clipboard content:

EXAMPLE.JSON
{
  "features": [
    {
      "id": "image-ocr",
      "name": "Image OCR",
      "acceptedInputTypes": ["image"]
    }
  ]
}

Supported input types:

  • text - Plain text
  • image - Image (Base64)
  • files - File path list
  • html - HTML rich text

Best Practices

  1. Provide multilingual keywords: Include both English and Chinese in keywords
  2. Use meaningful Feature names: Names automatically generate pinyin tokens
  3. Declare acceptedInputTypes: Explicitly state what input types your Feature can handle
  4. Use appropriate command types: over for general features, match for specific prefix triggers

Technical Notes

  • Search tokens are generated at Feature registration and feed the scoring pipeline.
  • matchFeature and fuzzyMatch return match types, scores, and highlight ranges for rendering.
Was this helpful?