@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 { getHighlighter } from 'shiki/bundle/full';
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
- * Theme registation
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
- * Language registation
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: any;
144
- Marks: any;
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: any;
167
- Marks: any;
165
+ Nodes: never;
166
+ Marks: "bold";
168
167
  Commands: {
169
- [x: string]: any;
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: any;
196
- Marks: any;
194
+ Nodes: never;
195
+ Marks: "code";
197
196
  Commands: {
198
- [x: string]: any;
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: any;
215
- Marks: any;
213
+ Nodes: "codeBlock";
214
+ Marks: never;
216
215
  Commands: {
217
- [x: string]: any;
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: any;
344
- Marks: any;
345
+ Nodes: "heading";
346
+ Marks: never;
345
347
  Commands: {
346
- [x: string]: any;
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: any;
413
- Marks: any;
416
+ Nodes: never;
417
+ Marks: "italic";
414
418
  Commands: {
415
- [x: string]: any;
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: any;
442
- Marks: any;
445
+ Nodes: never;
446
+ Marks: "link";
443
447
  Commands: {
444
- [x: string]: any;
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: any;
485
- Marks: any;
491
+ Nodes: "list";
492
+ Marks: never;
486
493
  Commands: {
487
- [x: string]: any;
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: any;
619
- Marks: any;
633
+ Nodes: never;
634
+ Marks: "strike";
620
635
  Commands: {
621
- [x: string]: any;
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: any;
648
- Marks: any;
662
+ Nodes: "table" | "tableRow" | "tableCell" | "tableHeaderCell";
663
+ Marks: never;
649
664
  Commands: {
650
- [x: string]: any;
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: any;
721
- Marks: any;
740
+ Nodes: never;
741
+ Marks: never;
722
742
  Commands: {
723
- [x: string]: any;
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: any;
782
- Marks: any;
801
+ Nodes: never;
802
+ Marks: "underline";
783
803
  Commands: {
784
- [x: string]: any;
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
- declare function getSearchState(state: EditorState): {
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 interface QueryImpl {
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
- function createHighlighterLoader() {
127
- let highlighterPromise, highlighter, loadLangs = /* @__PURE__ */ new Set();
128
- return function(lang, options) {
129
- return highlighterPromise ? highlighter ? loadLangs.has(lang) ? { highlighter } : { promise: highlighter.loadLanguage(lang).then(() => {
130
- loadLangs.add(lang);
131
- }).catch((error) => {
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, highlighterLoader = createHighlighterLoader();
140
- return function(options) {
141
- let language = options.language || "", { highlighter, promise } = highlighterLoader(
142
- language,
143
- highlighterOptions
144
- );
145
- return highlighter ? (parser || (parser = createParser(highlighter)), parser(options)) : promise || [];
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
- Plugin,
7
- PluginKey,
8
- TextSelection
9
- } from "@prosekit/pm/state";
10
- import { DecorationSet, Decoration } from "@prosekit/pm/view";
11
-
12
- // src/search/prosemirror-search/query.ts
13
- import { Slice, Fragment } from "@prosekit/pm/model";
14
- import "@prosekit/pm/state";
15
- var SearchQuery = class {
16
- /// Create a query object.
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 }));
@@ -0,0 +1,5 @@
1
+ // src/code-block/shiki-import.ts
2
+ import { getSingletonHighlighter } from "shiki/bundle/full";
3
+ export {
4
+ getSingletonHighlighter
5
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@prosekit/extensions",
3
3
  "type": "module",
4
- "version": "0.5.3",
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.6.0",
175
+ "prosemirror-highlight": "^0.8.0",
176
+ "prosemirror-search": "^0.1.0",
176
177
  "prosemirror-tables": "^1.3.7",
177
- "shiki": "^1.6.2",
178
- "@prosekit/core": "^0.5.5",
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.4.5",
184
+ "typescript": "^5.5.2",
184
185
  "vitest": "^1.6.0",
185
186
  "@prosekit/dev": "0.0.0"
186
187
  },
@@ -1,5 +0,0 @@
1
- // src/code-block/shiki-import.ts
2
- import { getHighlighter } from "shiki/bundle/full";
3
- export {
4
- getHighlighter
5
- };