snapshot of https://github.com/ueberdosis/tiptap.git (main, 2026-09-15; blobs > 131072B omitted)
Some checks failed
Verify / Install node dependencies (push) Failing after 2s
Verify / Build packages (push) Has been skipped
Verify / Check linting & formatting (push) Has been skipped
Verify / Run unit tests (push) Has been skipped
Verify / Run e2e tests (shard 1/4) (push) Has been skipped
Verify / Run e2e tests (shard 2/4) (push) Has been skipped
Verify / Run e2e tests (shard 3/4) (push) Has been skipped
Verify / Run e2e tests (shard 4/4) (push) Has been skipped
Publish / Resolve publish config (push) Failing after 2s
Publish / Send notification to Slack (push) Has been skipped
Publish / Send failure notification to Slack (push) Failing after 8s
Verify / Merge e2e reports (push) Has been skipped
Publish / Build (push) Has been skipped
Publish / Bump Versions OR Release to Registry (push) Has been skipped
Some checks failed
Verify / Install node dependencies (push) Failing after 2s
Verify / Build packages (push) Has been skipped
Verify / Check linting & formatting (push) Has been skipped
Verify / Run unit tests (push) Has been skipped
Verify / Run e2e tests (shard 1/4) (push) Has been skipped
Verify / Run e2e tests (shard 2/4) (push) Has been skipped
Verify / Run e2e tests (shard 3/4) (push) Has been skipped
Verify / Run e2e tests (shard 4/4) (push) Has been skipped
Publish / Resolve publish config (push) Failing after 2s
Publish / Send notification to Slack (push) Has been skipped
Publish / Send failure notification to Slack (push) Failing after 8s
Verify / Merge e2e reports (push) Has been skipped
Publish / Build (push) Has been skipped
Publish / Bump Versions OR Release to Registry (push) Has been skipped
This commit is contained in:
70
packages/extension-find-and-replace/src/search/search.ts
Normal file
70
packages/extension-find-and-replace/src/search/search.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import type { Node as PMNode } from '@tiptap/pm/model'
|
||||
|
||||
import { createSearchRegex } from './regex.js'
|
||||
import { searchTextblock } from './textblock-search.js'
|
||||
import type { SearchOptions, SearchResult, TextblockSearchTarget } from './types.js'
|
||||
|
||||
export type { SearchOptions, SearchResult, TextblockSearchTarget } from './types.js'
|
||||
export { createSearchRegex } from './regex.js'
|
||||
|
||||
/**
|
||||
* Searches textblocks for a term and returns their matched ranges.
|
||||
* @param textblocks The textblocks and their document positions.
|
||||
* @param term The search term, treated as regex source when `useRegex` is enabled.
|
||||
* @param options Case sensitivity, regex mode, and whole word matching.
|
||||
* @returns The list of matched ranges in textblock order.
|
||||
*/
|
||||
export function searchTextblocks(
|
||||
textblocks: readonly TextblockSearchTarget[],
|
||||
term: string,
|
||||
options: SearchOptions,
|
||||
): SearchResult[] {
|
||||
const regex = createSearchRegex(term, options)
|
||||
|
||||
if (!regex) {
|
||||
return []
|
||||
}
|
||||
|
||||
return textblocks.flatMap(({ node, pos }) => searchTextblock(regex, node, pos))
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches all textblocks of a document for a term and returns the matched ranges.
|
||||
* Matches may span multiple text nodes (e.g. across marks), but never leave a textblock.
|
||||
* @param doc The document to search in.
|
||||
* @param term The search term, treated as regex source when `useRegex` is enabled.
|
||||
* @param options Case sensitivity, regex mode, and whole word matching.
|
||||
* @returns The list of matched ranges in document order.
|
||||
*/
|
||||
export function searchDocument(doc: PMNode, term: string, options: SearchOptions): SearchResult[] {
|
||||
const textblocks: TextblockSearchTarget[] = []
|
||||
|
||||
doc.descendants((node, pos) => {
|
||||
if (!node.isTextblock) {
|
||||
return true
|
||||
}
|
||||
|
||||
textblocks.push({ node, pos })
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
return searchTextblocks(textblocks, term, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the index of the first result at or after a position, wrapping around
|
||||
* to the first result when the position is behind the last result.
|
||||
* @param results The current search results.
|
||||
* @param from The position to search from.
|
||||
* @returns The result index, or `null` when there are no results.
|
||||
*/
|
||||
export function findNextIndex(results: SearchResult[], from: number): number | null {
|
||||
if (results.length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
const index = results.findIndex(result => result.from >= from)
|
||||
|
||||
return index === -1 ? 0 : index
|
||||
}
|
||||
Reference in New Issue
Block a user