@prosekit/extensions 0.3.0 → 0.3.2

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.
@@ -8,6 +8,7 @@ import { ExtensionTyping } from '@prosekit/core';
8
8
  import { IndentListOptions } from 'prosemirror-flat-list';
9
9
  import { InputRule } from '@prosekit/pm/inputrules';
10
10
  import { ListAttributes } from 'prosemirror-flat-list';
11
+ import { ListDOMSerializer } from 'prosemirror-flat-list';
11
12
  import { NodeRange } from 'prosemirror-model';
12
13
  import { NodeType } from '@prosekit/pm/model';
13
14
  import { Options } from 'tsup';
@@ -246,7 +247,7 @@ export declare function defineDropCursor(options?: DropCursorOptions): Extension
246
247
  *
247
248
  * @public
248
249
  */
249
- export declare function defineEnterRule({ regex, handler, }: EnterRuleOptions): Extension;
250
+ export declare function defineEnterRule({ regex, handler, stop, }: EnterRuleOptions): Extension;
250
251
 
251
252
  /**
252
253
  * @public
@@ -355,6 +356,10 @@ expandLink: [];
355
356
  };
356
357
  }>;
357
358
 
359
+ export declare function defineLinkEnterRule(): Extension<ExtensionTyping<string, string, CommandArgs>>;
360
+
361
+ export declare function defineLinkInputRule(): Extension<ExtensionTyping<string, string, CommandArgs>>;
362
+
358
363
  export declare function defineLinkSpec(): Extension< {
359
364
  MARKS: "link";
360
365
  }>;
@@ -469,7 +474,7 @@ MARKS: "strike";
469
474
  *
470
475
  * @public
471
476
  */
472
- export declare function defineTextBlockEnterRule({ regex, type, attrs, }: TextBlockEnterRuleOptions): Extension;
477
+ export declare function defineTextBlockEnterRule({ regex, type, attrs, stop, }: TextBlockEnterRuleOptions): Extension;
473
478
 
474
479
  /**
475
480
  * Defines an input rule that changes the type of a textblock when the matched
@@ -605,6 +610,12 @@ export declare type EnterRuleOptions = {
605
610
  * A handler function to be called when an enter rule is triggered.
606
611
  */
607
612
  handler: EnterRuleHandler;
613
+ /**
614
+ * Whether to stop further handlers from being called if this rule is triggered.
615
+ *
616
+ * @default false
617
+ */
618
+ stop?: boolean;
608
619
  };
609
620
 
610
621
  export declare function getPluginState(state: EditorState): PredictionPluginState | undefined;
@@ -628,6 +639,10 @@ export declare interface ImageAttrs {
628
639
  src?: string | null;
629
640
  }
630
641
 
642
+ export declare const LINK_RE: RegExp;
643
+
644
+ export declare const LINK_SPACE_RE: RegExp;
645
+
631
646
  /**
632
647
  * @public
633
648
  */
@@ -635,6 +650,8 @@ export declare interface LinkAttrs {
635
650
  href: string;
636
651
  }
637
652
 
653
+ export { ListDOMSerializer }
654
+
638
655
  declare type MatchHandler = (options: {
639
656
  state: EditorState;
640
657
  match: RegExpExecArray;
@@ -642,7 +659,7 @@ declare type MatchHandler = (options: {
642
659
  to: number;
643
660
  ignoreMatch: () => void;
644
661
  deleteMatch: () => void;
645
- }) => Transaction | null | void;
662
+ }) => void;
646
663
  export { MatchHandler }
647
664
  export { MatchHandler as MatchHandler_alias_1 }
648
665
 
@@ -700,6 +717,12 @@ export declare type TextBlockEnterRuleOptions = {
700
717
  * Attributes to set on the node.
701
718
  */
702
719
  attrs?: Attrs | null | ((match: RegExpMatchArray) => Attrs | null);
720
+ /**
721
+ * Whether to stop further handlers from being called if this rule is triggered.
722
+ *
723
+ * @default true
724
+ */
725
+ stop?: boolean;
703
726
  };
704
727
 
705
728
  export { }
@@ -0,0 +1,111 @@
1
+ // src/enter-rule/index.ts
2
+ import {
3
+ Facet,
4
+ OBJECT_REPLACEMENT_CHARACTER,
5
+ getNodeType,
6
+ isTextSelection,
7
+ pluginFacet
8
+ } from "@prosekit/core";
9
+ import { keydownHandler } from "@prosekit/pm/keymap";
10
+ import {
11
+ ProseMirrorPlugin
12
+ } from "@prosekit/pm/state";
13
+ function defineEnterRule({
14
+ regex,
15
+ handler,
16
+ stop = false
17
+ }) {
18
+ const rule = new EnterRule(regex, handler, stop);
19
+ return enterRule.extension([rule]);
20
+ }
21
+ function defineTextBlockEnterRule({
22
+ regex,
23
+ type,
24
+ attrs,
25
+ stop = true
26
+ }) {
27
+ return defineEnterRule({
28
+ regex,
29
+ handler: ({ state, from, to, match }) => {
30
+ const nodeType = getNodeType(state.schema, type);
31
+ const $start = state.doc.resolve(from);
32
+ if (!$start.node(-1).canReplaceWith($start.index(-1), $start.indexAfter(-1), nodeType)) {
33
+ return null;
34
+ }
35
+ const nodeAttrs = attrs && typeof attrs === "function" ? attrs(match) : attrs;
36
+ return state.tr.delete(from, to).setBlockType(from, from, nodeType, nodeAttrs);
37
+ },
38
+ stop
39
+ });
40
+ }
41
+ var EnterRule = class {
42
+ constructor(regex, handler, stop) {
43
+ this.regex = regex;
44
+ this.handler = handler;
45
+ this.stop = stop;
46
+ }
47
+ };
48
+ var enterRule = Facet.define({
49
+ converter: () => {
50
+ let rules = [];
51
+ const command = (state, dispatch, view) => {
52
+ if (!view)
53
+ return false;
54
+ return execRules(view, rules, dispatch);
55
+ };
56
+ const handler = keydownHandler({ Enter: command });
57
+ const plugin = new ProseMirrorPlugin({ props: { handleKeyDown: handler } });
58
+ const pluginFunc = () => [plugin];
59
+ return {
60
+ create: (inputs) => {
61
+ rules = inputs;
62
+ return pluginFunc;
63
+ },
64
+ update: (inputs) => {
65
+ rules = inputs;
66
+ return null;
67
+ }
68
+ };
69
+ },
70
+ next: pluginFacet
71
+ });
72
+ function execRules(view, rules, dispatch) {
73
+ if (view.composing)
74
+ return false;
75
+ const state = view.state;
76
+ const selection = state.selection;
77
+ if (!isTextSelection(selection))
78
+ return false;
79
+ const $cursor = selection.$cursor;
80
+ if (!$cursor || $cursor.parent.type.spec.code)
81
+ return false;
82
+ const textBefore = $cursor.parent.textBetween(
83
+ Math.max(0, $cursor.parentOffset - MAX_MATCH),
84
+ $cursor.parentOffset,
85
+ null,
86
+ OBJECT_REPLACEMENT_CHARACTER
87
+ );
88
+ for (const rule of rules) {
89
+ rule.regex.lastIndex = 0;
90
+ const match = rule.regex.exec(textBefore);
91
+ const tr = match && rule.handler({
92
+ state,
93
+ from: $cursor.pos - match[0].length,
94
+ to: $cursor.pos,
95
+ match
96
+ });
97
+ if (!tr)
98
+ continue;
99
+ dispatch == null ? void 0 : dispatch(tr);
100
+ if (rule.stop) {
101
+ return true;
102
+ }
103
+ }
104
+ return false;
105
+ }
106
+ var MAX_MATCH = 200;
107
+
108
+ export {
109
+ defineEnterRule,
110
+ defineTextBlockEnterRule
111
+ };
@@ -1,3 +1,6 @@
1
+ import {
2
+ defineTextBlockEnterRule
3
+ } from "./chunk-6DQPSMHC.js";
1
4
  import {
2
5
  defineTextBlockInputRule
3
6
  } from "./chunk-DYFRBXUX.js";
@@ -41,91 +44,6 @@ function defineCodeBlockHighlight({
41
44
  );
42
45
  }
43
46
 
44
- // src/enter-rule/index.ts
45
- import {
46
- Facet,
47
- getNodeType,
48
- isTextSelection,
49
- keymapFacet,
50
- OBJECT_REPLACEMENT_CHARACTER
51
- } from "@prosekit/core";
52
- function defineEnterRule({
53
- regex,
54
- handler
55
- }) {
56
- const rule = new EnterRule(regex, handler);
57
- return inputRuleFacet.extension([rule]);
58
- }
59
- function defineTextBlockEnterRule({
60
- regex,
61
- type,
62
- attrs
63
- }) {
64
- return defineEnterRule({
65
- regex,
66
- handler: ({ state, from, to, match }) => {
67
- const nodeType = getNodeType(state.schema, type);
68
- const $start = state.doc.resolve(from);
69
- if (!$start.node(-1).canReplaceWith($start.index(-1), $start.indexAfter(-1), nodeType)) {
70
- return null;
71
- }
72
- const nodeAttrs = attrs && typeof attrs === "function" ? attrs(match) : attrs;
73
- return state.tr.delete(from, to).setBlockType(from, from, nodeType, nodeAttrs);
74
- }
75
- });
76
- }
77
- var EnterRule = class {
78
- constructor(regex, handler) {
79
- this.regex = regex;
80
- this.handler = handler;
81
- }
82
- };
83
- var inputRuleFacet = Facet.define({
84
- convert: (inputs) => {
85
- return {
86
- Enter: (state, dispatch, view) => {
87
- if (!view)
88
- return false;
89
- return execRules(view, inputs, dispatch);
90
- }
91
- };
92
- },
93
- next: keymapFacet
94
- });
95
- function execRules(view, rules, dispatch) {
96
- if (view.composing)
97
- return false;
98
- const state = view.state;
99
- const selection = state.selection;
100
- if (!isTextSelection(selection))
101
- return false;
102
- const $cursor = selection.$cursor;
103
- if (!$cursor || $cursor.parent.type.spec.code)
104
- return false;
105
- const textBefore = $cursor.parent.textBetween(
106
- Math.max(0, $cursor.parentOffset - MAX_MATCH),
107
- $cursor.parentOffset,
108
- null,
109
- OBJECT_REPLACEMENT_CHARACTER
110
- );
111
- for (const rule of rules) {
112
- rule.regex.lastIndex = 0;
113
- const match = rule.regex.exec(textBefore);
114
- const tr = match && rule.handler({
115
- state,
116
- from: $cursor.pos - match[0].length,
117
- to: $cursor.pos,
118
- match
119
- });
120
- if (!tr)
121
- continue;
122
- dispatch == null ? void 0 : dispatch(tr);
123
- return true;
124
- }
125
- return false;
126
- }
127
- var MAX_MATCH = 200;
128
-
129
47
  // src/code-block/code-block-input-rule.ts
130
48
  function defineCodeBlockInputRule() {
131
49
  return defineTextBlockInputRule({
@@ -1,4 +1,6 @@
1
1
  export { defineLinkSpec } from './_tsup-dts-rollup';
2
2
  export { defineLinkCommands } from './_tsup-dts-rollup';
3
+ export { defineLinkInputRule } from './_tsup-dts-rollup';
4
+ export { defineLinkEnterRule } from './_tsup-dts-rollup';
3
5
  export { defineLink } from './_tsup-dts-rollup';
4
6
  export { LinkAttrs } from './_tsup-dts-rollup';
@@ -1,16 +1,39 @@
1
+ import {
2
+ defineEnterRule
3
+ } from "./chunk-6DQPSMHC.js";
4
+ import {
5
+ defineInputRule
6
+ } from "./chunk-DYFRBXUX.js";
7
+
1
8
  // src/link/index.ts
2
9
  import {
3
- defineCommands,
4
10
  addMark,
11
+ defineCommands,
5
12
  defineMarkSpec,
6
- union,
13
+ expandMark,
7
14
  removeMark,
8
15
  toggleMark,
9
- expandMark
16
+ union
10
17
  } from "@prosekit/core";
18
+ import { InputRule } from "@prosekit/pm/inputrules";
19
+
20
+ // src/link/link-regex.ts
21
+ var TLD_RE_PATTERN = "a(?:a(?:a|rp)|b(?:arth|b(?:ott|vie)?|c|le|ogado|udhabi)|c(?:ademy|c(?:enture|ountants?)|o|tor)?|d(?:s|ult)?|e(?:g|ro|tna)?|f(?:l|rica)?|g(?:akhan|ency)?|i(?:g|r(?:bus|force|tel))?|kdn|l(?:faromeo|i(?:baba|pay)|l(?:finanz|state|y)|s(?:ace|tom))?|m(?:azon|e(?:rican(?:express|family)|x)|fam|ica|sterdam)?|n(?:alytics|droid|quan|z)|ol?|p(?:artments|p(?:le)?)|q(?:uarelle)?|r(?:a(?:b|mco)|chi|my|pa|te?)?|s(?:da|ia|sociates)?|t(?:hleta|torney)?|u(?:ction|di(?:ble|o)?|spost|t(?:hor|os?))?|vianca|ws?|xa?|z(?:ure)?)|b(?:a(?:by|idu|n(?:a(?:mex|narepublic)|d|k)|r(?:c(?:elona|lay(?:card|s))|efoot|gains)?|s(?:eball|ketball)|uhaus|yern)?|b(?:c|t|va)?|c[gn]|d|e(?:a(?:ts|uty)|er|ntley|rlin|st(?:buy)?|t)?|f|g|h(?:arti)?|i(?:ble|d|ke|ngo?|o|z)?|j|l(?:ack(?:friday)?|o(?:ckbuster|g|omberg)|ue)|m[sw]?|n(?:pparibas)?|o(?:ats|ehringer|fa|m|nd|o(?:k(?:ing)?)?|s(?:ch|t(?:ik|on))|t|utique|x)?|r(?:adesco|idgestone|o(?:adway|ker|ther)|ussels)?|s|t|u(?:ild(?:ers)?|siness|y|zz)|v|w|y|zh?)|c(?:a(?:b|fe|l(?:l|vinklein)?|m(?:era|p)?|non|p(?:etown|ital(?:one)?)|r(?:avan|ds|e(?:ers?)?|s)?|s(?:a|e|h|ino)|t(?:ering|holic)?)?|b(?:a|n|re|s)|c|d|e(?:nter|o|rn)|f[ad]?|g|h(?:a(?:n(?:el|nel)|rity|se|t)|eap|intai|r(?:istmas|ome)|urch)?|i(?:priani|rcle|sco|t(?:adel|ic?|y(?:eats)?))?|k|l(?:aims|eaning|i(?:ck|ni(?:c|que))|o(?:thing|ud)|ub(?:med)?)?|m|n|o(?:ach|des|ffee|l(?:lege|ogne)|m(?:cast|m(?:bank|unity)|p(?:a(?:ny|re)|uter)|sec)?|n(?:dos|s(?:truction|ulting)|t(?:act|ractors))|o(?:king(?:channel)?|l|p)|rsica|u(?:ntry|pons?|rses))?|pa|r(?:edit(?:card|union)?|icket|own|s|uises?)?|u(?:isinella)?|v|w|x|y(?:mru|ou)?|z)|d(?:a(?:bur|d|nce|t(?:a|e|ing|sun)|y)|clk|ds|e(?:al(?:er|s)?|gree|l(?:ivery|l|oitte|ta)|mocrat|nt(?:al|ist)|si(?:gn)?|v)?|hl|i(?:amonds|et|gital|rect(?:ory)?|s(?:co(?:unt|ver)|h)|y)|j|k|m|np|o(?:c(?:s|tor)|g|mains|t|wnload)?|rive|tv|u(?:bai|nlop|pont|rban)|v(?:ag|r)|z)|e(?:a(?:rth|t)|co?|d(?:eka|u(?:cation)?)|e|g|m(?:ail|erck)|n(?:ergy|gineer(?:ing)?|terprises)|pson|quipment|r(?:icsson|ni)?|s(?:q|tate)?|t(?:isalat)?|u(?:rovision|s)?|vents|x(?:change|p(?:ert|osed|ress)|traspace))|f(?:a(?:ge|i(?:l|rwinds|th)|mily|ns?|rm(?:ers)?|s(?:hion|t))|e(?:dex|edback|rr(?:ari|ero))|i(?:at|d(?:elity|o)|lm|na(?:l|nc(?:e|ial))|r(?:e(?:stone)?|mdale)|sh(?:ing)?|t(?:ness)?)?|j|k|l(?:i(?:ckr|ghts|r)|o(?:rist|wers)|y)|m|o(?:o(?:d(?:network)?|tball)?|r(?:d|ex|sale|um)|undation|x)?|r(?:e(?:e|senius)|l|o(?:gans|nt(?:door|ier)))?|tr|u(?:jitsu|nd?|rniture|tbol)|yi)|g(?:a(?:l(?:l(?:ery|o|up))?|mes?|p|rden|y)?|b(?:iz)?|dn?|e(?:a|nt(?:ing)?|orge)?|f|g(?:ee)?|h|i(?:fts?|v(?:es|ing))?|l(?:ass|e|ob(?:al|o))?|m(?:ail|bh|o|x)?|n|o(?:daddy|l(?:d(?:point)?|f)|o(?:dyear|g(?:le)?)?|p|t|v)|p|q|r(?:a(?:inger|phics|tis)|een|ipe|o(?:cery|up))?|s|t|u(?:ardian|cci|ge|i(?:de|tars)|ru)?|w|y)|h(?:a(?:ir|mburg|ngout|us)|bo|dfc(?:bank)?|e(?:alth(?:care)?|l(?:p|sinki)|r(?:e|mes))|gtv|i(?:phop|samitsu|tachi|v)|kt?|m|n|o(?:ckey|l(?:dings|iday)|me(?:depot|goods|s(?:ense)?)|nda|rse|s(?:pital|t(?:ing)?)|t(?:el(?:es|s)|mail)?|use|w)|r|sbc|t|u(?:ghes)?|y(?:att|undai))|i(?:bm|c(?:bc|e|u)|d|e(?:ee)?|fm|kano|l|m(?:amat|db|mo(?:bilien)?)?|n(?:c|dustries|f(?:initi|o)|g|k|s(?:titute|ur(?:ance|e))|t(?:ernational|uit)?|vestments)?|o|piranga|q|r(?:ish)?|s(?:maili|t(?:anbul)?)?|t(?:au|v)?)|j(?:a(?:guar|va)|cb|e(?:ep|tzt|welry)?|io|ll|mp?|nj|o(?:b(?:s|urg)|t|y)?|p(?:morgan|rs)?|u(?:egos|niper))|k(?:aufen|ddi|e(?:rry(?:hotels|logistics|properties))?|fh|g|h|i(?:a|ds|m|nd(?:er|le)|tchen|wi)?|m|n|o(?:eln|matsu|sher)|p(?:mg|n)?|r(?:d|ed)?|uokgroup|w|y(?:oto)?|z)|l(?:a(?:caixa|m(?:borghini|er)|n(?:c(?:aster|ia)|d(?:rover)?|xess)|salle|t(?:ino|robe)?|w(?:yer)?)?|b|c|ds|e(?:ase|clerc|frak|g(?:al|o)|xus)|gbt|i(?:dl|fe(?:insurance|style)?|ghting|ke|lly|m(?:ited|o)|n(?:coln|de|k)|psy|v(?:e|ing))?|k|l[cp]|o(?:ans?|c(?:ker|us)|l|ndon|tt[eo]|ve)|pl(?:financial)?|r|s|t(?:da?)?|u(?:ndbeck|x(?:e|ury))?|v|y)|m(?:a(?:cys|drid|i(?:f|son)|keup|n(?:agement|go)?|p|r(?:ket(?:ing|s)?|riott|shalls)|serati|ttel)?|ba|c(?:kinsey)?|d|e(?:d(?:ia)?|et|lbourne|m(?:e|orial)|nu?|rckmsd)?|g|h|i(?:ami|crosoft|l|n[it]|t(?:subishi)?)|k|l[bs]?|ma?|n|o(?:bi(?:le)?|da|e|i|m|n(?:ash|ey|ster)|r(?:mon|tgage)|scow|to(?:rcycles)?|v(?:ie)?)?|p|q|r|sd?|t[nr]?|u(?:s(?:eum|ic)|tual)?|v|w|x|y|z)|n(?:a(?:b|goya|me|tura|vy)?|ba|c|e(?:c|t(?:bank|flix|work)?|ustar|ws?|x(?:t(?:direct)?|us))?|fl?|go?|hk|i(?:co|k(?:e|on)|nja|ssa[ny])?|l|o(?:kia|rt(?:hwesternmutual|on)|w(?:ruz|tv)?)?|p|r[aw]?|tt|u|yc|z)|o(?:b(?:i|server)|ffice|kinawa|l(?:ayan(?:group)?|dnavy|lo)|m(?:ega)?|n(?:e|g|l(?:ine)?)|oo|pen|r(?:a(?:cle|nge)|g(?:anic)?|igins)|saka|t(?:suka|t)|vh)|p(?:a(?:ge|nasonic|r(?:is|s|t(?:ners|s|y))|ssagens|y)?|ccw|et?|f(?:izer)?|g|h(?:armacy|d|ilips|o(?:ne|to(?:graphy|s)?)|ysio)?|i(?:c(?:s|t(?:et|ures))|d|n[gk]?|oneer|zza)|k|l(?:a(?:ce|y(?:station)?)|u(?:mbing|s))?|m|nc?|o(?:hl|ker|litie|rn|st)|r(?:a(?:merica|xi)|ess|ime|o(?:d(?:uctions)?|f|gressive|mo|pert(?:ies|y)|tection)?|u(?:dential)?)?|s|t|ub|wc?|y)|q(?:a|pon|ue(?:bec|st))|r(?:a(?:cing|dio)|e(?:a(?:d|l(?:estate|t(?:or|y)))|cipes|d(?:stone|umbrella)?|hab|i(?:sen?|t)|liance|n(?:t(?:als)?)?|p(?:air|ort|ublican)|st(?:aurant)?|views?|xroth)?|i(?:c(?:h(?:ardli)?|oh)|l|o|p)|o(?:c(?:her|ks)|deo|gers|om)?|s(?:vp)?|u(?:gby|hr|n)?|we?|yukyu)|s(?:a(?:arland|fe(?:ty)?|kura|l(?:e|on)|ms(?:club|ung)|n(?:dvik(?:coromant)?|ofi)|p|rl|s|ve|xo)?|b[is]?|c(?:a|b|h(?:aeffler|midt|o(?:larships|ol)|ule|warz)|ience|ot)?|d|e(?:a(?:rch|t)|cur(?:e|ity)|ek|lect|ner|rvices|ven|w|xy?)?|fr|g|h(?:a(?:ngrila|rp|w)|ell|i(?:a|ksha)|o(?:es|p(?:ping)?|uji|w(?:time)?))?|i(?:lk|n(?:a|gles)|te)?|j|k(?:in?|y(?:pe)?)?|l(?:ing)?|m(?:art|ile)?|n(?:cf)?|o(?:c(?:cer|ial)|ft(?:bank|ware)|hu|l(?:ar|utions)|n[gy]|y)?|p(?:a(?:ce)?|o(?:rt|t))|rl?|s|t(?:a(?:da|ples|r|te(?:bank|farm))|c(?:group)?|o(?:ckholm|r(?:age|e))|ream|ud(?:io|y)|yle)?|u(?:cks|pp(?:l(?:ies|y)|ort)|r(?:f|gery)|zuki)?|v|w(?:atch|iss)|x|y(?:dney|stems)?|z)|t(?:a(?:b|ipei|lk|obao|rget|t(?:a(?:motors|r)|too)|xi?)|ci?|dk?|e(?:am|ch(?:nology)?|l|masek|nnis|va)|f|g|h(?:d|eat(?:er|re))?|i(?:aa|ckets|enda|ffany|ps|r(?:es|ol))|j(?:maxx|x)?|k(?:maxx)?|l|m(?:all)?|n|o(?:day|kyo|ols|p|ray|shiba|tal|urs|wn|y(?:ota|s))?|r(?:a(?:d(?:e|ing)|ining|vel(?:channel|ers(?:insurance)?)?)|ust|v)?|t|u(?:be|i|nes|shu)|vs?|w|z)|u(?:a|b(?:ank|s)|g|k|n(?:i(?:com|versity)|o)|ol|ps|s|y|z)|v(?:a(?:cations|n(?:a|guard))?|c|e(?:gas|ntures|r(?:isign|sicherung)|t)?|g|i(?:ajes|deo|g|king|llas|n|p|rgin|s(?:a|ion)|v[ao])?|laanderen|n|o(?:dka|l(?:kswagen|vo)|t(?:e|ing|o)|yage)|u(?:elos)?)|w(?:a(?:l(?:es|mart|ter)|ng(?:gou)?|tch(?:es)?)|e(?:ather(?:channel)?|b(?:cam|er|site)|d(?:ding)?|i(?:bo|r))|f|hoswho|i(?:en|ki|lliamhill|n(?:dows|e|ners)?)|me|o(?:lterskluwer|odside|r(?:ks?|ld)|w)|s|t[cf])|x(?:box|erox|finity|i(?:huan|n)|xx|yz)|y(?:a(?:chts|hoo|maxun|ndex)|e|o(?:dobashi|ga|kohama|u(?:tube)?)|t|un)|z(?:a(?:ppos|ra)?|ero|ip|m|one|uerich|w)";
22
+ var LINK_RE_BASE_PATTERN = (
23
+ // start of the link group
24
+ "((?:(?:(?:https?:)?\\/\\/)?(?:(?:[a-z0-9\\u00a1-\\uffff][a-z0-9\\u00a1-\\uffff_-]{0,62})?[a-z0-9\\u00a1-\\uffff]\\.)+(?:" + TLD_RE_PATTERN + "))(?::\\d{2,5})?(?:[/?#]\\S*)?)"
25
+ );
26
+ var LINK_STOP_PATTERN = "(?:\\.|\\,|\\;\\!)?";
27
+ var LINK_RE_PATTERN = LINK_RE_BASE_PATTERN + LINK_STOP_PATTERN + "$";
28
+ var LINK_SPACE_RE_PATTERN = LINK_RE_BASE_PATTERN + LINK_STOP_PATTERN + "\\s$";
29
+ var LINK_RE = new RegExp(LINK_RE_PATTERN, "gi");
30
+ var LINK_SPACE_RE = new RegExp(LINK_SPACE_RE_PATTERN, "gi");
31
+
32
+ // src/link/index.ts
11
33
  function defineLinkSpec() {
12
34
  return defineMarkSpec({
13
35
  name: "link",
36
+ inclusive: false,
14
37
  parseDOM: [
15
38
  {
16
39
  tag: "a[href]",
@@ -38,11 +61,42 @@ function defineLinkCommands() {
38
61
  expandLink: () => expandMark({ type: "link" })
39
62
  });
40
63
  }
64
+ function defineLinkInputRule() {
65
+ return defineInputRule(
66
+ new InputRule(LINK_SPACE_RE, (state, match, from) => {
67
+ const href = match[1];
68
+ if (!href)
69
+ return null;
70
+ const mark = state.schema.marks.link.create({ href });
71
+ return state.tr.addMark(from, from + href.length, mark).insertText(" ");
72
+ })
73
+ );
74
+ }
75
+ function defineLinkEnterRule() {
76
+ return defineEnterRule({
77
+ regex: LINK_RE,
78
+ handler: ({ state, from, match }) => {
79
+ const href = match[1];
80
+ if (!href)
81
+ return null;
82
+ const mark = state.schema.marks.link.create({ href });
83
+ const tr = state.tr.addMark(from, from + href.length, mark);
84
+ return tr.docChanged ? tr : null;
85
+ }
86
+ });
87
+ }
41
88
  function defineLink() {
42
- return union([defineLinkSpec(), defineLinkCommands()]);
89
+ return union([
90
+ defineLinkSpec(),
91
+ defineLinkCommands(),
92
+ defineLinkInputRule(),
93
+ defineLinkEnterRule()
94
+ ]);
43
95
  }
44
96
  export {
45
97
  defineLink,
46
98
  defineLinkCommands,
99
+ defineLinkEnterRule,
100
+ defineLinkInputRule,
47
101
  defineLinkSpec
48
102
  };
@@ -4,3 +4,4 @@ export { defineListKeymap } from './_tsup-dts-rollup';
4
4
  export { defineListInputRules } from './_tsup-dts-rollup';
5
5
  export { defineListCommands } from './_tsup-dts-rollup';
6
6
  export { defineList } from './_tsup-dts-rollup';
7
+ export { ListDOMSerializer } from './_tsup-dts-rollup';
@@ -27,6 +27,7 @@ import {
27
27
  listInputRules,
28
28
  listKeymap
29
29
  } from "prosemirror-flat-list";
30
+ import { ListDOMSerializer } from "prosemirror-flat-list";
30
31
  function defineListSpec() {
31
32
  return defineNodeSpec({ ...createListSpec(), name: "list" });
32
33
  }
@@ -65,6 +66,7 @@ function defineList() {
65
66
  ]);
66
67
  }
67
68
  export {
69
+ ListDOMSerializer,
68
70
  defineList,
69
71
  defineListCommands,
70
72
  defineListInputRules,
@@ -33,9 +33,8 @@ var virtualSelectionPlugin = new ProseMirrorPlugin({
33
33
  view.dispatch(setFocusMeta(view.state.tr, false));
34
34
  },
35
35
  blur: (view) => {
36
- var _a;
37
- const dom = view.dom;
38
- const activeElement = (_a = dom == null ? void 0 : dom.ownerDocument) == null ? void 0 : _a.activeElement;
36
+ const { dom, root } = view;
37
+ const activeElement = root.activeElement;
39
38
  if (activeElement === dom)
40
39
  return;
41
40
  view.dispatch(setFocusMeta(view.state.tr, true));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@prosekit/extensions",
3
3
  "type": "module",
4
- "version": "0.3.0",
4
+ "version": "0.3.2",
5
5
  "private": false,
6
6
  "author": {
7
7
  "name": "ocavue",
@@ -134,11 +134,11 @@
134
134
  "dist"
135
135
  ],
136
136
  "dependencies": {
137
- "@prosekit/core": "^0.3.0",
137
+ "@prosekit/core": "^0.4.0",
138
138
  "@prosekit/pm": "^0.1.1",
139
139
  "prosemirror-dropcursor": "^1.8.1",
140
140
  "prosemirror-flat-list": "^0.4.6",
141
- "prosemirror-highlight": "^0.4.1"
141
+ "prosemirror-highlight": "^0.5.0"
142
142
  },
143
143
  "peerDependencies": {
144
144
  "shikiji": ">= 0.9.0"
@@ -151,7 +151,7 @@
151
151
  "devDependencies": {
152
152
  "@prosekit/dev": "*",
153
153
  "shikiji": "^0.10.2",
154
- "tsup": "^8.0.1",
154
+ "tsup": "^8.0.2",
155
155
  "typescript": "^5.3.3",
156
156
  "vitest": "^1.2.2"
157
157
  },