@prosekit/extensions 0.10.1 → 0.11.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.
- package/dist/drop-indicator-QKkPzJIx.js +255 -0
- package/dist/list/style.css +124 -84
- package/dist/prosekit-extensions-code-block.d.ts +1 -1
- package/dist/prosekit-extensions-drop-cursor.d.ts +2 -0
- package/dist/prosekit-extensions-drop-cursor.js +2 -0
- package/dist/prosekit-extensions-drop-indicator.d.ts +134 -0
- package/dist/prosekit-extensions-drop-indicator.js +3 -0
- package/dist/prosekit-extensions-link.js +1 -1
- package/dist/prosekit-extensions-list.js +46 -3
- package/dist/prosekit-extensions-mark-rule.js +1 -1
- package/dist/prosekit-extensions-placeholder.js +1 -1
- package/dist/prosekit-extensions-table.js +1 -1
- package/dist/prosekit-extensions-virtual-selection.js +1 -1
- package/dist/shiki-highlighter-chunk.d.ts +1 -1
- package/package.json +17 -9
- /package/dist/{mark-rule-wEOcDt6i.js → mark-rule-D7zaa32n.js} +0 -0
- /package/dist/{shiki-highlighter-chunk-CZGvZlhf.d.ts → shiki-highlighter-chunk-NV2F_Qjl.d.ts} +0 -0
- /package/dist/{table-dVQqzLlz.js → table-3rDWFyBH.js} +0 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { defineFacet, defineFacetPayload, isNodeSelection, pluginFacet } from "@prosekit/core";
|
|
2
|
+
import { NodeSelection, Plugin, PluginKey, TextSelection } from "@prosekit/pm/state";
|
|
3
|
+
import { isHTMLElement } from "@ocavue/utils";
|
|
4
|
+
|
|
5
|
+
//#region src/drop-indicator/drop-target.ts
|
|
6
|
+
function getTargetsByView(view) {
|
|
7
|
+
let stack = [[-1, view.state.doc]];
|
|
8
|
+
let targets = [];
|
|
9
|
+
while (stack.length > 0) {
|
|
10
|
+
const [pos, node] = stack.pop();
|
|
11
|
+
if (pos >= 0) {
|
|
12
|
+
let dom = view.nodeDOM(pos);
|
|
13
|
+
if (dom && isHTMLElement(dom)) {
|
|
14
|
+
let rect = dom.getBoundingClientRect();
|
|
15
|
+
let { top, bottom, left: x1, right: x2 } = rect;
|
|
16
|
+
targets.push([pos, [
|
|
17
|
+
x1,
|
|
18
|
+
top,
|
|
19
|
+
x2,
|
|
20
|
+
top
|
|
21
|
+
]], [pos + node.nodeSize, [
|
|
22
|
+
x1,
|
|
23
|
+
bottom,
|
|
24
|
+
x2,
|
|
25
|
+
bottom
|
|
26
|
+
]]);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (node.isBlock && !node.isTextblock) {
|
|
30
|
+
let childPos = pos + 1;
|
|
31
|
+
for (let child of node.children) {
|
|
32
|
+
stack.push([childPos, child]);
|
|
33
|
+
childPos += child.nodeSize;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return targets;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* @internal
|
|
41
|
+
*/
|
|
42
|
+
function buildGetTarget(view, onDrag) {
|
|
43
|
+
let prevTargets = [];
|
|
44
|
+
let prevDoc;
|
|
45
|
+
let prevRect;
|
|
46
|
+
const getTargets = () => {
|
|
47
|
+
const rect = view.dom.getBoundingClientRect();
|
|
48
|
+
const doc = view.state.doc;
|
|
49
|
+
if (prevTargets && prevDoc && prevRect && rect.width === prevRect.width && rect.height === prevRect.height && rect.x === prevRect.x && rect.y === prevRect.y && prevDoc.eq(doc)) return prevTargets;
|
|
50
|
+
prevRect = rect;
|
|
51
|
+
prevDoc = doc;
|
|
52
|
+
prevTargets = getTargetsByView(view);
|
|
53
|
+
return prevTargets;
|
|
54
|
+
};
|
|
55
|
+
const getTarget = (point, event) => {
|
|
56
|
+
if (!view.editable || view.isDestroyed) return;
|
|
57
|
+
const compare = (p1, p2) => {
|
|
58
|
+
const [pos1, line1] = p1;
|
|
59
|
+
const [pos2, line2] = p2;
|
|
60
|
+
const p1Distance = pointLineDistance(point, line1);
|
|
61
|
+
const p2Distance = pointLineDistance(point, line2);
|
|
62
|
+
return p1Distance - p2Distance || pos1 - pos2;
|
|
63
|
+
};
|
|
64
|
+
const targets = getTargets();
|
|
65
|
+
targets.sort(compare);
|
|
66
|
+
const target = targets.find((target$1) => onDrag({
|
|
67
|
+
view,
|
|
68
|
+
pos: target$1[0],
|
|
69
|
+
event
|
|
70
|
+
}) !== false);
|
|
71
|
+
if (target && isDraggingToItself(view, target[0])) return void 0;
|
|
72
|
+
return target;
|
|
73
|
+
};
|
|
74
|
+
return getTarget;
|
|
75
|
+
}
|
|
76
|
+
function pointPointDistance(a, b) {
|
|
77
|
+
return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]);
|
|
78
|
+
}
|
|
79
|
+
function pointLineDistance(point, line) {
|
|
80
|
+
return Math.min(pointPointDistance(point, [line[0], line[1]]), pointPointDistance(point, [line[2], line[3]]));
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Whether the dragging node is being dragged to the same position. For example,
|
|
84
|
+
* dragging a list node into a new position that is just below the list node, or
|
|
85
|
+
* dragging a nested quoteblock into itself.
|
|
86
|
+
*/
|
|
87
|
+
function isDraggingToItself(view, pos) {
|
|
88
|
+
const dragging = view.dragging;
|
|
89
|
+
if (!dragging) return;
|
|
90
|
+
const { move } = dragging;
|
|
91
|
+
if (!move) return;
|
|
92
|
+
const selection = view.state.selection;
|
|
93
|
+
if (!isNodeSelection(selection)) return;
|
|
94
|
+
const { from, to } = selection;
|
|
95
|
+
return from <= pos && pos <= to;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
//#endregion
|
|
99
|
+
//#region src/drop-indicator/drop-indicator-plugin.ts
|
|
100
|
+
/**
|
|
101
|
+
* @internal
|
|
102
|
+
*/
|
|
103
|
+
function createDropIndicatorPlugin(options) {
|
|
104
|
+
let getTarget;
|
|
105
|
+
return new Plugin({
|
|
106
|
+
key: new PluginKey("prosekit-drop-indicator"),
|
|
107
|
+
view: (view) => {
|
|
108
|
+
getTarget = buildGetTarget(view, options.onDrag);
|
|
109
|
+
return createDropIndicatorView(view, getTarget, options);
|
|
110
|
+
},
|
|
111
|
+
props: { handleDrop(view, event, slice, move) {
|
|
112
|
+
if (!getTarget) return false;
|
|
113
|
+
const target = getTarget([event.clientX, event.clientY], event);
|
|
114
|
+
if (!target) return false;
|
|
115
|
+
event.preventDefault();
|
|
116
|
+
let insertPos = target[0];
|
|
117
|
+
let tr = view.state.tr;
|
|
118
|
+
if (move) {
|
|
119
|
+
let { node } = view.dragging || {};
|
|
120
|
+
if (node) node.replace(tr);
|
|
121
|
+
else tr.deleteSelection();
|
|
122
|
+
}
|
|
123
|
+
let pos = tr.mapping.map(insertPos);
|
|
124
|
+
let isNode = slice.openStart == 0 && slice.openEnd == 0 && slice.content.childCount == 1;
|
|
125
|
+
let beforeInsert = tr.doc;
|
|
126
|
+
if (isNode) tr.replaceRangeWith(pos, pos, slice.content.firstChild);
|
|
127
|
+
else tr.replaceRange(pos, pos, slice);
|
|
128
|
+
if (tr.doc.eq(beforeInsert)) return true;
|
|
129
|
+
let $pos = tr.doc.resolve(pos);
|
|
130
|
+
if (isNode && NodeSelection.isSelectable(slice.content.firstChild) && $pos.nodeAfter && $pos.nodeAfter.sameMarkup(slice.content.firstChild)) tr.setSelection(new NodeSelection($pos));
|
|
131
|
+
else {
|
|
132
|
+
let end = tr.mapping.map(insertPos);
|
|
133
|
+
tr.mapping.maps[tr.mapping.maps.length - 1].forEach((_from, _to, _newFrom, newTo) => end = newTo);
|
|
134
|
+
tr.setSelection(selectionBetween(view, $pos, tr.doc.resolve(end)));
|
|
135
|
+
}
|
|
136
|
+
view.focus();
|
|
137
|
+
view.dispatch(tr.setMeta("uiEvent", "drop"));
|
|
138
|
+
return true;
|
|
139
|
+
} }
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
function selectionBetween(view, $anchor, $head, bias) {
|
|
143
|
+
return view.someProp("createSelectionBetween", (f) => f(view, $anchor, $head)) || TextSelection.between($anchor, $head, bias);
|
|
144
|
+
}
|
|
145
|
+
function createDropIndicatorView(view, getTarget, options) {
|
|
146
|
+
let dom = view.dom;
|
|
147
|
+
let hideId;
|
|
148
|
+
let prevX;
|
|
149
|
+
let prevY;
|
|
150
|
+
let hasDragOverEvent = false;
|
|
151
|
+
const scheduleHide = () => {
|
|
152
|
+
if (hideId) clearTimeout(hideId);
|
|
153
|
+
hasDragOverEvent = false;
|
|
154
|
+
hideId = setTimeout(() => {
|
|
155
|
+
if (hasDragOverEvent) return;
|
|
156
|
+
options.onHide();
|
|
157
|
+
}, 30);
|
|
158
|
+
};
|
|
159
|
+
const handleDragOver = (event) => {
|
|
160
|
+
hasDragOverEvent = true;
|
|
161
|
+
const { clientX, clientY } = event;
|
|
162
|
+
if (prevX === clientX && prevY === clientY) return;
|
|
163
|
+
prevX = clientX;
|
|
164
|
+
prevY = clientY;
|
|
165
|
+
let target = getTarget([clientX, clientY], event);
|
|
166
|
+
if (!target) {
|
|
167
|
+
scheduleHide();
|
|
168
|
+
return;
|
|
169
|
+
} else {
|
|
170
|
+
const [pos, [x1, y1, x2, y2]] = target;
|
|
171
|
+
const line = {
|
|
172
|
+
p1: {
|
|
173
|
+
x: x1,
|
|
174
|
+
y: y1
|
|
175
|
+
},
|
|
176
|
+
p2: {
|
|
177
|
+
x: x2,
|
|
178
|
+
y: y2
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
options.onShow({
|
|
182
|
+
view,
|
|
183
|
+
pos,
|
|
184
|
+
line
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
dom.addEventListener("dragover", handleDragOver);
|
|
189
|
+
dom.addEventListener("dragend", scheduleHide);
|
|
190
|
+
dom.addEventListener("drop", scheduleHide);
|
|
191
|
+
dom.addEventListener("dragleave", scheduleHide);
|
|
192
|
+
const destroy = () => {
|
|
193
|
+
dom.removeEventListener("dragover", handleDragOver);
|
|
194
|
+
dom.removeEventListener("dragend", scheduleHide);
|
|
195
|
+
dom.removeEventListener("drop", scheduleHide);
|
|
196
|
+
dom.removeEventListener("dragleave", scheduleHide);
|
|
197
|
+
};
|
|
198
|
+
return { destroy };
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
//#endregion
|
|
202
|
+
//#region src/drop-indicator/drop-indicator-facet.ts
|
|
203
|
+
/**
|
|
204
|
+
* @internal
|
|
205
|
+
*/
|
|
206
|
+
function defineDropIndicatorPayload(payload) {
|
|
207
|
+
return defineFacetPayload(dropIndicatorFacet, [payload]);
|
|
208
|
+
}
|
|
209
|
+
const dropIndicatorFacet = defineFacet({
|
|
210
|
+
parent: pluginFacet,
|
|
211
|
+
singleton: true,
|
|
212
|
+
reducer: (payloads) => {
|
|
213
|
+
let showHandlers = payloads.map((p) => p.onShow).filter((x) => !!x);
|
|
214
|
+
let hideHandlers = payloads.map((p) => p.onHide).filter((x) => !!x);
|
|
215
|
+
let dragHandlers = payloads.map((p) => p.onDrag).filter((x) => !!x);
|
|
216
|
+
let showHandler = (options) => {
|
|
217
|
+
for (let fn of showHandlers) fn(options);
|
|
218
|
+
};
|
|
219
|
+
let hideHandler = () => {
|
|
220
|
+
for (let fn of hideHandlers) fn();
|
|
221
|
+
};
|
|
222
|
+
let dragHandler = (options) => {
|
|
223
|
+
for (let fn of dragHandlers) if (fn(options) === false) return false;
|
|
224
|
+
return true;
|
|
225
|
+
};
|
|
226
|
+
if (showHandlers.length === 0) return [];
|
|
227
|
+
return createDropIndicatorPlugin({
|
|
228
|
+
onDrag: dragHandler,
|
|
229
|
+
onShow: showHandler,
|
|
230
|
+
onHide: hideHandler
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
//#endregion
|
|
236
|
+
//#region src/drop-indicator/drop-indicator.ts
|
|
237
|
+
/**
|
|
238
|
+
* Defines an extension that controls the behavior of the drop indicator.
|
|
239
|
+
*
|
|
240
|
+
* This extension itself doesn't draw the drop indicator, but it provides the
|
|
241
|
+
* necessary callbacks to do so. You probably don't want to use this extension
|
|
242
|
+
* directly, but rather use the `<DropIndicator>` component.
|
|
243
|
+
*
|
|
244
|
+
* You can add this extension multiple times. If any extension has `onDrag`
|
|
245
|
+
* callback defined, and it returns `false`, then the drop point will be
|
|
246
|
+
* discarded.
|
|
247
|
+
*
|
|
248
|
+
* @public
|
|
249
|
+
*/
|
|
250
|
+
function defineDropIndicator(options) {
|
|
251
|
+
return defineDropIndicatorPayload(options ?? {});
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
//#endregion
|
|
255
|
+
export { defineDropIndicator };
|
package/dist/list/style.css
CHANGED
|
@@ -1,89 +1,129 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
margin-bottom: 0;
|
|
6
|
-
margin-left: 32px;
|
|
7
|
-
margin-bottom: 0;
|
|
8
|
-
position: relative;
|
|
9
|
-
display: list-item;
|
|
10
|
-
list-style: none;
|
|
11
|
-
}
|
|
12
|
-
.prosemirror-flat-list.ProseMirror-selectednode {
|
|
13
|
-
outline: none;
|
|
14
|
-
}
|
|
15
|
-
.prosemirror-flat-list.ProseMirror-selectednode:after {
|
|
16
|
-
content: "";
|
|
17
|
-
position: absolute;
|
|
18
|
-
left: -32px;
|
|
19
|
-
right: -2px;
|
|
20
|
-
top: -2px;
|
|
21
|
-
bottom: -2px;
|
|
22
|
-
border: 2px solid #8cf;
|
|
23
|
-
pointer-events: none;
|
|
24
|
-
}
|
|
25
|
-
.prosemirror-flat-list[data-list-kind=bullet] {
|
|
26
|
-
list-style: disc;
|
|
27
|
-
}
|
|
28
|
-
.prosemirror-flat-list[data-list-kind=ordered] > * {
|
|
29
|
-
contain: style;
|
|
30
|
-
}
|
|
31
|
-
.prosemirror-flat-list[data-list-kind=ordered]::before {
|
|
32
|
-
position: absolute;
|
|
33
|
-
right: 100%;
|
|
34
|
-
font-variant-numeric: tabular-nums;
|
|
35
|
-
content: counter(prosemirror-flat-list-counter, decimal) ". ";
|
|
1
|
+
:root {
|
|
2
|
+
--prosekit-list-bullet-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='2.5' fill='currentColor'/%3E%3C/svg%3E");
|
|
3
|
+
--prosekit-list-toggle-open-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpolygon points='8,10 12,14 16,10' fill='currentColor'/%3E%3C/svg%3E");
|
|
4
|
+
--prosekit-list-toggle-closed-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpolygon points='10,8 14,12 10,16' fill='currentColor'/%3E%3C/svg%3E");
|
|
36
5
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
@supports (counter-set: prosemirror-flat-list-counter 1) {
|
|
45
|
-
[data-list-order]:is(.prosemirror-flat-list[data-list-kind=ordered]:first-child, :not(.prosemirror-flat-list[data-list-kind=ordered]) + .prosemirror-flat-list[data-list-kind=ordered]) {
|
|
46
|
-
counter-set: prosemirror-flat-list-counter var(--prosemirror-flat-list-order);
|
|
6
|
+
|
|
7
|
+
.prosemirror-flat-list {
|
|
8
|
+
& {
|
|
9
|
+
position: relative;
|
|
10
|
+
margin: 0;
|
|
11
|
+
padding: 0;
|
|
12
|
+
list-style: none;
|
|
47
13
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
14
|
+
|
|
15
|
+
& > .list-marker {
|
|
16
|
+
position: absolute;
|
|
17
|
+
left: 0;
|
|
18
|
+
width: 1.5em;
|
|
19
|
+
width: 1lh;
|
|
20
|
+
height: 1.5em;
|
|
21
|
+
height: 1lh;
|
|
22
|
+
text-align: center;
|
|
52
23
|
}
|
|
53
|
-
}
|
|
54
|
-
.prosemirror-flat-list[data-list-kind=task] > .list-marker {
|
|
55
|
-
position: absolute;
|
|
56
|
-
right: 100%;
|
|
57
|
-
text-align: center;
|
|
58
|
-
width: 1.5em;
|
|
59
|
-
width: 1lh;
|
|
60
|
-
}
|
|
61
|
-
:is(.prosemirror-flat-list[data-list-kind=task] > .list-marker),
|
|
62
|
-
:is(.prosemirror-flat-list[data-list-kind=task] > .list-marker) * {
|
|
63
|
-
cursor: pointer;
|
|
64
|
-
}
|
|
65
|
-
.prosemirror-flat-list[data-list-kind=toggle] > .list-marker {
|
|
66
|
-
position: absolute;
|
|
67
|
-
right: 100%;
|
|
68
|
-
text-align: center;
|
|
69
|
-
width: 1.5em;
|
|
70
|
-
width: 1lh;
|
|
71
|
-
}
|
|
72
|
-
.prosemirror-flat-list[data-list-kind=toggle] > .list-marker::before {
|
|
73
|
-
content: "\23f7";
|
|
74
|
-
}
|
|
75
|
-
.prosemirror-flat-list[data-list-kind=toggle][data-list-collapsable][data-list-collapsed] > .list-marker::before {
|
|
76
|
-
content: "\23f5";
|
|
77
|
-
}
|
|
78
|
-
.prosemirror-flat-list[data-list-kind=toggle][data-list-collapsable] > .list-marker {
|
|
79
|
-
cursor: pointer;
|
|
80
|
-
}
|
|
81
|
-
.prosemirror-flat-list[data-list-kind=toggle]:not([data-list-collapsable]) > .list-marker {
|
|
82
|
-
opacity: 40%;
|
|
83
|
-
pointer-events: none;
|
|
84
|
-
}
|
|
85
|
-
.prosemirror-flat-list[data-list-kind=toggle][data-list-collapsable][data-list-collapsed] > .list-content > *:nth-child(n+2) {
|
|
86
|
-
display: none;
|
|
87
|
-
}
|
|
88
24
|
|
|
25
|
+
& > .list-content {
|
|
26
|
+
margin-left: 1.5em;
|
|
27
|
+
margin-left: 1lh;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
&[data-list-kind="bullet"] > .list-marker,
|
|
31
|
+
&[data-list-kind="toggle"] > .list-marker {
|
|
32
|
+
background-color: currentColor;
|
|
33
|
+
mask-position: center;
|
|
34
|
+
mask-repeat: no-repeat;
|
|
35
|
+
mask-size: contain;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
&[data-list-kind="bullet"] {
|
|
39
|
+
& > .list-marker {
|
|
40
|
+
mask-image: var(--prosekit-list-bullet-icon);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
&[data-list-kind="toggle"] {
|
|
45
|
+
& > .list-marker {
|
|
46
|
+
mask-image: var(--prosekit-list-toggle-open-icon);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
&[data-list-collapsable][data-list-collapsed] > .list-marker {
|
|
50
|
+
mask-image: var(--prosekit-list-toggle-closed-icon);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
&[data-list-kind="ordered"] {
|
|
55
|
+
/*
|
|
56
|
+
Ensure that the counters in children don't escape, so that the sub lists
|
|
57
|
+
won't affect the counter of the parent list.
|
|
58
|
+
|
|
59
|
+
See also https://github.com/ocavue/prosemirror-flat-list/issues/23
|
|
60
|
+
*/
|
|
61
|
+
& > * {
|
|
62
|
+
contain: style;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
&::before {
|
|
66
|
+
position: absolute;
|
|
67
|
+
right: calc(100% - 1.5em);
|
|
68
|
+
right: calc(100% - 1lh);
|
|
69
|
+
content: counter(prosemirror-flat-list-counter, decimal) ". ";
|
|
70
|
+
font-variant-numeric: tabular-nums;
|
|
71
|
+
}
|
|
72
|
+
counter-increment: prosemirror-flat-list-counter;
|
|
73
|
+
|
|
74
|
+
/*
|
|
75
|
+
Reset the counter for the first list node in the sequence.
|
|
76
|
+
*/
|
|
77
|
+
&:first-child,
|
|
78
|
+
:not(&) + & {
|
|
79
|
+
counter-reset: prosemirror-flat-list-counter;
|
|
80
|
+
|
|
81
|
+
/*
|
|
82
|
+
If the first list node has a custom order number, set the counter to that value.
|
|
83
|
+
*/
|
|
84
|
+
&[data-list-order] {
|
|
85
|
+
@supports (counter-set: prosemirror-flat-list-counter 1) {
|
|
86
|
+
counter-set: prosemirror-flat-list-counter var(--prosemirror-flat-list-order);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/*
|
|
90
|
+
Safari older than version 17.2 doesn't support `counter-set`
|
|
91
|
+
*/
|
|
92
|
+
@supports not (counter-set: prosemirror-flat-list-counter 1) {
|
|
93
|
+
counter-increment: prosemirror-flat-list-counter var(--prosemirror-flat-list-order);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
&[data-list-kind="task"] {
|
|
100
|
+
& > .list-marker {
|
|
101
|
+
&,
|
|
102
|
+
& * {
|
|
103
|
+
/* Make sure that the checkbox is at the center */
|
|
104
|
+
display: flex;
|
|
105
|
+
align-items: center;
|
|
106
|
+
justify-content: center;
|
|
107
|
+
margin: 0;
|
|
108
|
+
padding: 0;
|
|
109
|
+
cursor: pointer;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
&[data-list-kind="toggle"] {
|
|
115
|
+
&[data-list-collapsable] > .list-marker {
|
|
116
|
+
cursor: pointer;
|
|
117
|
+
}
|
|
118
|
+
&:not([data-list-collapsable]) > .list-marker {
|
|
119
|
+
opacity: 40%;
|
|
120
|
+
pointer-events: none;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* If collapsed, hide the second and futher children */
|
|
124
|
+
&[data-list-collapsable][data-list-collapsed] > .list-content > *:nth-child(n+2) {
|
|
125
|
+
display: none;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
89
129
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ShikiHighlighterOptions } from "./shiki-highlighter-chunk-
|
|
1
|
+
import { ShikiHighlighterOptions } from "./shiki-highlighter-chunk-NV2F_Qjl.js";
|
|
2
2
|
import { Extension, PlainExtension, Union } from "@prosekit/core";
|
|
3
3
|
import { Parser } from "prosemirror-highlight";
|
|
4
4
|
import { BundledLanguage as ShikiBundledLanguage, BundledLanguageInfo as ShikiBundledLanguageInfo, BundledTheme as ShikiBundledTheme, BundledThemeInfo as ShikiBundledThemeInfo, SpecialLanguage, bundledLanguagesInfo as shikiBundledLanguagesInfo, bundledThemesInfo as shikiBundledThemesInfo } from "shiki";
|
|
@@ -28,6 +28,8 @@ type DropCursorExtension = PlainExtension;
|
|
|
28
28
|
*
|
|
29
29
|
* See [prosemirror-dropcursor](https://github.com/ProseMirror/prosemirror-dropcursor) for more information.
|
|
30
30
|
*
|
|
31
|
+
* You probably want to use `<DropIndicator />` component instead of this extension.
|
|
32
|
+
*
|
|
31
33
|
* @public
|
|
32
34
|
*/
|
|
33
35
|
declare function defineDropCursor(options?: DropCursorOptions): DropCursorExtension;
|
|
@@ -7,6 +7,8 @@ import { dropCursor } from "prosemirror-dropcursor";
|
|
|
7
7
|
*
|
|
8
8
|
* See [prosemirror-dropcursor](https://github.com/ProseMirror/prosemirror-dropcursor) for more information.
|
|
9
9
|
*
|
|
10
|
+
* You probably want to use `<DropIndicator />` component instead of this extension.
|
|
11
|
+
*
|
|
10
12
|
* @public
|
|
11
13
|
*/
|
|
12
14
|
function defineDropCursor(options) {
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { PlainExtension } from "@prosekit/core";
|
|
2
|
+
import { NodeSelection } from "@prosekit/pm/state";
|
|
3
|
+
import { EditorView } from "@prosekit/pm/view";
|
|
4
|
+
import { Slice } from "@prosekit/pm/model";
|
|
5
|
+
|
|
6
|
+
//#region src/drop-indicator/types.d.ts
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A function that will be called when the `dragover` event is fired. You can
|
|
10
|
+
* return `false` to disable the current drop point and thus hide the drop
|
|
11
|
+
* indicator.
|
|
12
|
+
*
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
15
|
+
type DragEventHandler = (options: DragEventHandlerOptions) => boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Options for {@link DragEventHandler}.
|
|
18
|
+
*
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
interface DragEventHandlerOptions {
|
|
22
|
+
/**
|
|
23
|
+
* The editor's view.
|
|
24
|
+
*/
|
|
25
|
+
view: EditorView;
|
|
26
|
+
/**
|
|
27
|
+
* The drop position in current document.
|
|
28
|
+
*/
|
|
29
|
+
pos: number;
|
|
30
|
+
/**
|
|
31
|
+
* The `dragover` event.
|
|
32
|
+
*/
|
|
33
|
+
event: DragEvent;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* A function that will be called when the drop indicator should be shown.
|
|
37
|
+
*
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
40
|
+
type ShowHandler = (options: ShowHandlerOptions) => void;
|
|
41
|
+
/**
|
|
42
|
+
* Options for {@link ShowHandler}.
|
|
43
|
+
*
|
|
44
|
+
* @public
|
|
45
|
+
*/
|
|
46
|
+
interface ShowHandlerOptions {
|
|
47
|
+
/**
|
|
48
|
+
* The editor's view.
|
|
49
|
+
*/
|
|
50
|
+
view: EditorView;
|
|
51
|
+
/**
|
|
52
|
+
* The ProseMirror position that the drop indicator should be shown at.
|
|
53
|
+
*/
|
|
54
|
+
pos: number;
|
|
55
|
+
/**
|
|
56
|
+
* The line that the drop indicator should be shown at.
|
|
57
|
+
*/
|
|
58
|
+
line: Line;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
63
|
+
interface Point {
|
|
64
|
+
readonly x: number;
|
|
65
|
+
readonly y: number;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* @internal
|
|
69
|
+
*/
|
|
70
|
+
interface Line {
|
|
71
|
+
readonly p1: Point;
|
|
72
|
+
readonly p2: Point;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* An interface matching the internal ProseMirror implementation.
|
|
76
|
+
*
|
|
77
|
+
* See https://github.com/ProseMirror/prosemirror-view/blob/1.38.1/src/input.ts#L657
|
|
78
|
+
*
|
|
79
|
+
* @internal
|
|
80
|
+
*/
|
|
81
|
+
interface ViewDragging {
|
|
82
|
+
readonly slice: Slice;
|
|
83
|
+
readonly move: boolean;
|
|
84
|
+
readonly node?: NodeSelection;
|
|
85
|
+
}
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region src/drop-indicator/drop-indicator-facet.d.ts
|
|
88
|
+
/**
|
|
89
|
+
* @internal
|
|
90
|
+
*/
|
|
91
|
+
interface DropIndicatorPayload {
|
|
92
|
+
/**
|
|
93
|
+
* A callback that is called when the drop indicator should be shown.
|
|
94
|
+
*/
|
|
95
|
+
onShow?: ShowHandler;
|
|
96
|
+
/**
|
|
97
|
+
* A callback that is called when the drop indicator should be hidden.
|
|
98
|
+
*/
|
|
99
|
+
onHide?: VoidFunction;
|
|
100
|
+
/**
|
|
101
|
+
* A callback that is called when the `dragover` event is fired. You can
|
|
102
|
+
* return `false` to disable the current drop point and thus hide the drop
|
|
103
|
+
* indicator.
|
|
104
|
+
*/
|
|
105
|
+
onDrag?: DragEventHandler;
|
|
106
|
+
}
|
|
107
|
+
//#endregion
|
|
108
|
+
//#region src/drop-indicator/drop-indicator.d.ts
|
|
109
|
+
/**
|
|
110
|
+
* @internal
|
|
111
|
+
*/
|
|
112
|
+
type DropIndicatorExtension = PlainExtension;
|
|
113
|
+
/**
|
|
114
|
+
* Defines an extension that controls the behavior of the drop indicator.
|
|
115
|
+
*
|
|
116
|
+
* This extension itself doesn't draw the drop indicator, but it provides the
|
|
117
|
+
* necessary callbacks to do so. You probably don't want to use this extension
|
|
118
|
+
* directly, but rather use the `<DropIndicator>` component.
|
|
119
|
+
*
|
|
120
|
+
* You can add this extension multiple times. If any extension has `onDrag`
|
|
121
|
+
* callback defined, and it returns `false`, then the drop point will be
|
|
122
|
+
* discarded.
|
|
123
|
+
*
|
|
124
|
+
* @public
|
|
125
|
+
*/
|
|
126
|
+
declare function defineDropIndicator(options?: DropIndicatorOptions): DropIndicatorExtension;
|
|
127
|
+
/**
|
|
128
|
+
* Options for {@link defineDropIndicator}.
|
|
129
|
+
*
|
|
130
|
+
* @public
|
|
131
|
+
*/
|
|
132
|
+
interface DropIndicatorOptions extends DropIndicatorPayload {}
|
|
133
|
+
//#endregion
|
|
134
|
+
export { type DragEventHandler, type DragEventHandlerOptions, type DropIndicatorExtension, type DropIndicatorOptions, type Line, type Point, type ShowHandler, type ShowHandlerOptions, type ViewDragging, defineDropIndicator };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineInputRule } from "./input-rule-Gji4N7Oe.js";
|
|
2
2
|
import { defineEnterRule } from "./enter-rule-RdhEA900.js";
|
|
3
|
-
import { defineMarkRule } from "./mark-rule-
|
|
3
|
+
import { defineMarkRule } from "./mark-rule-D7zaa32n.js";
|
|
4
4
|
import { addMark, defineCommands, defineMarkSpec, expandMark, removeMark, toggleMark, union } from "@prosekit/core";
|
|
5
5
|
import { InputRule } from "@prosekit/pm/inputrules";
|
|
6
6
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { defineInputRule } from "./input-rule-Gji4N7Oe.js";
|
|
2
|
+
import { defineDropIndicator } from "./drop-indicator-QKkPzJIx.js";
|
|
2
3
|
import { defineClipboardSerializer, defineCommands, defineKeymap, defineNodeSpec, definePlugin, insertNode, union } from "@prosekit/core";
|
|
3
4
|
import { Plugin } from "@prosekit/pm/state";
|
|
4
5
|
import { chainCommands, deleteSelection } from "@prosekit/pm/commands";
|
|
5
|
-
import { ListDOMSerializer, createDedentListCommand, createIndentListCommand, createListEventPlugin, createListRenderingPlugin, createListSpec, createMoveListCommand, createSafariInputMethodWorkaroundPlugin, createSplitListCommand, createToggleCollapsedCommand, createToggleListCommand, createUnwrapListCommand, createWrapInListCommand, deleteCommand, enterCommand, joinCollapsedListBackward, joinListElements, joinListUp, listInputRules, listToDOM, protectCollapsed, unwrapListSlice } from "prosemirror-flat-list";
|
|
6
6
|
import { isElementLike } from "@ocavue/utils";
|
|
7
|
+
import { ListDOMSerializer, createDedentListCommand, createIndentListCommand, createListEventPlugin, createListRenderingPlugin, createListSpec, createMoveListCommand, createSafariInputMethodWorkaroundPlugin, createSplitListCommand, createToggleCollapsedCommand, createToggleListCommand, createUnwrapListCommand, createWrapInListCommand, deleteCommand, enterCommand, joinCollapsedListBackward, joinListElements, joinListUp, listInputRules, listToDOM, protectCollapsed, unwrapListSlice } from "prosemirror-flat-list";
|
|
7
8
|
|
|
8
9
|
//#region src/list/list-commands.ts
|
|
9
10
|
function insertList(attrs) {
|
|
@@ -31,6 +32,31 @@ function defineListCommands() {
|
|
|
31
32
|
});
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/list/list-drop-indicator.ts
|
|
37
|
+
/**
|
|
38
|
+
* Configures drop indicator to avoid unexpected drop point.
|
|
39
|
+
*
|
|
40
|
+
* We don't want to drag a list node and drop it as the first
|
|
41
|
+
* child of another list node.
|
|
42
|
+
*
|
|
43
|
+
* @internal
|
|
44
|
+
*/
|
|
45
|
+
function defineListDropIndicator() {
|
|
46
|
+
return defineDropIndicator({ onDrag });
|
|
47
|
+
}
|
|
48
|
+
const onDrag = ({ view, pos }) => {
|
|
49
|
+
const slice = view.dragging?.slice;
|
|
50
|
+
if (slice && slice.openStart === 0 && slice.openEnd === 0 && slice.content.childCount === 1) {
|
|
51
|
+
const node = slice.content.child(0);
|
|
52
|
+
if (node.type.name === "list") {
|
|
53
|
+
const $pos = view.state.doc.resolve(pos);
|
|
54
|
+
if ($pos.parent.type.name === "list" && $pos.index() === 0) return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return true;
|
|
58
|
+
};
|
|
59
|
+
|
|
34
60
|
//#endregion
|
|
35
61
|
//#region src/list/list-input-rules.ts
|
|
36
62
|
/**
|
|
@@ -120,12 +146,29 @@ function defineListSerializer() {
|
|
|
120
146
|
|
|
121
147
|
//#endregion
|
|
122
148
|
//#region src/list/list-spec.ts
|
|
149
|
+
function getMarkers(node) {
|
|
150
|
+
const attrs = node.attrs;
|
|
151
|
+
switch (attrs.kind) {
|
|
152
|
+
case "task": return [["label", ["input", {
|
|
153
|
+
type: "checkbox",
|
|
154
|
+
checked: attrs.checked ? "" : void 0
|
|
155
|
+
}]]];
|
|
156
|
+
default: return [];
|
|
157
|
+
}
|
|
158
|
+
}
|
|
123
159
|
/**
|
|
124
160
|
* @internal
|
|
125
161
|
*/
|
|
126
162
|
function defineListSpec() {
|
|
163
|
+
const spec = createListSpec();
|
|
127
164
|
return defineNodeSpec({
|
|
128
|
-
...
|
|
165
|
+
...spec,
|
|
166
|
+
toDOM: (node) => {
|
|
167
|
+
return listToDOM({
|
|
168
|
+
node,
|
|
169
|
+
getMarkers
|
|
170
|
+
});
|
|
171
|
+
},
|
|
129
172
|
name: "list"
|
|
130
173
|
});
|
|
131
174
|
}
|
|
@@ -136,7 +179,7 @@ function defineListSpec() {
|
|
|
136
179
|
* @public
|
|
137
180
|
*/
|
|
138
181
|
function defineList() {
|
|
139
|
-
return union(defineListSpec(), defineListPlugins(), defineListKeymap(), defineListInputRules(), defineListCommands(), defineListSerializer());
|
|
182
|
+
return union(defineListSpec(), defineListPlugins(), defineListKeymap(), defineListInputRules(), defineListCommands(), defineListSerializer(), defineListDropIndicator());
|
|
140
183
|
}
|
|
141
184
|
|
|
142
185
|
//#endregion
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { findTable } from "./table-
|
|
1
|
+
import { findTable } from "./table-3rDWFyBH.js";
|
|
2
2
|
import { definePlugin, isInCodeBlock, maybeRun } from "@prosekit/core";
|
|
3
3
|
import { Plugin, PluginKey } from "@prosekit/pm/state";
|
|
4
4
|
import { Decoration, DecorationSet } from "@prosekit/pm/view";
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { defineTable, defineTableCellSpec, defineTableCommands, defineTableHeaderCellSpec, defineTablePlugins, defineTableRowSpec, defineTableSpec, exitTable, findTable, insertTable, isCellSelection, moveTableColumn, moveTableRow, selectTable, selectTableCell, selectTableColumn, selectTableRow } from "./table-
|
|
1
|
+
import { defineTable, defineTableCellSpec, defineTableCommands, defineTableHeaderCellSpec, defineTablePlugins, defineTableRowSpec, defineTableSpec, exitTable, findTable, insertTable, isCellSelection, moveTableColumn, moveTableRow, selectTable, selectTableCell, selectTableColumn, selectTableRow } from "./table-3rDWFyBH.js";
|
|
2
2
|
|
|
3
3
|
export { defineTable, defineTableCellSpec, defineTableCommands, defineTableHeaderCellSpec, defineTablePlugins, defineTableRowSpec, defineTableSpec, exitTable, findTable, insertTable, isCellSelection, moveTableColumn, moveTableRow, selectTable, selectTableCell, selectTableColumn, selectTableRow };
|
|
@@ -48,7 +48,7 @@ const virtualSelectionPlugin = new ProseMirrorPlugin({
|
|
|
48
48
|
},
|
|
49
49
|
decorations: (state) => {
|
|
50
50
|
const { selection, doc } = state;
|
|
51
|
-
if (selection.empty || !getFocusState(state)) return null;
|
|
51
|
+
if (selection.empty || !getFocusState(state) || !selection.visible) return null;
|
|
52
52
|
return DecorationSet.create(doc, [Decoration.inline(selection.from, selection.to, { class: "prosekit-virtual-selection" })]);
|
|
53
53
|
}
|
|
54
54
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { HighlighterOptions, HighlighterResult, ShikiHighlighterOptions, createOrGetHighlighter } from "./shiki-highlighter-chunk-
|
|
1
|
+
import { HighlighterOptions, HighlighterResult, ShikiHighlighterOptions, createOrGetHighlighter } from "./shiki-highlighter-chunk-NV2F_Qjl.js";
|
|
2
2
|
export { HighlighterOptions, HighlighterResult, ShikiHighlighterOptions, createOrGetHighlighter };
|
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.11.1",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "A collection of common extensions for ProseKit",
|
|
7
7
|
"author": {
|
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
},
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"funding": "https://github.com/sponsors/ocavue",
|
|
13
|
-
"homepage": "https://github.com/
|
|
13
|
+
"homepage": "https://github.com/prosekit/prosekit#readme",
|
|
14
14
|
"repository": {
|
|
15
15
|
"type": "git",
|
|
16
|
-
"url": "git+https://github.com/
|
|
16
|
+
"url": "git+https://github.com/prosekit/prosekit.git",
|
|
17
17
|
"directory": "packages/extensions"
|
|
18
18
|
},
|
|
19
19
|
"bugs": {
|
|
20
|
-
"url": "https://github.com/
|
|
20
|
+
"url": "https://github.com/prosekit/prosekit/issues"
|
|
21
21
|
},
|
|
22
22
|
"keywords": [
|
|
23
23
|
"ProseMirror"
|
|
@@ -65,6 +65,10 @@
|
|
|
65
65
|
"types": "./dist/prosekit-extensions-drop-cursor.d.ts",
|
|
66
66
|
"default": "./dist/prosekit-extensions-drop-cursor.js"
|
|
67
67
|
},
|
|
68
|
+
"./drop-indicator": {
|
|
69
|
+
"types": "./dist/prosekit-extensions-drop-indicator.d.ts",
|
|
70
|
+
"default": "./dist/prosekit-extensions-drop-indicator.js"
|
|
71
|
+
},
|
|
68
72
|
"./enter-rule": {
|
|
69
73
|
"types": "./dist/prosekit-extensions-enter-rule.d.ts",
|
|
70
74
|
"default": "./dist/prosekit-extensions-enter-rule.js"
|
|
@@ -198,7 +202,7 @@
|
|
|
198
202
|
"dist"
|
|
199
203
|
],
|
|
200
204
|
"dependencies": {
|
|
201
|
-
"@ocavue/utils": "^0.
|
|
205
|
+
"@ocavue/utils": "^0.6.0",
|
|
202
206
|
"prosemirror-changeset": "^2.3.1",
|
|
203
207
|
"prosemirror-dropcursor": "^1.8.2",
|
|
204
208
|
"prosemirror-flat-list": "^0.5.5",
|
|
@@ -206,9 +210,9 @@
|
|
|
206
210
|
"prosemirror-highlight": "^0.13.0",
|
|
207
211
|
"prosemirror-search": "^1.1.0",
|
|
208
212
|
"prosemirror-tables": "^1.7.1",
|
|
209
|
-
"shiki": "^3.
|
|
210
|
-
"@prosekit/
|
|
211
|
-
"@prosekit/
|
|
213
|
+
"shiki": "^3.9.1",
|
|
214
|
+
"@prosekit/pm": "^0.1.11",
|
|
215
|
+
"@prosekit/core": "^0.8.3"
|
|
212
216
|
},
|
|
213
217
|
"peerDependencies": {
|
|
214
218
|
"loro-crdt": ">= 0.16.7",
|
|
@@ -242,7 +246,7 @@
|
|
|
242
246
|
"remark-html": "^16.0.1",
|
|
243
247
|
"remark-parse": "^11.0.0",
|
|
244
248
|
"remark-stringify": "^11.0.0",
|
|
245
|
-
"tsdown": "^0.13.
|
|
249
|
+
"tsdown": "^0.13.1",
|
|
246
250
|
"type-fest": "^4.41.0",
|
|
247
251
|
"typescript": "~5.8.3",
|
|
248
252
|
"unified": "^11.0.5",
|
|
@@ -268,6 +272,7 @@
|
|
|
268
272
|
"commit/style": "./src/commit/style.css",
|
|
269
273
|
"prosekit-extensions-doc": "./src/doc/index.ts",
|
|
270
274
|
"prosekit-extensions-drop-cursor": "./src/drop-cursor/index.ts",
|
|
275
|
+
"prosekit-extensions-drop-indicator": "./src/drop-indicator/index.ts",
|
|
271
276
|
"prosekit-extensions-enter-rule": "./src/enter-rule/index.ts",
|
|
272
277
|
"prosekit-extensions-file": "./src/file/index.ts",
|
|
273
278
|
"prosekit-extensions-gap-cursor": "./src/gap-cursor/index.ts",
|
|
@@ -338,6 +343,9 @@
|
|
|
338
343
|
"drop-cursor": [
|
|
339
344
|
"./dist/prosekit-extensions-drop-cursor.d.ts"
|
|
340
345
|
],
|
|
346
|
+
"drop-indicator": [
|
|
347
|
+
"./dist/prosekit-extensions-drop-indicator.d.ts"
|
|
348
|
+
],
|
|
341
349
|
"enter-rule": [
|
|
342
350
|
"./dist/prosekit-extensions-enter-rule.d.ts"
|
|
343
351
|
],
|
|
File without changes
|
/package/dist/{shiki-highlighter-chunk-CZGvZlhf.d.ts → shiki-highlighter-chunk-NV2F_Qjl.d.ts}
RENAMED
|
File without changes
|
|
File without changes
|