@prosekit/extensions 0.5.3 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,7 +9,8 @@ import { Command } from '@prosekit/pm/state';
|
|
9
9
|
import { DedentListOptions } from 'prosemirror-flat-list';
|
10
10
|
import { EditorState } from '@prosekit/pm/state';
|
11
11
|
import { Extension } from '@prosekit/core';
|
12
|
-
import {
|
12
|
+
import { getSingletonHighlighter } from 'shiki/bundle/full';
|
13
|
+
import type { Highlighter } from 'shiki';
|
13
14
|
import { IndentListOptions } from 'prosemirror-flat-list';
|
14
15
|
import { InputRule } from '@prosekit/pm/inputrules';
|
15
16
|
import { ListAttributes } from 'prosemirror-flat-list';
|
@@ -22,7 +23,6 @@ import { Parser } from 'prosemirror-highlight';
|
|
22
23
|
import { Plugin as Plugin_2 } from '@prosekit/pm/state';
|
23
24
|
import { PluginKey } from '@prosekit/pm/state';
|
24
25
|
import { ProseMirrorNode } from '@prosekit/pm/model';
|
25
|
-
import { Slice } from '@prosekit/pm/model';
|
26
26
|
import type { SpecialLanguage } from 'shiki';
|
27
27
|
import { ToggleCollapsedOptions } from 'prosemirror-flat-list';
|
28
28
|
import { Transaction } from '@prosekit/pm/state';
|
@@ -89,13 +89,14 @@ export { CodeBlockAttrs as CodeBlockAttrs_alias_1 }
|
|
89
89
|
*/
|
90
90
|
export declare interface CodeBlockShikiOptions {
|
91
91
|
/**
|
92
|
-
*
|
92
|
+
* A list of shiki themes to pre-load. The first theme in the list will be
|
93
|
+
* used to render the code block.
|
93
94
|
*
|
94
95
|
* @default ['one-dark-pro']
|
95
96
|
*/
|
96
97
|
themes?: BundledTheme[];
|
97
98
|
/**
|
98
|
-
*
|
99
|
+
* A list of shiki languages to pre-load.
|
99
100
|
*
|
100
101
|
* @default ['text']
|
101
102
|
*/
|
@@ -140,11 +141,9 @@ export declare function defineAutocomplete(rule: AutocompleteRule): Extension;
|
|
140
141
|
* @public
|
141
142
|
*/
|
142
143
|
export declare function defineBlockquote(): Extension< {
|
143
|
-
Nodes:
|
144
|
-
Marks:
|
145
|
-
Commands:
|
146
|
-
[x: string]: any;
|
147
|
-
};
|
144
|
+
Nodes: "blockquote";
|
145
|
+
Marks: never;
|
146
|
+
Commands: never;
|
148
147
|
}>;
|
149
148
|
|
150
149
|
/**
|
@@ -163,10 +162,10 @@ Commands: never;
|
|
163
162
|
* @public
|
164
163
|
*/
|
165
164
|
export declare function defineBold(): Extension< {
|
166
|
-
Nodes:
|
167
|
-
Marks:
|
165
|
+
Nodes: never;
|
166
|
+
Marks: "bold";
|
168
167
|
Commands: {
|
169
|
-
|
168
|
+
toggleBold: [];
|
170
169
|
};
|
171
170
|
}>;
|
172
171
|
|
@@ -192,10 +191,10 @@ Commands: never;
|
|
192
191
|
* @public
|
193
192
|
*/
|
194
193
|
export declare function defineCode(): Extension< {
|
195
|
-
Nodes:
|
196
|
-
Marks:
|
194
|
+
Nodes: never;
|
195
|
+
Marks: "code";
|
197
196
|
Commands: {
|
198
|
-
|
197
|
+
toggleCode: [];
|
199
198
|
};
|
200
199
|
}>;
|
201
200
|
|
@@ -211,10 +210,13 @@ Commands: {
|
|
211
210
|
* @public
|
212
211
|
*/
|
213
212
|
declare function defineCodeBlock(): Extension< {
|
214
|
-
Nodes:
|
215
|
-
Marks:
|
213
|
+
Nodes: "codeBlock";
|
214
|
+
Marks: never;
|
216
215
|
Commands: {
|
217
|
-
|
216
|
+
setCodeBlock: [attrs?: CodeBlockAttrs | undefined];
|
217
|
+
insertCodeBlock: [attrs?: CodeBlockAttrs | undefined];
|
218
|
+
toggleCodeBlock: [attrs?: CodeBlockAttrs | undefined];
|
219
|
+
setCodeBlockAttrs: [attrs: CodeBlockAttrs];
|
218
220
|
};
|
219
221
|
}>;
|
220
222
|
export { defineCodeBlock }
|
@@ -340,10 +342,12 @@ export declare function defineEnterRule({ regex, handler, stop, }: EnterRuleOpti
|
|
340
342
|
* @public
|
341
343
|
*/
|
342
344
|
export declare function defineHeading(): Extension< {
|
343
|
-
Nodes:
|
344
|
-
Marks:
|
345
|
+
Nodes: "heading";
|
346
|
+
Marks: never;
|
345
347
|
Commands: {
|
346
|
-
|
348
|
+
setHeading: [attrs?: HeadingAttrs | undefined];
|
349
|
+
insertHeading: [attrs?: HeadingAttrs | undefined];
|
350
|
+
toggleHeading: [attrs?: HeadingAttrs | undefined];
|
347
351
|
};
|
348
352
|
}>;
|
349
353
|
|
@@ -409,10 +413,10 @@ export declare function defineInputRule(rule: InputRule): Extension;
|
|
409
413
|
* @public
|
410
414
|
*/
|
411
415
|
export declare function defineItalic(): Extension< {
|
412
|
-
Nodes:
|
413
|
-
Marks:
|
416
|
+
Nodes: never;
|
417
|
+
Marks: "italic";
|
414
418
|
Commands: {
|
415
|
-
|
419
|
+
toggleItalic: [];
|
416
420
|
};
|
417
421
|
}>;
|
418
422
|
|
@@ -438,10 +442,13 @@ Commands: never;
|
|
438
442
|
* @public
|
439
443
|
*/
|
440
444
|
export declare function defineLink(): Extension< {
|
441
|
-
Nodes:
|
442
|
-
Marks:
|
445
|
+
Nodes: never;
|
446
|
+
Marks: "link";
|
443
447
|
Commands: {
|
444
|
-
[
|
448
|
+
addLink: [attrs: LinkAttrs];
|
449
|
+
removeLink: [];
|
450
|
+
toggleLink: [attrs: LinkAttrs];
|
451
|
+
expandLink: [];
|
445
452
|
};
|
446
453
|
}>;
|
447
454
|
|
@@ -481,10 +488,18 @@ Commands: never;
|
|
481
488
|
* @public
|
482
489
|
*/
|
483
490
|
export declare function defineList(): Extension<{
|
484
|
-
Nodes:
|
485
|
-
Marks:
|
491
|
+
Nodes: "list";
|
492
|
+
Marks: never;
|
486
493
|
Commands: {
|
487
|
-
|
494
|
+
dedentList: [options?: DedentListOptions | undefined];
|
495
|
+
indentList: [options?: IndentListOptions | undefined];
|
496
|
+
moveList: [direction: "up" | "down"];
|
497
|
+
splitList: [];
|
498
|
+
toggleCollapsed: [(ToggleCollapsedOptions | undefined)?];
|
499
|
+
toggleList: [attrs: ListAttributes];
|
500
|
+
unwrapList: [options?: UnwrapListOptions | undefined];
|
501
|
+
wrapInList: [getAttrs: ListAttributes | ((range: NodeRange) => ListAttributes | null)];
|
502
|
+
insertList: [attrs?: ListAttributes | undefined];
|
488
503
|
};
|
489
504
|
}>;
|
490
505
|
|
@@ -615,10 +630,10 @@ export declare function defineSearchQuery(options: SearchQueryOptions): Extensio
|
|
615
630
|
* @public
|
616
631
|
*/
|
617
632
|
export declare function defineStrike(): Extension< {
|
618
|
-
Nodes:
|
619
|
-
Marks:
|
633
|
+
Nodes: never;
|
634
|
+
Marks: "strike";
|
620
635
|
Commands: {
|
621
|
-
|
636
|
+
toggleStrike: [];
|
622
637
|
};
|
623
638
|
}>;
|
624
639
|
|
@@ -644,10 +659,15 @@ Commands: never;
|
|
644
659
|
* @public
|
645
660
|
*/
|
646
661
|
export declare function defineTable(): Extension< {
|
647
|
-
Nodes:
|
648
|
-
Marks:
|
662
|
+
Nodes: "table" | "tableRow" | "tableCell" | "tableHeaderCell";
|
663
|
+
Marks: never;
|
649
664
|
Commands: {
|
650
|
-
|
665
|
+
insertTable: [{
|
666
|
+
row: number;
|
667
|
+
col: number;
|
668
|
+
header: boolean;
|
669
|
+
}];
|
670
|
+
exitTable: [];
|
651
671
|
};
|
652
672
|
}>;
|
653
673
|
|
@@ -717,10 +737,10 @@ export { defineTableSpec as defineTableSpec_alias_1 }
|
|
717
737
|
* @public
|
718
738
|
*/
|
719
739
|
export declare function defineTextAlign(options: TextAlignOptions): Extension<{
|
720
|
-
Nodes:
|
721
|
-
Marks:
|
740
|
+
Nodes: never;
|
741
|
+
Marks: never;
|
722
742
|
Commands: {
|
723
|
-
[
|
743
|
+
setTextAlign: [value: string | null];
|
724
744
|
};
|
725
745
|
}>;
|
726
746
|
|
@@ -778,10 +798,10 @@ export declare function defineTextBlockInputRule({ regex, type, attrs, }: {
|
|
778
798
|
* @public
|
779
799
|
*/
|
780
800
|
export declare function defineUnderline(): Extension< {
|
781
|
-
Nodes:
|
782
|
-
Marks:
|
801
|
+
Nodes: never;
|
802
|
+
Marks: "underline";
|
783
803
|
Commands: {
|
784
|
-
|
804
|
+
toggleUnderline: [];
|
785
805
|
};
|
786
806
|
}>;
|
787
807
|
|
@@ -918,37 +938,11 @@ export declare type EnterRuleOptions = {
|
|
918
938
|
*/
|
919
939
|
export declare const exitTable: Command;
|
920
940
|
|
921
|
-
declare const findNext: Command;
|
922
|
-
export { findNext }
|
923
|
-
export { findNext as findNext_alias_1 }
|
924
|
-
|
925
|
-
declare const findNextNoWrap: Command;
|
926
|
-
export { findNextNoWrap }
|
927
|
-
export { findNextNoWrap as findNextNoWrap_alias_1 }
|
928
|
-
|
929
|
-
declare const findPrev: Command;
|
930
|
-
export { findPrev }
|
931
|
-
export { findPrev as findPrev_alias_1 }
|
932
|
-
|
933
|
-
declare const findPrevNoWrap: Command;
|
934
|
-
export { findPrevNoWrap }
|
935
|
-
export { findPrevNoWrap as findPrevNoWrap_alias_1 }
|
936
|
-
|
937
941
|
export declare function getCheckRanges(transactions: readonly Transaction[], oldState: EditorState, newState: EditorState): Array<[number, number]>;
|
938
942
|
|
939
|
-
export { getHighlighter }
|
940
|
-
|
941
943
|
export declare function getPluginState(state: EditorState): PredictionPluginState | undefined;
|
942
944
|
|
943
|
-
|
944
|
-
query: SearchQuery;
|
945
|
-
range: {
|
946
|
-
from: number;
|
947
|
-
to: number;
|
948
|
-
} | null;
|
949
|
-
} | undefined;
|
950
|
-
export { getSearchState }
|
951
|
-
export { getSearchState as getSearchState_alias_1 }
|
945
|
+
export { getSingletonHighlighter }
|
952
946
|
|
953
947
|
export declare function getTrMeta(tr: Transaction): PredictionPluginState;
|
954
948
|
|
@@ -956,12 +950,20 @@ export declare interface HeadingAttrs {
|
|
956
950
|
level: number;
|
957
951
|
}
|
958
952
|
|
959
|
-
declare type HighlighterOptions = {
|
953
|
+
export declare type HighlighterOptions = {
|
960
954
|
themes: BundledTheme[];
|
961
955
|
langs: (BundledLanguage | SpecialLanguage)[];
|
962
956
|
langAlias?: Record<string, BundledLanguage>;
|
963
957
|
};
|
964
958
|
|
959
|
+
declare type HighlighterResult = {
|
960
|
+
highlighter: Highlighter;
|
961
|
+
promise?: undefined;
|
962
|
+
} | {
|
963
|
+
highlighter?: undefined;
|
964
|
+
promise: Promise<void>;
|
965
|
+
};
|
966
|
+
|
965
967
|
/**
|
966
968
|
* @public
|
967
969
|
*
|
@@ -1095,64 +1097,7 @@ export declare interface PredictionPluginState {
|
|
1095
1097
|
} | null;
|
1096
1098
|
}
|
1097
1099
|
|
1098
|
-
declare
|
1099
|
-
findNext(state: EditorState, from: number, to: number): SearchResult | null;
|
1100
|
-
findPrev(state: EditorState, from: number, to: number): SearchResult | null;
|
1101
|
-
}
|
1102
|
-
|
1103
|
-
declare const replaceAll: Command;
|
1104
|
-
export { replaceAll }
|
1105
|
-
export { replaceAll as replaceAll_alias_1 }
|
1106
|
-
|
1107
|
-
declare const replaceCurrent: Command;
|
1108
|
-
export { replaceCurrent }
|
1109
|
-
export { replaceCurrent as replaceCurrent_alias_1 }
|
1110
|
-
|
1111
|
-
declare const replaceNext: Command;
|
1112
|
-
export { replaceNext }
|
1113
|
-
export { replaceNext as replaceNext_alias_1 }
|
1114
|
-
|
1115
|
-
declare const replaceNextNoWrap: Command;
|
1116
|
-
export { replaceNextNoWrap }
|
1117
|
-
export { replaceNextNoWrap as replaceNextNoWrap_alias_1 }
|
1118
|
-
|
1119
|
-
declare function search(options?: {
|
1120
|
-
initialQuery?: SearchQuery;
|
1121
|
-
initialRange?: {
|
1122
|
-
from: number;
|
1123
|
-
to: number;
|
1124
|
-
};
|
1125
|
-
}): Plugin_2;
|
1126
|
-
export { search }
|
1127
|
-
export { search as search_alias_1 }
|
1128
|
-
|
1129
|
-
declare class SearchQuery {
|
1130
|
-
readonly search: string;
|
1131
|
-
readonly caseSensitive: boolean;
|
1132
|
-
readonly literal: boolean;
|
1133
|
-
readonly regexp: boolean;
|
1134
|
-
readonly replace: string;
|
1135
|
-
readonly valid: boolean;
|
1136
|
-
readonly wholeWord: boolean;
|
1137
|
-
impl: QueryImpl;
|
1138
|
-
constructor(config: {
|
1139
|
-
search: string;
|
1140
|
-
caseSensitive?: boolean;
|
1141
|
-
literal?: boolean;
|
1142
|
-
regexp?: boolean;
|
1143
|
-
replace?: string;
|
1144
|
-
wholeWord?: boolean;
|
1145
|
-
});
|
1146
|
-
eq(other: SearchQuery): boolean;
|
1147
|
-
findNext(state: EditorState, from?: number, to?: number): SearchResult | null;
|
1148
|
-
findPrev(state: EditorState, from?: number, to?: number): SearchResult | null;
|
1149
|
-
checkResult(state: EditorState, result: SearchResult): boolean;
|
1150
|
-
unquote(string: string): string;
|
1151
|
-
getReplacement(state: EditorState, result: SearchResult): Slice;
|
1152
|
-
}
|
1153
|
-
export { SearchQuery }
|
1154
|
-
export { SearchQuery as SearchQuery_alias_1 }
|
1155
|
-
export { SearchQuery as SearchQuery_alias_2 }
|
1100
|
+
export declare function prepareHighlighter(options: HighlighterOptions): HighlighterResult;
|
1156
1101
|
|
1157
1102
|
/**
|
1158
1103
|
* Options for {@link defineSearchQuery}
|
@@ -1196,22 +1141,6 @@ export declare interface SearchQueryOptions {
|
|
1196
1141
|
wholeWord?: boolean;
|
1197
1142
|
}
|
1198
1143
|
|
1199
|
-
declare interface SearchResult {
|
1200
|
-
from: number;
|
1201
|
-
to: number;
|
1202
|
-
match: RegExpMatchArray | null;
|
1203
|
-
}
|
1204
|
-
export { SearchResult }
|
1205
|
-
export { SearchResult as SearchResult_alias_1 }
|
1206
|
-
export { SearchResult as SearchResult_alias_2 }
|
1207
|
-
|
1208
|
-
declare function setSearchState(tr: Transaction, query: SearchQuery, range?: {
|
1209
|
-
from: number;
|
1210
|
-
to: number;
|
1211
|
-
} | null): Transaction;
|
1212
|
-
export { setSearchState }
|
1213
|
-
export { setSearchState as setSearchState_alias_1 }
|
1214
|
-
|
1215
1144
|
/**
|
1216
1145
|
* @internal
|
1217
1146
|
*/
|
@@ -1266,6 +1195,4 @@ export declare type TextBlockEnterRuleOptions = {
|
|
1266
1195
|
stop?: boolean;
|
1267
1196
|
};
|
1268
1197
|
|
1269
|
-
export declare function validRegExp(source: string): boolean;
|
1270
|
-
|
1271
1198
|
export { }
|
@@ -123,26 +123,46 @@ function defineCodeBlockHighlight({
|
|
123
123
|
|
124
124
|
// src/code-block/shiki-parser.ts
|
125
125
|
import { createParser } from "prosemirror-highlight/shiki";
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
console.warn(`Failed to load language '${lang}'`, error);
|
133
|
-
}) } : { promise: highlighterPromise } : (highlighterPromise = import("./shiki-import-25BJYIO2.js").then(({ getHighlighter }) => getHighlighter(options)).then((h) => {
|
134
|
-
highlighter = h;
|
135
|
-
}), { promise: highlighterPromise });
|
136
|
-
};
|
126
|
+
|
127
|
+
// src/code-block/shiki-highlighter.ts
|
128
|
+
var highlighter, loadedLangs = /* @__PURE__ */ new Set(), loadedThemes = /* @__PURE__ */ new Set();
|
129
|
+
async function createHighlighter(options) {
|
130
|
+
let { getSingletonHighlighter } = await import("./shiki-import-UFUFVKJ2.js");
|
131
|
+
highlighter || (highlighter = await getSingletonHighlighter(options));
|
137
132
|
}
|
133
|
+
async function loadLanguages(langs) {
|
134
|
+
for (let lang of langs) {
|
135
|
+
if (!highlighter) break;
|
136
|
+
await highlighter.loadLanguage(lang), loadedLangs.add(lang);
|
137
|
+
}
|
138
|
+
}
|
139
|
+
async function loadThemes(themes) {
|
140
|
+
for (let theme of themes) {
|
141
|
+
if (!highlighter) break;
|
142
|
+
await highlighter.loadTheme(theme), loadedThemes.add(theme);
|
143
|
+
}
|
144
|
+
}
|
145
|
+
function prepareHighlighter(options) {
|
146
|
+
if (!highlighter)
|
147
|
+
return { promise: createHighlighter(options) };
|
148
|
+
let langs = options.langs.filter((lang) => !loadedLangs.has(lang));
|
149
|
+
if (langs.length > 0)
|
150
|
+
return { promise: loadLanguages(langs) };
|
151
|
+
let themes = options.themes.filter((theme) => !loadedThemes.has(theme));
|
152
|
+
return themes.length > 0 ? { promise: loadThemes(themes) } : { highlighter };
|
153
|
+
}
|
154
|
+
|
155
|
+
// src/code-block/shiki-parser.ts
|
138
156
|
function createLazyParser(highlighterOptions) {
|
139
|
-
let parser
|
140
|
-
return function(options) {
|
141
|
-
let language = options.language || "", { highlighter, promise } =
|
142
|
-
language,
|
143
|
-
highlighterOptions
|
144
|
-
);
|
145
|
-
return
|
157
|
+
let parser;
|
158
|
+
return prepareHighlighter(highlighterOptions), function(options) {
|
159
|
+
let language = options.language || "", { highlighter: highlighter2, promise } = prepareHighlighter({
|
160
|
+
langs: [language],
|
161
|
+
themes: highlighterOptions.themes
|
162
|
+
});
|
163
|
+
return highlighter2 ? (parser || (parser = createParser(highlighter2, {
|
164
|
+
theme: highlighterOptions.themes[0]
|
165
|
+
})), parser(options)) : promise;
|
146
166
|
};
|
147
167
|
}
|
148
168
|
|
@@ -1,350 +1,17 @@
|
|
1
1
|
// src/search/index.ts
|
2
2
|
import { defineCommands, definePlugin } from "@prosekit/core";
|
3
|
-
|
4
|
-
// src/search/prosemirror-search/search.ts
|
5
3
|
import {
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
constructor(config) {
|
18
|
-
this.search = config.search, this.caseSensitive = !!config.caseSensitive, this.literal = !!config.literal, this.regexp = !!config.regexp, this.replace = config.replace || "", this.valid = !!this.search && !(this.regexp && !validRegExp(this.search)), this.wholeWord = !!config.wholeWord, this.impl = this.valid ? this.regexp ? new RegExpQuery(this) : new StringQuery(this) : nullQuery;
|
19
|
-
}
|
20
|
-
/// Compare this query to another query.
|
21
|
-
eq(other) {
|
22
|
-
return this.search == other.search && this.replace == other.replace && this.caseSensitive == other.caseSensitive && this.regexp == other.regexp && this.wholeWord == other.wholeWord;
|
23
|
-
}
|
24
|
-
/// Find the next occurrence of this query in the given range.
|
25
|
-
findNext(state, from = 0, to = state.doc.content.size) {
|
26
|
-
for (; ; ) {
|
27
|
-
if (from >= to) return null;
|
28
|
-
let result = this.impl.findNext(state, from, to);
|
29
|
-
if (!result || this.checkResult(state, result)) return result;
|
30
|
-
from = result.from + 1;
|
31
|
-
}
|
32
|
-
}
|
33
|
-
/// Find the previous occurrence of this query in the given range.
|
34
|
-
/// Note that, if `to` is given, it should be _less_ than `from`.
|
35
|
-
findPrev(state, from = state.doc.content.size, to = 0) {
|
36
|
-
for (; ; ) {
|
37
|
-
if (from <= to) return null;
|
38
|
-
let result = this.impl.findPrev(state, from, to);
|
39
|
-
if (!result || this.checkResult(state, result)) return result;
|
40
|
-
from = result.to - 1;
|
41
|
-
}
|
42
|
-
}
|
43
|
-
/// @internal
|
44
|
-
checkResult(state, result) {
|
45
|
-
return this.wholeWord ? checkWordBoundary(state, result.from) && checkWordBoundary(state, result.to) : !0;
|
46
|
-
}
|
47
|
-
/// @internal
|
48
|
-
unquote(string) {
|
49
|
-
return this.literal ? string : string.replace(
|
50
|
-
/\\([\\nrt])/g,
|
51
|
-
(_, ch) => ch == "n" ? `
|
52
|
-
` : ch == "r" ? "\r" : ch == "t" ? " " : "\\"
|
53
|
-
);
|
54
|
-
}
|
55
|
-
/// Get a replacement slice for a given search result.
|
56
|
-
getReplacement(state, result) {
|
57
|
-
let marks = state.doc.resolve(result.from).marksAcross(state.doc.resolve(result.to)), text = this.unquote(this.replace), nodes = [], i = 0, { match } = result;
|
58
|
-
if (match) {
|
59
|
-
text = text.replace(
|
60
|
-
/\$([\d$&+])/g,
|
61
|
-
(m, i2) => i2 == "$" ? "$" : i2 == "&" ? match[0] : i2 != "0" && +i2 < match.length ? match[+i2] : m
|
62
|
-
);
|
63
|
-
for (let pos = result.from; ; ) {
|
64
|
-
let obj = text.indexOf("\uFFFC", i);
|
65
|
-
if (obj < 0) break;
|
66
|
-
let found = findLeafBetween(state, pos, result.to);
|
67
|
-
if (!found) break;
|
68
|
-
obj > i && nodes.push(state.schema.text(text.slice(i, obj), marks)), nodes.push(found.node), i = obj + 1, pos = found.pos + 1;
|
69
|
-
}
|
70
|
-
}
|
71
|
-
return i < text.length && nodes.push(state.schema.text(text.slice(i), marks)), new Slice(Fragment.from(nodes), 0, 0);
|
72
|
-
}
|
73
|
-
}, nullQuery = new class {
|
74
|
-
findNext() {
|
75
|
-
return null;
|
76
|
-
}
|
77
|
-
findPrev() {
|
78
|
-
return null;
|
79
|
-
}
|
80
|
-
}(), StringQuery = class {
|
81
|
-
constructor(query) {
|
82
|
-
this.query = query;
|
83
|
-
let string = query.unquote(query.search);
|
84
|
-
query.caseSensitive || (string = string.toLowerCase()), this.string = string;
|
85
|
-
}
|
86
|
-
findNext(state, from, to) {
|
87
|
-
return scanTextblocks(state.doc, from, to, (node, start) => {
|
88
|
-
let off = Math.max(from, start), content = textContent(node).slice(
|
89
|
-
off - start,
|
90
|
-
Math.min(node.content.size, to - start)
|
91
|
-
), index = (this.query.caseSensitive ? content : content.toLowerCase()).indexOf(this.string);
|
92
|
-
return index < 0 ? null : {
|
93
|
-
from: off + index,
|
94
|
-
to: off + index + this.string.length,
|
95
|
-
match: null
|
96
|
-
};
|
97
|
-
});
|
98
|
-
}
|
99
|
-
findPrev(state, from, to) {
|
100
|
-
return scanTextblocks(state.doc, from, to, (node, start) => {
|
101
|
-
let off = Math.max(start, to), content = textContent(node).slice(
|
102
|
-
off - start,
|
103
|
-
Math.min(node.content.size, from - start)
|
104
|
-
);
|
105
|
-
this.query.caseSensitive || (content = content.toLowerCase());
|
106
|
-
let index = content.lastIndexOf(this.string);
|
107
|
-
return index < 0 ? null : {
|
108
|
-
from: off + index,
|
109
|
-
to: off + index + this.string.length,
|
110
|
-
match: null
|
111
|
-
};
|
112
|
-
});
|
113
|
-
}
|
114
|
-
}, baseFlags = "g" + (/x/.unicode == null ? "" : "u"), RegExpQuery = class {
|
115
|
-
constructor(query) {
|
116
|
-
this.query = query;
|
117
|
-
this.regexp = new RegExp(
|
118
|
-
query.search,
|
119
|
-
baseFlags + (query.caseSensitive ? "" : "i")
|
120
|
-
);
|
121
|
-
}
|
122
|
-
findNext(state, from, to) {
|
123
|
-
return scanTextblocks(state.doc, from, to, (node, start) => {
|
124
|
-
let content = textContent(node).slice(
|
125
|
-
0,
|
126
|
-
Math.min(node.content.size, to - start)
|
127
|
-
);
|
128
|
-
this.regexp.lastIndex = from - start;
|
129
|
-
let match = this.regexp.exec(content);
|
130
|
-
return match ? {
|
131
|
-
from: start + match.index,
|
132
|
-
to: start + match.index + match[0].length,
|
133
|
-
match
|
134
|
-
} : null;
|
135
|
-
});
|
136
|
-
}
|
137
|
-
findPrev(state, from, to) {
|
138
|
-
return scanTextblocks(state.doc, from, to, (node, start) => {
|
139
|
-
let content = textContent(node).slice(
|
140
|
-
0,
|
141
|
-
Math.min(node.content.size, from - start)
|
142
|
-
), match;
|
143
|
-
for (let off = 0; ; ) {
|
144
|
-
this.regexp.lastIndex = off;
|
145
|
-
let next = this.regexp.exec(content);
|
146
|
-
if (!next) break;
|
147
|
-
match = next, off = next.index + 1;
|
148
|
-
}
|
149
|
-
return match ? {
|
150
|
-
from: start + match.index,
|
151
|
-
to: start + match.index + match[0].length,
|
152
|
-
match
|
153
|
-
} : null;
|
154
|
-
});
|
155
|
-
}
|
156
|
-
};
|
157
|
-
function validRegExp(source) {
|
158
|
-
try {
|
159
|
-
return new RegExp(source, baseFlags), !0;
|
160
|
-
} catch (e) {
|
161
|
-
return !1;
|
162
|
-
}
|
163
|
-
}
|
164
|
-
var TextContentCache = /* @__PURE__ */ new WeakMap();
|
165
|
-
function textContent(node) {
|
166
|
-
let cached = TextContentCache.get(node);
|
167
|
-
if (cached) return cached;
|
168
|
-
let content = "";
|
169
|
-
for (let i = 0; i < node.childCount; i++) {
|
170
|
-
let child = node.child(i);
|
171
|
-
child.isText ? content += child.text : child.isLeaf ? content += "\uFFFC" : content += " " + textContent(child) + " ";
|
172
|
-
}
|
173
|
-
return TextContentCache.set(node, content), content;
|
174
|
-
}
|
175
|
-
function scanTextblocks(node, from, to, f, nodeStart = 0) {
|
176
|
-
if (node.inlineContent)
|
177
|
-
return f(node, nodeStart);
|
178
|
-
if (!node.isLeaf)
|
179
|
-
if (from > to)
|
180
|
-
for (let i = node.childCount - 1, pos = nodeStart + node.content.size; i >= 0 && pos > to; i--) {
|
181
|
-
let child = node.child(i);
|
182
|
-
if (pos -= child.nodeSize, pos < from) {
|
183
|
-
let result = scanTextblocks(child, from, to, f, pos + 1);
|
184
|
-
if (result != null) return result;
|
185
|
-
}
|
186
|
-
}
|
187
|
-
else
|
188
|
-
for (let i = 0, pos = nodeStart; i < node.childCount && pos < to; i++) {
|
189
|
-
let child = node.child(i), start = pos;
|
190
|
-
if (pos += child.nodeSize, pos > from) {
|
191
|
-
let result = scanTextblocks(child, from, to, f, start + 1);
|
192
|
-
if (result != null) return result;
|
193
|
-
}
|
194
|
-
}
|
195
|
-
return null;
|
196
|
-
}
|
197
|
-
function checkWordBoundary(state, pos) {
|
198
|
-
let $pos = state.doc.resolve(pos), before = $pos.nodeBefore, after = $pos.nodeAfter;
|
199
|
-
return !before || !after || !before.isText || !after.isText ? !0 : !/\p{L}$/u.test(before.text) || !/^\p{L}/u.test(after.text);
|
200
|
-
}
|
201
|
-
function findLeafBetween(state, from, to) {
|
202
|
-
let found = null;
|
203
|
-
return state.doc.nodesBetween(from, to, (node, pos) => {
|
204
|
-
if (found) return !1;
|
205
|
-
node.isLeaf && node.isInline && !node.isText && (found = { node, pos });
|
206
|
-
}), found;
|
207
|
-
}
|
208
|
-
|
209
|
-
// src/search/prosemirror-search/search.ts
|
210
|
-
var SearchState = class {
|
211
|
-
constructor(query, range, deco) {
|
212
|
-
this.query = query;
|
213
|
-
this.range = range;
|
214
|
-
this.deco = deco;
|
215
|
-
}
|
216
|
-
};
|
217
|
-
function buildMatchDeco(state, query, range) {
|
218
|
-
if (!query.valid) return DecorationSet.empty;
|
219
|
-
let deco = [], sel = state.selection;
|
220
|
-
for (let pos = range ? range.from : 0, end = range ? range.to : state.doc.content.size; ; ) {
|
221
|
-
let next = query.findNext(state, pos, end);
|
222
|
-
if (!next) break;
|
223
|
-
let cls = next.from == sel.from && next.to == sel.to ? "ProseMirror-active-search-match" : "ProseMirror-search-match";
|
224
|
-
deco.push(Decoration.inline(next.from, next.to, { class: cls })), pos = next.to;
|
225
|
-
}
|
226
|
-
return DecorationSet.create(state.doc, deco);
|
227
|
-
}
|
228
|
-
var searchKey = new PluginKey("search");
|
229
|
-
function search(options = {}) {
|
230
|
-
return new Plugin({
|
231
|
-
key: searchKey,
|
232
|
-
state: {
|
233
|
-
init(_config, state) {
|
234
|
-
let query = options.initialQuery || new SearchQuery({ search: "" }), range = options.initialRange || null;
|
235
|
-
return new SearchState(
|
236
|
-
query,
|
237
|
-
range,
|
238
|
-
buildMatchDeco(state, query, range)
|
239
|
-
);
|
240
|
-
},
|
241
|
-
apply(tr, search2, _oldState, state) {
|
242
|
-
let set = tr.getMeta(searchKey);
|
243
|
-
if (set)
|
244
|
-
return new SearchState(
|
245
|
-
set.query,
|
246
|
-
set.range,
|
247
|
-
buildMatchDeco(state, set.query, set.range)
|
248
|
-
);
|
249
|
-
if (tr.docChanged || tr.selectionSet) {
|
250
|
-
let range = search2.range;
|
251
|
-
if (range) {
|
252
|
-
let from = tr.mapping.map(range.from, 1), to = tr.mapping.map(range.to, -1);
|
253
|
-
range = from < to ? { from, to } : null;
|
254
|
-
}
|
255
|
-
search2 = new SearchState(
|
256
|
-
search2.query,
|
257
|
-
range,
|
258
|
-
buildMatchDeco(state, search2.query, range)
|
259
|
-
);
|
260
|
-
}
|
261
|
-
return search2;
|
262
|
-
}
|
263
|
-
},
|
264
|
-
props: {
|
265
|
-
decorations: (state) => searchKey.getState(state).deco
|
266
|
-
}
|
267
|
-
});
|
268
|
-
}
|
269
|
-
function nextMatch(search2, state, wrap, curFrom, curTo) {
|
270
|
-
let range = search2.range || { from: 0, to: state.doc.content.size }, next = search2.query.findNext(state, Math.max(curTo, range.from), range.to);
|
271
|
-
return !next && wrap && (next = search2.query.findNext(state, range.from, Math.min(curFrom, range.to))), next;
|
272
|
-
}
|
273
|
-
function prevMatch(search2, state, wrap, curFrom, curTo) {
|
274
|
-
let range = search2.range || { from: 0, to: state.doc.content.size }, prev = search2.query.findPrev(
|
275
|
-
state,
|
276
|
-
Math.min(curFrom, range.to),
|
277
|
-
range.from
|
278
|
-
);
|
279
|
-
return !prev && wrap && (prev = search2.query.findPrev(state, range.to, Math.max(curTo, range.from))), prev;
|
280
|
-
}
|
281
|
-
function findCommand(wrap, dir) {
|
282
|
-
return (state, dispatch) => {
|
283
|
-
let search2 = searchKey.getState(state);
|
284
|
-
if (!search2 || !search2.query.valid) return !1;
|
285
|
-
let { from, to } = state.selection, next = dir > 0 ? nextMatch(search2, state, wrap, from, to) : prevMatch(search2, state, wrap, from, to);
|
286
|
-
if (!next) return !1;
|
287
|
-
let selection = TextSelection.create(state.doc, next.from, next.to);
|
288
|
-
return dispatch && dispatch(state.tr.setSelection(selection).scrollIntoView()), !0;
|
289
|
-
};
|
290
|
-
}
|
291
|
-
var findNext = findCommand(!0, 1), findNextNoWrap = findCommand(!1, 1), findPrev = findCommand(!0, -1), findPrevNoWrap = findCommand(!1, -1);
|
292
|
-
function replaceCommand(wrap, moveForward) {
|
293
|
-
return (state, dispatch) => {
|
294
|
-
let search2 = searchKey.getState(state);
|
295
|
-
if (!search2 || !search2.query.valid) return !1;
|
296
|
-
let { from } = state.selection, next = nextMatch(search2, state, wrap, from, from);
|
297
|
-
if (!next) return !1;
|
298
|
-
if (!dispatch) return !0;
|
299
|
-
if (state.selection.from == next.from && state.selection.to == next.to) {
|
300
|
-
let tr = state.tr.replace(
|
301
|
-
next.from,
|
302
|
-
next.to,
|
303
|
-
search2.query.getReplacement(state, next)
|
304
|
-
), after = moveForward && nextMatch(search2, state, wrap, next.from, next.to);
|
305
|
-
after ? tr.setSelection(
|
306
|
-
TextSelection.create(
|
307
|
-
tr.doc,
|
308
|
-
tr.mapping.map(after.from, 1),
|
309
|
-
tr.mapping.map(after.to, -1)
|
310
|
-
)
|
311
|
-
) : tr.setSelection(
|
312
|
-
TextSelection.create(tr.doc, next.from, tr.mapping.map(next.to, 1))
|
313
|
-
), dispatch(tr.scrollIntoView());
|
314
|
-
} else if (moveForward)
|
315
|
-
dispatch(
|
316
|
-
state.tr.setSelection(TextSelection.create(state.doc, next.from, next.to)).scrollIntoView()
|
317
|
-
);
|
318
|
-
else
|
319
|
-
return !1;
|
320
|
-
return !0;
|
321
|
-
};
|
322
|
-
}
|
323
|
-
var replaceNext = replaceCommand(!0, !0), replaceNextNoWrap = replaceCommand(!1, !0), replaceCurrent = replaceCommand(!1, !1), replaceAll = (state, dispatch) => {
|
324
|
-
let search2 = searchKey.getState(state);
|
325
|
-
if (!search2) return !1;
|
326
|
-
let matches = [], range = search2.range || { from: 0, to: state.doc.content.size };
|
327
|
-
for (let pos = range.from; ; ) {
|
328
|
-
let next = search2.query.findNext(state, pos, range.to);
|
329
|
-
if (!next) break;
|
330
|
-
matches.push(next), pos = next.to;
|
331
|
-
}
|
332
|
-
if (dispatch) {
|
333
|
-
let tr = state.tr;
|
334
|
-
for (let i = matches.length - 1; i >= 0; i--) {
|
335
|
-
let match = matches[i];
|
336
|
-
tr.replace(
|
337
|
-
match.from,
|
338
|
-
match.to,
|
339
|
-
search2.query.getReplacement(state, match)
|
340
|
-
);
|
341
|
-
}
|
342
|
-
dispatch(tr);
|
343
|
-
}
|
344
|
-
return !0;
|
345
|
-
};
|
346
|
-
|
347
|
-
// src/search/index.ts
|
4
|
+
SearchQuery,
|
5
|
+
findNext,
|
6
|
+
findNextNoWrap,
|
7
|
+
findPrev,
|
8
|
+
findPrevNoWrap,
|
9
|
+
replaceAll,
|
10
|
+
replaceCurrent,
|
11
|
+
replaceNext,
|
12
|
+
replaceNextNoWrap,
|
13
|
+
search
|
14
|
+
} from "prosemirror-search";
|
348
15
|
function defineSearchQuery(options) {
|
349
16
|
let query = new SearchQuery(options);
|
350
17
|
return definePlugin(search({ initialQuery: query }));
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@prosekit/extensions",
|
3
3
|
"type": "module",
|
4
|
-
"version": "0.
|
4
|
+
"version": "0.6.1",
|
5
5
|
"private": false,
|
6
6
|
"author": {
|
7
7
|
"name": "ocavue",
|
@@ -172,15 +172,16 @@
|
|
172
172
|
"dependencies": {
|
173
173
|
"prosemirror-dropcursor": "^1.8.1",
|
174
174
|
"prosemirror-flat-list": "^0.5.0",
|
175
|
-
"prosemirror-highlight": "^0.
|
175
|
+
"prosemirror-highlight": "^0.8.0",
|
176
|
+
"prosemirror-search": "^0.1.0",
|
176
177
|
"prosemirror-tables": "^1.3.7",
|
177
|
-
"shiki": "^1.
|
178
|
-
"@prosekit/core": "^0.
|
178
|
+
"shiki": "^1.9.0",
|
179
|
+
"@prosekit/core": "^0.6.1",
|
179
180
|
"@prosekit/pm": "^0.1.5"
|
180
181
|
},
|
181
182
|
"devDependencies": {
|
182
183
|
"tsup": "^8.1.0",
|
183
|
-
"typescript": "^5.
|
184
|
+
"typescript": "^5.5.2",
|
184
185
|
"vitest": "^1.6.0",
|
185
186
|
"@prosekit/dev": "0.0.0"
|
186
187
|
},
|