@ckeditor/ckeditor5-find-and-replace
Version:
Find and replace feature for CKEditor 5.
44 lines (43 loc) • 2.53 kB
JavaScript
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
import { sortSearchResultsByMarkerPositions } from './findandreplacestate.js';
import { ReplaceCommandBase } from './replacecommandbase.js';
/**
* The replace command. It is used by the {@link module:find-and-replace/findandreplace~FindAndReplace find and replace feature}.
*/
export default class ReplaceCommand extends ReplaceCommandBase {
/**
* Replace a given find result by a string or a callback.
*
* @param result A single result from the find command.
*
* @fires execute
*/
execute(replacementText, result) {
// We save highlight offset here, as the information about the highlighted result will be lost after the changes.
//
// It happens because result list is partially regenerated if the result is removed from the paragraph.
// Partially means that all sibling result items that are placed in the same paragraph are removed and added again,
// which causes the highlighted result to be malformed (usually it's set to first but it's not guaranteed).
//
// While this saving can be done in editing state, it's better to keep it here, as it's a part of the command logic
// and might be super tricky to implement in multi-root documents.
//
// Keep in mind that the highlighted offset is indexed from 1, as it's displayed to the user. It's why we subtract 1 here.
//
// More info: https://github.com/ckeditor/ckeditor5/issues/16648
const oldHighlightOffset = Math.max(this._state.highlightedOffset - 1, 0);
this._replace(replacementText, result);
// Let's revert the highlight offset to the previous value.
if (this._state.results.length) {
// Highlight offset operates on sorted array, so we need to sort the results first.
// It's not guaranteed that items in state results are sorted, usually they are, but it's not guaranteed when
// the result is removed from the paragraph with other highlighted results.
const sortedResults = sortSearchResultsByMarkerPositions(this.editor.model, [...this._state.results]);
// Just make sure that we don't overflow the results array, so use modulo.
this._state.highlightedResult = sortedResults[oldHighlightOffset % sortedResults.length];
}
}
}