文件
mynode/packages/editor/ProseMirror/plugins/searchPlugin.ts
chen 301194963b
一些检查失败了
automerge / automerge (push) Has been cancelled
react-native-android-build-apk / AssembleRelease (push) Has been cancelled
Build macOS M1 / Main (push) Has been cancelled
Joplin Continuous Integration / Main (macos-15-intel) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-11-vs2026-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-2025) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04-arm) (push) Has been cancelled
Joplin UI tests / Main (ubuntu-22.04) (push) Has been cancelled
Joplin UI tests / Main (windows-2025) (push) Has been cancelled
Joplin UI tests / Mobile (push) Has been cancelled
Close stale issues / ProcessStaleIssues (push) Has been cancelled
feat: Initial clean release of CHM
2026-11-04 11:29:39 +08:00

110 行
3.0 KiB
TypeScript

import { getSearchState, search, SearchQuery, setSearchState } from 'prosemirror-search';
import { SearchState } from '../../types';
import { Plugin, EditorState, Command, Transaction } from 'prosemirror-state';
import { EditorEvent, EditorEventType } from '../../events';
type VisibleMetaState = {
visible: boolean;
changeSource: string;
};
const getVisibleMeta = (tr: Transaction): VisibleMetaState|undefined => (
tr.getMeta(visiblePlugin)
);
const setVisibleMeta = (tr: Transaction, metaState: VisibleMetaState): Transaction => (
tr.setMeta(visiblePlugin, metaState)
);
const visiblePlugin = new Plugin({
state: {
init: () => false,
apply: (tr, value) => {
const visibleMeta = getVisibleMeta(tr);
if (visibleMeta) {
return visibleMeta.visible;
}
return value;
},
},
});
export const getSearchVisible = (state: EditorState) => {
return visiblePlugin.getState(state);
};
export const setSearchVisible = (visible: boolean): Command => (state, dispatch) => {
if (getSearchVisible(state) === visible) {
return false;
}
if (dispatch) {
dispatch(setVisibleMeta(state.tr, { visible, changeSource: 'setSearchVisible' }));
}
return true;
};
const searchExtension = (onEditorEvent: (event: EditorEvent)=> void) => {
let lastState: SearchState|null = null;
const checkSearchStateChange = (state: EditorState, transaction: Transaction) => {
const currentQuery = getSearchState(state).query;
const currentVisible = getSearchVisible(state);
const currentState: SearchState = {
useRegex: currentQuery.regexp,
caseSensitive: currentQuery.caseSensitive,
searchText: currentQuery.search,
replaceText: currentQuery.replace,
dialogVisible: currentVisible,
};
let changed = false;
for (const entryName of Object.keys(currentState)) {
const entryKey = entryName as keyof SearchState;
if (!lastState || currentState[entryKey] !== lastState[entryKey]) {
changed = true;
break;
}
}
if (changed) {
lastState = currentState;
onEditorEvent({
kind: EditorEventType.UpdateSearchDialog,
searchState: currentState,
changeSources: [getVisibleMeta(transaction)?.changeSource ?? 'unknown'],
});
}
};
const checkStateChangePlugin = new Plugin<null>({
state: {
init: ()=>null,
apply: (transaction, oldValue, _oldState, state) => {
checkSearchStateChange(state, transaction);
return oldValue;
},
},
});
return {
plugin: [
search({}),
visiblePlugin,
checkStateChangePlugin,
],
updateState: (editorState: EditorState, searchState: SearchState, changeSource: string) => {
let transaction = editorState.tr;
transaction = setSearchState(transaction, new SearchQuery({
search: searchState.searchText,
caseSensitive: searchState.caseSensitive,
regexp: searchState.useRegex,
replace: searchState.replaceText,
}));
setVisibleMeta(transaction, { changeSource, visible: searchState.dialogVisible });
lastState = { ...searchState };
return transaction;
},
};
};
export default searchExtension;