@prosekit/extensions 0.0.0-next-20240427200701 → 0.0.0-next-20240427202431

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.
@@ -419,6 +419,8 @@ export declare function defineLinkEnterRule(): Extension<ExtensionTyping<string,
419
419
 
420
420
  export declare function defineLinkInputRule(): Extension<ExtensionTyping<string, string, CommandArgs>>;
421
421
 
422
+ export declare function defineLinkMarkRule(): Extension<ExtensionTyping<string, string, CommandArgs>>;
423
+
422
424
  export declare function defineLinkSpec(): Extension< {
423
425
  MARKS: "link";
424
426
  }>;
@@ -0,0 +1,185 @@
1
+ // src/mark-rule/index.ts
2
+ import { Facet, pluginFacet } from "@prosekit/core";
3
+ import { ProseMirrorPlugin } from "@prosekit/pm/state";
4
+
5
+ // src/mark-rule/apply.ts
6
+ import { OBJECT_REPLACEMENT_CHARACTER, getMarkType } from "@prosekit/core";
7
+ import "@prosekit/pm/model";
8
+ import "@prosekit/pm/state";
9
+
10
+ // src/mark-rule/range.ts
11
+ import "@prosekit/pm/state";
12
+ function getSpanTextRanges($from, $to) {
13
+ const nodeRange = $from.blockRange($to);
14
+ if (!nodeRange) {
15
+ return [];
16
+ }
17
+ const stack = [];
18
+ let start = nodeRange.start;
19
+ for (let i = nodeRange.startIndex; i < nodeRange.endIndex; i++) {
20
+ const child = nodeRange.parent.child(i);
21
+ stack.push([start, child]);
22
+ start += child.nodeSize;
23
+ }
24
+ const ranges = [];
25
+ while (stack.length > 0) {
26
+ const [start2, node] = stack.pop();
27
+ if (node.type.spec.code) {
28
+ continue;
29
+ }
30
+ if (node.type.isTextblock) {
31
+ ranges.push([start2 + 1, start2 + 1 + node.content.size]);
32
+ continue;
33
+ }
34
+ node.forEach((child, offset) => {
35
+ stack.push([start2 + offset + 1, child]);
36
+ });
37
+ }
38
+ return ranges;
39
+ }
40
+ function getInlineTextRange($from, $to) {
41
+ return [$from.start(), $to.end()];
42
+ }
43
+ function getTextRanges(doc, from, to) {
44
+ const $from = doc.resolve(from);
45
+ const $to = doc.resolve(to);
46
+ if ($from.sameParent($to) && $from.parent.isTextblock) {
47
+ return [getInlineTextRange($from, $to)];
48
+ } else {
49
+ const nodeRange = $from.blockRange($to);
50
+ if (!nodeRange) {
51
+ return [];
52
+ }
53
+ return getSpanTextRanges($from, $to);
54
+ }
55
+ }
56
+ function getMapRange(transactions, oldState, newState) {
57
+ let lo = oldState.selection.from;
58
+ let hi = oldState.selection.to;
59
+ for (const tr of transactions) {
60
+ for (const map of tr.mapping.maps) {
61
+ lo = map.map(lo);
62
+ hi = map.map(hi);
63
+ map.forEach((_oldStart, _oldEnd, newStart, newEnd) => {
64
+ lo = Math.min(lo, hi, newStart);
65
+ hi = Math.max(hi, hi, newEnd);
66
+ });
67
+ }
68
+ }
69
+ lo = Math.min(lo, hi, newState.selection.from);
70
+ hi = Math.min(lo, hi, newState.selection.to);
71
+ return [lo, hi];
72
+ }
73
+ function getCheckRanges(transactions, oldState, newState) {
74
+ const [from, to] = getMapRange(transactions, oldState, newState);
75
+ return getTextRanges(newState.doc, from, to);
76
+ }
77
+
78
+ // src/mark-rule/apply.ts
79
+ function getExpectedMarkings(rules, doc, from, to) {
80
+ const text = doc.textBetween(from, to, OBJECT_REPLACEMENT_CHARACTER);
81
+ const result = [];
82
+ for (const rule of rules) {
83
+ rule.regex.lastIndex = 0;
84
+ const matches = text.matchAll(rule.regex);
85
+ const markType = getMarkType(doc.type.schema, rule.type);
86
+ for (const match of matches) {
87
+ const index = match.index;
88
+ if (index == null)
89
+ continue;
90
+ const attrs = rule.getAttrs(match);
91
+ const mark = markType.create(attrs);
92
+ result.push([mark, from + index, from + index + match[0].length]);
93
+ }
94
+ }
95
+ return result;
96
+ }
97
+ function getReceivedMarkings(rules, doc, from, to) {
98
+ const result = [];
99
+ const schema = doc.type.schema;
100
+ const markTypes = rules.map((rule) => getMarkType(schema, rule.type));
101
+ doc.nodesBetween(from, to, (node, pos) => {
102
+ if (!node.isInline) {
103
+ return;
104
+ }
105
+ for (const markType of markTypes) {
106
+ const mark = node.marks.find((mark2) => mark2.type === markType);
107
+ if (mark) {
108
+ result.push([mark, pos, pos + node.nodeSize]);
109
+ }
110
+ }
111
+ });
112
+ return result;
113
+ }
114
+ function markingEquals(a, b) {
115
+ return a[1] === b[1] && a[2] === b[2] && a[0].eq(b[0]);
116
+ }
117
+ function markingDiffs(a, b) {
118
+ return a.filter((x) => !b.some((y) => markingEquals(x, y)));
119
+ }
120
+ function applyMarkRules(rules, transactions, oldState, newState) {
121
+ if (transactions.length === 0 || transactions.every((tr2) => !tr2.docChanged)) {
122
+ return null;
123
+ }
124
+ const ranges = getCheckRanges(transactions, oldState, newState);
125
+ const toRemove = [];
126
+ const toCreate = [];
127
+ for (const [from, to] of ranges) {
128
+ const expected = getExpectedMarkings(rules, newState.doc, from, to);
129
+ const received = getReceivedMarkings(rules, newState.doc, from, to);
130
+ toRemove.push(...markingDiffs(received, expected));
131
+ toCreate.push(...markingDiffs(expected, received));
132
+ }
133
+ if (toCreate.length === 0 && toRemove.length === 0) {
134
+ return null;
135
+ }
136
+ const tr = newState.tr;
137
+ for (const [mark, from, to] of toRemove) {
138
+ tr.removeMark(from, to, mark);
139
+ }
140
+ for (const [mark, from, to] of toCreate) {
141
+ tr.addMark(from, to, mark);
142
+ }
143
+ return tr;
144
+ }
145
+
146
+ // src/mark-rule/rule.ts
147
+ import "@prosekit/pm/model";
148
+ var MarkRule = class {
149
+ constructor({ regex, type, attrs = null }) {
150
+ this.regex = regex;
151
+ this.type = type;
152
+ this.getAttrs = typeof attrs === "function" ? attrs : () => attrs;
153
+ }
154
+ };
155
+
156
+ // src/mark-rule/index.ts
157
+ function defineMarkRule(options) {
158
+ return markRuleFacet.extension([new MarkRule(options)]);
159
+ }
160
+ var markRuleFacet = Facet.define({
161
+ converter: () => {
162
+ let rules = [];
163
+ const plugin = new ProseMirrorPlugin({
164
+ appendTransaction: (transactions, oldState, newState) => {
165
+ return applyMarkRules(rules, transactions, oldState, newState);
166
+ }
167
+ });
168
+ const pluginFunc = () => [plugin];
169
+ return {
170
+ create: (inputs) => {
171
+ rules = inputs;
172
+ return pluginFunc;
173
+ },
174
+ update: (inputs) => {
175
+ rules = inputs;
176
+ return null;
177
+ }
178
+ };
179
+ },
180
+ next: pluginFacet
181
+ });
182
+
183
+ export {
184
+ defineMarkRule
185
+ };
@@ -2,5 +2,6 @@ export { defineLinkSpec } from './_tsup-dts-rollup';
2
2
  export { defineLinkCommands } from './_tsup-dts-rollup';
3
3
  export { defineLinkInputRule } from './_tsup-dts-rollup';
4
4
  export { defineLinkEnterRule } from './_tsup-dts-rollup';
5
+ export { defineLinkMarkRule } from './_tsup-dts-rollup';
5
6
  export { defineLink } from './_tsup-dts-rollup';
6
7
  export { LinkAttrs } from './_tsup-dts-rollup';
@@ -1,3 +1,6 @@
1
+ import {
2
+ defineMarkRule
3
+ } from "./chunk-TXF4SPMB.js";
1
4
  import {
2
5
  defineEnterRule
3
6
  } from "./chunk-ASTUC4KT.js";
@@ -85,6 +88,13 @@ function defineLinkEnterRule() {
85
88
  }
86
89
  });
87
90
  }
91
+ function defineLinkMarkRule() {
92
+ return defineMarkRule({
93
+ regex: LINK_RE,
94
+ type: "link",
95
+ attrs: (match) => ({ href: match[1] })
96
+ });
97
+ }
88
98
  function defineLink() {
89
99
  return union([
90
100
  defineLinkSpec(),
@@ -98,5 +108,6 @@ export {
98
108
  defineLinkCommands,
99
109
  defineLinkEnterRule,
100
110
  defineLinkInputRule,
111
+ defineLinkMarkRule,
101
112
  defineLinkSpec
102
113
  };
@@ -1,184 +1,6 @@
1
- // src/mark-rule/index.ts
2
- import { Facet, pluginFacet } from "@prosekit/core";
3
- import { ProseMirrorPlugin } from "@prosekit/pm/state";
4
-
5
- // src/mark-rule/apply.ts
6
- import { OBJECT_REPLACEMENT_CHARACTER, getMarkType } from "@prosekit/core";
7
- import "@prosekit/pm/model";
8
- import "@prosekit/pm/state";
9
-
10
- // src/mark-rule/range.ts
11
- import "@prosekit/pm/state";
12
- function getSpanTextRanges($from, $to) {
13
- const nodeRange = $from.blockRange($to);
14
- if (!nodeRange) {
15
- return [];
16
- }
17
- const stack = [];
18
- let start = nodeRange.start;
19
- for (let i = nodeRange.startIndex; i < nodeRange.endIndex; i++) {
20
- const child = nodeRange.parent.child(i);
21
- stack.push([start, child]);
22
- start += child.nodeSize;
23
- }
24
- const ranges = [];
25
- while (stack.length > 0) {
26
- const [start2, node] = stack.pop();
27
- if (node.type.spec.code) {
28
- continue;
29
- }
30
- if (node.type.isTextblock) {
31
- ranges.push([start2 + 1, start2 + 1 + node.content.size]);
32
- continue;
33
- }
34
- node.forEach((child, offset) => {
35
- stack.push([start2 + offset + 1, child]);
36
- });
37
- }
38
- return ranges;
39
- }
40
- function getInlineTextRange($from, $to) {
41
- return [$from.start(), $to.end()];
42
- }
43
- function getTextRanges(doc, from, to) {
44
- const $from = doc.resolve(from);
45
- const $to = doc.resolve(to);
46
- if ($from.sameParent($to) && $from.parent.isTextblock) {
47
- return [getInlineTextRange($from, $to)];
48
- } else {
49
- const nodeRange = $from.blockRange($to);
50
- if (!nodeRange) {
51
- return [];
52
- }
53
- return getSpanTextRanges($from, $to);
54
- }
55
- }
56
- function getMapRange(transactions, oldState, newState) {
57
- let lo = oldState.selection.from;
58
- let hi = oldState.selection.to;
59
- for (const tr of transactions) {
60
- for (const map of tr.mapping.maps) {
61
- lo = map.map(lo);
62
- hi = map.map(hi);
63
- map.forEach((_oldStart, _oldEnd, newStart, newEnd) => {
64
- lo = Math.min(lo, hi, newStart);
65
- hi = Math.max(hi, hi, newEnd);
66
- });
67
- }
68
- }
69
- lo = Math.min(lo, hi, newState.selection.from);
70
- hi = Math.min(lo, hi, newState.selection.to);
71
- return [lo, hi];
72
- }
73
- function getCheckRanges(transactions, oldState, newState) {
74
- const [from, to] = getMapRange(transactions, oldState, newState);
75
- return getTextRanges(newState.doc, from, to);
76
- }
77
-
78
- // src/mark-rule/apply.ts
79
- function getExpectedMarkings(rules, doc, from, to) {
80
- const text = doc.textBetween(from, to, OBJECT_REPLACEMENT_CHARACTER);
81
- const result = [];
82
- for (const rule of rules) {
83
- rule.regex.lastIndex = 0;
84
- const matches = text.matchAll(rule.regex);
85
- const markType = getMarkType(doc.type.schema, rule.type);
86
- for (const match of matches) {
87
- const index = match.index;
88
- if (index == null)
89
- continue;
90
- const attrs = rule.getAttrs(match);
91
- const mark = markType.create(attrs);
92
- result.push([mark, from + index, from + index + match[0].length]);
93
- }
94
- }
95
- return result;
96
- }
97
- function getReceivedMarkings(rules, doc, from, to) {
98
- const result = [];
99
- const schema = doc.type.schema;
100
- const markTypes = rules.map((rule) => getMarkType(schema, rule.type));
101
- doc.nodesBetween(from, to, (node, pos) => {
102
- if (!node.isInline) {
103
- return;
104
- }
105
- for (const markType of markTypes) {
106
- const mark = node.marks.find((mark2) => mark2.type === markType);
107
- if (mark) {
108
- result.push([mark, pos, pos + node.nodeSize]);
109
- }
110
- }
111
- });
112
- return result;
113
- }
114
- function markingEquals(a, b) {
115
- return a[1] === b[1] && a[2] === b[2] && a[0].eq(b[0]);
116
- }
117
- function markingDiffs(a, b) {
118
- return a.filter((x) => !b.some((y) => markingEquals(x, y)));
119
- }
120
- function applyMarkRules(rules, transactions, oldState, newState) {
121
- if (transactions.length === 0 || transactions.every((tr2) => !tr2.docChanged)) {
122
- return null;
123
- }
124
- const ranges = getCheckRanges(transactions, oldState, newState);
125
- const toRemove = [];
126
- const toCreate = [];
127
- for (const [from, to] of ranges) {
128
- const expected = getExpectedMarkings(rules, newState.doc, from, to);
129
- const received = getReceivedMarkings(rules, newState.doc, from, to);
130
- toRemove.push(...markingDiffs(received, expected));
131
- toCreate.push(...markingDiffs(expected, received));
132
- }
133
- if (toCreate.length === 0 && toRemove.length === 0) {
134
- return null;
135
- }
136
- const tr = newState.tr;
137
- for (const [mark, from, to] of toRemove) {
138
- tr.removeMark(from, to, mark);
139
- }
140
- for (const [mark, from, to] of toCreate) {
141
- tr.addMark(from, to, mark);
142
- }
143
- return tr;
144
- }
145
-
146
- // src/mark-rule/rule.ts
147
- import "@prosekit/pm/model";
148
- var MarkRule = class {
149
- constructor({ regex, type, attrs = null }) {
150
- this.regex = regex;
151
- this.type = type;
152
- this.getAttrs = typeof attrs === "function" ? attrs : () => attrs;
153
- }
154
- };
155
-
156
- // src/mark-rule/index.ts
157
- function defineMarkRule(options) {
158
- return markRuleFacet.extension([new MarkRule(options)]);
159
- }
160
- var markRuleFacet = Facet.define({
161
- converter: () => {
162
- let rules = [];
163
- const plugin = new ProseMirrorPlugin({
164
- appendTransaction: (transactions, oldState, newState) => {
165
- return applyMarkRules(rules, transactions, oldState, newState);
166
- }
167
- });
168
- const pluginFunc = () => [plugin];
169
- return {
170
- create: (inputs) => {
171
- rules = inputs;
172
- return pluginFunc;
173
- },
174
- update: (inputs) => {
175
- rules = inputs;
176
- return null;
177
- }
178
- };
179
- },
180
- next: pluginFacet
181
- });
1
+ import {
2
+ defineMarkRule
3
+ } from "./chunk-TXF4SPMB.js";
182
4
  export {
183
5
  defineMarkRule
184
6
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@prosekit/extensions",
3
3
  "type": "module",
4
- "version": "0.0.0-next-20240427200701",
4
+ "version": "0.0.0-next-20240427202431",
5
5
  "private": false,
6
6
  "author": {
7
7
  "name": "ocavue",
@@ -152,8 +152,8 @@
152
152
  "dist"
153
153
  ],
154
154
  "dependencies": {
155
- "@prosekit/core": "0.0.0-next-20240427200701",
156
- "@prosekit/pm": "0.0.0-next-20240427200701",
155
+ "@prosekit/core": "0.0.0-next-20240427202431",
156
+ "@prosekit/pm": "0.0.0-next-20240427202431",
157
157
  "prosemirror-dropcursor": "^1.8.1",
158
158
  "prosemirror-flat-list": "^0.5.0",
159
159
  "prosemirror-highlight": "^0.5.0",