@pixerate/editor 0.19.0 → 0.21.0
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/README.md +95 -4
- package/dist/agent/index.cjs +625 -2
- package/dist/agent/index.cjs.map +1 -1
- package/dist/agent/index.d.cts +286 -2
- package/dist/agent/index.d.ts +286 -2
- package/dist/agent/index.js +624 -1
- package/dist/agent/index.js.map +1 -1
- package/dist/canvas/index.cjs +1240 -22
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +515 -3
- package/dist/canvas/index.d.ts +515 -3
- package/dist/canvas/index.js +1219 -1
- package/dist/canvas/index.js.map +1 -1
- package/dist/chunk-3TYMNULT.js +1367 -0
- package/dist/chunk-3TYMNULT.js.map +1 -0
- package/dist/chunk-4QPLEUL2.cjs +4480 -0
- package/dist/chunk-4QPLEUL2.cjs.map +1 -0
- package/dist/chunk-4SUNJZWB.cjs +553 -0
- package/dist/chunk-4SUNJZWB.cjs.map +1 -0
- package/dist/chunk-A7DKIA72.js +2657 -0
- package/dist/chunk-A7DKIA72.js.map +1 -0
- package/dist/chunk-AXV2ZW34.cjs +118 -0
- package/dist/chunk-AXV2ZW34.cjs.map +1 -0
- package/dist/chunk-B2ZRLN4S.js +118 -0
- package/dist/chunk-B2ZRLN4S.js.map +1 -0
- package/dist/chunk-CYFJCKC4.js +4480 -0
- package/dist/chunk-CYFJCKC4.js.map +1 -0
- package/dist/chunk-GVW4P7BG.js +2706 -0
- package/dist/chunk-GVW4P7BG.js.map +1 -0
- package/dist/chunk-JACER6TE.cjs +1 -0
- package/dist/chunk-JACER6TE.cjs.map +1 -0
- package/dist/chunk-JYRIOFEN.cjs +2657 -0
- package/dist/chunk-JYRIOFEN.cjs.map +1 -0
- package/dist/chunk-KYRZDWM4.js +299 -0
- package/dist/chunk-KYRZDWM4.js.map +1 -0
- package/dist/chunk-LA7PEGU3.cjs +299 -0
- package/dist/chunk-LA7PEGU3.cjs.map +1 -0
- package/dist/chunk-N7FG6CBO.js +1 -0
- package/dist/chunk-N7FG6CBO.js.map +1 -0
- package/dist/chunk-OYXSKQFR.js +553 -0
- package/dist/chunk-OYXSKQFR.js.map +1 -0
- package/dist/chunk-TVRC4KVT.cjs +1367 -0
- package/dist/chunk-TVRC4KVT.cjs.map +1 -0
- package/dist/chunk-U6NDQFOK.cjs +2706 -0
- package/dist/chunk-U6NDQFOK.cjs.map +1 -0
- package/dist/controller-OUdxPY-X.d.cts +754 -0
- package/dist/controller-OUdxPY-X.d.ts +754 -0
- package/dist/extensions/index.cjs +144 -3
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.d.cts +9 -144
- package/dist/extensions/index.d.ts +9 -144
- package/dist/extensions/index.js +145 -4
- package/dist/grammar/index.cjs +31 -3
- package/dist/grammar/index.cjs.map +1 -1
- package/dist/grammar/index.d.cts +239 -19
- package/dist/grammar/index.d.ts +239 -19
- package/dist/grammar/index.js +31 -3
- package/dist/history/index.d.cts +2 -41
- package/dist/history/index.d.ts +2 -41
- package/dist/index-Ng1pG7JE.d.ts +899 -0
- package/dist/index-k3mFbPx_.d.cts +899 -0
- package/dist/index.cjs +457 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +99 -12
- package/dist/index.d.ts +99 -12
- package/dist/index.js +457 -20
- package/dist/index.js.map +1 -1
- package/dist/registry-iAHbqkYt.d.cts +128 -0
- package/dist/registry-iAHbqkYt.d.ts +128 -0
- package/dist/serializers/index.cjs +26 -3
- package/dist/serializers/index.cjs.map +1 -1
- package/dist/serializers/index.d.cts +119 -6
- package/dist/serializers/index.d.ts +119 -6
- package/dist/serializers/index.js +24 -1
- package/dist/spreadsheet/index.cjs +122 -2
- package/dist/spreadsheet/index.cjs.map +1 -1
- package/dist/spreadsheet/index.d.cts +371 -313
- package/dist/spreadsheet/index.d.ts +371 -313
- package/dist/spreadsheet/index.js +127 -7
- package/dist/tokens-CyLZmIei.d.cts +76 -0
- package/dist/tokens-CyLZmIei.d.ts +76 -0
- package/dist/track-changes-G8JcWB8b.d.cts +306 -0
- package/dist/track-changes-G8JcWB8b.d.ts +306 -0
- package/dist/types-BZgcDsC5.d.cts +42 -0
- package/dist/types-BZgcDsC5.d.ts +42 -0
- package/dist/{types-JV3S8VeR.d.cts → types-DMe0vFB1.d.cts} +1 -1
- package/dist/{types-JV3S8VeR.d.ts → types-DMe0vFB1.d.ts} +1 -1
- package/package.json +11 -4
- package/dist/chunk-7FWEWE6T.js +0 -1888
- package/dist/chunk-7FWEWE6T.js.map +0 -1
- package/dist/chunk-AIZUKWTL.js +0 -1715
- package/dist/chunk-AIZUKWTL.js.map +0 -1
- package/dist/chunk-GLSIZKOX.js +0 -17
- package/dist/chunk-GLSIZKOX.js.map +0 -1
- package/dist/chunk-LDES3EOS.cjs +0 -1888
- package/dist/chunk-LDES3EOS.cjs.map +0 -1
- package/dist/chunk-LLUAKTLW.cjs +0 -532
- package/dist/chunk-LLUAKTLW.cjs.map +0 -1
- package/dist/chunk-MPPXH7U5.cjs +0 -336
- package/dist/chunk-MPPXH7U5.cjs.map +0 -1
- package/dist/chunk-O7LOPQMH.js +0 -336
- package/dist/chunk-O7LOPQMH.js.map +0 -1
- package/dist/chunk-QGVMBCT5.js +0 -532
- package/dist/chunk-QGVMBCT5.js.map +0 -1
- package/dist/chunk-SEDR75VH.cjs +0 -17
- package/dist/chunk-SEDR75VH.cjs.map +0 -1
- package/dist/chunk-YQCI4CCN.cjs +0 -1715
- package/dist/chunk-YQCI4CCN.cjs.map +0 -1
- package/dist/mention-Dcevh3ff.d.cts +0 -32
- package/dist/mention-Dcevh3ff.d.ts +0 -32
- package/dist/tokens-7kRTEtPb.d.cts +0 -39
- package/dist/tokens-7kRTEtPb.d.ts +0 -39
|
@@ -0,0 +1,4480 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class;
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
var _chunkAXV2ZW34cjs = require('./chunk-AXV2ZW34.cjs');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
var _chunkLA7PEGU3cjs = require('./chunk-LA7PEGU3.cjs');
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
var _chunkTVRC4KVTcjs = require('./chunk-TVRC4KVT.cjs');
|
|
25
|
+
|
|
26
|
+
// src/extensions/gradient-text.ts
|
|
27
|
+
var _core = require('@tiptap/core');
|
|
28
|
+
var _state = require('@tiptap/pm/state');
|
|
29
|
+
var _view2 = require('@tiptap/pm/view');
|
|
30
|
+
var createGradientDecorations = (doc, options) => {
|
|
31
|
+
const decorations = [];
|
|
32
|
+
const speed = _nullishCoalesce(options.speed, () => ( 1));
|
|
33
|
+
const jsonVarSet = options.jsonVariables ? options.jsonVariables instanceof Set ? options.jsonVariables : new Set(options.jsonVariables) : null;
|
|
34
|
+
const conditionalTags = [];
|
|
35
|
+
doc.descendants((node, pos) => {
|
|
36
|
+
if (node.isText) {
|
|
37
|
+
const text = node.text || "";
|
|
38
|
+
let match;
|
|
39
|
+
const tmplRegex = new RegExp(_chunkAXV2ZW34cjs.TEMPLATE_REGEX.source, _chunkAXV2ZW34cjs.TEMPLATE_REGEX.flags);
|
|
40
|
+
while ((match = tmplRegex.exec(text)) !== null) {
|
|
41
|
+
const templateName = match[1].trim();
|
|
42
|
+
const colors = _optionalChain([options, 'access', _2 => _2.templateColorMap, 'optionalAccess', _3 => _3.get, 'call', _4 => _4(templateName)]);
|
|
43
|
+
if (colors) {
|
|
44
|
+
const start2 = pos + match.index;
|
|
45
|
+
const end = start2 + match[0].length;
|
|
46
|
+
const { from: colorFrom, to: colorTo } = colors;
|
|
47
|
+
const style = `--bg-size: ${speed * 300}%; --color-from: ${colorFrom}; --color-to: ${colorTo}; caret-color: #111 !important; background-image: linear-gradient(to right, ${colorFrom}, ${colorTo}, ${colorFrom}); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; color: transparent;`;
|
|
48
|
+
decorations.push(
|
|
49
|
+
_view2.Decoration.inline(start2, end, {
|
|
50
|
+
class: "inline animate-gradient bg-gradient-to-r from-[var(--color-from)] via-[var(--color-to)] to-[var(--color-from)] bg-[length:var(--bg-size)_100%] bg-clip-text text-transparent border border-(--color-to)/20 px-1 py-0.5 rounded-sm cursor-pointer",
|
|
51
|
+
style,
|
|
52
|
+
"data-template": templateName
|
|
53
|
+
})
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const instRegex = new RegExp(
|
|
58
|
+
_chunkAXV2ZW34cjs.INSTRUCTION_REGEX.source,
|
|
59
|
+
_chunkAXV2ZW34cjs.INSTRUCTION_REGEX.flags
|
|
60
|
+
);
|
|
61
|
+
while ((match = instRegex.exec(text)) !== null) {
|
|
62
|
+
const content = match[1].trim();
|
|
63
|
+
const colors = _optionalChain([options, 'access', _5 => _5.templateColorMap, 'optionalAccess', _6 => _6.get, 'call', _7 => _7(content)]) || {
|
|
64
|
+
from: "#ffaa40",
|
|
65
|
+
to: "#9c40ff"
|
|
66
|
+
};
|
|
67
|
+
const start2 = pos + match.index;
|
|
68
|
+
const end = start2 + match[0].length;
|
|
69
|
+
const { from: colorFrom, to: colorTo } = colors;
|
|
70
|
+
const style = `--bg-size: ${speed * 300}%; --color-from: ${colorFrom}; --color-to: ${colorTo}; caret-color: #111 !important; background-image: linear-gradient(to right, #fb7185, #8b5cf6, #fb7185); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; color: transparent;`;
|
|
71
|
+
decorations.push(
|
|
72
|
+
_view2.Decoration.inline(start2, end, {
|
|
73
|
+
class: "italic animate-gradient bg-gradient-to-r from-rose-400 from-50% to-violet-500 to-50% bg-size-[200%_100%] bg-clip-text text-transparent inline-flex items-baseline gap-0.5",
|
|
74
|
+
style
|
|
75
|
+
})
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
const varRegex = new RegExp(
|
|
79
|
+
_chunkAXV2ZW34cjs.VARIABLE_REGEX.source,
|
|
80
|
+
_chunkAXV2ZW34cjs.VARIABLE_REGEX.flags
|
|
81
|
+
);
|
|
82
|
+
while ((match = varRegex.exec(text)) !== null) {
|
|
83
|
+
const parsed = _chunkAXV2ZW34cjs.parseVariableBody.call(void 0, match[1]);
|
|
84
|
+
const start2 = pos + match.index;
|
|
85
|
+
const end = start2 + match[0].length;
|
|
86
|
+
if (parsed.kind === "conditional") {
|
|
87
|
+
conditionalTags.push({
|
|
88
|
+
conditional: parsed.conditional,
|
|
89
|
+
name: parsed.name,
|
|
90
|
+
start: start2,
|
|
91
|
+
end
|
|
92
|
+
});
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const variableName = parsed.name;
|
|
96
|
+
const isJsonVar = _optionalChain([jsonVarSet, 'optionalAccess', _8 => _8.has, 'call', _9 => _9(variableName)]);
|
|
97
|
+
const attrs = {
|
|
98
|
+
class: isJsonVar ? "bg-violet-400/40 border-b-4 border-rose-300 dark:border-rose-800 inline-flex items-baseline px-1 py-0 text-foreground/80 gap-0.5 rounded-xs" : "bg-rose-400/40 border-b-4 border-violet-300 dark:border-violet-800 inline-flex items-baseline px-1 py-0 text-foreground/80 gap-0.5 rounded-xs",
|
|
99
|
+
"data-variable": variableName
|
|
100
|
+
};
|
|
101
|
+
if (parsed.defaultValue !== void 0) {
|
|
102
|
+
attrs.class += " border-dashed";
|
|
103
|
+
attrs["data-default"] = parsed.defaultValue;
|
|
104
|
+
}
|
|
105
|
+
if (parsed.description !== void 0) {
|
|
106
|
+
attrs["data-description"] = parsed.description;
|
|
107
|
+
}
|
|
108
|
+
const title = [
|
|
109
|
+
parsed.description,
|
|
110
|
+
parsed.defaultValue !== void 0 ? `Default: ${parsed.defaultValue || "(empty)"}` : void 0
|
|
111
|
+
].filter(Boolean).join(" \xB7 ");
|
|
112
|
+
if (title) attrs.title = title;
|
|
113
|
+
decorations.push(_view2.Decoration.inline(start2, end, attrs));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
_chunkAXV2ZW34cjs.matchConditionalTags.call(void 0, conditionalTags).forEach((result, i) => {
|
|
118
|
+
const tag = conditionalTags[i];
|
|
119
|
+
decorations.push(
|
|
120
|
+
_view2.Decoration.inline(
|
|
121
|
+
tag.start,
|
|
122
|
+
tag.end,
|
|
123
|
+
result.error ? {
|
|
124
|
+
class: "underline decoration-wavy decoration-red-500 text-red-600 dark:text-red-400",
|
|
125
|
+
"data-conditional-error": result.error,
|
|
126
|
+
title: result.error === "unclosed-section" ? `Section "${tag.name}" is never closed with {/${tag.name}}` : `{/${tag.name}} does not close any open section`
|
|
127
|
+
} : {
|
|
128
|
+
class: "bg-amber-400/30 text-amber-700 dark:text-amber-300 font-medium px-0.5 rounded-xs",
|
|
129
|
+
"data-conditional": tag.conditional,
|
|
130
|
+
"data-variable-condition": tag.name
|
|
131
|
+
}
|
|
132
|
+
)
|
|
133
|
+
);
|
|
134
|
+
});
|
|
135
|
+
return decorations;
|
|
136
|
+
};
|
|
137
|
+
var GradientText = _core.Mark.create({
|
|
138
|
+
name: "gradientText",
|
|
139
|
+
addOptions() {
|
|
140
|
+
return {
|
|
141
|
+
templateColorMap: /* @__PURE__ */ new Map(),
|
|
142
|
+
speed: 1,
|
|
143
|
+
jsonVariables: void 0,
|
|
144
|
+
onTemplateClick: void 0
|
|
145
|
+
};
|
|
146
|
+
},
|
|
147
|
+
renderHTML({ HTMLAttributes }) {
|
|
148
|
+
const defaultColors = {
|
|
149
|
+
from: "#ffaa40",
|
|
150
|
+
to: "#9c40ff"
|
|
151
|
+
};
|
|
152
|
+
const speed = _nullishCoalesce(this.options.speed, () => ( 1));
|
|
153
|
+
const style = `--bg-size: ${speed * 300}%; --color-from: ${defaultColors.from}; --color-to: ${defaultColors.to}; caret-color: #111 !important;`;
|
|
154
|
+
return [
|
|
155
|
+
"span",
|
|
156
|
+
{
|
|
157
|
+
class: "inline animate-gradient bg-gradient-to-r from-[var(--color-from)] via-[var(--color-to)] to-[var(--color-from)] bg-[length:var(--bg-size)_100%] bg-clip-text text-transparent",
|
|
158
|
+
style,
|
|
159
|
+
...HTMLAttributes
|
|
160
|
+
},
|
|
161
|
+
0
|
|
162
|
+
];
|
|
163
|
+
},
|
|
164
|
+
parseHTML() {
|
|
165
|
+
return [
|
|
166
|
+
{
|
|
167
|
+
tag: "span",
|
|
168
|
+
getAttrs: (node) => node.classList.contains("animate-gradient") && node.classList.contains("bg-clip-text") && null
|
|
169
|
+
}
|
|
170
|
+
];
|
|
171
|
+
},
|
|
172
|
+
addProseMirrorPlugins() {
|
|
173
|
+
const markOptions = this.options;
|
|
174
|
+
return [
|
|
175
|
+
new (0, _state.Plugin)({
|
|
176
|
+
state: {
|
|
177
|
+
init(_, { doc }) {
|
|
178
|
+
return _view2.DecorationSet.create(
|
|
179
|
+
doc,
|
|
180
|
+
createGradientDecorations(doc, markOptions)
|
|
181
|
+
);
|
|
182
|
+
},
|
|
183
|
+
apply(tr, value) {
|
|
184
|
+
const newDoc = tr.doc;
|
|
185
|
+
if (tr.docChanged) {
|
|
186
|
+
return _view2.DecorationSet.create(
|
|
187
|
+
newDoc,
|
|
188
|
+
createGradientDecorations(newDoc, markOptions)
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
return value.map(tr.mapping, newDoc);
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
props: {
|
|
195
|
+
decorations(state) {
|
|
196
|
+
return this.getState(state);
|
|
197
|
+
},
|
|
198
|
+
handleClickOn(view, pos, _node, _nodePos, event) {
|
|
199
|
+
const decorationSet = this.getState(
|
|
200
|
+
view.state
|
|
201
|
+
);
|
|
202
|
+
const decorations = decorationSet.find(pos, pos + 1);
|
|
203
|
+
for (const decoration of decorations) {
|
|
204
|
+
const decorationWithAttrs = decoration;
|
|
205
|
+
const templateName = _optionalChain([decorationWithAttrs, 'access', _10 => _10.type, 'optionalAccess', _11 => _11.attrs, 'optionalAccess', _12 => _12["data-template"]]);
|
|
206
|
+
if (templateName) {
|
|
207
|
+
if (markOptions.onTemplateClick) {
|
|
208
|
+
markOptions.onTemplateClick(templateName, event);
|
|
209
|
+
}
|
|
210
|
+
if (typeof window !== "undefined") {
|
|
211
|
+
window.dispatchEvent(
|
|
212
|
+
new CustomEvent("show-gradient-popover", {
|
|
213
|
+
detail: {
|
|
214
|
+
templateName,
|
|
215
|
+
target: event.target
|
|
216
|
+
}
|
|
217
|
+
})
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
})
|
|
227
|
+
];
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// src/extensions/slash-commands.ts
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
var SlashCommands = _core.Extension.create({
|
|
235
|
+
name: "slashCommands",
|
|
236
|
+
addOptions() {
|
|
237
|
+
return {
|
|
238
|
+
trigger: "/",
|
|
239
|
+
onMatch: void 0,
|
|
240
|
+
onClear: void 0,
|
|
241
|
+
containerId: void 0
|
|
242
|
+
};
|
|
243
|
+
},
|
|
244
|
+
addProseMirrorPlugins() {
|
|
245
|
+
const opts = this.options;
|
|
246
|
+
return [
|
|
247
|
+
new (0, _state.Plugin)({
|
|
248
|
+
view() {
|
|
249
|
+
return {
|
|
250
|
+
update(view) {
|
|
251
|
+
const { state } = view;
|
|
252
|
+
const { selection } = state;
|
|
253
|
+
const { $from } = selection;
|
|
254
|
+
if (!$from.parent.isTextblock) {
|
|
255
|
+
_optionalChain([opts, 'access', _13 => _13.onClear, 'optionalCall', _14 => _14()]);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
const textBeforeCursor = $from.parent.textBetween(
|
|
259
|
+
0,
|
|
260
|
+
$from.parentOffset
|
|
261
|
+
);
|
|
262
|
+
const slashMatch = textBeforeCursor.match(
|
|
263
|
+
/(?:^|\s)\/([a-zA-Z0-9_-]*)$/
|
|
264
|
+
);
|
|
265
|
+
if (slashMatch) {
|
|
266
|
+
const matchIndex = _nullishCoalesce(slashMatch.index, () => ( 0));
|
|
267
|
+
const offsetInParent = matchIndex + (slashMatch[0].startsWith(" ") ? 1 : 0);
|
|
268
|
+
const matchFrom = $from.start() + offsetInParent;
|
|
269
|
+
const matchTo = $from.pos;
|
|
270
|
+
const coords = view.coordsAtPos($from.pos);
|
|
271
|
+
let relativeCoords = {
|
|
272
|
+
top: coords.top,
|
|
273
|
+
left: coords.left,
|
|
274
|
+
bottom: coords.bottom,
|
|
275
|
+
right: coords.right
|
|
276
|
+
};
|
|
277
|
+
if (opts.containerId && typeof document !== "undefined") {
|
|
278
|
+
const container = document.getElementById(opts.containerId);
|
|
279
|
+
if (container) {
|
|
280
|
+
const rect = container.getBoundingClientRect();
|
|
281
|
+
relativeCoords = {
|
|
282
|
+
top: coords.bottom - rect.top + 5,
|
|
283
|
+
left: coords.left - rect.left,
|
|
284
|
+
bottom: coords.bottom - rect.top,
|
|
285
|
+
right: coords.right - rect.left
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
_optionalChain([opts, 'access', _15 => _15.onMatch, 'optionalCall', _16 => _16({
|
|
290
|
+
match: slashMatch,
|
|
291
|
+
query: slashMatch[1] || "",
|
|
292
|
+
from: matchFrom,
|
|
293
|
+
to: matchTo,
|
|
294
|
+
coords: relativeCoords
|
|
295
|
+
})]);
|
|
296
|
+
} else {
|
|
297
|
+
_optionalChain([opts, 'access', _17 => _17.onClear, 'optionalCall', _18 => _18()]);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
})
|
|
303
|
+
];
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
// src/extensions/template-suggestions.ts
|
|
308
|
+
|
|
309
|
+
var _suggestion = require('@tiptap/suggestion'); var _suggestion2 = _interopRequireDefault(_suggestion);
|
|
310
|
+
var TemplateSuggestions = _core.Extension.create({
|
|
311
|
+
name: "templateSuggestions",
|
|
312
|
+
addOptions() {
|
|
313
|
+
return {
|
|
314
|
+
templates: [],
|
|
315
|
+
char: "{{",
|
|
316
|
+
onSuggestion: void 0
|
|
317
|
+
};
|
|
318
|
+
},
|
|
319
|
+
addProseMirrorPlugins() {
|
|
320
|
+
const opts = this.options;
|
|
321
|
+
const suggestionConfig = {
|
|
322
|
+
char: opts.char || "{{",
|
|
323
|
+
items: ({ query }) => {
|
|
324
|
+
const lower = query.toLowerCase();
|
|
325
|
+
return (opts.templates || []).filter(
|
|
326
|
+
(t) => t.name.toLowerCase().includes(lower)
|
|
327
|
+
);
|
|
328
|
+
},
|
|
329
|
+
command: ({ editor, range, props }) => {
|
|
330
|
+
editor.chain().focus().deleteRange(range).insertContent(`{{${props.name}}}`).run();
|
|
331
|
+
},
|
|
332
|
+
render: () => {
|
|
333
|
+
return {
|
|
334
|
+
onStart: (props) => {
|
|
335
|
+
_optionalChain([opts, 'access', _19 => _19.onSuggestion, 'optionalCall', _20 => _20(props)]);
|
|
336
|
+
},
|
|
337
|
+
onUpdate: (props) => {
|
|
338
|
+
_optionalChain([opts, 'access', _21 => _21.onSuggestion, 'optionalCall', _22 => _22(props)]);
|
|
339
|
+
},
|
|
340
|
+
onExit: () => {
|
|
341
|
+
_optionalChain([opts, 'access', _23 => _23.onSuggestion, 'optionalCall', _24 => _24({
|
|
342
|
+
query: "",
|
|
343
|
+
range: { from: 0, to: 0 },
|
|
344
|
+
items: [],
|
|
345
|
+
command: () => {
|
|
346
|
+
}
|
|
347
|
+
})]);
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
const SuggestionFn = typeof _suggestion2.default === "function" ? _suggestion2.default : _optionalChain([_suggestion2.default, 'optionalAccess', _25 => _25.default]) || _optionalChain([_suggestion2.default, 'optionalAccess', _26 => _26.Suggestion]);
|
|
353
|
+
return [
|
|
354
|
+
SuggestionFn({
|
|
355
|
+
editor: this.editor,
|
|
356
|
+
...suggestionConfig
|
|
357
|
+
})
|
|
358
|
+
];
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
// src/extensions/loading-node.ts
|
|
363
|
+
|
|
364
|
+
var LoadingNode = _core.Node.create({
|
|
365
|
+
name: "loadingNode",
|
|
366
|
+
group: "inline",
|
|
367
|
+
inline: true,
|
|
368
|
+
selectable: true,
|
|
369
|
+
atom: true,
|
|
370
|
+
addAttributes() {
|
|
371
|
+
return {
|
|
372
|
+
id: {
|
|
373
|
+
default: null,
|
|
374
|
+
parseHTML: (element) => element.getAttribute("data-id"),
|
|
375
|
+
renderHTML: (attributes) => {
|
|
376
|
+
if (!attributes.id) return {};
|
|
377
|
+
return { "data-id": attributes.id };
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
},
|
|
382
|
+
parseHTML() {
|
|
383
|
+
return [
|
|
384
|
+
{
|
|
385
|
+
tag: 'span[data-type="loading"]'
|
|
386
|
+
}
|
|
387
|
+
];
|
|
388
|
+
},
|
|
389
|
+
renderHTML({ HTMLAttributes }) {
|
|
390
|
+
return [
|
|
391
|
+
"span",
|
|
392
|
+
_core.mergeAttributes.call(void 0, HTMLAttributes, {
|
|
393
|
+
"data-type": "loading",
|
|
394
|
+
class: "inline-flex items-center px-1.5 py-0.5 text-xs text-muted-foreground animate-pulse"
|
|
395
|
+
}),
|
|
396
|
+
"\u23F3"
|
|
397
|
+
];
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
// src/extensions/SmilieReplacer.ts
|
|
402
|
+
|
|
403
|
+
var SMILIE_REPLACEMENTS = [
|
|
404
|
+
[/-___- $/, "\u{1F611} "],
|
|
405
|
+
[/:'-\) $/, "\u{1F602} "],
|
|
406
|
+
[/':-\) $/, "\u{1F605} "],
|
|
407
|
+
[/':-D $/, "\u{1F605} "],
|
|
408
|
+
[/>:-\) $/, "\u{1F606} "],
|
|
409
|
+
[/-__- $/, "\u{1F611} "],
|
|
410
|
+
[/':-\( $/, "\u{1F613} "],
|
|
411
|
+
[/:'-\( $/, "\u{1F622} "],
|
|
412
|
+
[/>:-\( $/, "\u{1F620} "],
|
|
413
|
+
[/O:-\) $/, "\u{1F607} "],
|
|
414
|
+
[/:'\) $/, "\u{1F602} "],
|
|
415
|
+
[/:-D $/, "\u{1F603} "],
|
|
416
|
+
[/':\) $/, "\u{1F605} "],
|
|
417
|
+
[/;-\) $/, "\u{1F609} "],
|
|
418
|
+
[/B-\) $/, "\u{1F60E} "],
|
|
419
|
+
[/:-\* $/, "\u{1F618} "],
|
|
420
|
+
[/:-\) $/, "\u{1F642} "],
|
|
421
|
+
[/-_- $/, "\u{1F611} "],
|
|
422
|
+
[/:-O $/, "\u{1F62E} "],
|
|
423
|
+
[/:-P $/, "\u{1F61B} "],
|
|
424
|
+
[/:-p $/, "\u{1F61B} "],
|
|
425
|
+
[/:-\/ $/, "\u{1F615} "],
|
|
426
|
+
[/:-\( $/, "\u{1F61E} "],
|
|
427
|
+
[/:'\( $/, "\u{1F622} "],
|
|
428
|
+
[/:D $/, "\u{1F603} "],
|
|
429
|
+
[/=D $/, "\u{1F603} "],
|
|
430
|
+
[/;\) $/, "\u{1F609} "],
|
|
431
|
+
[/B\) $/, "\u{1F60E} "],
|
|
432
|
+
[/:\) $/, "\u{1F642} "],
|
|
433
|
+
[/=\) $/, "\u{1F642} "],
|
|
434
|
+
[/:O $/, "\u{1F62E} "],
|
|
435
|
+
[/:P $/, "\u{1F61B} "],
|
|
436
|
+
[/:p $/, "\u{1F61B} "],
|
|
437
|
+
[/:\/ $/, "\u{1F615} "],
|
|
438
|
+
[/:\( $/, "\u{1F61E} "],
|
|
439
|
+
[/<3 $/, "\u2764\uFE0F "],
|
|
440
|
+
[/<\/3 $/, "\u{1F494} "],
|
|
441
|
+
[/\/shrug $/, "\xAF\\_(\u30C4)_/\xAF "]
|
|
442
|
+
];
|
|
443
|
+
var smilieAutocorrectRules = SMILIE_REPLACEMENTS.map(
|
|
444
|
+
([find, replace], index) => ({
|
|
445
|
+
id: `smilie:${index}`,
|
|
446
|
+
find: new RegExp(find.source.replace(/'/g, "['\u2018\u2019]"), find.flags),
|
|
447
|
+
replace
|
|
448
|
+
})
|
|
449
|
+
);
|
|
450
|
+
var SmilieReplacer = _core.Extension.create({
|
|
451
|
+
name: "smilieReplacer",
|
|
452
|
+
addInputRules() {
|
|
453
|
+
return SMILIE_REPLACEMENTS.map(
|
|
454
|
+
([find, replace]) => _core.textInputRule.call(void 0, { find, replace })
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
// src/extensions/ColorHighlighter.ts
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
function findHexColors(doc) {
|
|
464
|
+
const hexColorRegex = /(#[0-9a-fA-F]{3,8})\b/g;
|
|
465
|
+
const decorations = [];
|
|
466
|
+
doc.descendants((node, position) => {
|
|
467
|
+
if (!node.text) return;
|
|
468
|
+
let match;
|
|
469
|
+
while ((match = hexColorRegex.exec(node.text)) !== null) {
|
|
470
|
+
const color = match[0];
|
|
471
|
+
const from = position + match.index;
|
|
472
|
+
const to = from + color.length;
|
|
473
|
+
decorations.push(
|
|
474
|
+
_view2.Decoration.inline(from, to, {
|
|
475
|
+
class: "color-highlight px-1 py-0.5 rounded text-xs font-mono border",
|
|
476
|
+
style: `--color: ${color}; background-color: ${color}20; border-color: ${color}; color: ${color};`
|
|
477
|
+
})
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
});
|
|
481
|
+
return _view2.DecorationSet.create(doc, decorations);
|
|
482
|
+
}
|
|
483
|
+
var ColorHighlighter = _core.Extension.create({
|
|
484
|
+
name: "colorHighlighter",
|
|
485
|
+
addProseMirrorPlugins() {
|
|
486
|
+
return [
|
|
487
|
+
new (0, _state.Plugin)({
|
|
488
|
+
state: {
|
|
489
|
+
init(_, { doc }) {
|
|
490
|
+
return findHexColors(doc);
|
|
491
|
+
},
|
|
492
|
+
apply(transaction, oldState) {
|
|
493
|
+
return transaction.docChanged ? findHexColors(transaction.doc) : oldState;
|
|
494
|
+
}
|
|
495
|
+
},
|
|
496
|
+
props: {
|
|
497
|
+
decorations(state) {
|
|
498
|
+
return this.getState(state);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
})
|
|
502
|
+
];
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
// src/extensions/FontSize.ts
|
|
507
|
+
|
|
508
|
+
var _extensiontextstyle = require('@tiptap/extension-text-style'); var _TextStyle = _interopRequireWildcard(_extensiontextstyle);
|
|
509
|
+
var FontSize = _core.Extension.create({
|
|
510
|
+
name: "fontSize",
|
|
511
|
+
addOptions() {
|
|
512
|
+
return {
|
|
513
|
+
types: ["textStyle"]
|
|
514
|
+
};
|
|
515
|
+
},
|
|
516
|
+
addGlobalAttributes() {
|
|
517
|
+
return [
|
|
518
|
+
{
|
|
519
|
+
types: this.options.types,
|
|
520
|
+
attributes: {
|
|
521
|
+
fontSize: {
|
|
522
|
+
default: null,
|
|
523
|
+
parseHTML: (element) => element.style.fontSize.replace(/['"]+/g, ""),
|
|
524
|
+
renderHTML: (attributes) => {
|
|
525
|
+
if (!attributes.fontSize) {
|
|
526
|
+
return {};
|
|
527
|
+
}
|
|
528
|
+
return {
|
|
529
|
+
style: `font-size: ${attributes.fontSize}`
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
];
|
|
536
|
+
},
|
|
537
|
+
addCommands() {
|
|
538
|
+
return {
|
|
539
|
+
setFontSize: (fontSize) => ({ chain }) => chain().setMark("textStyle", { fontSize }).run(),
|
|
540
|
+
unsetFontSize: () => ({ chain }) => chain().setMark("textStyle", { fontSize: null }).removeEmptyTextStyle().run()
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
// src/extensions/rich-text-preset.ts
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
var _starterkit = require('@tiptap/starter-kit'); var _StarterKit = _interopRequireWildcard(_starterkit);
|
|
551
|
+
var _extensioncolor = require('@tiptap/extension-color'); var _Color = _interopRequireWildcard(_extensioncolor);
|
|
552
|
+
var _extensionhighlight = require('@tiptap/extension-highlight'); var _Highlight = _interopRequireWildcard(_extensionhighlight);
|
|
553
|
+
var _extensionlink = require('@tiptap/extension-link'); var _Link = _interopRequireWildcard(_extensionlink);
|
|
554
|
+
var _extensiontasklist = require('@tiptap/extension-task-list'); var _TaskList = _interopRequireWildcard(_extensiontasklist);
|
|
555
|
+
var _extensiontaskitem = require('@tiptap/extension-task-item'); var _TaskItem = _interopRequireWildcard(_extensiontaskitem);
|
|
556
|
+
var _extensiontextalign = require('@tiptap/extension-text-align'); var _TextAlign = _interopRequireWildcard(_extensiontextalign);
|
|
557
|
+
|
|
558
|
+
var _extensiontypography = require('@tiptap/extension-typography'); var _Typography = _interopRequireWildcard(_extensiontypography);
|
|
559
|
+
var _extensionunderline = require('@tiptap/extension-underline'); var _Underline = _interopRequireWildcard(_extensionunderline);
|
|
560
|
+
var _extensionplaceholder = require('@tiptap/extension-placeholder'); var _Placeholder = _interopRequireWildcard(_extensionplaceholder);
|
|
561
|
+
var _extensioncharactercount = require('@tiptap/extension-character-count'); var _CharacterCount = _interopRequireWildcard(_extensioncharactercount);
|
|
562
|
+
|
|
563
|
+
// src/extensions/mention.ts
|
|
564
|
+
|
|
565
|
+
|
|
566
|
+
var _extensionmention = require('@tiptap/extension-mention');
|
|
567
|
+
var BaseMention = _extensionmention.Mention || _optionalChain([_extensionmention.Mention, 'optionalAccess', _27 => _27.default, 'optionalAccess', _28 => _28.default]) || _optionalChain([_extensionmention.Mention, 'optionalAccess', _29 => _29.default]) || _extensionmention.Mention;
|
|
568
|
+
var Mention = BaseMention.extend({
|
|
569
|
+
addAttributes() {
|
|
570
|
+
return {
|
|
571
|
+
..._optionalChain([this, 'access', _30 => _30.parent, 'optionalCall', _31 => _31()]),
|
|
572
|
+
type: {
|
|
573
|
+
default: null,
|
|
574
|
+
parseHTML: (element) => element.getAttribute("data-type-name") || element.getAttribute("data-entity-type"),
|
|
575
|
+
renderHTML: (attributes) => {
|
|
576
|
+
if (!attributes.type) return {};
|
|
577
|
+
return { "data-type-name": attributes.type };
|
|
578
|
+
}
|
|
579
|
+
},
|
|
580
|
+
avatarUrl: {
|
|
581
|
+
default: null,
|
|
582
|
+
parseHTML: (element) => element.getAttribute("data-avatar-url"),
|
|
583
|
+
renderHTML: (attributes) => {
|
|
584
|
+
if (!attributes.avatarUrl) return {};
|
|
585
|
+
return { "data-avatar-url": attributes.avatarUrl };
|
|
586
|
+
}
|
|
587
|
+
},
|
|
588
|
+
color: {
|
|
589
|
+
default: null,
|
|
590
|
+
parseHTML: (element) => element.getAttribute("data-color"),
|
|
591
|
+
renderHTML: (attributes) => {
|
|
592
|
+
if (!attributes.color) return {};
|
|
593
|
+
return { "data-color": attributes.color };
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
});
|
|
599
|
+
function createMentionExtension(options = {}) {
|
|
600
|
+
const { HTMLAttributes = {}, ...rest } = options;
|
|
601
|
+
return Mention.configure({
|
|
602
|
+
HTMLAttributes: {
|
|
603
|
+
class: "pixerate-mention-node",
|
|
604
|
+
...HTMLAttributes
|
|
605
|
+
},
|
|
606
|
+
...rest
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// ../../node_modules/.pnpm/tiptap-markdown@0.8.10_@tiptap+core@2.27.3_@tiptap+pm@2.27.3_/node_modules/tiptap-markdown/dist/tiptap-markdown.es.js
|
|
611
|
+
|
|
612
|
+
var _prosemirrormarkdown = require('prosemirror-markdown');
|
|
613
|
+
var _markdownit = require('markdown-it'); var _markdownit2 = _interopRequireDefault(_markdownit);
|
|
614
|
+
var _model = require('@tiptap/pm/model');
|
|
615
|
+
var _markdownittasklists = require('markdown-it-task-lists'); var _markdownittasklists2 = _interopRequireDefault(_markdownittasklists);
|
|
616
|
+
|
|
617
|
+
var __defProp = Object.defineProperty;
|
|
618
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
619
|
+
var __publicField = (obj, key, value) => {
|
|
620
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
621
|
+
return value;
|
|
622
|
+
};
|
|
623
|
+
var MarkdownTightLists = _core.Extension.create({
|
|
624
|
+
name: "markdownTightLists",
|
|
625
|
+
addOptions: () => ({
|
|
626
|
+
tight: true,
|
|
627
|
+
tightClass: "tight",
|
|
628
|
+
listTypes: ["bulletList", "orderedList"]
|
|
629
|
+
}),
|
|
630
|
+
addGlobalAttributes() {
|
|
631
|
+
return [{
|
|
632
|
+
types: this.options.listTypes,
|
|
633
|
+
attributes: {
|
|
634
|
+
tight: {
|
|
635
|
+
default: this.options.tight,
|
|
636
|
+
parseHTML: (element) => element.getAttribute("data-tight") === "true" || !element.querySelector("p"),
|
|
637
|
+
renderHTML: (attributes) => ({
|
|
638
|
+
class: attributes.tight ? this.options.tightClass : null,
|
|
639
|
+
"data-tight": attributes.tight ? "true" : null
|
|
640
|
+
})
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
}];
|
|
644
|
+
},
|
|
645
|
+
addCommands() {
|
|
646
|
+
var _this = this;
|
|
647
|
+
return {
|
|
648
|
+
toggleTight: function() {
|
|
649
|
+
let tight = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : null;
|
|
650
|
+
return (_ref) => {
|
|
651
|
+
let {
|
|
652
|
+
editor,
|
|
653
|
+
commands
|
|
654
|
+
} = _ref;
|
|
655
|
+
function toggleTight(name) {
|
|
656
|
+
if (!editor.isActive(name)) {
|
|
657
|
+
return false;
|
|
658
|
+
}
|
|
659
|
+
const attrs = editor.getAttributes(name);
|
|
660
|
+
return commands.updateAttributes(name, {
|
|
661
|
+
tight: tight !== null && tight !== void 0 ? tight : !(attrs !== null && attrs !== void 0 && attrs.tight)
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
return _this.options.listTypes.some((name) => toggleTight(name));
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
});
|
|
670
|
+
var md = _markdownit2.default.call(void 0, );
|
|
671
|
+
function scanDelims(text, pos) {
|
|
672
|
+
md.inline.State.prototype.scanDelims.call({
|
|
673
|
+
src: text,
|
|
674
|
+
posMax: text.length
|
|
675
|
+
});
|
|
676
|
+
const state = new md.inline.State(text, null, null, []);
|
|
677
|
+
return state.scanDelims(pos, true);
|
|
678
|
+
}
|
|
679
|
+
function shiftDelim(text, delim, start2, offset) {
|
|
680
|
+
let res = text.substring(0, start2) + text.substring(start2 + delim.length);
|
|
681
|
+
res = res.substring(0, start2 + offset) + delim + res.substring(start2 + offset);
|
|
682
|
+
return res;
|
|
683
|
+
}
|
|
684
|
+
function trimStart(text, delim, from, to) {
|
|
685
|
+
let pos = from, res = text;
|
|
686
|
+
while (pos < to) {
|
|
687
|
+
if (scanDelims(res, pos).can_open) {
|
|
688
|
+
break;
|
|
689
|
+
}
|
|
690
|
+
res = shiftDelim(res, delim, pos, 1);
|
|
691
|
+
pos++;
|
|
692
|
+
}
|
|
693
|
+
return {
|
|
694
|
+
text: res,
|
|
695
|
+
from: pos,
|
|
696
|
+
to
|
|
697
|
+
};
|
|
698
|
+
}
|
|
699
|
+
function trimEnd(text, delim, from, to) {
|
|
700
|
+
let pos = to, res = text;
|
|
701
|
+
while (pos > from) {
|
|
702
|
+
if (scanDelims(res, pos).can_close) {
|
|
703
|
+
break;
|
|
704
|
+
}
|
|
705
|
+
res = shiftDelim(res, delim, pos, -1);
|
|
706
|
+
pos--;
|
|
707
|
+
}
|
|
708
|
+
return {
|
|
709
|
+
text: res,
|
|
710
|
+
from,
|
|
711
|
+
to: pos
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
function trimInline(text, delim, from, to) {
|
|
715
|
+
let state = {
|
|
716
|
+
text,
|
|
717
|
+
from,
|
|
718
|
+
to
|
|
719
|
+
};
|
|
720
|
+
state = trimStart(state.text, delim, state.from, state.to);
|
|
721
|
+
state = trimEnd(state.text, delim, state.from, state.to);
|
|
722
|
+
if (state.to - state.from < delim.length + 1) {
|
|
723
|
+
state.text = state.text.substring(0, state.from) + state.text.substring(state.to + delim.length);
|
|
724
|
+
}
|
|
725
|
+
return state.text;
|
|
726
|
+
}
|
|
727
|
+
var MarkdownSerializerState = class extends _prosemirrormarkdown.MarkdownSerializerState {
|
|
728
|
+
constructor(nodes, marks, options) {
|
|
729
|
+
super(nodes, marks, options !== null && options !== void 0 ? options : {});
|
|
730
|
+
__publicField(this, "inTable", false);
|
|
731
|
+
this.inlines = [];
|
|
732
|
+
}
|
|
733
|
+
render(node, parent, index) {
|
|
734
|
+
super.render(node, parent, index);
|
|
735
|
+
const top = this.inlines[this.inlines.length - 1];
|
|
736
|
+
if (top !== null && top !== void 0 && top.start && top !== null && top !== void 0 && top.end) {
|
|
737
|
+
const {
|
|
738
|
+
delimiter,
|
|
739
|
+
start: start2,
|
|
740
|
+
end
|
|
741
|
+
} = this.normalizeInline(top);
|
|
742
|
+
this.out = trimInline(this.out, delimiter, start2, end);
|
|
743
|
+
this.inlines.pop();
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
markString(mark, open, parent, index) {
|
|
747
|
+
const info = this.marks[mark.type.name];
|
|
748
|
+
if (info.expelEnclosingWhitespace) {
|
|
749
|
+
if (open) {
|
|
750
|
+
this.inlines.push({
|
|
751
|
+
start: this.out.length,
|
|
752
|
+
delimiter: info.open
|
|
753
|
+
});
|
|
754
|
+
} else {
|
|
755
|
+
const top = this.inlines.pop();
|
|
756
|
+
this.inlines.push({
|
|
757
|
+
...top,
|
|
758
|
+
end: this.out.length
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
return super.markString(mark, open, parent, index);
|
|
763
|
+
}
|
|
764
|
+
normalizeInline(inline) {
|
|
765
|
+
let {
|
|
766
|
+
start: start2,
|
|
767
|
+
end
|
|
768
|
+
} = inline;
|
|
769
|
+
while (this.out.charAt(start2).match(/\s/)) {
|
|
770
|
+
start2++;
|
|
771
|
+
}
|
|
772
|
+
return {
|
|
773
|
+
...inline,
|
|
774
|
+
start: start2
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
};
|
|
778
|
+
var HTMLMark = _core.Mark.create({
|
|
779
|
+
name: "markdownHTMLMark",
|
|
780
|
+
/**
|
|
781
|
+
* @return {{markdown: MarkdownMarkSpec}}
|
|
782
|
+
*/
|
|
783
|
+
addStorage() {
|
|
784
|
+
return {
|
|
785
|
+
markdown: {
|
|
786
|
+
serialize: {
|
|
787
|
+
open(state, mark) {
|
|
788
|
+
var _getMarkTags$, _getMarkTags;
|
|
789
|
+
if (!this.editor.storage.markdown.options.html) {
|
|
790
|
+
console.warn(`Tiptap Markdown: "${mark.type.name}" mark is only available in html mode`);
|
|
791
|
+
return "";
|
|
792
|
+
}
|
|
793
|
+
return (_getMarkTags$ = (_getMarkTags = getMarkTags(mark)) === null || _getMarkTags === void 0 ? void 0 : _getMarkTags[0]) !== null && _getMarkTags$ !== void 0 ? _getMarkTags$ : "";
|
|
794
|
+
},
|
|
795
|
+
close(state, mark) {
|
|
796
|
+
var _getMarkTags$2, _getMarkTags2;
|
|
797
|
+
if (!this.editor.storage.markdown.options.html) {
|
|
798
|
+
return "";
|
|
799
|
+
}
|
|
800
|
+
return (_getMarkTags$2 = (_getMarkTags2 = getMarkTags(mark)) === null || _getMarkTags2 === void 0 ? void 0 : _getMarkTags2[1]) !== null && _getMarkTags$2 !== void 0 ? _getMarkTags$2 : "";
|
|
801
|
+
}
|
|
802
|
+
},
|
|
803
|
+
parse: {
|
|
804
|
+
// handled by markdown-it
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
};
|
|
808
|
+
}
|
|
809
|
+
});
|
|
810
|
+
function getMarkTags(mark) {
|
|
811
|
+
const schema = mark.type.schema;
|
|
812
|
+
const node = schema.text(" ", [mark]);
|
|
813
|
+
const html = _core.getHTMLFromFragment.call(void 0, _model.Fragment.from(node), schema);
|
|
814
|
+
const match = html.match(/^(<.*?>) (<\/.*?>)$/);
|
|
815
|
+
return match ? [match[1], match[2]] : null;
|
|
816
|
+
}
|
|
817
|
+
function elementFromString(value) {
|
|
818
|
+
const wrappedValue = `<body>${value}</body>`;
|
|
819
|
+
return new window.DOMParser().parseFromString(wrappedValue, "text/html").body;
|
|
820
|
+
}
|
|
821
|
+
function escapeHTML(value) {
|
|
822
|
+
return value === null || value === void 0 ? void 0 : value.replace(/</g, "<").replace(/>/g, ">");
|
|
823
|
+
}
|
|
824
|
+
function extractElement(node) {
|
|
825
|
+
const parent = node.parentElement;
|
|
826
|
+
const prepend = parent.cloneNode();
|
|
827
|
+
while (parent.firstChild && parent.firstChild !== node) {
|
|
828
|
+
prepend.appendChild(parent.firstChild);
|
|
829
|
+
}
|
|
830
|
+
if (prepend.childNodes.length > 0) {
|
|
831
|
+
parent.parentElement.insertBefore(prepend, parent);
|
|
832
|
+
}
|
|
833
|
+
parent.parentElement.insertBefore(node, parent);
|
|
834
|
+
if (parent.childNodes.length === 0) {
|
|
835
|
+
parent.remove();
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
function unwrapElement(node) {
|
|
839
|
+
const parent = node.parentNode;
|
|
840
|
+
while (node.firstChild)
|
|
841
|
+
parent.insertBefore(node.firstChild, node);
|
|
842
|
+
parent.removeChild(node);
|
|
843
|
+
}
|
|
844
|
+
var HTMLNode = _core.Node.create({
|
|
845
|
+
name: "markdownHTMLNode",
|
|
846
|
+
addStorage() {
|
|
847
|
+
return {
|
|
848
|
+
markdown: {
|
|
849
|
+
serialize(state, node, parent) {
|
|
850
|
+
if (this.editor.storage.markdown.options.html) {
|
|
851
|
+
state.write(serializeHTML(node, parent));
|
|
852
|
+
} else {
|
|
853
|
+
console.warn(`Tiptap Markdown: "${node.type.name}" node is only available in html mode`);
|
|
854
|
+
state.write(`[${node.type.name}]`);
|
|
855
|
+
}
|
|
856
|
+
if (node.isBlock) {
|
|
857
|
+
state.closeBlock(node);
|
|
858
|
+
}
|
|
859
|
+
},
|
|
860
|
+
parse: {
|
|
861
|
+
// handled by markdown-it
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
};
|
|
865
|
+
}
|
|
866
|
+
});
|
|
867
|
+
function serializeHTML(node, parent) {
|
|
868
|
+
const schema = node.type.schema;
|
|
869
|
+
const html = _core.getHTMLFromFragment.call(void 0, _model.Fragment.from(node), schema);
|
|
870
|
+
if (node.isBlock && (parent instanceof _model.Fragment || parent.type.name === schema.topNodeType.name)) {
|
|
871
|
+
return formatBlock(html);
|
|
872
|
+
}
|
|
873
|
+
return html;
|
|
874
|
+
}
|
|
875
|
+
function formatBlock(html) {
|
|
876
|
+
const dom = elementFromString(html);
|
|
877
|
+
const element = dom.firstElementChild;
|
|
878
|
+
element.innerHTML = element.innerHTML.trim() ? `
|
|
879
|
+
${element.innerHTML}
|
|
880
|
+
` : `
|
|
881
|
+
`;
|
|
882
|
+
return element.outerHTML;
|
|
883
|
+
}
|
|
884
|
+
var Blockquote = _core.Node.create({
|
|
885
|
+
name: "blockquote"
|
|
886
|
+
});
|
|
887
|
+
var Blockquote$1 = Blockquote.extend({
|
|
888
|
+
/**
|
|
889
|
+
* @return {{markdown: MarkdownNodeSpec}}
|
|
890
|
+
*/
|
|
891
|
+
addStorage() {
|
|
892
|
+
return {
|
|
893
|
+
markdown: {
|
|
894
|
+
serialize: _prosemirrormarkdown.defaultMarkdownSerializer.nodes.blockquote,
|
|
895
|
+
parse: {
|
|
896
|
+
// handled by markdown-it
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
});
|
|
902
|
+
var BulletList = _core.Node.create({
|
|
903
|
+
name: "bulletList"
|
|
904
|
+
});
|
|
905
|
+
var BulletList$1 = BulletList.extend({
|
|
906
|
+
/**
|
|
907
|
+
* @return {{markdown: MarkdownNodeSpec}}
|
|
908
|
+
*/
|
|
909
|
+
addStorage() {
|
|
910
|
+
return {
|
|
911
|
+
markdown: {
|
|
912
|
+
serialize(state, node) {
|
|
913
|
+
return state.renderList(node, " ", () => (this.editor.storage.markdown.options.bulletListMarker || "-") + " ");
|
|
914
|
+
},
|
|
915
|
+
parse: {
|
|
916
|
+
// handled by markdown-it
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
};
|
|
920
|
+
}
|
|
921
|
+
});
|
|
922
|
+
var CodeBlock = _core.Node.create({
|
|
923
|
+
name: "codeBlock"
|
|
924
|
+
});
|
|
925
|
+
var CodeBlock$1 = CodeBlock.extend({
|
|
926
|
+
/**
|
|
927
|
+
* @return {{markdown: MarkdownNodeSpec}}
|
|
928
|
+
*/
|
|
929
|
+
addStorage() {
|
|
930
|
+
return {
|
|
931
|
+
markdown: {
|
|
932
|
+
serialize(state, node) {
|
|
933
|
+
state.write("```" + (node.attrs.language || "") + "\n");
|
|
934
|
+
state.text(node.textContent, false);
|
|
935
|
+
state.ensureNewLine();
|
|
936
|
+
state.write("```");
|
|
937
|
+
state.closeBlock(node);
|
|
938
|
+
},
|
|
939
|
+
parse: {
|
|
940
|
+
setup(markdownit2) {
|
|
941
|
+
var _this$options$languag;
|
|
942
|
+
markdownit2.set({
|
|
943
|
+
langPrefix: (_this$options$languag = this.options.languageClassPrefix) !== null && _this$options$languag !== void 0 ? _this$options$languag : "language-"
|
|
944
|
+
});
|
|
945
|
+
},
|
|
946
|
+
updateDOM(element) {
|
|
947
|
+
element.innerHTML = element.innerHTML.replace(/\n<\/code><\/pre>/g, "</code></pre>");
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
});
|
|
954
|
+
var HardBreak = _core.Node.create({
|
|
955
|
+
name: "hardBreak"
|
|
956
|
+
});
|
|
957
|
+
var HardBreak$1 = HardBreak.extend({
|
|
958
|
+
/**
|
|
959
|
+
* @return {{markdown: MarkdownNodeSpec}}
|
|
960
|
+
*/
|
|
961
|
+
addStorage() {
|
|
962
|
+
return {
|
|
963
|
+
markdown: {
|
|
964
|
+
serialize(state, node, parent, index) {
|
|
965
|
+
for (let i = index + 1; i < parent.childCount; i++)
|
|
966
|
+
if (parent.child(i).type != node.type) {
|
|
967
|
+
state.write(state.inTable ? HTMLNode.storage.markdown.serialize.call(this, state, node, parent) : "\\\n");
|
|
968
|
+
return;
|
|
969
|
+
}
|
|
970
|
+
},
|
|
971
|
+
parse: {
|
|
972
|
+
// handled by markdown-it
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
};
|
|
976
|
+
}
|
|
977
|
+
});
|
|
978
|
+
var Heading = _core.Node.create({
|
|
979
|
+
name: "heading"
|
|
980
|
+
});
|
|
981
|
+
var Heading$1 = Heading.extend({
|
|
982
|
+
/**
|
|
983
|
+
* @return {{markdown: MarkdownNodeSpec}}
|
|
984
|
+
*/
|
|
985
|
+
addStorage() {
|
|
986
|
+
return {
|
|
987
|
+
markdown: {
|
|
988
|
+
serialize: _prosemirrormarkdown.defaultMarkdownSerializer.nodes.heading,
|
|
989
|
+
parse: {
|
|
990
|
+
// handled by markdown-it
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
};
|
|
994
|
+
}
|
|
995
|
+
});
|
|
996
|
+
var HorizontalRule = _core.Node.create({
|
|
997
|
+
name: "horizontalRule"
|
|
998
|
+
});
|
|
999
|
+
var HorizontalRule$1 = HorizontalRule.extend({
|
|
1000
|
+
/**
|
|
1001
|
+
* @return {{markdown: MarkdownNodeSpec}}
|
|
1002
|
+
*/
|
|
1003
|
+
addStorage() {
|
|
1004
|
+
return {
|
|
1005
|
+
markdown: {
|
|
1006
|
+
serialize: _prosemirrormarkdown.defaultMarkdownSerializer.nodes.horizontal_rule,
|
|
1007
|
+
parse: {
|
|
1008
|
+
// handled by markdown-it
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
};
|
|
1012
|
+
}
|
|
1013
|
+
});
|
|
1014
|
+
var Image = _core.Node.create({
|
|
1015
|
+
name: "image"
|
|
1016
|
+
});
|
|
1017
|
+
var Image$1 = Image.extend({
|
|
1018
|
+
/**
|
|
1019
|
+
* @return {{markdown: MarkdownNodeSpec}}
|
|
1020
|
+
*/
|
|
1021
|
+
addStorage() {
|
|
1022
|
+
return {
|
|
1023
|
+
markdown: {
|
|
1024
|
+
serialize: _prosemirrormarkdown.defaultMarkdownSerializer.nodes.image,
|
|
1025
|
+
parse: {
|
|
1026
|
+
// handled by markdown-it
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
};
|
|
1030
|
+
}
|
|
1031
|
+
});
|
|
1032
|
+
var ListItem = _core.Node.create({
|
|
1033
|
+
name: "listItem"
|
|
1034
|
+
});
|
|
1035
|
+
var ListItem$1 = ListItem.extend({
|
|
1036
|
+
/**
|
|
1037
|
+
* @return {{markdown: MarkdownNodeSpec}}
|
|
1038
|
+
*/
|
|
1039
|
+
addStorage() {
|
|
1040
|
+
return {
|
|
1041
|
+
markdown: {
|
|
1042
|
+
serialize: _prosemirrormarkdown.defaultMarkdownSerializer.nodes.list_item,
|
|
1043
|
+
parse: {
|
|
1044
|
+
// handled by markdown-it
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
};
|
|
1048
|
+
}
|
|
1049
|
+
});
|
|
1050
|
+
var OrderedList = _core.Node.create({
|
|
1051
|
+
name: "orderedList"
|
|
1052
|
+
});
|
|
1053
|
+
function findIndexOfAdjacentNode(node, parent, index) {
|
|
1054
|
+
let i = 0;
|
|
1055
|
+
for (; index - i > 0; i++) {
|
|
1056
|
+
if (parent.child(index - i - 1).type.name !== node.type.name) {
|
|
1057
|
+
break;
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
return i;
|
|
1061
|
+
}
|
|
1062
|
+
var OrderedList$1 = OrderedList.extend({
|
|
1063
|
+
/**
|
|
1064
|
+
* @return {{markdown: MarkdownNodeSpec}}
|
|
1065
|
+
*/
|
|
1066
|
+
addStorage() {
|
|
1067
|
+
return {
|
|
1068
|
+
markdown: {
|
|
1069
|
+
serialize(state, node, parent, index) {
|
|
1070
|
+
const start2 = node.attrs.start || 1;
|
|
1071
|
+
const maxW = String(start2 + node.childCount - 1).length;
|
|
1072
|
+
const space = state.repeat(" ", maxW + 2);
|
|
1073
|
+
const adjacentIndex = findIndexOfAdjacentNode(node, parent, index);
|
|
1074
|
+
const separator = adjacentIndex % 2 ? ") " : ". ";
|
|
1075
|
+
state.renderList(node, space, (i) => {
|
|
1076
|
+
const nStr = String(start2 + i);
|
|
1077
|
+
return state.repeat(" ", maxW - nStr.length) + nStr + separator;
|
|
1078
|
+
});
|
|
1079
|
+
},
|
|
1080
|
+
parse: {
|
|
1081
|
+
// handled by markdown-it
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
};
|
|
1085
|
+
}
|
|
1086
|
+
});
|
|
1087
|
+
var Paragraph = _core.Node.create({
|
|
1088
|
+
name: "paragraph"
|
|
1089
|
+
});
|
|
1090
|
+
var Paragraph$1 = Paragraph.extend({
|
|
1091
|
+
/**
|
|
1092
|
+
* @return {{markdown: MarkdownNodeSpec}}
|
|
1093
|
+
*/
|
|
1094
|
+
addStorage() {
|
|
1095
|
+
return {
|
|
1096
|
+
markdown: {
|
|
1097
|
+
serialize: _prosemirrormarkdown.defaultMarkdownSerializer.nodes.paragraph,
|
|
1098
|
+
parse: {
|
|
1099
|
+
// handled by markdown-it
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
};
|
|
1103
|
+
}
|
|
1104
|
+
});
|
|
1105
|
+
function childNodes(node) {
|
|
1106
|
+
var _node$content$content, _node$content;
|
|
1107
|
+
return (_node$content$content = node === null || node === void 0 || (_node$content = node.content) === null || _node$content === void 0 ? void 0 : _node$content.content) !== null && _node$content$content !== void 0 ? _node$content$content : [];
|
|
1108
|
+
}
|
|
1109
|
+
var Table = _core.Node.create({
|
|
1110
|
+
name: "table"
|
|
1111
|
+
});
|
|
1112
|
+
var Table$1 = Table.extend({
|
|
1113
|
+
/**
|
|
1114
|
+
* @return {{markdown: MarkdownNodeSpec}}
|
|
1115
|
+
*/
|
|
1116
|
+
addStorage() {
|
|
1117
|
+
return {
|
|
1118
|
+
markdown: {
|
|
1119
|
+
serialize(state, node, parent) {
|
|
1120
|
+
if (!isMarkdownSerializable(node)) {
|
|
1121
|
+
HTMLNode.storage.markdown.serialize.call(this, state, node, parent);
|
|
1122
|
+
return;
|
|
1123
|
+
}
|
|
1124
|
+
state.inTable = true;
|
|
1125
|
+
node.forEach((row, p, i) => {
|
|
1126
|
+
state.write("| ");
|
|
1127
|
+
row.forEach((col, p2, j) => {
|
|
1128
|
+
if (j) {
|
|
1129
|
+
state.write(" | ");
|
|
1130
|
+
}
|
|
1131
|
+
const cellContent = col.firstChild;
|
|
1132
|
+
if (cellContent.textContent.trim()) {
|
|
1133
|
+
state.renderInline(cellContent);
|
|
1134
|
+
}
|
|
1135
|
+
});
|
|
1136
|
+
state.write(" |");
|
|
1137
|
+
state.ensureNewLine();
|
|
1138
|
+
if (!i) {
|
|
1139
|
+
const delimiterRow = Array.from({
|
|
1140
|
+
length: row.childCount
|
|
1141
|
+
}).map(() => "---").join(" | ");
|
|
1142
|
+
state.write(`| ${delimiterRow} |`);
|
|
1143
|
+
state.ensureNewLine();
|
|
1144
|
+
}
|
|
1145
|
+
});
|
|
1146
|
+
state.closeBlock(node);
|
|
1147
|
+
state.inTable = false;
|
|
1148
|
+
},
|
|
1149
|
+
parse: {
|
|
1150
|
+
// handled by markdown-it
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
};
|
|
1154
|
+
}
|
|
1155
|
+
});
|
|
1156
|
+
function hasSpan(node) {
|
|
1157
|
+
return node.attrs.colspan > 1 || node.attrs.rowspan > 1;
|
|
1158
|
+
}
|
|
1159
|
+
function isMarkdownSerializable(node) {
|
|
1160
|
+
const rows = childNodes(node);
|
|
1161
|
+
const firstRow = rows[0];
|
|
1162
|
+
const bodyRows = rows.slice(1);
|
|
1163
|
+
if (childNodes(firstRow).some((cell) => cell.type.name !== "tableHeader" || hasSpan(cell) || cell.childCount > 1)) {
|
|
1164
|
+
return false;
|
|
1165
|
+
}
|
|
1166
|
+
if (bodyRows.some((row) => childNodes(row).some((cell) => cell.type.name === "tableHeader" || hasSpan(cell) || cell.childCount > 1))) {
|
|
1167
|
+
return false;
|
|
1168
|
+
}
|
|
1169
|
+
return true;
|
|
1170
|
+
}
|
|
1171
|
+
var TaskItem = _core.Node.create({
|
|
1172
|
+
name: "taskItem"
|
|
1173
|
+
});
|
|
1174
|
+
var TaskItem$1 = TaskItem.extend({
|
|
1175
|
+
/**
|
|
1176
|
+
* @return {{markdown: MarkdownNodeSpec}}
|
|
1177
|
+
*/
|
|
1178
|
+
addStorage() {
|
|
1179
|
+
return {
|
|
1180
|
+
markdown: {
|
|
1181
|
+
serialize(state, node) {
|
|
1182
|
+
const check = node.attrs.checked ? "[x]" : "[ ]";
|
|
1183
|
+
state.write(`${check} `);
|
|
1184
|
+
state.renderContent(node);
|
|
1185
|
+
},
|
|
1186
|
+
parse: {
|
|
1187
|
+
updateDOM(element) {
|
|
1188
|
+
[...element.querySelectorAll(".task-list-item")].forEach((item) => {
|
|
1189
|
+
const input = item.querySelector("input");
|
|
1190
|
+
item.setAttribute("data-type", "taskItem");
|
|
1191
|
+
if (input) {
|
|
1192
|
+
item.setAttribute("data-checked", input.checked);
|
|
1193
|
+
input.remove();
|
|
1194
|
+
}
|
|
1195
|
+
});
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
};
|
|
1200
|
+
}
|
|
1201
|
+
});
|
|
1202
|
+
var TaskList = _core.Node.create({
|
|
1203
|
+
name: "taskList"
|
|
1204
|
+
});
|
|
1205
|
+
var TaskList$1 = TaskList.extend({
|
|
1206
|
+
/**
|
|
1207
|
+
* @return {{markdown: MarkdownNodeSpec}}
|
|
1208
|
+
*/
|
|
1209
|
+
addStorage() {
|
|
1210
|
+
return {
|
|
1211
|
+
markdown: {
|
|
1212
|
+
serialize: BulletList$1.storage.markdown.serialize,
|
|
1213
|
+
parse: {
|
|
1214
|
+
setup(markdownit2) {
|
|
1215
|
+
markdownit2.use(_markdownittasklists2.default);
|
|
1216
|
+
},
|
|
1217
|
+
updateDOM(element) {
|
|
1218
|
+
[...element.querySelectorAll(".contains-task-list")].forEach((list) => {
|
|
1219
|
+
list.setAttribute("data-type", "taskList");
|
|
1220
|
+
});
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
};
|
|
1225
|
+
}
|
|
1226
|
+
});
|
|
1227
|
+
var Text = _core.Node.create({
|
|
1228
|
+
name: "text"
|
|
1229
|
+
});
|
|
1230
|
+
var Text$1 = Text.extend({
|
|
1231
|
+
/**
|
|
1232
|
+
* @return {{markdown: MarkdownNodeSpec}}
|
|
1233
|
+
*/
|
|
1234
|
+
addStorage() {
|
|
1235
|
+
return {
|
|
1236
|
+
markdown: {
|
|
1237
|
+
serialize(state, node) {
|
|
1238
|
+
state.text(escapeHTML(node.text));
|
|
1239
|
+
},
|
|
1240
|
+
parse: {
|
|
1241
|
+
// handled by markdown-it
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
};
|
|
1245
|
+
}
|
|
1246
|
+
});
|
|
1247
|
+
var Bold = _core.Mark.create({
|
|
1248
|
+
name: "bold"
|
|
1249
|
+
});
|
|
1250
|
+
var Bold$1 = Bold.extend({
|
|
1251
|
+
/**
|
|
1252
|
+
* @return {{markdown: MarkdownMarkSpec}}
|
|
1253
|
+
*/
|
|
1254
|
+
addStorage() {
|
|
1255
|
+
return {
|
|
1256
|
+
markdown: {
|
|
1257
|
+
serialize: _prosemirrormarkdown.defaultMarkdownSerializer.marks.strong,
|
|
1258
|
+
parse: {
|
|
1259
|
+
// handled by markdown-it
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
};
|
|
1263
|
+
}
|
|
1264
|
+
});
|
|
1265
|
+
var Code = _core.Mark.create({
|
|
1266
|
+
name: "code"
|
|
1267
|
+
});
|
|
1268
|
+
var Code$1 = Code.extend({
|
|
1269
|
+
/**
|
|
1270
|
+
* @return {{markdown: MarkdownMarkSpec}}
|
|
1271
|
+
*/
|
|
1272
|
+
addStorage() {
|
|
1273
|
+
return {
|
|
1274
|
+
markdown: {
|
|
1275
|
+
serialize: _prosemirrormarkdown.defaultMarkdownSerializer.marks.code,
|
|
1276
|
+
parse: {
|
|
1277
|
+
// handled by markdown-it
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
};
|
|
1281
|
+
}
|
|
1282
|
+
});
|
|
1283
|
+
var Italic = _core.Mark.create({
|
|
1284
|
+
name: "italic"
|
|
1285
|
+
});
|
|
1286
|
+
var Italic$1 = Italic.extend({
|
|
1287
|
+
/**
|
|
1288
|
+
* @return {{markdown: MarkdownMarkSpec}}
|
|
1289
|
+
*/
|
|
1290
|
+
addStorage() {
|
|
1291
|
+
return {
|
|
1292
|
+
markdown: {
|
|
1293
|
+
serialize: _prosemirrormarkdown.defaultMarkdownSerializer.marks.em,
|
|
1294
|
+
parse: {
|
|
1295
|
+
// handled by markdown-it
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
};
|
|
1299
|
+
}
|
|
1300
|
+
});
|
|
1301
|
+
var Link = _core.Mark.create({
|
|
1302
|
+
name: "link"
|
|
1303
|
+
});
|
|
1304
|
+
var Link$1 = Link.extend({
|
|
1305
|
+
/**
|
|
1306
|
+
* @return {{markdown: MarkdownMarkSpec}}
|
|
1307
|
+
*/
|
|
1308
|
+
addStorage() {
|
|
1309
|
+
return {
|
|
1310
|
+
markdown: {
|
|
1311
|
+
serialize: _prosemirrormarkdown.defaultMarkdownSerializer.marks.link,
|
|
1312
|
+
parse: {
|
|
1313
|
+
// handled by markdown-it
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
};
|
|
1317
|
+
}
|
|
1318
|
+
});
|
|
1319
|
+
var Strike = _core.Mark.create({
|
|
1320
|
+
name: "strike"
|
|
1321
|
+
});
|
|
1322
|
+
var Strike$1 = Strike.extend({
|
|
1323
|
+
/**
|
|
1324
|
+
* @return {{markdown: MarkdownMarkSpec}}
|
|
1325
|
+
*/
|
|
1326
|
+
addStorage() {
|
|
1327
|
+
return {
|
|
1328
|
+
markdown: {
|
|
1329
|
+
serialize: {
|
|
1330
|
+
open: "~~",
|
|
1331
|
+
close: "~~",
|
|
1332
|
+
expelEnclosingWhitespace: true
|
|
1333
|
+
},
|
|
1334
|
+
parse: {
|
|
1335
|
+
// handled by markdown-it
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
};
|
|
1339
|
+
}
|
|
1340
|
+
});
|
|
1341
|
+
var markdownExtensions = [Blockquote$1, BulletList$1, CodeBlock$1, HardBreak$1, Heading$1, HorizontalRule$1, HTMLNode, Image$1, ListItem$1, OrderedList$1, Paragraph$1, Table$1, TaskItem$1, TaskList$1, Text$1, Bold$1, Code$1, HTMLMark, Italic$1, Link$1, Strike$1];
|
|
1342
|
+
function getMarkdownSpec(extension) {
|
|
1343
|
+
var _extension$storage, _markdownExtensions$f;
|
|
1344
|
+
const markdownSpec = (_extension$storage = extension.storage) === null || _extension$storage === void 0 ? void 0 : _extension$storage.markdown;
|
|
1345
|
+
const defaultMarkdownSpec = (_markdownExtensions$f = markdownExtensions.find((e) => e.name === extension.name)) === null || _markdownExtensions$f === void 0 ? void 0 : _markdownExtensions$f.storage.markdown;
|
|
1346
|
+
if (markdownSpec || defaultMarkdownSpec) {
|
|
1347
|
+
return {
|
|
1348
|
+
...defaultMarkdownSpec,
|
|
1349
|
+
...markdownSpec
|
|
1350
|
+
};
|
|
1351
|
+
}
|
|
1352
|
+
return null;
|
|
1353
|
+
}
|
|
1354
|
+
var MarkdownSerializer = class {
|
|
1355
|
+
constructor(editor) {
|
|
1356
|
+
__publicField(this, "editor", null);
|
|
1357
|
+
this.editor = editor;
|
|
1358
|
+
}
|
|
1359
|
+
serialize(content) {
|
|
1360
|
+
const state = new MarkdownSerializerState(this.nodes, this.marks, {
|
|
1361
|
+
hardBreakNodeName: HardBreak$1.name
|
|
1362
|
+
});
|
|
1363
|
+
state.renderContent(content);
|
|
1364
|
+
return state.out;
|
|
1365
|
+
}
|
|
1366
|
+
get nodes() {
|
|
1367
|
+
var _this$editor$extensio;
|
|
1368
|
+
return {
|
|
1369
|
+
...Object.fromEntries(Object.keys(this.editor.schema.nodes).map((name) => [name, this.serializeNode(HTMLNode)])),
|
|
1370
|
+
...Object.fromEntries((_this$editor$extensio = this.editor.extensionManager.extensions.filter((extension) => extension.type === "node" && this.serializeNode(extension)).map((extension) => [extension.name, this.serializeNode(extension)])) !== null && _this$editor$extensio !== void 0 ? _this$editor$extensio : [])
|
|
1371
|
+
};
|
|
1372
|
+
}
|
|
1373
|
+
get marks() {
|
|
1374
|
+
var _this$editor$extensio2;
|
|
1375
|
+
return {
|
|
1376
|
+
...Object.fromEntries(Object.keys(this.editor.schema.marks).map((name) => [name, this.serializeMark(HTMLMark)])),
|
|
1377
|
+
...Object.fromEntries((_this$editor$extensio2 = this.editor.extensionManager.extensions.filter((extension) => extension.type === "mark" && this.serializeMark(extension)).map((extension) => [extension.name, this.serializeMark(extension)])) !== null && _this$editor$extensio2 !== void 0 ? _this$editor$extensio2 : [])
|
|
1378
|
+
};
|
|
1379
|
+
}
|
|
1380
|
+
serializeNode(node) {
|
|
1381
|
+
var _getMarkdownSpec;
|
|
1382
|
+
return (_getMarkdownSpec = getMarkdownSpec(node)) === null || _getMarkdownSpec === void 0 || (_getMarkdownSpec = _getMarkdownSpec.serialize) === null || _getMarkdownSpec === void 0 ? void 0 : _getMarkdownSpec.bind({
|
|
1383
|
+
editor: this.editor,
|
|
1384
|
+
options: node.options
|
|
1385
|
+
});
|
|
1386
|
+
}
|
|
1387
|
+
serializeMark(mark) {
|
|
1388
|
+
var _getMarkdownSpec2;
|
|
1389
|
+
const serialize = (_getMarkdownSpec2 = getMarkdownSpec(mark)) === null || _getMarkdownSpec2 === void 0 ? void 0 : _getMarkdownSpec2.serialize;
|
|
1390
|
+
return serialize ? {
|
|
1391
|
+
...serialize,
|
|
1392
|
+
open: typeof serialize.open === "function" ? serialize.open.bind({
|
|
1393
|
+
editor: this.editor,
|
|
1394
|
+
options: mark.options
|
|
1395
|
+
}) : serialize.open,
|
|
1396
|
+
close: typeof serialize.close === "function" ? serialize.close.bind({
|
|
1397
|
+
editor: this.editor,
|
|
1398
|
+
options: mark.options
|
|
1399
|
+
}) : serialize.close
|
|
1400
|
+
} : null;
|
|
1401
|
+
}
|
|
1402
|
+
};
|
|
1403
|
+
var MarkdownParser = class {
|
|
1404
|
+
constructor(editor, _ref) {
|
|
1405
|
+
__publicField(this, "editor", null);
|
|
1406
|
+
__publicField(this, "md", null);
|
|
1407
|
+
let {
|
|
1408
|
+
html,
|
|
1409
|
+
linkify,
|
|
1410
|
+
breaks
|
|
1411
|
+
} = _ref;
|
|
1412
|
+
this.editor = editor;
|
|
1413
|
+
this.md = this.withPatchedRenderer(_markdownit2.default.call(void 0, {
|
|
1414
|
+
html,
|
|
1415
|
+
linkify,
|
|
1416
|
+
breaks
|
|
1417
|
+
}));
|
|
1418
|
+
}
|
|
1419
|
+
parse(content) {
|
|
1420
|
+
let {
|
|
1421
|
+
inline
|
|
1422
|
+
} = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
|
|
1423
|
+
if (typeof content === "string") {
|
|
1424
|
+
this.editor.extensionManager.extensions.forEach((extension) => {
|
|
1425
|
+
var _getMarkdownSpec;
|
|
1426
|
+
return (_getMarkdownSpec = getMarkdownSpec(extension)) === null || _getMarkdownSpec === void 0 || (_getMarkdownSpec = _getMarkdownSpec.parse) === null || _getMarkdownSpec === void 0 || (_getMarkdownSpec = _getMarkdownSpec.setup) === null || _getMarkdownSpec === void 0 ? void 0 : _getMarkdownSpec.call({
|
|
1427
|
+
editor: this.editor,
|
|
1428
|
+
options: extension.options
|
|
1429
|
+
}, this.md);
|
|
1430
|
+
});
|
|
1431
|
+
const renderedHTML = this.md.render(content);
|
|
1432
|
+
const element = elementFromString(renderedHTML);
|
|
1433
|
+
this.editor.extensionManager.extensions.forEach((extension) => {
|
|
1434
|
+
var _getMarkdownSpec2;
|
|
1435
|
+
return (_getMarkdownSpec2 = getMarkdownSpec(extension)) === null || _getMarkdownSpec2 === void 0 || (_getMarkdownSpec2 = _getMarkdownSpec2.parse) === null || _getMarkdownSpec2 === void 0 || (_getMarkdownSpec2 = _getMarkdownSpec2.updateDOM) === null || _getMarkdownSpec2 === void 0 ? void 0 : _getMarkdownSpec2.call({
|
|
1436
|
+
editor: this.editor,
|
|
1437
|
+
options: extension.options
|
|
1438
|
+
}, element);
|
|
1439
|
+
});
|
|
1440
|
+
this.normalizeDOM(element, {
|
|
1441
|
+
inline,
|
|
1442
|
+
content
|
|
1443
|
+
});
|
|
1444
|
+
return element.innerHTML;
|
|
1445
|
+
}
|
|
1446
|
+
return content;
|
|
1447
|
+
}
|
|
1448
|
+
normalizeDOM(node, _ref2) {
|
|
1449
|
+
let {
|
|
1450
|
+
inline,
|
|
1451
|
+
content
|
|
1452
|
+
} = _ref2;
|
|
1453
|
+
this.normalizeBlocks(node);
|
|
1454
|
+
node.querySelectorAll("*").forEach((el) => {
|
|
1455
|
+
var _el$nextSibling;
|
|
1456
|
+
if (((_el$nextSibling = el.nextSibling) === null || _el$nextSibling === void 0 ? void 0 : _el$nextSibling.nodeType) === Node.TEXT_NODE && !el.closest("pre")) {
|
|
1457
|
+
el.nextSibling.textContent = el.nextSibling.textContent.replace(/^\n/, "");
|
|
1458
|
+
}
|
|
1459
|
+
});
|
|
1460
|
+
if (inline) {
|
|
1461
|
+
this.normalizeInline(node, content);
|
|
1462
|
+
}
|
|
1463
|
+
return node;
|
|
1464
|
+
}
|
|
1465
|
+
normalizeBlocks(node) {
|
|
1466
|
+
const blocks = Object.values(this.editor.schema.nodes).filter((node2) => node2.isBlock);
|
|
1467
|
+
const selector = blocks.map((block) => {
|
|
1468
|
+
var _block$spec$parseDOM;
|
|
1469
|
+
return (_block$spec$parseDOM = block.spec.parseDOM) === null || _block$spec$parseDOM === void 0 ? void 0 : _block$spec$parseDOM.map((spec) => spec.tag);
|
|
1470
|
+
}).flat().filter(Boolean).join(",");
|
|
1471
|
+
if (!selector) {
|
|
1472
|
+
return;
|
|
1473
|
+
}
|
|
1474
|
+
[...node.querySelectorAll(selector)].forEach((el) => {
|
|
1475
|
+
if (el.parentElement.matches("p")) {
|
|
1476
|
+
extractElement(el);
|
|
1477
|
+
}
|
|
1478
|
+
});
|
|
1479
|
+
}
|
|
1480
|
+
normalizeInline(node, content) {
|
|
1481
|
+
var _node$firstElementChi;
|
|
1482
|
+
if ((_node$firstElementChi = node.firstElementChild) !== null && _node$firstElementChi !== void 0 && _node$firstElementChi.matches("p")) {
|
|
1483
|
+
var _content$match$, _content$match, _content$match$2, _content$match2;
|
|
1484
|
+
const firstParagraph = node.firstElementChild;
|
|
1485
|
+
const {
|
|
1486
|
+
nextElementSibling
|
|
1487
|
+
} = firstParagraph;
|
|
1488
|
+
const startSpaces = (_content$match$ = (_content$match = content.match(/^\s+/)) === null || _content$match === void 0 ? void 0 : _content$match[0]) !== null && _content$match$ !== void 0 ? _content$match$ : "";
|
|
1489
|
+
const endSpaces = !nextElementSibling ? (_content$match$2 = (_content$match2 = content.match(/\s+$/)) === null || _content$match2 === void 0 ? void 0 : _content$match2[0]) !== null && _content$match$2 !== void 0 ? _content$match$2 : "" : "";
|
|
1490
|
+
if (content.match(/^\n\n/)) {
|
|
1491
|
+
firstParagraph.innerHTML = `${firstParagraph.innerHTML}${endSpaces}`;
|
|
1492
|
+
return;
|
|
1493
|
+
}
|
|
1494
|
+
unwrapElement(firstParagraph);
|
|
1495
|
+
node.innerHTML = `${startSpaces}${node.innerHTML}${endSpaces}`;
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
/**
|
|
1499
|
+
* @param {markdownit} md
|
|
1500
|
+
*/
|
|
1501
|
+
withPatchedRenderer(md2) {
|
|
1502
|
+
const withoutNewLine = (renderer) => function() {
|
|
1503
|
+
const rendered = renderer(...arguments);
|
|
1504
|
+
if (rendered === "\n") {
|
|
1505
|
+
return rendered;
|
|
1506
|
+
}
|
|
1507
|
+
if (rendered[rendered.length - 1] === "\n") {
|
|
1508
|
+
return rendered.slice(0, -1);
|
|
1509
|
+
}
|
|
1510
|
+
return rendered;
|
|
1511
|
+
};
|
|
1512
|
+
md2.renderer.rules.hardbreak = withoutNewLine(md2.renderer.rules.hardbreak);
|
|
1513
|
+
md2.renderer.rules.softbreak = withoutNewLine(md2.renderer.rules.softbreak);
|
|
1514
|
+
md2.renderer.rules.fence = withoutNewLine(md2.renderer.rules.fence);
|
|
1515
|
+
md2.renderer.rules.code_block = withoutNewLine(md2.renderer.rules.code_block);
|
|
1516
|
+
md2.renderer.renderToken = withoutNewLine(md2.renderer.renderToken.bind(md2.renderer));
|
|
1517
|
+
return md2;
|
|
1518
|
+
}
|
|
1519
|
+
};
|
|
1520
|
+
var MarkdownClipboard = _core.Extension.create({
|
|
1521
|
+
name: "markdownClipboard",
|
|
1522
|
+
addOptions() {
|
|
1523
|
+
return {
|
|
1524
|
+
transformPastedText: false,
|
|
1525
|
+
transformCopiedText: false
|
|
1526
|
+
};
|
|
1527
|
+
},
|
|
1528
|
+
addProseMirrorPlugins() {
|
|
1529
|
+
return [new (0, _state.Plugin)({
|
|
1530
|
+
key: new (0, _state.PluginKey)("markdownClipboard"),
|
|
1531
|
+
props: {
|
|
1532
|
+
clipboardTextParser: (text, context, plainText) => {
|
|
1533
|
+
if (plainText || !this.options.transformPastedText) {
|
|
1534
|
+
return null;
|
|
1535
|
+
}
|
|
1536
|
+
const parsed = this.editor.storage.markdown.parser.parse(text, {
|
|
1537
|
+
inline: true
|
|
1538
|
+
});
|
|
1539
|
+
return _model.DOMParser.fromSchema(this.editor.schema).parseSlice(elementFromString(parsed), {
|
|
1540
|
+
preserveWhitespace: true,
|
|
1541
|
+
context
|
|
1542
|
+
});
|
|
1543
|
+
},
|
|
1544
|
+
/**
|
|
1545
|
+
* @param {import('prosemirror-model').Slice} slice
|
|
1546
|
+
*/
|
|
1547
|
+
clipboardTextSerializer: (slice) => {
|
|
1548
|
+
if (!this.options.transformCopiedText) {
|
|
1549
|
+
return null;
|
|
1550
|
+
}
|
|
1551
|
+
return this.editor.storage.markdown.serializer.serialize(slice.content);
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
})];
|
|
1555
|
+
}
|
|
1556
|
+
});
|
|
1557
|
+
var Markdown = _core.Extension.create({
|
|
1558
|
+
name: "markdown",
|
|
1559
|
+
priority: 50,
|
|
1560
|
+
addOptions() {
|
|
1561
|
+
return {
|
|
1562
|
+
html: true,
|
|
1563
|
+
tightLists: true,
|
|
1564
|
+
tightListClass: "tight",
|
|
1565
|
+
bulletListMarker: "-",
|
|
1566
|
+
linkify: false,
|
|
1567
|
+
breaks: false,
|
|
1568
|
+
transformPastedText: false,
|
|
1569
|
+
transformCopiedText: false
|
|
1570
|
+
};
|
|
1571
|
+
},
|
|
1572
|
+
addCommands() {
|
|
1573
|
+
const commands = _core.extensions.Commands.config.addCommands();
|
|
1574
|
+
return {
|
|
1575
|
+
setContent: (content, emitUpdate, parseOptions) => (props) => {
|
|
1576
|
+
return commands.setContent(props.editor.storage.markdown.parser.parse(content), emitUpdate, parseOptions)(props);
|
|
1577
|
+
},
|
|
1578
|
+
insertContentAt: (range, content, options) => (props) => {
|
|
1579
|
+
return commands.insertContentAt(range, props.editor.storage.markdown.parser.parse(content, {
|
|
1580
|
+
inline: true
|
|
1581
|
+
}), options)(props);
|
|
1582
|
+
}
|
|
1583
|
+
};
|
|
1584
|
+
},
|
|
1585
|
+
onBeforeCreate() {
|
|
1586
|
+
this.editor.storage.markdown = {
|
|
1587
|
+
options: {
|
|
1588
|
+
...this.options
|
|
1589
|
+
},
|
|
1590
|
+
parser: new MarkdownParser(this.editor, this.options),
|
|
1591
|
+
serializer: new MarkdownSerializer(this.editor),
|
|
1592
|
+
getMarkdown: () => {
|
|
1593
|
+
return this.editor.storage.markdown.serializer.serialize(this.editor.state.doc);
|
|
1594
|
+
}
|
|
1595
|
+
};
|
|
1596
|
+
this.editor.options.initialContent = this.editor.options.content;
|
|
1597
|
+
this.editor.options.content = this.editor.storage.markdown.parser.parse(this.editor.options.content);
|
|
1598
|
+
},
|
|
1599
|
+
onCreate() {
|
|
1600
|
+
this.editor.options.content = this.editor.options.initialContent;
|
|
1601
|
+
delete this.editor.options.initialContent;
|
|
1602
|
+
},
|
|
1603
|
+
addStorage() {
|
|
1604
|
+
return {
|
|
1605
|
+
/// storage will be defined in onBeforeCreate() to prevent initial object overriding
|
|
1606
|
+
};
|
|
1607
|
+
},
|
|
1608
|
+
addExtensions() {
|
|
1609
|
+
return [MarkdownTightLists.configure({
|
|
1610
|
+
tight: this.options.tightLists,
|
|
1611
|
+
tightClass: this.options.tightListClass
|
|
1612
|
+
}), MarkdownClipboard.configure({
|
|
1613
|
+
transformPastedText: this.options.transformPastedText,
|
|
1614
|
+
transformCopiedText: this.options.transformCopiedText
|
|
1615
|
+
})];
|
|
1616
|
+
}
|
|
1617
|
+
});
|
|
1618
|
+
|
|
1619
|
+
// src/extensions/markdown.ts
|
|
1620
|
+
var resolveExt = (mod, name) => _optionalChain([mod, 'optionalAccess', _32 => _32[name]]) || _optionalChain([mod, 'optionalAccess', _33 => _33.default, 'optionalAccess', _34 => _34[name]]) || _optionalChain([mod, 'optionalAccess', _35 => _35.default, 'optionalAccess', _36 => _36.default]) || _optionalChain([mod, 'optionalAccess', _37 => _37.default]) || mod;
|
|
1621
|
+
var Markdown2 = resolveExt(Markdown, "Markdown");
|
|
1622
|
+
|
|
1623
|
+
// src/extensions/image.ts
|
|
1624
|
+
var _extensionimage = require('@tiptap/extension-image'); var _Image = _interopRequireWildcard(_extensionimage);
|
|
1625
|
+
|
|
1626
|
+
var resolveExt2 = (mod, name) => _optionalChain([mod, 'optionalAccess', _38 => _38[name]]) || _optionalChain([mod, 'optionalAccess', _39 => _39.default, 'optionalAccess', _40 => _40[name]]) || _optionalChain([mod, 'optionalAccess', _41 => _41.default, 'optionalAccess', _42 => _42.default]) || _optionalChain([mod, 'optionalAccess', _43 => _43.default]) || mod;
|
|
1627
|
+
var BaseImage = resolveExt2(_Image, "Image");
|
|
1628
|
+
var imagePastePluginKey = new (0, _state.PluginKey)("imagePasteHandler");
|
|
1629
|
+
function insertImageNode(view, src, alt) {
|
|
1630
|
+
const { schema } = view.state;
|
|
1631
|
+
const imageType = schema.nodes.image;
|
|
1632
|
+
if (!imageType) return;
|
|
1633
|
+
const node = imageType.create({ src, alt: alt || "" });
|
|
1634
|
+
const tr = view.state.tr.replaceSelectionWith(node);
|
|
1635
|
+
view.dispatch(tr);
|
|
1636
|
+
}
|
|
1637
|
+
function updateImageSrc(view, oldSrc, newSrc) {
|
|
1638
|
+
const { doc } = view.state;
|
|
1639
|
+
let foundPos = null;
|
|
1640
|
+
let foundAttrs = null;
|
|
1641
|
+
doc.descendants((node, pos) => {
|
|
1642
|
+
if (node.type.name === "image" && node.attrs.src === oldSrc) {
|
|
1643
|
+
foundPos = pos;
|
|
1644
|
+
foundAttrs = node.attrs;
|
|
1645
|
+
return false;
|
|
1646
|
+
}
|
|
1647
|
+
});
|
|
1648
|
+
if (foundPos !== null && foundAttrs) {
|
|
1649
|
+
const tr = view.state.tr.setNodeMarkup(foundPos, void 0, {
|
|
1650
|
+
...foundAttrs,
|
|
1651
|
+
src: newSrc
|
|
1652
|
+
});
|
|
1653
|
+
view.dispatch(tr);
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
function removeImageNode(view, src) {
|
|
1657
|
+
const { doc } = view.state;
|
|
1658
|
+
let foundPos = null;
|
|
1659
|
+
let nodeSize = 0;
|
|
1660
|
+
doc.descendants((node, pos) => {
|
|
1661
|
+
if (node.type.name === "image" && node.attrs.src === src) {
|
|
1662
|
+
foundPos = pos;
|
|
1663
|
+
nodeSize = node.nodeSize;
|
|
1664
|
+
return false;
|
|
1665
|
+
}
|
|
1666
|
+
});
|
|
1667
|
+
if (foundPos !== null) {
|
|
1668
|
+
const tr = view.state.tr.delete(foundPos, foundPos + nodeSize);
|
|
1669
|
+
view.dispatch(tr);
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
function handleImageInsertion(view, file, options) {
|
|
1673
|
+
if (typeof options.upload === "function") {
|
|
1674
|
+
const hasObjectUrl = typeof URL !== "undefined" && typeof URL.createObjectURL === "function";
|
|
1675
|
+
const tempUrl = hasObjectUrl ? URL.createObjectURL(file) : null;
|
|
1676
|
+
if (tempUrl) {
|
|
1677
|
+
insertImageNode(view, tempUrl, file.name);
|
|
1678
|
+
}
|
|
1679
|
+
Promise.resolve(options.upload(file)).then((uploadedUrl) => {
|
|
1680
|
+
if (!uploadedUrl) {
|
|
1681
|
+
throw new Error("Upload handler returned empty URL");
|
|
1682
|
+
}
|
|
1683
|
+
if (tempUrl) {
|
|
1684
|
+
updateImageSrc(view, tempUrl, uploadedUrl);
|
|
1685
|
+
if (typeof URL.revokeObjectURL === "function") {
|
|
1686
|
+
URL.revokeObjectURL(tempUrl);
|
|
1687
|
+
}
|
|
1688
|
+
} else {
|
|
1689
|
+
insertImageNode(view, uploadedUrl, file.name);
|
|
1690
|
+
}
|
|
1691
|
+
}).catch((err) => {
|
|
1692
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1693
|
+
console.error("Failed to upload pasted image:", error);
|
|
1694
|
+
if (tempUrl) {
|
|
1695
|
+
removeImageNode(view, tempUrl);
|
|
1696
|
+
if (typeof URL.revokeObjectURL === "function") {
|
|
1697
|
+
URL.revokeObjectURL(tempUrl);
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1700
|
+
if (typeof options.onUploadError === "function") {
|
|
1701
|
+
options.onUploadError(error, file);
|
|
1702
|
+
}
|
|
1703
|
+
});
|
|
1704
|
+
} else if (options.allowBase64 !== false) {
|
|
1705
|
+
const maxBase64Size = _nullishCoalesce(options.maxBase64Size, () => ( 65536));
|
|
1706
|
+
if (file.size > maxBase64Size) {
|
|
1707
|
+
const err = new Error(
|
|
1708
|
+
`Image size (${Math.round(file.size / 1024)}KB) exceeds maxBase64Size (${Math.round(
|
|
1709
|
+
maxBase64Size / 1024
|
|
1710
|
+
)}KB). Provide an upload handler to support large images.`
|
|
1711
|
+
);
|
|
1712
|
+
console.warn(`[Editor] ${err.message}`);
|
|
1713
|
+
if (typeof options.onUploadError === "function") {
|
|
1714
|
+
options.onUploadError(err, file);
|
|
1715
|
+
}
|
|
1716
|
+
return;
|
|
1717
|
+
}
|
|
1718
|
+
if (typeof FileReader !== "undefined") {
|
|
1719
|
+
const reader = new FileReader();
|
|
1720
|
+
reader.onload = () => {
|
|
1721
|
+
const src = reader.result;
|
|
1722
|
+
if (src) {
|
|
1723
|
+
insertImageNode(view, src, file.name);
|
|
1724
|
+
}
|
|
1725
|
+
};
|
|
1726
|
+
reader.readAsDataURL(file);
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
var Image2 = BaseImage.extend({
|
|
1731
|
+
addOptions() {
|
|
1732
|
+
return {
|
|
1733
|
+
..._optionalChain([this, 'access', _44 => _44.parent, 'optionalCall', _45 => _45()]),
|
|
1734
|
+
allowBase64: true,
|
|
1735
|
+
maxBase64Size: 65536,
|
|
1736
|
+
enablePaste: true,
|
|
1737
|
+
enableDrop: true,
|
|
1738
|
+
upload: void 0,
|
|
1739
|
+
onUploadError: void 0,
|
|
1740
|
+
HTMLAttributes: {
|
|
1741
|
+
class: "rounded-md max-w-full h-auto my-2"
|
|
1742
|
+
}
|
|
1743
|
+
};
|
|
1744
|
+
},
|
|
1745
|
+
addProseMirrorPlugins() {
|
|
1746
|
+
const parentPlugins = _optionalChain([this, 'access', _46 => _46.parent, 'optionalCall', _47 => _47()]) || [];
|
|
1747
|
+
const options = this.options;
|
|
1748
|
+
if (!options.enablePaste && !options.enableDrop) {
|
|
1749
|
+
return parentPlugins;
|
|
1750
|
+
}
|
|
1751
|
+
const pastePlugin = new (0, _state.Plugin)({
|
|
1752
|
+
key: imagePastePluginKey,
|
|
1753
|
+
props: {
|
|
1754
|
+
handlePaste(view, event) {
|
|
1755
|
+
if (!options.enablePaste) return false;
|
|
1756
|
+
const items = Array.from(_optionalChain([event, 'access', _48 => _48.clipboardData, 'optionalAccess', _49 => _49.items]) || []);
|
|
1757
|
+
const imageItems = items.filter(
|
|
1758
|
+
(item) => item.kind === "file" && item.type.startsWith("image/")
|
|
1759
|
+
);
|
|
1760
|
+
if (imageItems.length === 0) return false;
|
|
1761
|
+
event.preventDefault();
|
|
1762
|
+
for (const item of imageItems) {
|
|
1763
|
+
const file = item.getAsFile();
|
|
1764
|
+
if (!file) continue;
|
|
1765
|
+
handleImageInsertion(view, file, options);
|
|
1766
|
+
}
|
|
1767
|
+
return true;
|
|
1768
|
+
},
|
|
1769
|
+
handleDrop(view, event) {
|
|
1770
|
+
if (!options.enableDrop) return false;
|
|
1771
|
+
const files = Array.from(_optionalChain([event, 'access', _50 => _50.dataTransfer, 'optionalAccess', _51 => _51.files]) || []);
|
|
1772
|
+
const imageFiles = files.filter((f) => f.type.startsWith("image/"));
|
|
1773
|
+
if (imageFiles.length === 0) return false;
|
|
1774
|
+
event.preventDefault();
|
|
1775
|
+
for (const file of imageFiles) {
|
|
1776
|
+
handleImageInsertion(view, file, options);
|
|
1777
|
+
}
|
|
1778
|
+
return true;
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
});
|
|
1782
|
+
return [...parentPlugins, pastePlugin];
|
|
1783
|
+
}
|
|
1784
|
+
});
|
|
1785
|
+
|
|
1786
|
+
// src/extensions/comments.ts
|
|
1787
|
+
|
|
1788
|
+
|
|
1789
|
+
|
|
1790
|
+
var commentsPluginKey = new (0, _state.PluginKey)("comments");
|
|
1791
|
+
var COMMENT_MARK_NAME = "comment";
|
|
1792
|
+
function findCommentRanges(doc) {
|
|
1793
|
+
const result = /* @__PURE__ */ new Map();
|
|
1794
|
+
doc.descendants((node, pos) => {
|
|
1795
|
+
if (!node.isInline) return;
|
|
1796
|
+
node.marks.forEach((mark) => {
|
|
1797
|
+
if (mark.type.name !== COMMENT_MARK_NAME) return;
|
|
1798
|
+
const id = mark.attrs.commentId;
|
|
1799
|
+
if (!id) return;
|
|
1800
|
+
const ranges = _nullishCoalesce(result.get(id), () => ( []));
|
|
1801
|
+
const last = ranges[ranges.length - 1];
|
|
1802
|
+
const end = pos + node.nodeSize;
|
|
1803
|
+
if (last && last.to === pos) {
|
|
1804
|
+
last.to = end;
|
|
1805
|
+
} else {
|
|
1806
|
+
ranges.push({ from: pos, to: end });
|
|
1807
|
+
}
|
|
1808
|
+
result.set(id, ranges);
|
|
1809
|
+
});
|
|
1810
|
+
});
|
|
1811
|
+
return result;
|
|
1812
|
+
}
|
|
1813
|
+
function getCommentAnchors(doc) {
|
|
1814
|
+
const anchors = /* @__PURE__ */ new Map();
|
|
1815
|
+
findCommentRanges(doc).forEach((ranges, id) => {
|
|
1816
|
+
const from = ranges[0].from;
|
|
1817
|
+
const to = ranges[ranges.length - 1].to;
|
|
1818
|
+
anchors.set(id, {
|
|
1819
|
+
from,
|
|
1820
|
+
to,
|
|
1821
|
+
quote: ranges.map((r) => doc.textBetween(r.from, r.to, " ", " ")).join(" ")
|
|
1822
|
+
});
|
|
1823
|
+
});
|
|
1824
|
+
return anchors;
|
|
1825
|
+
}
|
|
1826
|
+
function getCommentIdsAt(state, pos = state.selection.from) {
|
|
1827
|
+
const $pos = state.doc.resolve(pos);
|
|
1828
|
+
const marks = [
|
|
1829
|
+
..._nullishCoalesce(_optionalChain([$pos, 'access', _52 => _52.nodeAfter, 'optionalAccess', _53 => _53.marks]), () => ( [])),
|
|
1830
|
+
..._nullishCoalesce(_optionalChain([$pos, 'access', _54 => _54.nodeBefore, 'optionalAccess', _55 => _55.marks]), () => ( []))
|
|
1831
|
+
];
|
|
1832
|
+
const ids = [];
|
|
1833
|
+
marks.forEach((m) => {
|
|
1834
|
+
if (m.type.name === COMMENT_MARK_NAME && m.attrs.commentId && !ids.includes(m.attrs.commentId)) {
|
|
1835
|
+
ids.push(m.attrs.commentId);
|
|
1836
|
+
}
|
|
1837
|
+
});
|
|
1838
|
+
return ids;
|
|
1839
|
+
}
|
|
1840
|
+
function getCommentStore(editor) {
|
|
1841
|
+
return _nullishCoalesce(_optionalChain([editor, 'optionalAccess', _56 => _56.storage, 'optionalAccess', _57 => _57[COMMENT_MARK_NAME], 'optionalAccess', _58 => _58.store]), () => ( null));
|
|
1842
|
+
}
|
|
1843
|
+
function resolveAuthor(author) {
|
|
1844
|
+
return typeof author === "function" ? author() : author;
|
|
1845
|
+
}
|
|
1846
|
+
var Comments = _core.Mark.create({
|
|
1847
|
+
name: COMMENT_MARK_NAME,
|
|
1848
|
+
// Typing at the edge of a comment does not extend it.
|
|
1849
|
+
inclusive: false,
|
|
1850
|
+
// Allow several comment marks (different threads) on the same text.
|
|
1851
|
+
excludes: "",
|
|
1852
|
+
addOptions() {
|
|
1853
|
+
return {
|
|
1854
|
+
store: null,
|
|
1855
|
+
author: { id: "anonymous", name: "Anonymous" },
|
|
1856
|
+
HTMLAttributes: {},
|
|
1857
|
+
commentClass: "pixerate-comment bg-amber-100 border-b-2 border-amber-400 dark:bg-amber-500/20 cursor-pointer",
|
|
1858
|
+
activeClass: "pixerate-comment-active bg-amber-200 dark:bg-amber-500/40",
|
|
1859
|
+
resolvedClass: "",
|
|
1860
|
+
activateOnSelection: true
|
|
1861
|
+
};
|
|
1862
|
+
},
|
|
1863
|
+
addStorage() {
|
|
1864
|
+
return {
|
|
1865
|
+
store: _nullishCoalesce(this.options.store, () => ( new (0, _chunkTVRC4KVTcjs.CommentStore)())),
|
|
1866
|
+
// tiptap-markdown: comments are not part of the exported markdown.
|
|
1867
|
+
markdown: { serialize: { open: "", close: "" }, parse: {} }
|
|
1868
|
+
};
|
|
1869
|
+
},
|
|
1870
|
+
addAttributes() {
|
|
1871
|
+
return {
|
|
1872
|
+
commentId: {
|
|
1873
|
+
default: null,
|
|
1874
|
+
parseHTML: (el) => el.getAttribute("data-comment-id"),
|
|
1875
|
+
renderHTML: (attrs) => attrs.commentId ? { "data-comment-id": attrs.commentId } : {}
|
|
1876
|
+
}
|
|
1877
|
+
};
|
|
1878
|
+
},
|
|
1879
|
+
parseHTML() {
|
|
1880
|
+
return [{ tag: "span[data-comment-id]" }];
|
|
1881
|
+
},
|
|
1882
|
+
renderHTML({ HTMLAttributes }) {
|
|
1883
|
+
return ["span", _core.mergeAttributes.call(void 0, this.options.HTMLAttributes, HTMLAttributes), 0];
|
|
1884
|
+
},
|
|
1885
|
+
addCommands() {
|
|
1886
|
+
const store = () => this.storage.store;
|
|
1887
|
+
return {
|
|
1888
|
+
addComment: (options = {}) => ({ state, tr, dispatch }) => {
|
|
1889
|
+
const { from, to, empty } = state.selection;
|
|
1890
|
+
if (empty) return false;
|
|
1891
|
+
if (dispatch) {
|
|
1892
|
+
const id = _nullishCoalesce(options.id, () => ( _chunkTVRC4KVTcjs.createReviewId.call(void 0, "comment")));
|
|
1893
|
+
tr.addMark(from, to, this.type.create({ commentId: id }));
|
|
1894
|
+
tr.setMeta(commentsPluginKey, "refresh");
|
|
1895
|
+
store().createThread({
|
|
1896
|
+
id,
|
|
1897
|
+
body: _nullishCoalesce(options.body, () => ( "")),
|
|
1898
|
+
author: _nullishCoalesce(options.author, () => ( resolveAuthor(this.options.author))),
|
|
1899
|
+
anchor: { from, to, quote: state.doc.textBetween(from, to, " ", " ") }
|
|
1900
|
+
});
|
|
1901
|
+
store().setActiveThread(id);
|
|
1902
|
+
}
|
|
1903
|
+
return true;
|
|
1904
|
+
},
|
|
1905
|
+
resolveComment: (id, resolved = true) => ({ tr, dispatch }) => {
|
|
1906
|
+
if (!store().getThread(id)) return false;
|
|
1907
|
+
if (dispatch) {
|
|
1908
|
+
store().resolveThread(id, resolved, resolveAuthor(this.options.author));
|
|
1909
|
+
tr.setMeta(commentsPluginKey, "refresh");
|
|
1910
|
+
}
|
|
1911
|
+
return true;
|
|
1912
|
+
},
|
|
1913
|
+
deleteComment: (id) => ({ state, tr, dispatch }) => {
|
|
1914
|
+
const ranges = _nullishCoalesce(findCommentRanges(state.doc).get(id), () => ( []));
|
|
1915
|
+
if (ranges.length === 0 && !store().getThread(id)) return false;
|
|
1916
|
+
if (dispatch) {
|
|
1917
|
+
ranges.forEach(({ from, to }) => {
|
|
1918
|
+
state.doc.nodesBetween(from, to, (node, pos) => {
|
|
1919
|
+
const mark = node.marks.find(
|
|
1920
|
+
(m) => m.type === this.type && m.attrs.commentId === id
|
|
1921
|
+
);
|
|
1922
|
+
if (mark) {
|
|
1923
|
+
tr.removeMark(Math.max(pos, from), Math.min(pos + node.nodeSize, to), mark);
|
|
1924
|
+
}
|
|
1925
|
+
});
|
|
1926
|
+
});
|
|
1927
|
+
tr.setMeta(commentsPluginKey, "refresh");
|
|
1928
|
+
store().deleteThread(id);
|
|
1929
|
+
}
|
|
1930
|
+
return true;
|
|
1931
|
+
},
|
|
1932
|
+
setActiveComment: (id) => ({ tr, dispatch }) => {
|
|
1933
|
+
if (id !== null && !store().getThread(id)) return false;
|
|
1934
|
+
if (dispatch) {
|
|
1935
|
+
store().setActiveThread(id);
|
|
1936
|
+
tr.setMeta(commentsPluginKey, "refresh");
|
|
1937
|
+
}
|
|
1938
|
+
return true;
|
|
1939
|
+
},
|
|
1940
|
+
focusComment: (id) => ({ state, tr, dispatch }) => {
|
|
1941
|
+
const ranges = findCommentRanges(state.doc).get(id);
|
|
1942
|
+
if (!ranges || ranges.length === 0) return false;
|
|
1943
|
+
if (dispatch) {
|
|
1944
|
+
const from = ranges[0].from;
|
|
1945
|
+
const to = ranges[ranges.length - 1].to;
|
|
1946
|
+
tr.setSelection(_state.TextSelection.create(tr.doc, from, to)).scrollIntoView();
|
|
1947
|
+
store().setActiveThread(id);
|
|
1948
|
+
tr.setMeta(commentsPluginKey, "refresh");
|
|
1949
|
+
}
|
|
1950
|
+
return true;
|
|
1951
|
+
}
|
|
1952
|
+
};
|
|
1953
|
+
},
|
|
1954
|
+
addProseMirrorPlugins() {
|
|
1955
|
+
const store = this.storage.store;
|
|
1956
|
+
const options = this.options;
|
|
1957
|
+
let cache = null;
|
|
1958
|
+
const buildDecorations = (doc) => {
|
|
1959
|
+
const snapshot = store.getSnapshot();
|
|
1960
|
+
if (cache && cache.doc === doc && cache.snapshot === snapshot) return cache.set;
|
|
1961
|
+
const decorations = [];
|
|
1962
|
+
findCommentRanges(doc).forEach((ranges, id) => {
|
|
1963
|
+
const thread = store.getThread(id);
|
|
1964
|
+
const resolved = _nullishCoalesce(_optionalChain([thread, 'optionalAccess', _59 => _59.resolved]), () => ( false));
|
|
1965
|
+
const active = snapshot.activeThreadId === id;
|
|
1966
|
+
const cls = [
|
|
1967
|
+
resolved ? options.resolvedClass : options.commentClass,
|
|
1968
|
+
active ? options.activeClass : ""
|
|
1969
|
+
].filter(Boolean).join(" ");
|
|
1970
|
+
if (!cls) return;
|
|
1971
|
+
ranges.forEach(({ from, to }) => {
|
|
1972
|
+
decorations.push(_view2.Decoration.inline(from, to, { class: cls }));
|
|
1973
|
+
});
|
|
1974
|
+
});
|
|
1975
|
+
const set = _view2.DecorationSet.create(doc, decorations);
|
|
1976
|
+
cache = { doc, snapshot, set };
|
|
1977
|
+
return set;
|
|
1978
|
+
};
|
|
1979
|
+
return [
|
|
1980
|
+
new (0, _state.Plugin)({
|
|
1981
|
+
key: commentsPluginKey,
|
|
1982
|
+
props: {
|
|
1983
|
+
decorations: (state) => buildDecorations(state.doc)
|
|
1984
|
+
},
|
|
1985
|
+
view: (view) => {
|
|
1986
|
+
let destroyed = false;
|
|
1987
|
+
let scheduled = false;
|
|
1988
|
+
const sync = () => store.syncAnchors(getCommentAnchors(view.state.doc));
|
|
1989
|
+
sync();
|
|
1990
|
+
const unsubscribe = store.subscribe(() => {
|
|
1991
|
+
if (scheduled) return;
|
|
1992
|
+
scheduled = true;
|
|
1993
|
+
queueMicrotask(() => {
|
|
1994
|
+
scheduled = false;
|
|
1995
|
+
if (destroyed) return;
|
|
1996
|
+
sync();
|
|
1997
|
+
if (_optionalChain([cache, 'optionalAccess', _60 => _60.snapshot]) !== store.getSnapshot()) {
|
|
1998
|
+
view.dispatch(
|
|
1999
|
+
view.state.tr.setMeta(commentsPluginKey, "refresh").setMeta("addToHistory", false)
|
|
2000
|
+
);
|
|
2001
|
+
}
|
|
2002
|
+
});
|
|
2003
|
+
});
|
|
2004
|
+
return {
|
|
2005
|
+
update(view2, prevState) {
|
|
2006
|
+
if (!prevState.doc.eq(view2.state.doc)) sync();
|
|
2007
|
+
if (options.activateOnSelection && !prevState.selection.eq(view2.state.selection)) {
|
|
2008
|
+
const ids = getCommentIdsAt(view2.state);
|
|
2009
|
+
const active = store.getSnapshot().activeThreadId;
|
|
2010
|
+
if (!active || !ids.includes(active)) {
|
|
2011
|
+
store.setActiveThread(_nullishCoalesce(ids[0], () => ( null)));
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
2014
|
+
},
|
|
2015
|
+
destroy() {
|
|
2016
|
+
destroyed = true;
|
|
2017
|
+
unsubscribe();
|
|
2018
|
+
}
|
|
2019
|
+
};
|
|
2020
|
+
}
|
|
2021
|
+
})
|
|
2022
|
+
];
|
|
2023
|
+
}
|
|
2024
|
+
});
|
|
2025
|
+
function getCommentAuthor(editor) {
|
|
2026
|
+
const ext = _optionalChain([editor, 'optionalAccess', _61 => _61.extensionManager, 'optionalAccess', _62 => _62.extensions, 'access', _63 => _63.find, 'call', _64 => _64((e) => e.name === COMMENT_MARK_NAME)]);
|
|
2027
|
+
return ext ? resolveAuthor(ext.options.author) : null;
|
|
2028
|
+
}
|
|
2029
|
+
|
|
2030
|
+
// src/extensions/file-import.ts
|
|
2031
|
+
|
|
2032
|
+
|
|
2033
|
+
|
|
2034
|
+
// src/import/registry.ts
|
|
2035
|
+
var ImportError = class extends Error {
|
|
2036
|
+
|
|
2037
|
+
|
|
2038
|
+
constructor(code, message, details = {}) {
|
|
2039
|
+
super(message, details.cause !== void 0 ? { cause: details.cause } : void 0);
|
|
2040
|
+
this.name = "ImportError";
|
|
2041
|
+
this.code = code;
|
|
2042
|
+
this.fileName = details.fileName;
|
|
2043
|
+
}
|
|
2044
|
+
};
|
|
2045
|
+
var normalizeExtension = (ext) => {
|
|
2046
|
+
const lower = ext.trim().toLowerCase();
|
|
2047
|
+
return lower.startsWith(".") ? lower : `.${lower}`;
|
|
2048
|
+
};
|
|
2049
|
+
var normalizeMimeType = (mime) => (_nullishCoalesce(mime, () => ( ""))).split(";")[0].trim().toLowerCase();
|
|
2050
|
+
function isFileLike(input) {
|
|
2051
|
+
return typeof input === "object" && input !== null && !(input instanceof ArrayBuffer) && !ArrayBuffer.isView(input);
|
|
2052
|
+
}
|
|
2053
|
+
function stripBom(text) {
|
|
2054
|
+
return text.charCodeAt(0) === 65279 ? text.slice(1) : text;
|
|
2055
|
+
}
|
|
2056
|
+
function createImportContext(input, details) {
|
|
2057
|
+
const readArrayBuffer = async () => {
|
|
2058
|
+
if (typeof input === "string") {
|
|
2059
|
+
return new TextEncoder().encode(input).buffer;
|
|
2060
|
+
}
|
|
2061
|
+
if (input instanceof ArrayBuffer) return input;
|
|
2062
|
+
if (ArrayBuffer.isView(input)) {
|
|
2063
|
+
return input.buffer.slice(input.byteOffset, input.byteOffset + input.byteLength);
|
|
2064
|
+
}
|
|
2065
|
+
if (typeof input.arrayBuffer === "function") return input.arrayBuffer();
|
|
2066
|
+
if (typeof input.text === "function") {
|
|
2067
|
+
return new TextEncoder().encode(await input.text()).buffer;
|
|
2068
|
+
}
|
|
2069
|
+
throw new TypeError("Import input cannot be read as binary data.");
|
|
2070
|
+
};
|
|
2071
|
+
const readText = async () => {
|
|
2072
|
+
if (typeof input === "string") return stripBom(input);
|
|
2073
|
+
if (isFileLike(input) && typeof input.text === "function") {
|
|
2074
|
+
return stripBom(await input.text());
|
|
2075
|
+
}
|
|
2076
|
+
return stripBom(new TextDecoder("utf-8").decode(await readArrayBuffer()));
|
|
2077
|
+
};
|
|
2078
|
+
return { ...details, readText, readArrayBuffer };
|
|
2079
|
+
}
|
|
2080
|
+
var ImportAdapterRegistry = (_class = class {constructor() { _class.prototype.__init.call(this); }
|
|
2081
|
+
__init() {this.adapters = []}
|
|
2082
|
+
/** Registers an adapter and returns a function that unregisters it. */
|
|
2083
|
+
register(adapter, options = {}) {
|
|
2084
|
+
const existing = this.adapters.findIndex((a) => a.id === adapter.id);
|
|
2085
|
+
if (existing !== -1) {
|
|
2086
|
+
if (!options.replace) {
|
|
2087
|
+
throw new Error(`Import adapter "${adapter.id}" is already registered.`);
|
|
2088
|
+
}
|
|
2089
|
+
this.adapters.splice(existing, 1);
|
|
2090
|
+
}
|
|
2091
|
+
this.adapters.push(adapter);
|
|
2092
|
+
return () => {
|
|
2093
|
+
this.unregister(adapter);
|
|
2094
|
+
};
|
|
2095
|
+
}
|
|
2096
|
+
/** Removes an adapter by id or instance. Returns whether it was registered. */
|
|
2097
|
+
unregister(adapterOrId) {
|
|
2098
|
+
const index = this.adapters.findIndex(
|
|
2099
|
+
(a) => typeof adapterOrId === "string" ? a.id === adapterOrId : a === adapterOrId
|
|
2100
|
+
);
|
|
2101
|
+
if (index === -1) return false;
|
|
2102
|
+
this.adapters.splice(index, 1);
|
|
2103
|
+
return true;
|
|
2104
|
+
}
|
|
2105
|
+
get(id) {
|
|
2106
|
+
return this.adapters.find((a) => a.id === id);
|
|
2107
|
+
}
|
|
2108
|
+
/** Registered adapters in registration order, optionally for one target. */
|
|
2109
|
+
list(target) {
|
|
2110
|
+
return this.adapters.filter((a) => target === void 0 || a.target === target);
|
|
2111
|
+
}
|
|
2112
|
+
/**
|
|
2113
|
+
* Finds the best adapter for a file. Extensions win over MIME types (browsers
|
|
2114
|
+
* often report `""` or `text/plain` for markdown), the longest matching
|
|
2115
|
+
* extension wins (`.md.txt` beats `.txt`), exact MIME types beat `type/*`
|
|
2116
|
+
* wildcards, then higher `priority`, then the most recently registered.
|
|
2117
|
+
*/
|
|
2118
|
+
find(query) {
|
|
2119
|
+
const fileName = _nullishCoalesce(_optionalChain([query, 'access', _65 => _65.fileName, 'optionalAccess', _66 => _66.toLowerCase, 'call', _67 => _67()]), () => ( ""));
|
|
2120
|
+
const mime = normalizeMimeType(query.mimeType);
|
|
2121
|
+
let best;
|
|
2122
|
+
let bestScore = 0;
|
|
2123
|
+
let bestPriority = -Infinity;
|
|
2124
|
+
this.adapters.forEach((adapter) => {
|
|
2125
|
+
if (query.target !== void 0 && adapter.target !== query.target) return;
|
|
2126
|
+
let score = 0;
|
|
2127
|
+
if (fileName) {
|
|
2128
|
+
for (const raw of adapter.extensions) {
|
|
2129
|
+
const ext = normalizeExtension(raw);
|
|
2130
|
+
if (fileName.endsWith(ext) && fileName.length > ext.length) {
|
|
2131
|
+
score = Math.max(score, 1e3 + ext.length);
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
if (score === 0 && mime) {
|
|
2136
|
+
for (const raw of adapter.mimeTypes) {
|
|
2137
|
+
const accepted = normalizeMimeType(raw);
|
|
2138
|
+
if (accepted === mime) score = Math.max(score, 2);
|
|
2139
|
+
else if (accepted.endsWith("/*") && mime.startsWith(accepted.slice(0, -1))) {
|
|
2140
|
+
score = Math.max(score, 1);
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
}
|
|
2144
|
+
if (score === 0) return;
|
|
2145
|
+
const priority = _nullishCoalesce(adapter.priority, () => ( 0));
|
|
2146
|
+
if (score > bestScore || score === bestScore && priority >= bestPriority) {
|
|
2147
|
+
best = adapter;
|
|
2148
|
+
bestScore = score;
|
|
2149
|
+
bestPriority = priority;
|
|
2150
|
+
}
|
|
2151
|
+
});
|
|
2152
|
+
return best;
|
|
2153
|
+
}
|
|
2154
|
+
/**
|
|
2155
|
+
* Returns a value for `<input type="file" accept="…">` covering every
|
|
2156
|
+
* registered extension and MIME type (optionally for one target).
|
|
2157
|
+
*/
|
|
2158
|
+
accept(target) {
|
|
2159
|
+
const values = /* @__PURE__ */ new Set();
|
|
2160
|
+
for (const adapter of this.list(target)) {
|
|
2161
|
+
adapter.extensions.forEach((ext) => values.add(normalizeExtension(ext)));
|
|
2162
|
+
adapter.mimeTypes.forEach((mime) => values.add(normalizeMimeType(mime)));
|
|
2163
|
+
}
|
|
2164
|
+
return Array.from(values).join(",");
|
|
2165
|
+
}
|
|
2166
|
+
/** Whether some adapter (optionally for `target`) accepts this file. */
|
|
2167
|
+
canImport(file, target) {
|
|
2168
|
+
return !!this.find({ fileName: file.name, mimeType: file.type, target });
|
|
2169
|
+
}
|
|
2170
|
+
/**
|
|
2171
|
+
* Imports a file (or string / binary input) with the matching adapter.
|
|
2172
|
+
* Rejects with an {@link ImportError} when no adapter matches or the
|
|
2173
|
+
* adapter fails.
|
|
2174
|
+
*/
|
|
2175
|
+
async importFile(input, options = {}) {
|
|
2176
|
+
const fileName = _nullishCoalesce(options.fileName, () => ( (isFileLike(input) ? input.name : void 0)));
|
|
2177
|
+
const mimeType = _nullishCoalesce(options.mimeType, () => ( (isFileLike(input) ? input.type : void 0)));
|
|
2178
|
+
let adapter;
|
|
2179
|
+
if (options.adapterId) {
|
|
2180
|
+
adapter = this.get(options.adapterId);
|
|
2181
|
+
if (!adapter) {
|
|
2182
|
+
throw new ImportError("unknown_adapter", `No import adapter with id "${options.adapterId}".`, { fileName });
|
|
2183
|
+
}
|
|
2184
|
+
} else {
|
|
2185
|
+
adapter = this.find({ fileName, mimeType, target: options.target });
|
|
2186
|
+
}
|
|
2187
|
+
if (!adapter) {
|
|
2188
|
+
const what = fileName || mimeType || "input";
|
|
2189
|
+
throw new ImportError(
|
|
2190
|
+
"unsupported_type",
|
|
2191
|
+
`No import adapter accepts ${what}${options.target ? ` for target "${options.target}"` : ""}.`,
|
|
2192
|
+
{ fileName }
|
|
2193
|
+
);
|
|
2194
|
+
}
|
|
2195
|
+
const context = createImportContext(input, { fileName, mimeType, target: adapter.target });
|
|
2196
|
+
try {
|
|
2197
|
+
const result = await adapter.import(input, context);
|
|
2198
|
+
return { adapterId: adapter.id, target: adapter.target, fileName, mimeType, result };
|
|
2199
|
+
} catch (error) {
|
|
2200
|
+
throw new ImportError(
|
|
2201
|
+
"adapter_failed",
|
|
2202
|
+
`Import adapter "${adapter.id}" failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
2203
|
+
{ fileName, cause: error }
|
|
2204
|
+
);
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
}, _class);
|
|
2208
|
+
|
|
2209
|
+
// src/import/adapters.ts
|
|
2210
|
+
var markdownImportAdapter = {
|
|
2211
|
+
id: "markdown",
|
|
2212
|
+
label: "Markdown",
|
|
2213
|
+
mimeTypes: ["text/markdown", "text/x-markdown"],
|
|
2214
|
+
extensions: [".md", ".mdown", ".markdown", ".mkdn", ".mkd", ".rmd", ".md.txt"],
|
|
2215
|
+
target: "document",
|
|
2216
|
+
async import(_input, context) {
|
|
2217
|
+
const text = await context.readText();
|
|
2218
|
+
return { html: _chunkTVRC4KVTcjs.markdownToTipTapHtml.call(void 0, text), text };
|
|
2219
|
+
}
|
|
2220
|
+
};
|
|
2221
|
+
var htmlImportAdapter = {
|
|
2222
|
+
id: "html",
|
|
2223
|
+
label: "HTML",
|
|
2224
|
+
mimeTypes: ["text/html", "application/xhtml+xml"],
|
|
2225
|
+
extensions: [".html", ".htm", ".xhtml"],
|
|
2226
|
+
target: "document",
|
|
2227
|
+
async import(_input, context) {
|
|
2228
|
+
const html = _chunkLA7PEGU3cjs.sanitizeImportedHtml.call(void 0, await context.readText());
|
|
2229
|
+
return { html, text: _chunkTVRC4KVTcjs.htmlToPlainText.call(void 0, html) };
|
|
2230
|
+
}
|
|
2231
|
+
};
|
|
2232
|
+
var plainTextImportAdapter = {
|
|
2233
|
+
id: "text",
|
|
2234
|
+
label: "Plain text",
|
|
2235
|
+
mimeTypes: ["text/plain"],
|
|
2236
|
+
extensions: [".txt", ".text"],
|
|
2237
|
+
target: "document",
|
|
2238
|
+
async import(_input, context) {
|
|
2239
|
+
const text = (await context.readText()).replace(/\r\n?/g, "\n");
|
|
2240
|
+
return { html: _chunkLA7PEGU3cjs.plainTextToParagraphHtml.call(void 0, text), text };
|
|
2241
|
+
}
|
|
2242
|
+
};
|
|
2243
|
+
var rtfImportAdapter = {
|
|
2244
|
+
id: "rtf",
|
|
2245
|
+
label: "Rich Text Format",
|
|
2246
|
+
mimeTypes: ["application/rtf", "text/rtf"],
|
|
2247
|
+
extensions: [".rtf"],
|
|
2248
|
+
target: "document",
|
|
2249
|
+
async import(_input, context) {
|
|
2250
|
+
const text = _chunkLA7PEGU3cjs.rtfToPlainText.call(void 0, await context.readText());
|
|
2251
|
+
return { html: _chunkLA7PEGU3cjs.plainTextToParagraphHtml.call(void 0, text), text };
|
|
2252
|
+
}
|
|
2253
|
+
};
|
|
2254
|
+
var BUILT_IN_IMPORT_ADAPTERS = [
|
|
2255
|
+
markdownImportAdapter,
|
|
2256
|
+
htmlImportAdapter,
|
|
2257
|
+
plainTextImportAdapter,
|
|
2258
|
+
rtfImportAdapter
|
|
2259
|
+
];
|
|
2260
|
+
function createImportAdapterRegistry(options = {}) {
|
|
2261
|
+
const registry = new ImportAdapterRegistry();
|
|
2262
|
+
if (options.builtIns !== false) {
|
|
2263
|
+
BUILT_IN_IMPORT_ADAPTERS.forEach((adapter) => registry.register(adapter));
|
|
2264
|
+
}
|
|
2265
|
+
return registry;
|
|
2266
|
+
}
|
|
2267
|
+
var defaultImportRegistry = createImportAdapterRegistry();
|
|
2268
|
+
function registerImportAdapter(adapter, options) {
|
|
2269
|
+
return defaultImportRegistry.register(adapter, options);
|
|
2270
|
+
}
|
|
2271
|
+
function unregisterImportAdapter(adapterOrId) {
|
|
2272
|
+
return defaultImportRegistry.unregister(adapterOrId);
|
|
2273
|
+
}
|
|
2274
|
+
function findImportAdapter(query) {
|
|
2275
|
+
return defaultImportRegistry.find(query);
|
|
2276
|
+
}
|
|
2277
|
+
function importFile(input, options) {
|
|
2278
|
+
return defaultImportRegistry.importFile(input, options);
|
|
2279
|
+
}
|
|
2280
|
+
function getImportAccept(target) {
|
|
2281
|
+
return defaultImportRegistry.accept(target);
|
|
2282
|
+
}
|
|
2283
|
+
|
|
2284
|
+
// src/import/editor.ts
|
|
2285
|
+
|
|
2286
|
+
|
|
2287
|
+
var toView = (target) => "state" in target && "dispatch" in target ? target : target.view;
|
|
2288
|
+
function htmlToSlice(html, schema) {
|
|
2289
|
+
const Parser = _nullishCoalesce(globalThis.DOMParser, () => ( _optionalChain([globalThis, 'access', _68 => _68.window, 'optionalAccess', _69 => _69.DOMParser])));
|
|
2290
|
+
if (!Parser) return null;
|
|
2291
|
+
const body = new Parser().parseFromString(`<body>${html}</body>`, "text/html").body;
|
|
2292
|
+
return new (0, _model.Slice)(_model.DOMParser.fromSchema(schema).parse(body).content, 0, 0);
|
|
2293
|
+
}
|
|
2294
|
+
function insertImportedDocument(target, content, options = {}) {
|
|
2295
|
+
const view = toView(target);
|
|
2296
|
+
const { state } = view;
|
|
2297
|
+
const htmlSlice = options.asPlainText ? null : htmlToSlice(content.html, state.schema);
|
|
2298
|
+
const size = state.doc.content.size;
|
|
2299
|
+
let from = options.at !== void 0 ? Math.max(0, Math.min(options.at, size)) : state.selection.from;
|
|
2300
|
+
let to = options.at !== void 0 ? from : state.selection.to;
|
|
2301
|
+
if (!htmlSlice && from === to && !state.doc.resolve(from).parent.inlineContent) {
|
|
2302
|
+
from = to = _state.Selection.near(state.doc.resolve(from)).from;
|
|
2303
|
+
}
|
|
2304
|
+
const tr = htmlSlice ? state.tr.replaceRange(from, to, htmlSlice) : state.tr.replace(from, to, _chunkTVRC4KVTcjs.plainTextToSlice.call(void 0, content.text, state.schema));
|
|
2305
|
+
const end = tr.mapping.map(to, 1);
|
|
2306
|
+
view.dispatch(tr.scrollIntoView().setMeta("uiEvent", "drop"));
|
|
2307
|
+
return end;
|
|
2308
|
+
}
|
|
2309
|
+
async function importFilesIntoEditor(target, files, options = {}) {
|
|
2310
|
+
const registry = _nullishCoalesce(options.registry, () => ( defaultImportRegistry));
|
|
2311
|
+
const outcomes = [];
|
|
2312
|
+
let at = options.at;
|
|
2313
|
+
for (const file of Array.from(files)) {
|
|
2314
|
+
try {
|
|
2315
|
+
const outcome = await registry.importFile(file, { target: "document" });
|
|
2316
|
+
const view = toView(target);
|
|
2317
|
+
if (view.isDestroyed) break;
|
|
2318
|
+
at = insertImportedDocument(view, outcome.result, { at, asPlainText: options.asPlainText });
|
|
2319
|
+
outcomes.push(outcome);
|
|
2320
|
+
_optionalChain([options, 'access', _70 => _70.onImport, 'optionalCall', _71 => _71(outcome, file)]);
|
|
2321
|
+
} catch (error) {
|
|
2322
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
2323
|
+
if (options.onError) options.onError(err, file);
|
|
2324
|
+
else console.error("[Editor] File import failed:", err);
|
|
2325
|
+
}
|
|
2326
|
+
}
|
|
2327
|
+
return outcomes;
|
|
2328
|
+
}
|
|
2329
|
+
|
|
2330
|
+
// src/extensions/file-import.ts
|
|
2331
|
+
var fileImportPluginKey = new (0, _state.PluginKey)("fileImport");
|
|
2332
|
+
function getImportableFiles(files, registry) {
|
|
2333
|
+
const list = Array.from(_nullishCoalesce(files, () => ( [])));
|
|
2334
|
+
if (list.length === 0) return null;
|
|
2335
|
+
return list.every((file) => registry.canImport(file, "document")) ? list : null;
|
|
2336
|
+
}
|
|
2337
|
+
function dropPosition(view, event) {
|
|
2338
|
+
try {
|
|
2339
|
+
return _optionalChain([view, 'access', _72 => _72.posAtCoords, 'call', _73 => _73({ left: event.clientX, top: event.clientY }), 'optionalAccess', _74 => _74.pos]);
|
|
2340
|
+
} catch (e2) {
|
|
2341
|
+
return void 0;
|
|
2342
|
+
}
|
|
2343
|
+
}
|
|
2344
|
+
var FileImport = _core.Extension.create({
|
|
2345
|
+
name: "fileImport",
|
|
2346
|
+
addOptions() {
|
|
2347
|
+
return {
|
|
2348
|
+
registry: void 0,
|
|
2349
|
+
asPlainText: false,
|
|
2350
|
+
enableDrop: true,
|
|
2351
|
+
enablePaste: true,
|
|
2352
|
+
onImport: void 0,
|
|
2353
|
+
onImportError: void 0
|
|
2354
|
+
};
|
|
2355
|
+
},
|
|
2356
|
+
addProseMirrorPlugins() {
|
|
2357
|
+
const options = this.options;
|
|
2358
|
+
const registry = () => _nullishCoalesce(options.registry, () => ( defaultImportRegistry));
|
|
2359
|
+
const run = (view, files, at) => {
|
|
2360
|
+
void importFilesIntoEditor(view, files, {
|
|
2361
|
+
registry: registry(),
|
|
2362
|
+
at,
|
|
2363
|
+
asPlainText: options.asPlainText,
|
|
2364
|
+
onImport: options.onImport,
|
|
2365
|
+
onError: options.onImportError
|
|
2366
|
+
});
|
|
2367
|
+
};
|
|
2368
|
+
return [
|
|
2369
|
+
new (0, _state.Plugin)({
|
|
2370
|
+
key: fileImportPluginKey,
|
|
2371
|
+
props: {
|
|
2372
|
+
handleDrop(view, event, _slice, moved) {
|
|
2373
|
+
if (!options.enableDrop || moved) return false;
|
|
2374
|
+
const files = getImportableFiles(_optionalChain([event, 'access', _75 => _75.dataTransfer, 'optionalAccess', _76 => _76.files]), registry());
|
|
2375
|
+
if (!files) return false;
|
|
2376
|
+
event.preventDefault();
|
|
2377
|
+
run(view, files, dropPosition(view, event));
|
|
2378
|
+
return true;
|
|
2379
|
+
},
|
|
2380
|
+
handlePaste(view, event) {
|
|
2381
|
+
if (!options.enablePaste) return false;
|
|
2382
|
+
const files = getImportableFiles(_optionalChain([event, 'access', _77 => _77.clipboardData, 'optionalAccess', _78 => _78.files]), registry());
|
|
2383
|
+
if (!files) return false;
|
|
2384
|
+
event.preventDefault();
|
|
2385
|
+
run(view, files);
|
|
2386
|
+
return true;
|
|
2387
|
+
}
|
|
2388
|
+
}
|
|
2389
|
+
})
|
|
2390
|
+
];
|
|
2391
|
+
}
|
|
2392
|
+
});
|
|
2393
|
+
|
|
2394
|
+
// src/extensions/rich-clipboard.ts
|
|
2395
|
+
|
|
2396
|
+
|
|
2397
|
+
var richClipboardPluginKey = new (0, _state.PluginKey)("richClipboard");
|
|
2398
|
+
function writeRichClipboard(view, event, options = {}) {
|
|
2399
|
+
const { state } = view;
|
|
2400
|
+
if (state.selection.empty) return false;
|
|
2401
|
+
const data = _chunkLA7PEGU3cjs.getClipboardData.call(void 0, event);
|
|
2402
|
+
if (!data || typeof data.setData !== "function") return false;
|
|
2403
|
+
const slice = state.selection.content();
|
|
2404
|
+
const { dom, text } = view.serializeForClipboard(slice);
|
|
2405
|
+
event.preventDefault();
|
|
2406
|
+
_optionalChain([data, 'access', _79 => _79.clearData, 'optionalCall', _80 => _80()]);
|
|
2407
|
+
data.setData("text/html", dom.innerHTML);
|
|
2408
|
+
data.setData("text/plain", text);
|
|
2409
|
+
data.setData(_nullishCoalesce(options.mimeType, () => ( _chunkLA7PEGU3cjs.PIXERATE_DOCUMENT_MIME)), _chunkLA7PEGU3cjs.serializeRichClipboardPayload.call(void 0, slice, state.schema));
|
|
2410
|
+
if (options.cut && view.editable) {
|
|
2411
|
+
view.dispatch(state.tr.deleteSelection().scrollIntoView().setMeta("uiEvent", "cut"));
|
|
2412
|
+
}
|
|
2413
|
+
return true;
|
|
2414
|
+
}
|
|
2415
|
+
var RichClipboard = _core.Extension.create({
|
|
2416
|
+
name: "richClipboard",
|
|
2417
|
+
addOptions() {
|
|
2418
|
+
return {
|
|
2419
|
+
mimeType: _chunkLA7PEGU3cjs.PIXERATE_DOCUMENT_MIME,
|
|
2420
|
+
plainTextMode: false
|
|
2421
|
+
};
|
|
2422
|
+
},
|
|
2423
|
+
addStorage() {
|
|
2424
|
+
return { plainTextMode: !!this.options.plainTextMode };
|
|
2425
|
+
},
|
|
2426
|
+
addProseMirrorPlugins() {
|
|
2427
|
+
const mimeType = _nullishCoalesce(this.options.mimeType, () => ( _chunkLA7PEGU3cjs.PIXERATE_DOCUMENT_MIME));
|
|
2428
|
+
const storage = this.storage;
|
|
2429
|
+
return [
|
|
2430
|
+
new (0, _state.Plugin)({
|
|
2431
|
+
key: richClipboardPluginKey,
|
|
2432
|
+
props: {
|
|
2433
|
+
handleDOMEvents: {
|
|
2434
|
+
copy: (view, event) => writeRichClipboard(view, event, { mimeType }),
|
|
2435
|
+
cut: (view, event) => writeRichClipboard(view, event, { cut: true, mimeType })
|
|
2436
|
+
},
|
|
2437
|
+
handlePaste(view, event) {
|
|
2438
|
+
if (storage.plainTextMode) return false;
|
|
2439
|
+
const slice = _chunkLA7PEGU3cjs.readRichClipboard.call(void 0, event, view.state.schema, mimeType);
|
|
2440
|
+
if (!slice) return false;
|
|
2441
|
+
event.preventDefault();
|
|
2442
|
+
view.dispatch(
|
|
2443
|
+
view.state.tr.replaceSelection(slice).scrollIntoView().setMeta("paste", true).setMeta("uiEvent", "paste")
|
|
2444
|
+
);
|
|
2445
|
+
return true;
|
|
2446
|
+
}
|
|
2447
|
+
}
|
|
2448
|
+
})
|
|
2449
|
+
];
|
|
2450
|
+
}
|
|
2451
|
+
});
|
|
2452
|
+
|
|
2453
|
+
// src/extensions/autocorrect.ts
|
|
2454
|
+
|
|
2455
|
+
var _history = require('@tiptap/pm/history');
|
|
2456
|
+
|
|
2457
|
+
var quoteOpener = /[\s ([{<—–‘“-]/;
|
|
2458
|
+
var smartQuoteRules = [
|
|
2459
|
+
{
|
|
2460
|
+
id: "smart-quotes:double",
|
|
2461
|
+
find: /(^|.)"$/su,
|
|
2462
|
+
replace: (m) => m[1] + (!m[1] || quoteOpener.test(m[1]) ? "\u201C" : "\u201D")
|
|
2463
|
+
},
|
|
2464
|
+
{
|
|
2465
|
+
id: "smart-quotes:single",
|
|
2466
|
+
find: /(^|.)'$/su,
|
|
2467
|
+
replace: (m) => m[1] + (!m[1] || quoteOpener.test(m[1]) ? "\u2018" : "\u2019")
|
|
2468
|
+
}
|
|
2469
|
+
];
|
|
2470
|
+
var symbolRules = [
|
|
2471
|
+
{ id: "symbols:em-dash", find: "--", replace: "\u2014" },
|
|
2472
|
+
{ id: "symbols:ellipsis", find: "...", replace: "\u2026" },
|
|
2473
|
+
{ id: "symbols:right-arrow", find: "->", replace: "\u2192" },
|
|
2474
|
+
{ id: "symbols:left-arrow", find: "<-", replace: "\u2190" },
|
|
2475
|
+
{ id: "symbols:copyright", find: /\([cC]\)$/, replace: "\xA9" },
|
|
2476
|
+
{ id: "symbols:registered", find: /\([rR]\)$/, replace: "\xAE" },
|
|
2477
|
+
{ id: "symbols:trademark", find: /\((?:tm|TM)\)$/, replace: "\u2122" }
|
|
2478
|
+
];
|
|
2479
|
+
var FRACTIONS = { "1/2": "\xBD", "1/4": "\xBC", "3/4": "\xBE" };
|
|
2480
|
+
var fractionRules = [
|
|
2481
|
+
{
|
|
2482
|
+
id: "fractions",
|
|
2483
|
+
find: /(^|[^\d/.,])([13]\/[24])([\s.,;:!?)])$/u,
|
|
2484
|
+
replace: (m) => FRACTIONS[m[2]] ? m[1] + FRACTIONS[m[2]] + m[3] : null
|
|
2485
|
+
}
|
|
2486
|
+
];
|
|
2487
|
+
var capitalizeSentenceRules = [
|
|
2488
|
+
{
|
|
2489
|
+
id: "capitalize-sentence",
|
|
2490
|
+
find: /(?:^|(\S+)(\s+))(\p{Ll}[^\s]*)(\s)$/u,
|
|
2491
|
+
replace: (m, ctx) => {
|
|
2492
|
+
const [, previous, space = "", word, trailing] = m;
|
|
2493
|
+
if (/[./@:\\]/.test(word.slice(0, -1))) return null;
|
|
2494
|
+
if (previous !== void 0) {
|
|
2495
|
+
if (!/[.!?]["'”’)]*$/.test(previous)) return null;
|
|
2496
|
+
const token = previous.replace(/["'”’)]+$/, "");
|
|
2497
|
+
if (ctx.isException(token)) return null;
|
|
2498
|
+
if (/^\p{L}\.$/u.test(token)) return null;
|
|
2499
|
+
if (/\.\./.test(token) || token.endsWith("\u2026")) return null;
|
|
2500
|
+
}
|
|
2501
|
+
return (_nullishCoalesce(previous, () => ( ""))) + space + word.charAt(0).toUpperCase() + word.slice(1) + trailing;
|
|
2502
|
+
}
|
|
2503
|
+
}
|
|
2504
|
+
];
|
|
2505
|
+
var twoInitialCapitalsRules = [
|
|
2506
|
+
{
|
|
2507
|
+
id: "two-initial-capitals",
|
|
2508
|
+
find: /(^|[^\p{L}\p{N}'’])(\p{Lu})(\p{Lu})(\p{Ll}{1,})([\s.,;:!?])$/u,
|
|
2509
|
+
replace: (m, ctx) => {
|
|
2510
|
+
const word = m[2] + m[3] + m[4];
|
|
2511
|
+
if (ctx.isException(word)) return null;
|
|
2512
|
+
return m[1] + m[2] + m[3].toLowerCase() + m[4] + m[5];
|
|
2513
|
+
}
|
|
2514
|
+
}
|
|
2515
|
+
];
|
|
2516
|
+
var defaultAutocorrectRules = [
|
|
2517
|
+
...smartQuoteRules,
|
|
2518
|
+
...symbolRules,
|
|
2519
|
+
...fractionRules,
|
|
2520
|
+
...capitalizeSentenceRules,
|
|
2521
|
+
...twoInitialCapitalsRules
|
|
2522
|
+
];
|
|
2523
|
+
var DEFAULT_AUTOCORRECT_EXCEPTIONS = [
|
|
2524
|
+
"a.m.",
|
|
2525
|
+
"abbr.",
|
|
2526
|
+
"approx.",
|
|
2527
|
+
"apt.",
|
|
2528
|
+
"assn.",
|
|
2529
|
+
"ave.",
|
|
2530
|
+
"ca.",
|
|
2531
|
+
"cf.",
|
|
2532
|
+
"co.",
|
|
2533
|
+
"corp.",
|
|
2534
|
+
"dept.",
|
|
2535
|
+
"dr.",
|
|
2536
|
+
"e.g.",
|
|
2537
|
+
"est.",
|
|
2538
|
+
"etc.",
|
|
2539
|
+
"fig.",
|
|
2540
|
+
"i.e.",
|
|
2541
|
+
"inc.",
|
|
2542
|
+
"jr.",
|
|
2543
|
+
"ltd.",
|
|
2544
|
+
"mr.",
|
|
2545
|
+
"mrs.",
|
|
2546
|
+
"ms.",
|
|
2547
|
+
"mt.",
|
|
2548
|
+
"no.",
|
|
2549
|
+
"p.",
|
|
2550
|
+
"p.m.",
|
|
2551
|
+
"pp.",
|
|
2552
|
+
"prof.",
|
|
2553
|
+
"sr.",
|
|
2554
|
+
"st.",
|
|
2555
|
+
"vol.",
|
|
2556
|
+
"vs.",
|
|
2557
|
+
"CDs",
|
|
2558
|
+
"IDs",
|
|
2559
|
+
"PCs",
|
|
2560
|
+
"GHz",
|
|
2561
|
+
"MHz",
|
|
2562
|
+
"KHz"
|
|
2563
|
+
];
|
|
2564
|
+
var autocorrectPluginKey = new (0, _state.PluginKey)("autocorrect");
|
|
2565
|
+
var WHOLE_WORD_DELIMITER = /[\s.,;:!?]/;
|
|
2566
|
+
function findAutocorrection(textBefore, rules, context) {
|
|
2567
|
+
const ctx = { ...context, textBefore };
|
|
2568
|
+
for (const rule of rules) {
|
|
2569
|
+
let match = null;
|
|
2570
|
+
if (typeof rule.find === "string") {
|
|
2571
|
+
const find = rule.find;
|
|
2572
|
+
if (rule.wholeWord) {
|
|
2573
|
+
const delimiter = textBefore.slice(-1);
|
|
2574
|
+
if (!WHOLE_WORD_DELIMITER.test(delimiter)) continue;
|
|
2575
|
+
const body = textBefore.slice(0, -1);
|
|
2576
|
+
if (!body.endsWith(find)) continue;
|
|
2577
|
+
const before = body.charAt(body.length - find.length - 1);
|
|
2578
|
+
if (before && /[\p{L}\p{N}_]/u.test(before)) continue;
|
|
2579
|
+
match = Object.assign([find + delimiter], {
|
|
2580
|
+
index: textBefore.length - find.length - 1,
|
|
2581
|
+
input: textBefore
|
|
2582
|
+
});
|
|
2583
|
+
} else {
|
|
2584
|
+
if (!textBefore.endsWith(find)) continue;
|
|
2585
|
+
match = Object.assign([find], {
|
|
2586
|
+
index: textBefore.length - find.length,
|
|
2587
|
+
input: textBefore
|
|
2588
|
+
});
|
|
2589
|
+
}
|
|
2590
|
+
} else {
|
|
2591
|
+
const regex = new RegExp(rule.find.source, rule.find.flags.replace("g", ""));
|
|
2592
|
+
match = textBefore.match(regex);
|
|
2593
|
+
if (!match || match.index + match[0].length !== textBefore.length) continue;
|
|
2594
|
+
}
|
|
2595
|
+
const original = match[0];
|
|
2596
|
+
if (ctx.isException(original.trim())) continue;
|
|
2597
|
+
let replacement;
|
|
2598
|
+
if (typeof rule.replace === "function") {
|
|
2599
|
+
replacement = rule.replace(match, ctx);
|
|
2600
|
+
} else {
|
|
2601
|
+
replacement = rule.wholeWord && typeof rule.find === "string" ? rule.replace + original.slice(-1) : rule.replace;
|
|
2602
|
+
}
|
|
2603
|
+
if (replacement == null || replacement === original) continue;
|
|
2604
|
+
return { ruleId: rule.id, start: match.index, original, replacement };
|
|
2605
|
+
}
|
|
2606
|
+
return null;
|
|
2607
|
+
}
|
|
2608
|
+
function isInsidePromptToken(textBefore) {
|
|
2609
|
+
if (textBefore.lastIndexOf("{") > textBefore.lastIndexOf("}")) return true;
|
|
2610
|
+
const underscores = textBefore.match(/__/g);
|
|
2611
|
+
return !!underscores && underscores.length % 2 === 1;
|
|
2612
|
+
}
|
|
2613
|
+
var Autocorrect = _core.Extension.create({
|
|
2614
|
+
name: "autocorrect",
|
|
2615
|
+
addOptions() {
|
|
2616
|
+
return {
|
|
2617
|
+
rules: defaultAutocorrectRules,
|
|
2618
|
+
exceptions: DEFAULT_AUTOCORRECT_EXCEPTIONS,
|
|
2619
|
+
ignoreNodes: ["codeBlock"],
|
|
2620
|
+
ignoreMarks: ["code"],
|
|
2621
|
+
ignorePromptTokens: true,
|
|
2622
|
+
onCorrection: void 0
|
|
2623
|
+
};
|
|
2624
|
+
},
|
|
2625
|
+
addStorage() {
|
|
2626
|
+
return {
|
|
2627
|
+
enabled: true,
|
|
2628
|
+
exceptions: new Set(this.options.exceptions.map((e) => e.toLowerCase()))
|
|
2629
|
+
};
|
|
2630
|
+
},
|
|
2631
|
+
addCommands() {
|
|
2632
|
+
return {
|
|
2633
|
+
undoAutocorrect: () => ({ state, tr, dispatch }) => {
|
|
2634
|
+
const last = _optionalChain([autocorrectPluginKey, 'access', _81 => _81.getState, 'call', _82 => _82(state), 'optionalAccess', _83 => _83.last]);
|
|
2635
|
+
if (!last) return false;
|
|
2636
|
+
if (state.doc.textBetween(last.from, last.to) !== last.replacement) return false;
|
|
2637
|
+
if (dispatch) {
|
|
2638
|
+
tr.insertText(last.original, last.from, last.to);
|
|
2639
|
+
tr.setMeta(autocorrectPluginKey, { undo: true });
|
|
2640
|
+
}
|
|
2641
|
+
return true;
|
|
2642
|
+
},
|
|
2643
|
+
setAutocorrectEnabled: (enabled) => () => {
|
|
2644
|
+
this.storage.enabled = enabled;
|
|
2645
|
+
return true;
|
|
2646
|
+
},
|
|
2647
|
+
addAutocorrectException: (text) => () => {
|
|
2648
|
+
this.storage.exceptions.add(text.toLowerCase());
|
|
2649
|
+
return true;
|
|
2650
|
+
},
|
|
2651
|
+
removeAutocorrectException: (text) => () => this.storage.exceptions.delete(text.toLowerCase())
|
|
2652
|
+
};
|
|
2653
|
+
},
|
|
2654
|
+
addProseMirrorPlugins() {
|
|
2655
|
+
const extension = this;
|
|
2656
|
+
const isIgnored = (state, from, to) => {
|
|
2657
|
+
const { ignoreNodes, ignoreMarks } = extension.options;
|
|
2658
|
+
const $from = state.doc.resolve(from);
|
|
2659
|
+
for (let d = $from.depth; d > 0; d--) {
|
|
2660
|
+
const node = $from.node(d);
|
|
2661
|
+
if (node.type.spec.code || ignoreNodes.includes(node.type.name)) return true;
|
|
2662
|
+
}
|
|
2663
|
+
const isIgnoredMark = (mark) => mark.type.spec.code || ignoreMarks.includes(mark.type.name);
|
|
2664
|
+
const marks = _nullishCoalesce(state.storedMarks, () => ( $from.marks()));
|
|
2665
|
+
if (marks.some(isIgnoredMark)) return true;
|
|
2666
|
+
let ignored = false;
|
|
2667
|
+
if (to > from) {
|
|
2668
|
+
state.doc.nodesBetween(from, to, (node) => {
|
|
2669
|
+
if (node.marks.some(isIgnoredMark)) ignored = true;
|
|
2670
|
+
});
|
|
2671
|
+
}
|
|
2672
|
+
return ignored;
|
|
2673
|
+
};
|
|
2674
|
+
const handleTextInput = (view, from, to, text) => {
|
|
2675
|
+
if (!extension.storage.enabled || view.composing) return false;
|
|
2676
|
+
const { state } = view;
|
|
2677
|
+
const pluginState = autocorrectPluginKey.getState(state);
|
|
2678
|
+
const $from = state.doc.resolve(from);
|
|
2679
|
+
if (!$from.parent.isTextblock || !$from.sameParent(state.doc.resolve(to))) {
|
|
2680
|
+
return false;
|
|
2681
|
+
}
|
|
2682
|
+
const insertTyped = () => {
|
|
2683
|
+
const tr2 = state.tr.insertText(text, from, to);
|
|
2684
|
+
if (_optionalChain([pluginState, 'optionalAccess', _84 => _84.closePending])) _history.closeHistory.call(void 0, tr2);
|
|
2685
|
+
view.dispatch(tr2);
|
|
2686
|
+
};
|
|
2687
|
+
if (isIgnored(state, from, to)) return false;
|
|
2688
|
+
const textBefore = $from.parent.textBetween(0, $from.parentOffset, void 0, "\uFFFC") + text;
|
|
2689
|
+
if (extension.options.ignorePromptTokens && isInsidePromptToken(textBefore)) {
|
|
2690
|
+
return false;
|
|
2691
|
+
}
|
|
2692
|
+
const currentWord = _nullishCoalesce(_optionalChain([/\S*$/, 'access', _85 => _85.exec, 'call', _86 => _86(textBefore), 'optionalAccess', _87 => _87[0]]), () => ( ""));
|
|
2693
|
+
if (/:\/\/|^www\./i.test(currentWord)) return false;
|
|
2694
|
+
const exceptions = extension.storage.exceptions;
|
|
2695
|
+
const found = findAutocorrection(textBefore, extension.options.rules, {
|
|
2696
|
+
state,
|
|
2697
|
+
isException: (value) => exceptions.has(value.toLowerCase())
|
|
2698
|
+
});
|
|
2699
|
+
if (!found) {
|
|
2700
|
+
if (!_optionalChain([pluginState, 'optionalAccess', _88 => _88.closePending])) return false;
|
|
2701
|
+
insertTyped();
|
|
2702
|
+
return true;
|
|
2703
|
+
}
|
|
2704
|
+
let { original, replacement } = found;
|
|
2705
|
+
let start2 = found.start;
|
|
2706
|
+
let prefix = 0;
|
|
2707
|
+
while (prefix < original.length && prefix < replacement.length && original[prefix] === replacement[prefix]) {
|
|
2708
|
+
prefix++;
|
|
2709
|
+
}
|
|
2710
|
+
let suffix = 0;
|
|
2711
|
+
while (suffix < original.length - prefix && suffix < replacement.length - prefix && original[original.length - 1 - suffix] === replacement[replacement.length - 1 - suffix]) {
|
|
2712
|
+
suffix++;
|
|
2713
|
+
}
|
|
2714
|
+
start2 += prefix;
|
|
2715
|
+
original = original.slice(prefix, original.length - suffix);
|
|
2716
|
+
replacement = replacement.slice(prefix, replacement.length - suffix);
|
|
2717
|
+
const textEnd = textBefore.length - suffix;
|
|
2718
|
+
insertTyped();
|
|
2719
|
+
const next = view.state;
|
|
2720
|
+
const blockStart = next.doc.resolve(from + text.length).start();
|
|
2721
|
+
const correctionFrom = blockStart + start2;
|
|
2722
|
+
const correctionTo = blockStart + textEnd;
|
|
2723
|
+
if (next.doc.textBetween(correctionFrom, correctionTo, void 0, "\uFFFC") !== original || isIgnored(next, correctionFrom, correctionTo)) {
|
|
2724
|
+
return true;
|
|
2725
|
+
}
|
|
2726
|
+
const correction = {
|
|
2727
|
+
ruleId: found.ruleId,
|
|
2728
|
+
from: correctionFrom,
|
|
2729
|
+
to: correctionFrom + replacement.length,
|
|
2730
|
+
original,
|
|
2731
|
+
replacement
|
|
2732
|
+
};
|
|
2733
|
+
const tr = next.tr.insertText(replacement, correctionFrom, correctionTo);
|
|
2734
|
+
_history.closeHistory.call(void 0, tr);
|
|
2735
|
+
tr.setMeta(autocorrectPluginKey, { correction });
|
|
2736
|
+
view.dispatch(tr);
|
|
2737
|
+
_optionalChain([extension, 'access', _89 => _89.options, 'access', _90 => _90.onCorrection, 'optionalCall', _91 => _91(correction)]);
|
|
2738
|
+
return true;
|
|
2739
|
+
};
|
|
2740
|
+
return [
|
|
2741
|
+
new (0, _state.Plugin)({
|
|
2742
|
+
key: autocorrectPluginKey,
|
|
2743
|
+
state: {
|
|
2744
|
+
init: () => ({ last: null, closePending: false }),
|
|
2745
|
+
apply: (tr, prev) => {
|
|
2746
|
+
const meta = tr.getMeta(autocorrectPluginKey);
|
|
2747
|
+
if (_optionalChain([meta, 'optionalAccess', _92 => _92.correction])) return { last: meta.correction, closePending: true };
|
|
2748
|
+
if (_optionalChain([meta, 'optionalAccess', _93 => _93.undo])) return { last: null, closePending: true };
|
|
2749
|
+
if (!tr.docChanged) return prev;
|
|
2750
|
+
if (!prev.last && !prev.closePending) return prev;
|
|
2751
|
+
return { last: null, closePending: false };
|
|
2752
|
+
}
|
|
2753
|
+
},
|
|
2754
|
+
props: { handleTextInput }
|
|
2755
|
+
})
|
|
2756
|
+
];
|
|
2757
|
+
}
|
|
2758
|
+
});
|
|
2759
|
+
|
|
2760
|
+
// src/extensions/document-structure/outline.ts
|
|
2761
|
+
|
|
2762
|
+
|
|
2763
|
+
|
|
2764
|
+
|
|
2765
|
+
|
|
2766
|
+
|
|
2767
|
+
|
|
2768
|
+
// src/extensions/document-structure/utils.ts
|
|
2769
|
+
|
|
2770
|
+
|
|
2771
|
+
var _transform = require('@tiptap/pm/transform');
|
|
2772
|
+
var idCounter = 0;
|
|
2773
|
+
function generateStructureId(prefix) {
|
|
2774
|
+
idCounter = (idCounter + 1) % 1296;
|
|
2775
|
+
const random = Math.random().toString(36).slice(2, 8).padEnd(6, "0");
|
|
2776
|
+
return `${prefix}-${random}${idCounter.toString(36).padStart(2, "0")}`;
|
|
2777
|
+
}
|
|
2778
|
+
function transactionsInsert(transactions, typeNames) {
|
|
2779
|
+
for (const tr of transactions) {
|
|
2780
|
+
for (const step of tr.steps) {
|
|
2781
|
+
if (!(step instanceof _transform.ReplaceStep || step instanceof _transform.ReplaceAroundStep)) {
|
|
2782
|
+
const mark = step.mark;
|
|
2783
|
+
if (mark && typeNames.includes(mark.type.name)) return true;
|
|
2784
|
+
continue;
|
|
2785
|
+
}
|
|
2786
|
+
let found = false;
|
|
2787
|
+
step.slice.content.descendants((node) => {
|
|
2788
|
+
if (found) return false;
|
|
2789
|
+
if (typeNames.includes(node.type.name) || node.marks.some((m) => typeNames.includes(m.type.name))) {
|
|
2790
|
+
found = true;
|
|
2791
|
+
}
|
|
2792
|
+
return !found;
|
|
2793
|
+
});
|
|
2794
|
+
if (found) return true;
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
return false;
|
|
2798
|
+
}
|
|
2799
|
+
function docContains(doc, typeNames) {
|
|
2800
|
+
let found = false;
|
|
2801
|
+
doc.descendants((node) => {
|
|
2802
|
+
if (found) return false;
|
|
2803
|
+
if (typeNames.includes(node.type.name) || node.marks.some((m) => typeNames.includes(m.type.name))) {
|
|
2804
|
+
found = true;
|
|
2805
|
+
}
|
|
2806
|
+
return !found;
|
|
2807
|
+
});
|
|
2808
|
+
return found;
|
|
2809
|
+
}
|
|
2810
|
+
function presenceStateSpec(typeNames) {
|
|
2811
|
+
return {
|
|
2812
|
+
init: (_config, state) => docContains(state.doc, typeNames),
|
|
2813
|
+
apply: (tr, present, _oldState, newState) => {
|
|
2814
|
+
if (!tr.docChanged) return present;
|
|
2815
|
+
if (!present && !transactionsInsert([tr], typeNames)) return false;
|
|
2816
|
+
return docContains(newState.doc, typeNames);
|
|
2817
|
+
}
|
|
2818
|
+
};
|
|
2819
|
+
}
|
|
2820
|
+
function arraysEqual(a, b, eq) {
|
|
2821
|
+
if (a.length !== b.length) return false;
|
|
2822
|
+
for (let i = 0; i < a.length; i++) {
|
|
2823
|
+
if (!eq(a[i], b[i])) return false;
|
|
2824
|
+
}
|
|
2825
|
+
return true;
|
|
2826
|
+
}
|
|
2827
|
+
function scrollDomAtPos(view, pos, behavior = "smooth") {
|
|
2828
|
+
try {
|
|
2829
|
+
const dom = _optionalChain([view, 'optionalAccess', _94 => _94.nodeDOM, 'optionalCall', _95 => _95(pos)]);
|
|
2830
|
+
if (dom && typeof dom.scrollIntoView === "function") {
|
|
2831
|
+
dom.scrollIntoView({ block: "start", behavior });
|
|
2832
|
+
}
|
|
2833
|
+
} catch (e3) {
|
|
2834
|
+
}
|
|
2835
|
+
}
|
|
2836
|
+
function syncInitialContent(editor, sync) {
|
|
2837
|
+
const { content } = editor.options;
|
|
2838
|
+
if (content == null || content === "") return;
|
|
2839
|
+
try {
|
|
2840
|
+
const doc = _core.createDocument.call(void 0, content, editor.schema, editor.options.parseOptions, {
|
|
2841
|
+
errorOnInvalidContent: false
|
|
2842
|
+
});
|
|
2843
|
+
const tr = sync(_state.EditorState.create({ doc }));
|
|
2844
|
+
if (_optionalChain([tr, 'optionalAccess', _96 => _96.docChanged])) editor.options.content = tr.doc;
|
|
2845
|
+
} catch (e4) {
|
|
2846
|
+
}
|
|
2847
|
+
}
|
|
2848
|
+
var STRUCTURE_PRIORITY = 45;
|
|
2849
|
+
|
|
2850
|
+
// src/extensions/document-structure/outline.ts
|
|
2851
|
+
var outlinePluginKey = new (0, _state.PluginKey)("outline");
|
|
2852
|
+
var outlineIdPluginKey = new (0, _state.PluginKey)("outlineIds");
|
|
2853
|
+
var sameHeading = (a, b) => a.id === b.id && a.level === b.level && a.text === b.text && a.pos === b.pos && a.depth === b.depth;
|
|
2854
|
+
function computeOutline(doc, types = ["heading"]) {
|
|
2855
|
+
const headings = [];
|
|
2856
|
+
const stack = [];
|
|
2857
|
+
doc.descendants((node, pos) => {
|
|
2858
|
+
if (types.includes(node.type.name)) {
|
|
2859
|
+
const level = Number(node.attrs.level) || 1;
|
|
2860
|
+
while (stack.length && stack[stack.length - 1] >= level) stack.pop();
|
|
2861
|
+
headings.push({
|
|
2862
|
+
id: _nullishCoalesce(node.attrs.id, () => ( `outline-${headings.length}`)),
|
|
2863
|
+
level,
|
|
2864
|
+
text: node.textContent,
|
|
2865
|
+
pos,
|
|
2866
|
+
index: headings.length,
|
|
2867
|
+
depth: stack.length
|
|
2868
|
+
});
|
|
2869
|
+
stack.push(level);
|
|
2870
|
+
return false;
|
|
2871
|
+
}
|
|
2872
|
+
return !node.isTextblock;
|
|
2873
|
+
});
|
|
2874
|
+
return headings;
|
|
2875
|
+
}
|
|
2876
|
+
function buildOutlineTree(headings) {
|
|
2877
|
+
const root = [];
|
|
2878
|
+
const stack = [];
|
|
2879
|
+
for (const heading of headings) {
|
|
2880
|
+
const item = { ...heading, children: [] };
|
|
2881
|
+
while (stack.length && stack[stack.length - 1].level >= item.level) {
|
|
2882
|
+
stack.pop();
|
|
2883
|
+
}
|
|
2884
|
+
if (stack.length) stack[stack.length - 1].children.push(item);
|
|
2885
|
+
else root.push(item);
|
|
2886
|
+
stack.push(item);
|
|
2887
|
+
}
|
|
2888
|
+
return root;
|
|
2889
|
+
}
|
|
2890
|
+
function getOutline(editorOrState) {
|
|
2891
|
+
const state = "state" in editorOrState ? editorOrState.state : editorOrState;
|
|
2892
|
+
return _nullishCoalesce(outlinePluginKey.getState(state), () => ( computeOutline(state.doc)));
|
|
2893
|
+
}
|
|
2894
|
+
function getActiveHeading(editorOrState, headings = getOutline(editorOrState)) {
|
|
2895
|
+
const state = "state" in editorOrState ? editorOrState.state : editorOrState;
|
|
2896
|
+
const head = state.selection.from;
|
|
2897
|
+
let lo = 0;
|
|
2898
|
+
let hi = headings.length - 1;
|
|
2899
|
+
let found = null;
|
|
2900
|
+
while (lo <= hi) {
|
|
2901
|
+
const mid = lo + hi >> 1;
|
|
2902
|
+
if (headings[mid].pos <= head) {
|
|
2903
|
+
found = headings[mid];
|
|
2904
|
+
lo = mid + 1;
|
|
2905
|
+
} else {
|
|
2906
|
+
hi = mid - 1;
|
|
2907
|
+
}
|
|
2908
|
+
}
|
|
2909
|
+
return found;
|
|
2910
|
+
}
|
|
2911
|
+
function findHeading(state, id) {
|
|
2912
|
+
return _nullishCoalesce(getOutline(state).find((h) => h.id === id), () => ( null));
|
|
2913
|
+
}
|
|
2914
|
+
var EMPTY_SNAPSHOT = Object.freeze({
|
|
2915
|
+
headings: [],
|
|
2916
|
+
tree: [],
|
|
2917
|
+
activeId: null
|
|
2918
|
+
});
|
|
2919
|
+
function createOutlineStore(editor) {
|
|
2920
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
2921
|
+
let snapshot = EMPTY_SNAPSHOT;
|
|
2922
|
+
const compute = () => {
|
|
2923
|
+
if (!editor || editor.isDestroyed) return EMPTY_SNAPSHOT;
|
|
2924
|
+
const headings = getOutline(editor);
|
|
2925
|
+
const activeId = _nullishCoalesce(_optionalChain([getActiveHeading, 'call', _97 => _97(editor, headings), 'optionalAccess', _98 => _98.id]), () => ( null));
|
|
2926
|
+
const sameStructure = arraysEqual(snapshot.headings, headings, sameHeading);
|
|
2927
|
+
if (sameStructure && snapshot.activeId === activeId) return snapshot;
|
|
2928
|
+
return {
|
|
2929
|
+
headings: sameStructure ? snapshot.headings : headings,
|
|
2930
|
+
tree: sameStructure ? snapshot.tree : buildOutlineTree(headings),
|
|
2931
|
+
activeId
|
|
2932
|
+
};
|
|
2933
|
+
};
|
|
2934
|
+
snapshot = compute();
|
|
2935
|
+
const onTransaction = () => {
|
|
2936
|
+
const next = compute();
|
|
2937
|
+
if (next !== snapshot) {
|
|
2938
|
+
snapshot = next;
|
|
2939
|
+
listeners.forEach((l) => l());
|
|
2940
|
+
}
|
|
2941
|
+
};
|
|
2942
|
+
return {
|
|
2943
|
+
getSnapshot: () => {
|
|
2944
|
+
if (!listeners.size) snapshot = compute();
|
|
2945
|
+
return snapshot;
|
|
2946
|
+
},
|
|
2947
|
+
subscribe(listener) {
|
|
2948
|
+
if (!listeners.size) {
|
|
2949
|
+
snapshot = compute();
|
|
2950
|
+
_optionalChain([editor, 'optionalAccess', _99 => _99.on, 'call', _100 => _100("transaction", onTransaction)]);
|
|
2951
|
+
}
|
|
2952
|
+
listeners.add(listener);
|
|
2953
|
+
return () => {
|
|
2954
|
+
listeners.delete(listener);
|
|
2955
|
+
if (!listeners.size) _optionalChain([editor, 'optionalAccess', _101 => _101.off, 'call', _102 => _102("transaction", onTransaction)]);
|
|
2956
|
+
};
|
|
2957
|
+
},
|
|
2958
|
+
destroy() {
|
|
2959
|
+
_optionalChain([editor, 'optionalAccess', _103 => _103.off, 'call', _104 => _104("transaction", onTransaction)]);
|
|
2960
|
+
listeners.clear();
|
|
2961
|
+
}
|
|
2962
|
+
};
|
|
2963
|
+
}
|
|
2964
|
+
function navigateToHeading(editor, heading, options = {}) {
|
|
2965
|
+
if (!editor || editor.isDestroyed) return false;
|
|
2966
|
+
const current = _nullishCoalesce(findHeading(editor.state, heading.id), () => ( getOutline(editor).find((h) => h.pos === heading.pos)));
|
|
2967
|
+
if (!current) return false;
|
|
2968
|
+
const { focus = true, behavior = "smooth" } = options;
|
|
2969
|
+
if (focus) {
|
|
2970
|
+
const tr = editor.state.tr.setSelection(_state.TextSelection.create(editor.state.doc, current.pos + 1)).scrollIntoView();
|
|
2971
|
+
editor.view.dispatch(tr);
|
|
2972
|
+
editor.view.focus();
|
|
2973
|
+
}
|
|
2974
|
+
scrollDomAtPos(editor.view, current.pos, behavior);
|
|
2975
|
+
return true;
|
|
2976
|
+
}
|
|
2977
|
+
function assignHeadingIds(state, types, generateId) {
|
|
2978
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2979
|
+
let tr = null;
|
|
2980
|
+
state.doc.descendants((node, pos) => {
|
|
2981
|
+
if (types.includes(node.type.name)) {
|
|
2982
|
+
let id = node.attrs.id;
|
|
2983
|
+
if (!id || seen.has(id)) {
|
|
2984
|
+
do {
|
|
2985
|
+
id = generateId();
|
|
2986
|
+
} while (seen.has(id));
|
|
2987
|
+
tr = _nullishCoalesce(tr, () => ( state.tr));
|
|
2988
|
+
tr.setNodeMarkup(pos, void 0, { ...node.attrs, id });
|
|
2989
|
+
}
|
|
2990
|
+
seen.add(id);
|
|
2991
|
+
return false;
|
|
2992
|
+
}
|
|
2993
|
+
return !node.isTextblock;
|
|
2994
|
+
});
|
|
2995
|
+
return tr;
|
|
2996
|
+
}
|
|
2997
|
+
var Outline = _core.Extension.create({
|
|
2998
|
+
name: "outline",
|
|
2999
|
+
priority: STRUCTURE_PRIORITY,
|
|
3000
|
+
addOptions() {
|
|
3001
|
+
return {
|
|
3002
|
+
types: ["heading"],
|
|
3003
|
+
generateId: () => generateStructureId("h"),
|
|
3004
|
+
onUpdate: void 0
|
|
3005
|
+
};
|
|
3006
|
+
},
|
|
3007
|
+
addStorage() {
|
|
3008
|
+
return { headings: [] };
|
|
3009
|
+
},
|
|
3010
|
+
addGlobalAttributes() {
|
|
3011
|
+
return [
|
|
3012
|
+
{
|
|
3013
|
+
types: this.options.types,
|
|
3014
|
+
attributes: {
|
|
3015
|
+
id: {
|
|
3016
|
+
default: null,
|
|
3017
|
+
keepOnSplit: false,
|
|
3018
|
+
parseHTML: (element) => element.getAttribute("id") || element.getAttribute("data-id"),
|
|
3019
|
+
renderHTML: (attributes) => attributes.id ? { id: attributes.id } : {}
|
|
3020
|
+
}
|
|
3021
|
+
}
|
|
3022
|
+
}
|
|
3023
|
+
];
|
|
3024
|
+
},
|
|
3025
|
+
addCommands() {
|
|
3026
|
+
return {
|
|
3027
|
+
focusHeading: (id, options = {}) => ({ state, tr, dispatch, view }) => {
|
|
3028
|
+
const heading = findHeading(state, id);
|
|
3029
|
+
if (!heading) return false;
|
|
3030
|
+
if (dispatch) {
|
|
3031
|
+
if (options.focus !== false) {
|
|
3032
|
+
tr.setSelection(_state.TextSelection.create(tr.doc, heading.pos + 1));
|
|
3033
|
+
tr.scrollIntoView();
|
|
3034
|
+
_optionalChain([view, 'optionalAccess', _105 => _105.focus, 'optionalCall', _106 => _106()]);
|
|
3035
|
+
}
|
|
3036
|
+
scrollDomAtPos(view, heading.pos, options.behavior);
|
|
3037
|
+
}
|
|
3038
|
+
return true;
|
|
3039
|
+
},
|
|
3040
|
+
scrollToHeading: (id, options = {}) => ({ state, dispatch, view }) => {
|
|
3041
|
+
const heading = findHeading(state, id);
|
|
3042
|
+
if (!heading) return false;
|
|
3043
|
+
if (dispatch) scrollDomAtPos(view, heading.pos, options.behavior);
|
|
3044
|
+
return true;
|
|
3045
|
+
}
|
|
3046
|
+
};
|
|
3047
|
+
},
|
|
3048
|
+
addProseMirrorPlugins() {
|
|
3049
|
+
const { types, generateId } = this.options;
|
|
3050
|
+
const storage = this.storage;
|
|
3051
|
+
const onUpdate = () => this.options.onUpdate;
|
|
3052
|
+
return [
|
|
3053
|
+
new (0, _state.Plugin)({
|
|
3054
|
+
key: outlinePluginKey,
|
|
3055
|
+
state: {
|
|
3056
|
+
init: (_config, state) => {
|
|
3057
|
+
const headings = computeOutline(state.doc, types);
|
|
3058
|
+
storage.headings = headings;
|
|
3059
|
+
return headings;
|
|
3060
|
+
},
|
|
3061
|
+
apply: (tr, prev, _oldState, newState) => {
|
|
3062
|
+
if (!tr.docChanged) return prev;
|
|
3063
|
+
const next = computeOutline(newState.doc, types);
|
|
3064
|
+
if (arraysEqual(prev, next, sameHeading)) return prev;
|
|
3065
|
+
storage.headings = next;
|
|
3066
|
+
_optionalChain([onUpdate, 'call', _107 => _107(), 'optionalCall', _108 => _108(next)]);
|
|
3067
|
+
return next;
|
|
3068
|
+
}
|
|
3069
|
+
}
|
|
3070
|
+
}),
|
|
3071
|
+
new (0, _state.Plugin)({
|
|
3072
|
+
key: outlineIdPluginKey,
|
|
3073
|
+
appendTransaction: (transactions, _oldState, newState) => {
|
|
3074
|
+
if (!transactions.some((tr) => tr.docChanged)) return null;
|
|
3075
|
+
return assignHeadingIds(newState, types, generateId);
|
|
3076
|
+
}
|
|
3077
|
+
})
|
|
3078
|
+
];
|
|
3079
|
+
},
|
|
3080
|
+
onBeforeCreate() {
|
|
3081
|
+
const { types, generateId } = this.options;
|
|
3082
|
+
syncInitialContent(this.editor, (state) => assignHeadingIds(state, types, generateId));
|
|
3083
|
+
}
|
|
3084
|
+
});
|
|
3085
|
+
|
|
3086
|
+
// src/extensions/document-structure/table-of-contents.ts
|
|
3087
|
+
|
|
3088
|
+
|
|
3089
|
+
|
|
3090
|
+
|
|
3091
|
+
|
|
3092
|
+
|
|
3093
|
+
|
|
3094
|
+
// src/extensions/document-structure/markdown-it.ts
|
|
3095
|
+
var installed = /* @__PURE__ */ new WeakMap();
|
|
3096
|
+
function once(md2, name) {
|
|
3097
|
+
let names = installed.get(md2);
|
|
3098
|
+
if (!names) {
|
|
3099
|
+
names = /* @__PURE__ */ new Set();
|
|
3100
|
+
installed.set(md2, names);
|
|
3101
|
+
}
|
|
3102
|
+
if (names.has(name)) return false;
|
|
3103
|
+
names.add(name);
|
|
3104
|
+
return true;
|
|
3105
|
+
}
|
|
3106
|
+
var escapeAttr = (value) => value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
3107
|
+
var TOC_LINE = /^(?:\[\[toc\]\]|\[toc\])\s*$/i;
|
|
3108
|
+
function tableOfContentsMarkdownIt(md2) {
|
|
3109
|
+
if (!once(md2, "toc")) return;
|
|
3110
|
+
md2.block.ruler.before(
|
|
3111
|
+
"reference",
|
|
3112
|
+
"pixerate_toc",
|
|
3113
|
+
(state, startLine, _endLine, silent) => {
|
|
3114
|
+
if (state.sCount[startLine] - state.blkIndent >= 4) return false;
|
|
3115
|
+
const start2 = state.bMarks[startLine] + state.tShift[startLine];
|
|
3116
|
+
const line = state.src.slice(start2, state.eMarks[startLine]);
|
|
3117
|
+
if (!TOC_LINE.test(line)) return false;
|
|
3118
|
+
if (silent) return true;
|
|
3119
|
+
const token = state.push("pixerate_toc", "nav", 0);
|
|
3120
|
+
token.block = true;
|
|
3121
|
+
token.map = [startLine, startLine + 1];
|
|
3122
|
+
state.line = startLine + 1;
|
|
3123
|
+
return true;
|
|
3124
|
+
},
|
|
3125
|
+
{ alt: ["paragraph", "reference"] }
|
|
3126
|
+
);
|
|
3127
|
+
md2.renderer.rules.pixerate_toc = () => '<nav data-type="table-of-contents"></nav>\n';
|
|
3128
|
+
}
|
|
3129
|
+
var FOOTNOTE_DEF = /^\[\^([^\]\s]+)\]:[ \t]?(.*)$/;
|
|
3130
|
+
function footnotesMarkdownIt(md2) {
|
|
3131
|
+
if (!once(md2, "footnotes")) return;
|
|
3132
|
+
md2.block.ruler.before(
|
|
3133
|
+
"reference",
|
|
3134
|
+
"pixerate_footnote_def",
|
|
3135
|
+
(state, startLine, endLine, silent) => {
|
|
3136
|
+
if (state.sCount[startLine] - state.blkIndent >= 4) return false;
|
|
3137
|
+
const start2 = state.bMarks[startLine] + state.tShift[startLine];
|
|
3138
|
+
const match = FOOTNOTE_DEF.exec(
|
|
3139
|
+
state.src.slice(start2, state.eMarks[startLine])
|
|
3140
|
+
);
|
|
3141
|
+
if (!match) return false;
|
|
3142
|
+
if (silent) return true;
|
|
3143
|
+
const paragraphs = [[match[2]]];
|
|
3144
|
+
let lastContentLine = startLine;
|
|
3145
|
+
let pendingBlank = false;
|
|
3146
|
+
for (let line = startLine + 1; line < endLine; line++) {
|
|
3147
|
+
const lineStart = state.bMarks[line] + state.tShift[line];
|
|
3148
|
+
const lineEnd = state.eMarks[line];
|
|
3149
|
+
if (lineStart >= lineEnd) {
|
|
3150
|
+
pendingBlank = true;
|
|
3151
|
+
continue;
|
|
3152
|
+
}
|
|
3153
|
+
if (state.sCount[line] - state.blkIndent < 4) break;
|
|
3154
|
+
const text = state.src.slice(lineStart, lineEnd);
|
|
3155
|
+
if (pendingBlank) paragraphs.push([text]);
|
|
3156
|
+
else paragraphs[paragraphs.length - 1].push(text);
|
|
3157
|
+
pendingBlank = false;
|
|
3158
|
+
lastContentLine = line;
|
|
3159
|
+
}
|
|
3160
|
+
const open = state.push("pixerate_footnote_open", "li", 1);
|
|
3161
|
+
open.meta = { label: match[1] };
|
|
3162
|
+
open.block = true;
|
|
3163
|
+
open.map = [startLine, lastContentLine + 1];
|
|
3164
|
+
for (const paragraph of paragraphs) {
|
|
3165
|
+
state.push("paragraph_open", "p", 1).block = true;
|
|
3166
|
+
const inline = state.push("inline", "", 0);
|
|
3167
|
+
inline.content = paragraph.join("\n").trim();
|
|
3168
|
+
inline.map = [startLine, lastContentLine + 1];
|
|
3169
|
+
inline.children = [];
|
|
3170
|
+
state.push("paragraph_close", "p", -1).block = true;
|
|
3171
|
+
}
|
|
3172
|
+
state.push("pixerate_footnote_close", "li", -1).block = true;
|
|
3173
|
+
state.line = lastContentLine + 1;
|
|
3174
|
+
return true;
|
|
3175
|
+
},
|
|
3176
|
+
{ alt: ["paragraph", "reference"] }
|
|
3177
|
+
);
|
|
3178
|
+
md2.inline.ruler.before("link", "pixerate_footnote_ref", (state, silent) => {
|
|
3179
|
+
const { src, pos, posMax } = state;
|
|
3180
|
+
if (src.charCodeAt(pos) !== 91 || src.charCodeAt(pos + 1) !== 94) {
|
|
3181
|
+
return false;
|
|
3182
|
+
}
|
|
3183
|
+
let end = pos + 2;
|
|
3184
|
+
while (end < posMax && src.charCodeAt(end) !== 93) {
|
|
3185
|
+
if (/\s/.test(src[end])) return false;
|
|
3186
|
+
end++;
|
|
3187
|
+
}
|
|
3188
|
+
if (end >= posMax || end === pos + 2) return false;
|
|
3189
|
+
if (!silent) {
|
|
3190
|
+
const token = state.push("pixerate_footnote_ref", "sup", 0);
|
|
3191
|
+
token.meta = { label: src.slice(pos + 2, end) };
|
|
3192
|
+
}
|
|
3193
|
+
state.pos = end + 1;
|
|
3194
|
+
return true;
|
|
3195
|
+
});
|
|
3196
|
+
md2.renderer.rules.pixerate_footnote_ref = (tokens, idx) => {
|
|
3197
|
+
const label = escapeAttr(tokens[idx].meta.label);
|
|
3198
|
+
return `<sup data-type="footnote-reference" data-id="${label}">${label}</sup>`;
|
|
3199
|
+
};
|
|
3200
|
+
md2.renderer.rules.pixerate_footnote_open = (tokens, idx) => {
|
|
3201
|
+
const label = escapeAttr(tokens[idx].meta.label);
|
|
3202
|
+
return `<section data-type="footnotes"><ol><li data-type="footnote" data-id="${label}">`;
|
|
3203
|
+
};
|
|
3204
|
+
md2.renderer.rules.pixerate_footnote_close = () => "</li></ol></section>\n";
|
|
3205
|
+
}
|
|
3206
|
+
function mergeFootnoteSections(element) {
|
|
3207
|
+
const sections = Array.from(
|
|
3208
|
+
element.querySelectorAll('section[data-type="footnotes"]')
|
|
3209
|
+
);
|
|
3210
|
+
if (!sections.length) return;
|
|
3211
|
+
const [first, ...rest] = sections;
|
|
3212
|
+
const list = first.querySelector("ol");
|
|
3213
|
+
if (!list) return;
|
|
3214
|
+
for (const section of rest) {
|
|
3215
|
+
section.querySelectorAll('li[data-type="footnote"]').forEach((li) => list.appendChild(li));
|
|
3216
|
+
section.remove();
|
|
3217
|
+
}
|
|
3218
|
+
element.appendChild(first);
|
|
3219
|
+
}
|
|
3220
|
+
|
|
3221
|
+
// src/extensions/document-structure/table-of-contents.ts
|
|
3222
|
+
var tableOfContentsPluginKey = new (0, _state.PluginKey)("tableOfContents");
|
|
3223
|
+
var sameEntry = (a, b) => a.id === b.id && a.level === b.level && a.text === b.text && a.depth === b.depth;
|
|
3224
|
+
function getTableOfContentsEntries(headings, minLevel = 1, maxLevel = 6) {
|
|
3225
|
+
const entries = [];
|
|
3226
|
+
const stack = [];
|
|
3227
|
+
for (const heading of headings) {
|
|
3228
|
+
if (heading.level < minLevel || heading.level > maxLevel) continue;
|
|
3229
|
+
while (stack.length && stack[stack.length - 1] >= heading.level) stack.pop();
|
|
3230
|
+
entries.push({
|
|
3231
|
+
// Fallback ids (`outline-n`) are not stored on the heading, so they
|
|
3232
|
+
// cannot be linked to.
|
|
3233
|
+
id: heading.id.startsWith("outline-") ? null : heading.id,
|
|
3234
|
+
level: heading.level,
|
|
3235
|
+
text: heading.text,
|
|
3236
|
+
depth: stack.length
|
|
3237
|
+
});
|
|
3238
|
+
stack.push(heading.level);
|
|
3239
|
+
}
|
|
3240
|
+
return entries;
|
|
3241
|
+
}
|
|
3242
|
+
function syncTableOfContents(state, headingTypes) {
|
|
3243
|
+
const headings = _nullishCoalesce(outlinePluginKey.getState(state), () => ( computeOutline(state.doc, headingTypes)));
|
|
3244
|
+
let tr = null;
|
|
3245
|
+
state.doc.descendants((node, pos) => {
|
|
3246
|
+
if (node.type.name === "tableOfContents") {
|
|
3247
|
+
const entries = getTableOfContentsEntries(
|
|
3248
|
+
headings,
|
|
3249
|
+
node.attrs.minLevel,
|
|
3250
|
+
node.attrs.maxLevel
|
|
3251
|
+
);
|
|
3252
|
+
if (!arraysEqual(_nullishCoalesce(node.attrs.entries, () => ( [])), entries, sameEntry)) {
|
|
3253
|
+
tr = _nullishCoalesce(tr, () => ( state.tr));
|
|
3254
|
+
tr.setNodeMarkup(pos, void 0, { ...node.attrs, entries });
|
|
3255
|
+
}
|
|
3256
|
+
return false;
|
|
3257
|
+
}
|
|
3258
|
+
return !node.isTextblock;
|
|
3259
|
+
});
|
|
3260
|
+
return tr;
|
|
3261
|
+
}
|
|
3262
|
+
var TableOfContents = _core.Node.create({
|
|
3263
|
+
name: "tableOfContents",
|
|
3264
|
+
priority: STRUCTURE_PRIORITY - 5,
|
|
3265
|
+
group: "block",
|
|
3266
|
+
atom: true,
|
|
3267
|
+
selectable: true,
|
|
3268
|
+
draggable: true,
|
|
3269
|
+
addOptions() {
|
|
3270
|
+
return {
|
|
3271
|
+
HTMLAttributes: {},
|
|
3272
|
+
headingTypes: ["heading"],
|
|
3273
|
+
defaultTitle: "Contents",
|
|
3274
|
+
emptyText: "Add headings to build the table of contents."
|
|
3275
|
+
};
|
|
3276
|
+
},
|
|
3277
|
+
addAttributes() {
|
|
3278
|
+
return {
|
|
3279
|
+
title: {
|
|
3280
|
+
default: this.options.defaultTitle,
|
|
3281
|
+
parseHTML: (element) => _nullishCoalesce(element.getAttribute("data-title"), () => ( this.options.defaultTitle)),
|
|
3282
|
+
renderHTML: (attributes) => ({
|
|
3283
|
+
"data-title": attributes.title
|
|
3284
|
+
})
|
|
3285
|
+
},
|
|
3286
|
+
minLevel: {
|
|
3287
|
+
default: 1,
|
|
3288
|
+
parseHTML: (element) => Number(element.getAttribute("data-min-level")) || 1,
|
|
3289
|
+
renderHTML: (attributes) => ({
|
|
3290
|
+
"data-min-level": attributes.minLevel
|
|
3291
|
+
})
|
|
3292
|
+
},
|
|
3293
|
+
maxLevel: {
|
|
3294
|
+
default: 3,
|
|
3295
|
+
parseHTML: (element) => Number(element.getAttribute("data-max-level")) || 3,
|
|
3296
|
+
renderHTML: (attributes) => ({
|
|
3297
|
+
"data-max-level": attributes.maxLevel
|
|
3298
|
+
})
|
|
3299
|
+
},
|
|
3300
|
+
entries: {
|
|
3301
|
+
default: [],
|
|
3302
|
+
rendered: false,
|
|
3303
|
+
// Entries are derived from the headings and recomputed after parsing.
|
|
3304
|
+
parseHTML: () => []
|
|
3305
|
+
}
|
|
3306
|
+
};
|
|
3307
|
+
},
|
|
3308
|
+
parseHTML() {
|
|
3309
|
+
return [{ tag: 'nav[data-type="table-of-contents"]', priority: 60 }];
|
|
3310
|
+
},
|
|
3311
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
3312
|
+
const entries = _nullishCoalesce(node.attrs.entries, () => ( []));
|
|
3313
|
+
const list = entries.length ? [
|
|
3314
|
+
"ol",
|
|
3315
|
+
{ class: "toc-list" },
|
|
3316
|
+
...entries.map((entry) => [
|
|
3317
|
+
"li",
|
|
3318
|
+
{
|
|
3319
|
+
class: "toc-entry",
|
|
3320
|
+
"data-level": entry.level,
|
|
3321
|
+
"data-depth": entry.depth,
|
|
3322
|
+
style: `margin-left: ${entry.depth * 1.25}em`
|
|
3323
|
+
},
|
|
3324
|
+
entry.id ? ["a", { href: `#${entry.id}`, "data-heading-id": entry.id }, entry.text] : ["span", {}, entry.text]
|
|
3325
|
+
])
|
|
3326
|
+
] : ["p", { class: "toc-empty" }, this.options.emptyText];
|
|
3327
|
+
return [
|
|
3328
|
+
"nav",
|
|
3329
|
+
_core.mergeAttributes.call(void 0, this.options.HTMLAttributes, HTMLAttributes, {
|
|
3330
|
+
"data-type": "table-of-contents",
|
|
3331
|
+
"aria-label": node.attrs.title || "Table of contents",
|
|
3332
|
+
class: "pixerate-toc"
|
|
3333
|
+
}),
|
|
3334
|
+
["p", { class: "toc-title" }, _nullishCoalesce(node.attrs.title, () => ( ""))],
|
|
3335
|
+
list
|
|
3336
|
+
];
|
|
3337
|
+
},
|
|
3338
|
+
renderText({ node }) {
|
|
3339
|
+
const entries = _nullishCoalesce(node.attrs.entries, () => ( []));
|
|
3340
|
+
return [node.attrs.title, ...entries.map((e) => `${" ".repeat(e.depth)}${e.text}`)].filter(Boolean).join("\n");
|
|
3341
|
+
},
|
|
3342
|
+
addStorage() {
|
|
3343
|
+
return {
|
|
3344
|
+
markdown: {
|
|
3345
|
+
serialize(state, node) {
|
|
3346
|
+
state.write("[[toc]]");
|
|
3347
|
+
state.closeBlock(node);
|
|
3348
|
+
},
|
|
3349
|
+
parse: {
|
|
3350
|
+
setup(markdownit2) {
|
|
3351
|
+
tableOfContentsMarkdownIt(markdownit2);
|
|
3352
|
+
}
|
|
3353
|
+
}
|
|
3354
|
+
}
|
|
3355
|
+
};
|
|
3356
|
+
},
|
|
3357
|
+
addCommands() {
|
|
3358
|
+
return {
|
|
3359
|
+
insertTableOfContents: (options = {}) => ({ commands }) => commands.insertContent({
|
|
3360
|
+
type: this.name,
|
|
3361
|
+
attrs: {
|
|
3362
|
+
title: _nullishCoalesce(options.title, () => ( this.options.defaultTitle)),
|
|
3363
|
+
minLevel: _nullishCoalesce(options.minLevel, () => ( 1)),
|
|
3364
|
+
maxLevel: _nullishCoalesce(options.maxLevel, () => ( 3))
|
|
3365
|
+
}
|
|
3366
|
+
})
|
|
3367
|
+
};
|
|
3368
|
+
},
|
|
3369
|
+
addProseMirrorPlugins() {
|
|
3370
|
+
const { headingTypes } = this.options;
|
|
3371
|
+
const editor = this.editor;
|
|
3372
|
+
return [
|
|
3373
|
+
new (0, _state.Plugin)({
|
|
3374
|
+
key: tableOfContentsPluginKey,
|
|
3375
|
+
state: presenceStateSpec([this.name]),
|
|
3376
|
+
appendTransaction: (transactions, _oldState, newState) => {
|
|
3377
|
+
if (!transactions.some((tr) => tr.docChanged)) return null;
|
|
3378
|
+
if (!tableOfContentsPluginKey.getState(newState)) return null;
|
|
3379
|
+
return syncTableOfContents(newState, headingTypes);
|
|
3380
|
+
},
|
|
3381
|
+
props: {
|
|
3382
|
+
handleDOMEvents: {
|
|
3383
|
+
click: (view, event) => {
|
|
3384
|
+
const target = event.target;
|
|
3385
|
+
const link = _optionalChain([target, 'optionalAccess', _109 => _109.closest, 'optionalCall', _110 => _110(
|
|
3386
|
+
'nav[data-type="table-of-contents"] a[data-heading-id]'
|
|
3387
|
+
)]);
|
|
3388
|
+
if (!link) return false;
|
|
3389
|
+
event.preventDefault();
|
|
3390
|
+
const id = link.getAttribute("data-heading-id");
|
|
3391
|
+
const heading = (_nullishCoalesce(outlinePluginKey.getState(view.state), () => ( computeOutline(view.state.doc, headingTypes)))).find((h) => h.id === id);
|
|
3392
|
+
if (!heading) return true;
|
|
3393
|
+
if (editor.isEditable) {
|
|
3394
|
+
view.dispatch(
|
|
3395
|
+
view.state.tr.setSelection(_state.TextSelection.create(view.state.doc, heading.pos + 1)).scrollIntoView()
|
|
3396
|
+
);
|
|
3397
|
+
view.focus();
|
|
3398
|
+
}
|
|
3399
|
+
scrollDomAtPos(view, heading.pos);
|
|
3400
|
+
return true;
|
|
3401
|
+
}
|
|
3402
|
+
}
|
|
3403
|
+
}
|
|
3404
|
+
})
|
|
3405
|
+
];
|
|
3406
|
+
},
|
|
3407
|
+
onBeforeCreate() {
|
|
3408
|
+
const { headingTypes } = this.options;
|
|
3409
|
+
syncInitialContent(this.editor, (state) => syncTableOfContents(state, headingTypes));
|
|
3410
|
+
}
|
|
3411
|
+
});
|
|
3412
|
+
|
|
3413
|
+
// src/extensions/document-structure/footnotes.ts
|
|
3414
|
+
|
|
3415
|
+
|
|
3416
|
+
|
|
3417
|
+
|
|
3418
|
+
|
|
3419
|
+
|
|
3420
|
+
|
|
3421
|
+
var footnotesPluginKey = new (0, _state.PluginKey)("footnotes");
|
|
3422
|
+
var REFERENCE = "footnoteReference";
|
|
3423
|
+
var LIST = "footnotes";
|
|
3424
|
+
var ITEM = "footnote";
|
|
3425
|
+
function paragraphsFromText(schema, text) {
|
|
3426
|
+
const parts = text.split(/\n\s*\n/);
|
|
3427
|
+
return parts.map(
|
|
3428
|
+
(part) => schema.nodes.paragraph.create(null, part ? schema.text(part) : void 0)
|
|
3429
|
+
);
|
|
3430
|
+
}
|
|
3431
|
+
function footnoteText(node) {
|
|
3432
|
+
const parts = [];
|
|
3433
|
+
node.forEach((child) => parts.push(child.textContent));
|
|
3434
|
+
return parts.join("\n\n");
|
|
3435
|
+
}
|
|
3436
|
+
function getFootnotes(doc) {
|
|
3437
|
+
const footnotes = /* @__PURE__ */ new Map();
|
|
3438
|
+
const refs = [];
|
|
3439
|
+
doc.descendants((node, pos) => {
|
|
3440
|
+
if (node.type.name === LIST) {
|
|
3441
|
+
node.forEach((child, offset) => {
|
|
3442
|
+
if (child.type.name === ITEM && !footnotes.has(child.attrs.id)) {
|
|
3443
|
+
footnotes.set(child.attrs.id, { node: child, pos: pos + 1 + offset });
|
|
3444
|
+
}
|
|
3445
|
+
});
|
|
3446
|
+
return false;
|
|
3447
|
+
}
|
|
3448
|
+
if (node.type.name === REFERENCE) refs.push({ id: node.attrs.id, pos });
|
|
3449
|
+
return true;
|
|
3450
|
+
});
|
|
3451
|
+
return refs.map((ref, index) => {
|
|
3452
|
+
const footnote = footnotes.get(ref.id);
|
|
3453
|
+
return {
|
|
3454
|
+
id: ref.id,
|
|
3455
|
+
number: index + 1,
|
|
3456
|
+
text: footnote ? footnoteText(footnote.node) : "",
|
|
3457
|
+
referencePos: ref.pos,
|
|
3458
|
+
footnotePos: _nullishCoalesce(_optionalChain([footnote, 'optionalAccess', _111 => _111.pos]), () => ( null))
|
|
3459
|
+
};
|
|
3460
|
+
});
|
|
3461
|
+
}
|
|
3462
|
+
function syncFootnotes(tr, options = {}) {
|
|
3463
|
+
const schema = tr.doc.type.schema;
|
|
3464
|
+
const listType = schema.nodes[LIST];
|
|
3465
|
+
const itemType = schema.nodes[ITEM];
|
|
3466
|
+
if (!listType || !itemType) return false;
|
|
3467
|
+
const generateId = _nullishCoalesce(options.generateId, () => ( (() => generateStructureId("fn"))));
|
|
3468
|
+
const refs = [];
|
|
3469
|
+
const lists = [];
|
|
3470
|
+
const existing = /* @__PURE__ */ new Map();
|
|
3471
|
+
tr.doc.descendants((node, pos) => {
|
|
3472
|
+
if (node.type === listType) {
|
|
3473
|
+
lists.push({ node, pos });
|
|
3474
|
+
node.forEach((child) => {
|
|
3475
|
+
if (child.type === itemType && !existing.has(child.attrs.id)) {
|
|
3476
|
+
existing.set(child.attrs.id, child);
|
|
3477
|
+
}
|
|
3478
|
+
});
|
|
3479
|
+
return false;
|
|
3480
|
+
}
|
|
3481
|
+
if (node.type.name === REFERENCE) refs.push({ node, pos });
|
|
3482
|
+
return true;
|
|
3483
|
+
});
|
|
3484
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3485
|
+
const desiredRefs = [];
|
|
3486
|
+
refs.forEach((ref, index) => {
|
|
3487
|
+
let id = ref.node.attrs.id;
|
|
3488
|
+
let copyOf;
|
|
3489
|
+
if (!id || seen.has(id)) {
|
|
3490
|
+
copyOf = id || void 0;
|
|
3491
|
+
do {
|
|
3492
|
+
id = generateId();
|
|
3493
|
+
} while (seen.has(id) || existing.has(id));
|
|
3494
|
+
}
|
|
3495
|
+
seen.add(id);
|
|
3496
|
+
desiredRefs.push({ pos: ref.pos, id, number: index + 1, copyOf });
|
|
3497
|
+
});
|
|
3498
|
+
const desiredItems = desiredRefs.map(({ id, number, copyOf }) => {
|
|
3499
|
+
const source = _nullishCoalesce(existing.get(id), () => ( (copyOf ? existing.get(copyOf) : void 0)));
|
|
3500
|
+
const content = _nullishCoalesce(_optionalChain([source, 'optionalAccess', _112 => _112.content]), () => ( paragraphsFromText(schema, _nullishCoalesce(_optionalChain([options, 'access', _113 => _113.contents, 'optionalAccess', _114 => _114[id]]), () => ( "")))));
|
|
3501
|
+
if (source && source.attrs.id === id && source.attrs.number === number) {
|
|
3502
|
+
return source;
|
|
3503
|
+
}
|
|
3504
|
+
return itemType.create({ id, number }, content);
|
|
3505
|
+
});
|
|
3506
|
+
const refsInSync = desiredRefs.every(
|
|
3507
|
+
(d, i) => refs[i].node.attrs.id === d.id && refs[i].node.attrs.number === d.number
|
|
3508
|
+
);
|
|
3509
|
+
const lastChild = tr.doc.lastChild;
|
|
3510
|
+
const listInSync = desiredItems.length ? lists.length === 1 && lastChild === lists[0].node && lists[0].node.childCount === desiredItems.length && desiredItems.every((item, i) => lists[0].node.child(i) === item) : lists.length === 0;
|
|
3511
|
+
if (refsInSync && listInSync) return false;
|
|
3512
|
+
desiredRefs.forEach((d, i) => {
|
|
3513
|
+
const node = refs[i].node;
|
|
3514
|
+
if (node.attrs.id !== d.id || node.attrs.number !== d.number) {
|
|
3515
|
+
tr.setNodeMarkup(d.pos, void 0, { ...node.attrs, id: d.id, number: d.number });
|
|
3516
|
+
}
|
|
3517
|
+
});
|
|
3518
|
+
if (!listInSync) {
|
|
3519
|
+
for (let i = lists.length - 1; i >= 0; i--) {
|
|
3520
|
+
tr.delete(lists[i].pos, lists[i].pos + lists[i].node.nodeSize);
|
|
3521
|
+
}
|
|
3522
|
+
if (desiredItems.length) {
|
|
3523
|
+
tr.insert(tr.doc.content.size, listType.create(null, desiredItems));
|
|
3524
|
+
}
|
|
3525
|
+
}
|
|
3526
|
+
return true;
|
|
3527
|
+
}
|
|
3528
|
+
function findFootnote(doc, id) {
|
|
3529
|
+
let found = null;
|
|
3530
|
+
doc.descendants((node, pos) => {
|
|
3531
|
+
if (found) return false;
|
|
3532
|
+
if (node.type.name === ITEM && node.attrs.id === id) {
|
|
3533
|
+
found = { node, pos };
|
|
3534
|
+
return false;
|
|
3535
|
+
}
|
|
3536
|
+
return true;
|
|
3537
|
+
});
|
|
3538
|
+
return found;
|
|
3539
|
+
}
|
|
3540
|
+
function findReferences(doc, id) {
|
|
3541
|
+
const refs = [];
|
|
3542
|
+
doc.descendants((node, pos) => {
|
|
3543
|
+
if (node.type.name === LIST) return false;
|
|
3544
|
+
if (node.type.name === REFERENCE && node.attrs.id === id) refs.push({ node, pos });
|
|
3545
|
+
return true;
|
|
3546
|
+
});
|
|
3547
|
+
return refs;
|
|
3548
|
+
}
|
|
3549
|
+
var FootnoteReference = _core.Node.create({
|
|
3550
|
+
name: REFERENCE,
|
|
3551
|
+
priority: STRUCTURE_PRIORITY - 5,
|
|
3552
|
+
group: "inline",
|
|
3553
|
+
inline: true,
|
|
3554
|
+
atom: true,
|
|
3555
|
+
selectable: true,
|
|
3556
|
+
addOptions() {
|
|
3557
|
+
return {
|
|
3558
|
+
HTMLAttributes: {},
|
|
3559
|
+
generateId: () => generateStructureId("fn")
|
|
3560
|
+
};
|
|
3561
|
+
},
|
|
3562
|
+
addAttributes() {
|
|
3563
|
+
return {
|
|
3564
|
+
id: {
|
|
3565
|
+
default: null,
|
|
3566
|
+
parseHTML: (element) => element.getAttribute("data-id"),
|
|
3567
|
+
renderHTML: (attributes) => attributes.id ? { "data-id": attributes.id } : {}
|
|
3568
|
+
},
|
|
3569
|
+
number: {
|
|
3570
|
+
default: null,
|
|
3571
|
+
parseHTML: (element) => Number(element.getAttribute("data-number")) || null,
|
|
3572
|
+
renderHTML: (attributes) => attributes.number ? { "data-number": attributes.number } : {}
|
|
3573
|
+
}
|
|
3574
|
+
};
|
|
3575
|
+
},
|
|
3576
|
+
parseHTML() {
|
|
3577
|
+
return [{ tag: 'sup[data-type="footnote-reference"]', priority: 60 }];
|
|
3578
|
+
},
|
|
3579
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
3580
|
+
const id = node.attrs.id;
|
|
3581
|
+
return [
|
|
3582
|
+
"sup",
|
|
3583
|
+
_core.mergeAttributes.call(void 0, this.options.HTMLAttributes, HTMLAttributes, {
|
|
3584
|
+
"data-type": "footnote-reference",
|
|
3585
|
+
class: "pixerate-footnote-ref",
|
|
3586
|
+
...id ? { id: `fnref-${id}` } : {}
|
|
3587
|
+
}),
|
|
3588
|
+
["a", id ? { href: `#fn-${id}` } : {}, String(_nullishCoalesce(node.attrs.number, () => ( "")))]
|
|
3589
|
+
];
|
|
3590
|
+
},
|
|
3591
|
+
renderText({ node }) {
|
|
3592
|
+
return `[${_nullishCoalesce(node.attrs.number, () => ( ""))}]`;
|
|
3593
|
+
},
|
|
3594
|
+
addStorage() {
|
|
3595
|
+
return {
|
|
3596
|
+
markdown: {
|
|
3597
|
+
serialize(state, node) {
|
|
3598
|
+
state.write(`[^${_nullishCoalesce(node.attrs.number, () => ( node.attrs.id))}]`);
|
|
3599
|
+
},
|
|
3600
|
+
parse: {
|
|
3601
|
+
setup(markdownit2) {
|
|
3602
|
+
footnotesMarkdownIt(markdownit2);
|
|
3603
|
+
},
|
|
3604
|
+
updateDOM(element) {
|
|
3605
|
+
mergeFootnoteSections(element);
|
|
3606
|
+
}
|
|
3607
|
+
}
|
|
3608
|
+
}
|
|
3609
|
+
};
|
|
3610
|
+
},
|
|
3611
|
+
addCommands() {
|
|
3612
|
+
return {
|
|
3613
|
+
insertFootnote: (options = {}) => ({ state, tr, dispatch }) => {
|
|
3614
|
+
const type = state.schema.nodes[REFERENCE];
|
|
3615
|
+
if (!type || !state.schema.nodes[ITEM]) return false;
|
|
3616
|
+
const { $from } = state.selection;
|
|
3617
|
+
for (let d = $from.depth; d > 0; d--) {
|
|
3618
|
+
if ($from.node(d).type.name === LIST) return false;
|
|
3619
|
+
}
|
|
3620
|
+
if (!$from.parent.inlineContent) return false;
|
|
3621
|
+
if (!dispatch) return true;
|
|
3622
|
+
const id = _nullishCoalesce(options.id, () => ( this.options.generateId()));
|
|
3623
|
+
tr.replaceSelectionWith(type.create({ id }), false);
|
|
3624
|
+
syncFootnotes(tr, {
|
|
3625
|
+
generateId: this.options.generateId,
|
|
3626
|
+
contents: options.content ? { [id]: options.content } : void 0
|
|
3627
|
+
});
|
|
3628
|
+
const focusContent = _nullishCoalesce(options.focusContent, () => ( !options.content));
|
|
3629
|
+
if (focusContent) {
|
|
3630
|
+
const footnote = findFootnote(tr.doc, id);
|
|
3631
|
+
if (footnote) {
|
|
3632
|
+
tr.setSelection(_state.TextSelection.create(tr.doc, footnote.pos + 2));
|
|
3633
|
+
}
|
|
3634
|
+
}
|
|
3635
|
+
tr.scrollIntoView();
|
|
3636
|
+
return true;
|
|
3637
|
+
},
|
|
3638
|
+
updateFootnote: (id, content) => ({ state, tr, dispatch }) => {
|
|
3639
|
+
const footnote = findFootnote(state.doc, id);
|
|
3640
|
+
if (!footnote) return false;
|
|
3641
|
+
if (dispatch) {
|
|
3642
|
+
tr.replaceWith(
|
|
3643
|
+
footnote.pos + 1,
|
|
3644
|
+
footnote.pos + footnote.node.nodeSize - 1,
|
|
3645
|
+
paragraphsFromText(state.schema, content)
|
|
3646
|
+
);
|
|
3647
|
+
}
|
|
3648
|
+
return true;
|
|
3649
|
+
},
|
|
3650
|
+
deleteFootnote: (id) => ({ state, tr, dispatch }) => {
|
|
3651
|
+
const refs = findReferences(state.doc, id);
|
|
3652
|
+
const footnote = findFootnote(state.doc, id);
|
|
3653
|
+
if (!refs.length && !footnote) return false;
|
|
3654
|
+
if (dispatch) {
|
|
3655
|
+
for (let i = refs.length - 1; i >= 0; i--) {
|
|
3656
|
+
tr.delete(refs[i].pos, refs[i].pos + refs[i].node.nodeSize);
|
|
3657
|
+
}
|
|
3658
|
+
syncFootnotes(tr, { generateId: this.options.generateId });
|
|
3659
|
+
}
|
|
3660
|
+
return true;
|
|
3661
|
+
},
|
|
3662
|
+
goToFootnote: (id) => ({ state, tr, dispatch, view }) => {
|
|
3663
|
+
const footnote = findFootnote(state.doc, id);
|
|
3664
|
+
if (!footnote) return false;
|
|
3665
|
+
if (dispatch) {
|
|
3666
|
+
tr.setSelection(
|
|
3667
|
+
_state.TextSelection.create(tr.doc, footnote.pos + footnote.node.nodeSize - 2)
|
|
3668
|
+
);
|
|
3669
|
+
tr.scrollIntoView();
|
|
3670
|
+
scrollDomAtPos(view, footnote.pos);
|
|
3671
|
+
}
|
|
3672
|
+
return true;
|
|
3673
|
+
},
|
|
3674
|
+
goToFootnoteReference: (id) => ({ state, tr, dispatch, view }) => {
|
|
3675
|
+
const [ref] = findReferences(state.doc, id);
|
|
3676
|
+
if (!ref) return false;
|
|
3677
|
+
if (dispatch) {
|
|
3678
|
+
tr.setSelection(_state.NodeSelection.create(tr.doc, ref.pos));
|
|
3679
|
+
tr.scrollIntoView();
|
|
3680
|
+
scrollDomAtPos(view, ref.pos);
|
|
3681
|
+
}
|
|
3682
|
+
return true;
|
|
3683
|
+
}
|
|
3684
|
+
};
|
|
3685
|
+
},
|
|
3686
|
+
addProseMirrorPlugins() {
|
|
3687
|
+
const generateId = this.options.generateId;
|
|
3688
|
+
const editor = this.editor;
|
|
3689
|
+
return [
|
|
3690
|
+
new (0, _state.Plugin)({
|
|
3691
|
+
key: footnotesPluginKey,
|
|
3692
|
+
state: presenceStateSpec([REFERENCE, LIST]),
|
|
3693
|
+
appendTransaction: (transactions, _oldState, newState) => {
|
|
3694
|
+
if (!transactions.some((tr2) => tr2.docChanged)) return null;
|
|
3695
|
+
if (!footnotesPluginKey.getState(newState)) return null;
|
|
3696
|
+
const tr = newState.tr;
|
|
3697
|
+
return syncFootnotes(tr, { generateId }) ? tr : null;
|
|
3698
|
+
},
|
|
3699
|
+
props: {
|
|
3700
|
+
handleClickOn: (_view, _pos, node, _nodePos, event) => {
|
|
3701
|
+
if (node.type.name !== REFERENCE || !node.attrs.id) return false;
|
|
3702
|
+
const target = event.target;
|
|
3703
|
+
if (!_optionalChain([target, 'optionalAccess', _115 => _115.closest, 'optionalCall', _116 => _116("a")])) return false;
|
|
3704
|
+
event.preventDefault();
|
|
3705
|
+
return editor.commands.goToFootnote(node.attrs.id);
|
|
3706
|
+
}
|
|
3707
|
+
}
|
|
3708
|
+
})
|
|
3709
|
+
];
|
|
3710
|
+
},
|
|
3711
|
+
onBeforeCreate() {
|
|
3712
|
+
const { generateId } = this.options;
|
|
3713
|
+
syncInitialContent(this.editor, (state) => {
|
|
3714
|
+
const tr = state.tr;
|
|
3715
|
+
return syncFootnotes(tr, { generateId }) ? tr : null;
|
|
3716
|
+
});
|
|
3717
|
+
}
|
|
3718
|
+
});
|
|
3719
|
+
var Footnotes = _core.Node.create({
|
|
3720
|
+
name: LIST,
|
|
3721
|
+
group: "block",
|
|
3722
|
+
content: `${ITEM}+`,
|
|
3723
|
+
isolating: true,
|
|
3724
|
+
selectable: false,
|
|
3725
|
+
draggable: false,
|
|
3726
|
+
parseHTML() {
|
|
3727
|
+
return [{ tag: 'section[data-type="footnotes"]', contentElement: "ol", priority: 60 }];
|
|
3728
|
+
},
|
|
3729
|
+
renderHTML({ HTMLAttributes }) {
|
|
3730
|
+
return [
|
|
3731
|
+
"section",
|
|
3732
|
+
_core.mergeAttributes.call(void 0, HTMLAttributes, {
|
|
3733
|
+
"data-type": "footnotes",
|
|
3734
|
+
class: "pixerate-footnotes",
|
|
3735
|
+
role: "doc-endnotes"
|
|
3736
|
+
}),
|
|
3737
|
+
["ol", 0]
|
|
3738
|
+
];
|
|
3739
|
+
},
|
|
3740
|
+
addStorage() {
|
|
3741
|
+
return {
|
|
3742
|
+
markdown: {
|
|
3743
|
+
serialize(state, node) {
|
|
3744
|
+
node.forEach((footnote) => {
|
|
3745
|
+
const label = _nullishCoalesce(footnote.attrs.number, () => ( footnote.attrs.id));
|
|
3746
|
+
state.wrapBlock(
|
|
3747
|
+
" ",
|
|
3748
|
+
`[^${label}]: `,
|
|
3749
|
+
footnote,
|
|
3750
|
+
() => state.renderContent(footnote)
|
|
3751
|
+
);
|
|
3752
|
+
});
|
|
3753
|
+
},
|
|
3754
|
+
parse: {}
|
|
3755
|
+
}
|
|
3756
|
+
};
|
|
3757
|
+
}
|
|
3758
|
+
});
|
|
3759
|
+
var Footnote = _core.Node.create({
|
|
3760
|
+
name: ITEM,
|
|
3761
|
+
content: "paragraph+",
|
|
3762
|
+
isolating: true,
|
|
3763
|
+
defining: true,
|
|
3764
|
+
addAttributes() {
|
|
3765
|
+
return {
|
|
3766
|
+
id: {
|
|
3767
|
+
default: null,
|
|
3768
|
+
parseHTML: (element) => element.getAttribute("data-id"),
|
|
3769
|
+
renderHTML: (attributes) => attributes.id ? { "data-id": attributes.id, id: `fn-${attributes.id}` } : {}
|
|
3770
|
+
},
|
|
3771
|
+
number: {
|
|
3772
|
+
default: null,
|
|
3773
|
+
parseHTML: (element) => Number(element.getAttribute("data-number")) || null,
|
|
3774
|
+
renderHTML: (attributes) => attributes.number ? { "data-number": attributes.number } : {}
|
|
3775
|
+
}
|
|
3776
|
+
};
|
|
3777
|
+
},
|
|
3778
|
+
parseHTML() {
|
|
3779
|
+
return [{ tag: 'li[data-type="footnote"]', priority: 60 }];
|
|
3780
|
+
},
|
|
3781
|
+
renderHTML({ HTMLAttributes }) {
|
|
3782
|
+
return [
|
|
3783
|
+
"li",
|
|
3784
|
+
_core.mergeAttributes.call(void 0, HTMLAttributes, {
|
|
3785
|
+
"data-type": "footnote",
|
|
3786
|
+
class: "pixerate-footnote"
|
|
3787
|
+
}),
|
|
3788
|
+
0
|
|
3789
|
+
];
|
|
3790
|
+
},
|
|
3791
|
+
addKeyboardShortcuts() {
|
|
3792
|
+
const atFootnoteStart = () => {
|
|
3793
|
+
const { selection } = this.editor.state;
|
|
3794
|
+
if (!selection.empty) return false;
|
|
3795
|
+
const { $from } = selection;
|
|
3796
|
+
if ($from.parentOffset !== 0 || $from.depth < 2) return false;
|
|
3797
|
+
const footnote = $from.node($from.depth - 1);
|
|
3798
|
+
return footnote.type.name === ITEM && $from.index($from.depth - 1) === 0;
|
|
3799
|
+
};
|
|
3800
|
+
return {
|
|
3801
|
+
Backspace: () => atFootnoteStart()
|
|
3802
|
+
};
|
|
3803
|
+
}
|
|
3804
|
+
});
|
|
3805
|
+
|
|
3806
|
+
// src/extensions/document-structure/bookmarks.ts
|
|
3807
|
+
|
|
3808
|
+
|
|
3809
|
+
var BOOKMARK = "bookmark";
|
|
3810
|
+
function getBookmarks(doc) {
|
|
3811
|
+
const byId = /* @__PURE__ */ new Map();
|
|
3812
|
+
doc.descendants((node, pos) => {
|
|
3813
|
+
if (!node.isText) return true;
|
|
3814
|
+
for (const mark of node.marks) {
|
|
3815
|
+
if (mark.type.name !== BOOKMARK || !mark.attrs.id) continue;
|
|
3816
|
+
const end = pos + node.nodeSize;
|
|
3817
|
+
const existing = byId.get(mark.attrs.id);
|
|
3818
|
+
if (existing) {
|
|
3819
|
+
existing.text += (existing.to === pos ? "" : " ") + node.text;
|
|
3820
|
+
existing.to = end;
|
|
3821
|
+
} else {
|
|
3822
|
+
byId.set(mark.attrs.id, {
|
|
3823
|
+
id: mark.attrs.id,
|
|
3824
|
+
name: _nullishCoalesce(mark.attrs.name, () => ( mark.attrs.id)),
|
|
3825
|
+
text: _nullishCoalesce(node.text, () => ( "")),
|
|
3826
|
+
from: pos,
|
|
3827
|
+
to: end
|
|
3828
|
+
});
|
|
3829
|
+
}
|
|
3830
|
+
}
|
|
3831
|
+
return false;
|
|
3832
|
+
});
|
|
3833
|
+
return Array.from(byId.values());
|
|
3834
|
+
}
|
|
3835
|
+
function forEachBookmarkRange(doc, id, fn) {
|
|
3836
|
+
doc.descendants((node, pos) => {
|
|
3837
|
+
if (!node.isText) return true;
|
|
3838
|
+
const mark = node.marks.find(
|
|
3839
|
+
(m) => m.type.name === BOOKMARK && m.attrs.id === id
|
|
3840
|
+
);
|
|
3841
|
+
if (mark) fn(pos, pos + node.nodeSize, mark);
|
|
3842
|
+
return false;
|
|
3843
|
+
});
|
|
3844
|
+
}
|
|
3845
|
+
var Bookmark = _core.Mark.create({
|
|
3846
|
+
name: BOOKMARK,
|
|
3847
|
+
inclusive: false,
|
|
3848
|
+
excludes: "",
|
|
3849
|
+
spanning: true,
|
|
3850
|
+
addOptions() {
|
|
3851
|
+
return {
|
|
3852
|
+
HTMLAttributes: {},
|
|
3853
|
+
generateId: () => generateStructureId("bm")
|
|
3854
|
+
};
|
|
3855
|
+
},
|
|
3856
|
+
addAttributes() {
|
|
3857
|
+
return {
|
|
3858
|
+
id: {
|
|
3859
|
+
default: null,
|
|
3860
|
+
parseHTML: (element) => element.getAttribute("data-bookmark-id"),
|
|
3861
|
+
renderHTML: (attributes) => attributes.id ? { "data-bookmark-id": attributes.id } : {}
|
|
3862
|
+
},
|
|
3863
|
+
name: {
|
|
3864
|
+
default: null,
|
|
3865
|
+
parseHTML: (element) => element.getAttribute("data-bookmark-name"),
|
|
3866
|
+
renderHTML: (attributes) => attributes.name ? { "data-bookmark-name": attributes.name } : {}
|
|
3867
|
+
}
|
|
3868
|
+
};
|
|
3869
|
+
},
|
|
3870
|
+
parseHTML() {
|
|
3871
|
+
return [{ tag: "span[data-bookmark-id]", priority: 60 }];
|
|
3872
|
+
},
|
|
3873
|
+
renderHTML({ HTMLAttributes }) {
|
|
3874
|
+
return [
|
|
3875
|
+
"span",
|
|
3876
|
+
_core.mergeAttributes.call(void 0, this.options.HTMLAttributes, HTMLAttributes, {
|
|
3877
|
+
class: "pixerate-bookmark"
|
|
3878
|
+
}),
|
|
3879
|
+
0
|
|
3880
|
+
];
|
|
3881
|
+
},
|
|
3882
|
+
addCommands() {
|
|
3883
|
+
return {
|
|
3884
|
+
setBookmark: ({ name, id }) => ({ state, tr, dispatch }) => {
|
|
3885
|
+
const type = state.schema.marks[BOOKMARK];
|
|
3886
|
+
if (!type || !name) return false;
|
|
3887
|
+
let { from, to } = state.selection;
|
|
3888
|
+
if (from === to) {
|
|
3889
|
+
const { $from } = state.selection;
|
|
3890
|
+
const text = $from.parent.textBetween(0, $from.parent.content.size, void 0, "\uFFFC");
|
|
3891
|
+
let start2 = $from.parentOffset;
|
|
3892
|
+
let end = $from.parentOffset;
|
|
3893
|
+
while (start2 > 0 && /[\p{L}\p{N}_'-]/u.test(text[start2 - 1])) start2--;
|
|
3894
|
+
while (end < text.length && /[\p{L}\p{N}_'-]/u.test(text[end])) end++;
|
|
3895
|
+
if (start2 === end) return false;
|
|
3896
|
+
from = $from.start() + start2;
|
|
3897
|
+
to = $from.start() + end;
|
|
3898
|
+
}
|
|
3899
|
+
if (!dispatch) return true;
|
|
3900
|
+
const sameName = getBookmarks(state.doc).find((b) => b.name === name);
|
|
3901
|
+
const bookmarkId = _nullishCoalesce(_nullishCoalesce(id, () => ( _optionalChain([sameName, 'optionalAccess', _117 => _117.id]))), () => ( this.options.generateId()));
|
|
3902
|
+
if (sameName) {
|
|
3903
|
+
forEachBookmarkRange(
|
|
3904
|
+
tr.doc,
|
|
3905
|
+
sameName.id,
|
|
3906
|
+
(f, t, mark) => tr.removeMark(f, t, mark)
|
|
3907
|
+
);
|
|
3908
|
+
}
|
|
3909
|
+
tr.addMark(from, to, type.create({ id: bookmarkId, name }));
|
|
3910
|
+
return true;
|
|
3911
|
+
},
|
|
3912
|
+
removeBookmark: (id) => ({ state, tr, dispatch }) => {
|
|
3913
|
+
let found = false;
|
|
3914
|
+
forEachBookmarkRange(state.doc, id, (from, to, mark) => {
|
|
3915
|
+
found = true;
|
|
3916
|
+
if (dispatch) tr.removeMark(from, to, mark);
|
|
3917
|
+
});
|
|
3918
|
+
return found;
|
|
3919
|
+
},
|
|
3920
|
+
renameBookmark: (id, name) => ({ state, tr, dispatch }) => {
|
|
3921
|
+
let found = false;
|
|
3922
|
+
forEachBookmarkRange(state.doc, id, (from, to, mark) => {
|
|
3923
|
+
found = true;
|
|
3924
|
+
if (dispatch) {
|
|
3925
|
+
tr.removeMark(from, to, mark);
|
|
3926
|
+
tr.addMark(from, to, mark.type.create({ ...mark.attrs, name }));
|
|
3927
|
+
}
|
|
3928
|
+
});
|
|
3929
|
+
return found;
|
|
3930
|
+
},
|
|
3931
|
+
goToBookmark: (id) => ({ state, tr, dispatch, view }) => {
|
|
3932
|
+
const bookmark = getBookmarks(state.doc).find((b) => b.id === id);
|
|
3933
|
+
if (!bookmark) return false;
|
|
3934
|
+
if (dispatch) {
|
|
3935
|
+
tr.setSelection(_state.TextSelection.create(tr.doc, bookmark.from, bookmark.to));
|
|
3936
|
+
tr.scrollIntoView();
|
|
3937
|
+
const domPos = state.doc.resolve(bookmark.from);
|
|
3938
|
+
scrollDomAtPos(view, domPos.before(domPos.depth));
|
|
3939
|
+
}
|
|
3940
|
+
return true;
|
|
3941
|
+
}
|
|
3942
|
+
};
|
|
3943
|
+
}
|
|
3944
|
+
});
|
|
3945
|
+
|
|
3946
|
+
// src/extensions/document-structure/cross-reference.ts
|
|
3947
|
+
|
|
3948
|
+
|
|
3949
|
+
|
|
3950
|
+
|
|
3951
|
+
|
|
3952
|
+
|
|
3953
|
+
var crossReferencePluginKey = new (0, _state.PluginKey)("crossReference");
|
|
3954
|
+
var NAME = "crossReference";
|
|
3955
|
+
function getCrossReferenceTargets(doc, headingTypes = ["heading"]) {
|
|
3956
|
+
const headings = computeOutline(doc, headingTypes).filter((h) => !h.id.startsWith("outline-")).map((h) => ({ type: "heading", id: h.id, text: h.text, name: h.text, level: h.level }));
|
|
3957
|
+
const bookmarks = getBookmarks(doc).map((b) => ({
|
|
3958
|
+
type: "bookmark",
|
|
3959
|
+
id: b.id,
|
|
3960
|
+
text: b.text,
|
|
3961
|
+
name: b.name
|
|
3962
|
+
}));
|
|
3963
|
+
return [...headings, ...bookmarks];
|
|
3964
|
+
}
|
|
3965
|
+
function syncCrossReferences(state, headingTypes) {
|
|
3966
|
+
let lookup = null;
|
|
3967
|
+
const resolve = () => {
|
|
3968
|
+
if (!lookup) {
|
|
3969
|
+
const next = { targets: /* @__PURE__ */ new Map(), headingsByText: /* @__PURE__ */ new Map() };
|
|
3970
|
+
for (const t of getCrossReferenceTargets(state.doc, headingTypes)) {
|
|
3971
|
+
next.targets.set(`${t.type}:${t.id}`, t);
|
|
3972
|
+
if (t.type === "heading" && !next.headingsByText.has(t.text)) {
|
|
3973
|
+
next.headingsByText.set(t.text, t);
|
|
3974
|
+
}
|
|
3975
|
+
}
|
|
3976
|
+
lookup = next;
|
|
3977
|
+
}
|
|
3978
|
+
return lookup;
|
|
3979
|
+
};
|
|
3980
|
+
let tr = null;
|
|
3981
|
+
state.doc.descendants((node, pos) => {
|
|
3982
|
+
if (node.type.name !== NAME) return true;
|
|
3983
|
+
const { targets, headingsByText } = resolve();
|
|
3984
|
+
const { targetType } = node.attrs;
|
|
3985
|
+
let { targetId } = node.attrs;
|
|
3986
|
+
let target = targets.get(`${targetType}:${targetId}`);
|
|
3987
|
+
if (!target && targetType === "heading" && node.attrs.label) {
|
|
3988
|
+
target = headingsByText.get(node.attrs.label);
|
|
3989
|
+
if (target) targetId = target.id;
|
|
3990
|
+
}
|
|
3991
|
+
const label = target ? target.text : node.attrs.label;
|
|
3992
|
+
const broken = !target;
|
|
3993
|
+
if (label !== node.attrs.label || broken !== node.attrs.broken || targetId !== node.attrs.targetId) {
|
|
3994
|
+
tr = _nullishCoalesce(tr, () => ( state.tr));
|
|
3995
|
+
tr.setNodeMarkup(pos, void 0, { ...node.attrs, targetId, label, broken });
|
|
3996
|
+
}
|
|
3997
|
+
return false;
|
|
3998
|
+
});
|
|
3999
|
+
return tr;
|
|
4000
|
+
}
|
|
4001
|
+
var CrossReference = _core.Node.create({
|
|
4002
|
+
name: NAME,
|
|
4003
|
+
priority: STRUCTURE_PRIORITY - 5,
|
|
4004
|
+
group: "inline",
|
|
4005
|
+
inline: true,
|
|
4006
|
+
atom: true,
|
|
4007
|
+
selectable: true,
|
|
4008
|
+
addOptions() {
|
|
4009
|
+
return {
|
|
4010
|
+
HTMLAttributes: {},
|
|
4011
|
+
headingTypes: ["heading"],
|
|
4012
|
+
brokenText: "Error! Reference source not found."
|
|
4013
|
+
};
|
|
4014
|
+
},
|
|
4015
|
+
addAttributes() {
|
|
4016
|
+
return {
|
|
4017
|
+
targetType: {
|
|
4018
|
+
default: "heading",
|
|
4019
|
+
parseHTML: (element) => _nullishCoalesce(element.getAttribute("data-target-type"), () => ( "heading")),
|
|
4020
|
+
renderHTML: (attributes) => ({
|
|
4021
|
+
"data-target-type": attributes.targetType
|
|
4022
|
+
})
|
|
4023
|
+
},
|
|
4024
|
+
targetId: {
|
|
4025
|
+
default: null,
|
|
4026
|
+
parseHTML: (element) => element.getAttribute("data-target-id"),
|
|
4027
|
+
renderHTML: (attributes) => attributes.targetId ? { "data-target-id": attributes.targetId } : {}
|
|
4028
|
+
},
|
|
4029
|
+
label: {
|
|
4030
|
+
default: "",
|
|
4031
|
+
parseHTML: (element) => _nullishCoalesce(_nullishCoalesce(element.getAttribute("data-label"), () => ( element.textContent)), () => ( "")),
|
|
4032
|
+
renderHTML: (attributes) => ({
|
|
4033
|
+
"data-label": attributes.label
|
|
4034
|
+
})
|
|
4035
|
+
},
|
|
4036
|
+
broken: {
|
|
4037
|
+
default: false,
|
|
4038
|
+
parseHTML: (element) => element.hasAttribute("data-broken"),
|
|
4039
|
+
renderHTML: (attributes) => attributes.broken ? { "data-broken": "true" } : {}
|
|
4040
|
+
}
|
|
4041
|
+
};
|
|
4042
|
+
},
|
|
4043
|
+
parseHTML() {
|
|
4044
|
+
return [{ tag: 'a[data-type="cross-reference"]', priority: 60 }];
|
|
4045
|
+
},
|
|
4046
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
4047
|
+
const { targetType, targetId, broken, label } = node.attrs;
|
|
4048
|
+
const href = !broken && targetType === "heading" && targetId ? { href: `#${targetId}` } : {};
|
|
4049
|
+
return [
|
|
4050
|
+
"a",
|
|
4051
|
+
_core.mergeAttributes.call(void 0, this.options.HTMLAttributes, HTMLAttributes, href, {
|
|
4052
|
+
"data-type": "cross-reference",
|
|
4053
|
+
class: broken ? "pixerate-cross-reference is-broken" : "pixerate-cross-reference"
|
|
4054
|
+
}),
|
|
4055
|
+
broken ? this.options.brokenText : label
|
|
4056
|
+
];
|
|
4057
|
+
},
|
|
4058
|
+
renderText({ node }) {
|
|
4059
|
+
return node.attrs.broken ? this.options.brokenText : node.attrs.label;
|
|
4060
|
+
},
|
|
4061
|
+
addCommands() {
|
|
4062
|
+
return {
|
|
4063
|
+
insertCrossReference: ({ targetType, targetId }) => ({ state, tr, dispatch }) => {
|
|
4064
|
+
const type = state.schema.nodes[NAME];
|
|
4065
|
+
if (!type || !state.selection.$from.parent.inlineContent) return false;
|
|
4066
|
+
const target = getCrossReferenceTargets(state.doc, this.options.headingTypes).find(
|
|
4067
|
+
(t) => t.type === targetType && t.id === targetId
|
|
4068
|
+
);
|
|
4069
|
+
if (!target) return false;
|
|
4070
|
+
if (dispatch) {
|
|
4071
|
+
tr.replaceSelectionWith(
|
|
4072
|
+
type.create({ targetType, targetId, label: target.text, broken: false }),
|
|
4073
|
+
false
|
|
4074
|
+
);
|
|
4075
|
+
}
|
|
4076
|
+
return true;
|
|
4077
|
+
},
|
|
4078
|
+
followCrossReference: (pos) => ({ state, tr, dispatch, view }) => {
|
|
4079
|
+
const node = pos != null ? state.doc.nodeAt(pos) : _nullishCoalesce(state.selection.node, () => ( null));
|
|
4080
|
+
if (!node || node.type.name !== NAME || node.attrs.broken) return false;
|
|
4081
|
+
const { targetType, targetId } = node.attrs;
|
|
4082
|
+
let range = null;
|
|
4083
|
+
if (targetType === "bookmark") {
|
|
4084
|
+
const bookmark = getBookmarks(state.doc).find((b) => b.id === targetId);
|
|
4085
|
+
if (bookmark) {
|
|
4086
|
+
const $from = state.doc.resolve(bookmark.from);
|
|
4087
|
+
range = {
|
|
4088
|
+
from: bookmark.from,
|
|
4089
|
+
to: bookmark.to,
|
|
4090
|
+
blockPos: $from.before($from.depth)
|
|
4091
|
+
};
|
|
4092
|
+
}
|
|
4093
|
+
} else {
|
|
4094
|
+
const heading = computeOutline(state.doc, this.options.headingTypes).find(
|
|
4095
|
+
(h) => h.id === targetId
|
|
4096
|
+
);
|
|
4097
|
+
if (heading) {
|
|
4098
|
+
range = { from: heading.pos + 1, to: heading.pos + 1, blockPos: heading.pos };
|
|
4099
|
+
}
|
|
4100
|
+
}
|
|
4101
|
+
if (!range) return false;
|
|
4102
|
+
if (dispatch) {
|
|
4103
|
+
tr.setSelection(_state.TextSelection.create(tr.doc, range.from, range.to));
|
|
4104
|
+
tr.scrollIntoView();
|
|
4105
|
+
scrollDomAtPos(view, range.blockPos);
|
|
4106
|
+
}
|
|
4107
|
+
return true;
|
|
4108
|
+
}
|
|
4109
|
+
};
|
|
4110
|
+
},
|
|
4111
|
+
addProseMirrorPlugins() {
|
|
4112
|
+
const { headingTypes } = this.options;
|
|
4113
|
+
const editor = this.editor;
|
|
4114
|
+
return [
|
|
4115
|
+
new (0, _state.Plugin)({
|
|
4116
|
+
key: crossReferencePluginKey,
|
|
4117
|
+
state: presenceStateSpec([NAME]),
|
|
4118
|
+
appendTransaction: (transactions, _oldState, newState) => {
|
|
4119
|
+
if (!transactions.some((tr) => tr.docChanged)) return null;
|
|
4120
|
+
if (!crossReferencePluginKey.getState(newState)) return null;
|
|
4121
|
+
return syncCrossReferences(newState, headingTypes);
|
|
4122
|
+
},
|
|
4123
|
+
props: {
|
|
4124
|
+
handleClickOn: (_view, _pos, node, nodePos, event) => {
|
|
4125
|
+
if (node.type.name !== NAME) return false;
|
|
4126
|
+
if (editor.isEditable && !(event.metaKey || event.ctrlKey)) return false;
|
|
4127
|
+
event.preventDefault();
|
|
4128
|
+
return editor.commands.followCrossReference(nodePos);
|
|
4129
|
+
}
|
|
4130
|
+
}
|
|
4131
|
+
})
|
|
4132
|
+
];
|
|
4133
|
+
},
|
|
4134
|
+
onBeforeCreate() {
|
|
4135
|
+
const { headingTypes } = this.options;
|
|
4136
|
+
syncInitialContent(this.editor, (state) => syncCrossReferences(state, headingTypes));
|
|
4137
|
+
}
|
|
4138
|
+
});
|
|
4139
|
+
|
|
4140
|
+
// src/extensions/document-structure/command-items.ts
|
|
4141
|
+
var start = (editor, args) => {
|
|
4142
|
+
const chain = editor.chain().focus();
|
|
4143
|
+
return _optionalChain([args, 'optionalAccess', _118 => _118.range]) ? chain.deleteRange(args.range) : chain;
|
|
4144
|
+
};
|
|
4145
|
+
var documentStructureCommandItems = [
|
|
4146
|
+
{
|
|
4147
|
+
id: "table-of-contents",
|
|
4148
|
+
title: "Table of contents",
|
|
4149
|
+
description: "Insert a linked list of the document's headings",
|
|
4150
|
+
keywords: ["toc", "contents", "outline", "index"],
|
|
4151
|
+
extension: "tableOfContents",
|
|
4152
|
+
run: (editor, args) => start(editor, args).insertTableOfContents().run()
|
|
4153
|
+
},
|
|
4154
|
+
{
|
|
4155
|
+
id: "footnote",
|
|
4156
|
+
title: "Footnote",
|
|
4157
|
+
description: "Insert a numbered footnote",
|
|
4158
|
+
keywords: ["footnote", "note", "fn", "citation"],
|
|
4159
|
+
extension: "footnoteReference",
|
|
4160
|
+
run: (editor, args) => start(editor, args).insertFootnote({ content: _optionalChain([args, 'optionalAccess', _119 => _119.content]) }).run()
|
|
4161
|
+
},
|
|
4162
|
+
{
|
|
4163
|
+
id: "bookmark",
|
|
4164
|
+
title: "Bookmark",
|
|
4165
|
+
description: "Name the selected text or word so it can be referenced",
|
|
4166
|
+
keywords: ["bookmark", "anchor", "name"],
|
|
4167
|
+
extension: "bookmark",
|
|
4168
|
+
requires: "name",
|
|
4169
|
+
run: (editor, args) => !!_optionalChain([args, 'optionalAccess', _120 => _120.name]) && start(editor, args).setBookmark({ name: args.name }).run()
|
|
4170
|
+
},
|
|
4171
|
+
{
|
|
4172
|
+
id: "cross-reference",
|
|
4173
|
+
title: "Cross-reference",
|
|
4174
|
+
description: "Insert a live reference to a heading or bookmark",
|
|
4175
|
+
keywords: ["cross", "reference", "xref", "link", "ref"],
|
|
4176
|
+
extension: "crossReference",
|
|
4177
|
+
requires: "target",
|
|
4178
|
+
run: (editor, args) => !!_optionalChain([args, 'optionalAccess', _121 => _121.targetType]) && !!args.targetId && start(editor, args).insertCrossReference({ targetType: args.targetType, targetId: args.targetId }).run()
|
|
4179
|
+
}
|
|
4180
|
+
];
|
|
4181
|
+
function getDocumentStructureCommandItems(editor, query = "") {
|
|
4182
|
+
if (!editor) return [];
|
|
4183
|
+
const installed2 = new Set(
|
|
4184
|
+
editor.extensionManager.extensions.map((extension) => extension.name)
|
|
4185
|
+
);
|
|
4186
|
+
const q = query.trim().toLowerCase();
|
|
4187
|
+
return documentStructureCommandItems.filter(
|
|
4188
|
+
(item) => installed2.has(item.extension) && (!q || item.title.toLowerCase().includes(q) || item.keywords.some((k) => k.startsWith(q)))
|
|
4189
|
+
);
|
|
4190
|
+
}
|
|
4191
|
+
|
|
4192
|
+
// src/extensions/rich-text-preset.ts
|
|
4193
|
+
var resolveExt3 = (mod, name) => _optionalChain([mod, 'optionalAccess', _122 => _122[name]]) || _optionalChain([mod, 'optionalAccess', _123 => _123.default, 'optionalAccess', _124 => _124[name]]) || _optionalChain([mod, 'optionalAccess', _125 => _125.default, 'optionalAccess', _126 => _126.default]) || _optionalChain([mod, 'optionalAccess', _127 => _127.default]) || mod;
|
|
4194
|
+
var StarterKit = resolveExt3(_StarterKit, "StarterKit");
|
|
4195
|
+
var Color = resolveExt3(_Color, "Color");
|
|
4196
|
+
var Highlight = resolveExt3(_Highlight, "Highlight");
|
|
4197
|
+
var Link2 = resolveExt3(_Link, "Link");
|
|
4198
|
+
var TaskList2 = resolveExt3(_TaskList, "TaskList");
|
|
4199
|
+
var TaskItem2 = resolveExt3(_TaskItem, "TaskItem");
|
|
4200
|
+
var TextAlign = resolveExt3(_TextAlign, "TextAlign");
|
|
4201
|
+
var TextStyle = resolveExt3(_TextStyle, "TextStyle");
|
|
4202
|
+
var Typography = resolveExt3(_Typography, "Typography");
|
|
4203
|
+
var Underline = resolveExt3(_Underline, "Underline");
|
|
4204
|
+
var Placeholder = resolveExt3(_Placeholder, "Placeholder");
|
|
4205
|
+
var CharacterCount = resolveExt3(_CharacterCount, "CharacterCount");
|
|
4206
|
+
var optionObject = (value) => typeof value === "object" && value !== null ? value : {};
|
|
4207
|
+
function createRichTextPreset(options = {}) {
|
|
4208
|
+
const {
|
|
4209
|
+
placeholder = "Start typing...",
|
|
4210
|
+
characterLimit,
|
|
4211
|
+
openLinksOnClick = false,
|
|
4212
|
+
enableSmilies = true,
|
|
4213
|
+
enableColorHighlighter = true,
|
|
4214
|
+
headingLevels = [1, 2, 3, 4]
|
|
4215
|
+
} = options;
|
|
4216
|
+
const extensions2 = [
|
|
4217
|
+
StarterKit.configure({
|
|
4218
|
+
orderedList: {
|
|
4219
|
+
HTMLAttributes: {
|
|
4220
|
+
class: "list-decimal pl-4"
|
|
4221
|
+
}
|
|
4222
|
+
},
|
|
4223
|
+
bulletList: {
|
|
4224
|
+
HTMLAttributes: {
|
|
4225
|
+
class: "list-disc pl-4"
|
|
4226
|
+
}
|
|
4227
|
+
},
|
|
4228
|
+
heading: {
|
|
4229
|
+
levels: headingLevels,
|
|
4230
|
+
HTMLAttributes: {
|
|
4231
|
+
class: "font-bold tracking-tight"
|
|
4232
|
+
}
|
|
4233
|
+
}
|
|
4234
|
+
}),
|
|
4235
|
+
TextStyle,
|
|
4236
|
+
Color,
|
|
4237
|
+
Highlight.configure({ multicolor: true }),
|
|
4238
|
+
Underline,
|
|
4239
|
+
...options.autocorrect ? [] : [Typography],
|
|
4240
|
+
TextAlign.configure({
|
|
4241
|
+
types: ["heading", "paragraph"]
|
|
4242
|
+
}),
|
|
4243
|
+
Link2.extend({
|
|
4244
|
+
addInputRules() {
|
|
4245
|
+
return [
|
|
4246
|
+
_core.markInputRule.call(void 0, {
|
|
4247
|
+
find: /(?:^|\s)\[([^\]]+)\]\(([^)]+)\)$/,
|
|
4248
|
+
type: this.type,
|
|
4249
|
+
getAttributes: (match) => ({
|
|
4250
|
+
href: match[2]
|
|
4251
|
+
})
|
|
4252
|
+
})
|
|
4253
|
+
];
|
|
4254
|
+
}
|
|
4255
|
+
}).configure({
|
|
4256
|
+
openOnClick: openLinksOnClick,
|
|
4257
|
+
autolink: true,
|
|
4258
|
+
defaultProtocol: "https",
|
|
4259
|
+
protocols: ["file", "vscode", "cursor"],
|
|
4260
|
+
HTMLAttributes: {
|
|
4261
|
+
target: "_blank",
|
|
4262
|
+
rel: "noopener noreferrer",
|
|
4263
|
+
class: "text-blue-500 underline underline-offset-2"
|
|
4264
|
+
}
|
|
4265
|
+
}),
|
|
4266
|
+
TaskList2,
|
|
4267
|
+
TaskItem2.extend({
|
|
4268
|
+
addInputRules() {
|
|
4269
|
+
return [
|
|
4270
|
+
_core.wrappingInputRule.call(void 0, {
|
|
4271
|
+
find: /^\s*(\[([ |x])?\])\s$/i,
|
|
4272
|
+
type: this.type,
|
|
4273
|
+
getAttributes: (match) => ({
|
|
4274
|
+
checked: _optionalChain([match, 'access', _128 => _128[2], 'optionalAccess', _129 => _129.toLowerCase, 'call', _130 => _130()]) === "x"
|
|
4275
|
+
})
|
|
4276
|
+
})
|
|
4277
|
+
];
|
|
4278
|
+
}
|
|
4279
|
+
}).configure({
|
|
4280
|
+
nested: true
|
|
4281
|
+
}),
|
|
4282
|
+
FontSize,
|
|
4283
|
+
Placeholder.configure({
|
|
4284
|
+
emptyEditorClass: "is-empty",
|
|
4285
|
+
placeholder: typeof placeholder === "function" ? placeholder : () => placeholder
|
|
4286
|
+
})
|
|
4287
|
+
];
|
|
4288
|
+
if (characterLimit) {
|
|
4289
|
+
extensions2.push(
|
|
4290
|
+
CharacterCount.configure({
|
|
4291
|
+
limit: characterLimit
|
|
4292
|
+
})
|
|
4293
|
+
);
|
|
4294
|
+
}
|
|
4295
|
+
if (enableSmilies) {
|
|
4296
|
+
extensions2.push(SmilieReplacer);
|
|
4297
|
+
}
|
|
4298
|
+
if (enableColorHighlighter) {
|
|
4299
|
+
extensions2.push(ColorHighlighter);
|
|
4300
|
+
}
|
|
4301
|
+
if (options.mention) {
|
|
4302
|
+
const mentionConfig = typeof options.mention === "object" ? options.mention : {};
|
|
4303
|
+
extensions2.push(
|
|
4304
|
+
Mention.configure({
|
|
4305
|
+
HTMLAttributes: {
|
|
4306
|
+
class: "pixerate-mention-node",
|
|
4307
|
+
...mentionConfig.HTMLAttributes || {}
|
|
4308
|
+
},
|
|
4309
|
+
...mentionConfig
|
|
4310
|
+
})
|
|
4311
|
+
);
|
|
4312
|
+
}
|
|
4313
|
+
if (options.markdown) {
|
|
4314
|
+
const markdownConfig = typeof options.markdown === "object" ? options.markdown : {};
|
|
4315
|
+
extensions2.push(
|
|
4316
|
+
Markdown2.configure({
|
|
4317
|
+
html: true,
|
|
4318
|
+
tightLists: true,
|
|
4319
|
+
tightListClass: "tight",
|
|
4320
|
+
bulletListMarker: "-",
|
|
4321
|
+
linkify: true,
|
|
4322
|
+
breaks: true,
|
|
4323
|
+
transformPastedText: true,
|
|
4324
|
+
transformCopiedText: true,
|
|
4325
|
+
...markdownConfig
|
|
4326
|
+
})
|
|
4327
|
+
);
|
|
4328
|
+
}
|
|
4329
|
+
if (options.image !== false) {
|
|
4330
|
+
const imageConfig = typeof options.image === "object" ? options.image : {};
|
|
4331
|
+
extensions2.push(
|
|
4332
|
+
Image2.configure({
|
|
4333
|
+
HTMLAttributes: {
|
|
4334
|
+
class: "rounded-md max-w-full h-auto my-2",
|
|
4335
|
+
...imageConfig.HTMLAttributes || {}
|
|
4336
|
+
},
|
|
4337
|
+
...imageConfig
|
|
4338
|
+
})
|
|
4339
|
+
);
|
|
4340
|
+
}
|
|
4341
|
+
if (options.comments) {
|
|
4342
|
+
extensions2.push(
|
|
4343
|
+
typeof options.comments === "object" ? Comments.configure(options.comments) : Comments
|
|
4344
|
+
);
|
|
4345
|
+
}
|
|
4346
|
+
if (options.trackChanges) {
|
|
4347
|
+
extensions2.push(
|
|
4348
|
+
typeof options.trackChanges === "object" ? _chunkTVRC4KVTcjs.TrackChanges.configure(options.trackChanges) : _chunkTVRC4KVTcjs.TrackChanges
|
|
4349
|
+
);
|
|
4350
|
+
}
|
|
4351
|
+
if (options.fileImport) {
|
|
4352
|
+
extensions2.push(
|
|
4353
|
+
FileImport.configure(
|
|
4354
|
+
typeof options.fileImport === "object" ? options.fileImport : {}
|
|
4355
|
+
)
|
|
4356
|
+
);
|
|
4357
|
+
}
|
|
4358
|
+
if (options.richClipboard) {
|
|
4359
|
+
extensions2.push(
|
|
4360
|
+
RichClipboard.configure(
|
|
4361
|
+
typeof options.richClipboard === "object" ? options.richClipboard : {}
|
|
4362
|
+
)
|
|
4363
|
+
);
|
|
4364
|
+
}
|
|
4365
|
+
if (options.autocorrect) {
|
|
4366
|
+
extensions2.push(Autocorrect.configure(optionObject(options.autocorrect)));
|
|
4367
|
+
}
|
|
4368
|
+
if (options.outline || options.tableOfContents || options.crossReferences) {
|
|
4369
|
+
extensions2.push(Outline.configure(optionObject(options.outline)));
|
|
4370
|
+
}
|
|
4371
|
+
if (options.tableOfContents) {
|
|
4372
|
+
extensions2.push(TableOfContents.configure(optionObject(options.tableOfContents)));
|
|
4373
|
+
}
|
|
4374
|
+
if (options.footnotes) {
|
|
4375
|
+
extensions2.push(
|
|
4376
|
+
FootnoteReference.configure(optionObject(options.footnotes)),
|
|
4377
|
+
Footnotes,
|
|
4378
|
+
Footnote
|
|
4379
|
+
);
|
|
4380
|
+
}
|
|
4381
|
+
if (options.bookmarks) {
|
|
4382
|
+
extensions2.push(Bookmark.configure(optionObject(options.bookmarks)));
|
|
4383
|
+
}
|
|
4384
|
+
if (options.crossReferences) {
|
|
4385
|
+
extensions2.push(CrossReference.configure(optionObject(options.crossReferences)));
|
|
4386
|
+
}
|
|
4387
|
+
return extensions2;
|
|
4388
|
+
}
|
|
4389
|
+
|
|
4390
|
+
|
|
4391
|
+
|
|
4392
|
+
|
|
4393
|
+
|
|
4394
|
+
|
|
4395
|
+
|
|
4396
|
+
|
|
4397
|
+
|
|
4398
|
+
|
|
4399
|
+
|
|
4400
|
+
|
|
4401
|
+
|
|
4402
|
+
|
|
4403
|
+
|
|
4404
|
+
|
|
4405
|
+
|
|
4406
|
+
|
|
4407
|
+
|
|
4408
|
+
|
|
4409
|
+
|
|
4410
|
+
|
|
4411
|
+
|
|
4412
|
+
|
|
4413
|
+
|
|
4414
|
+
|
|
4415
|
+
|
|
4416
|
+
|
|
4417
|
+
|
|
4418
|
+
|
|
4419
|
+
|
|
4420
|
+
|
|
4421
|
+
|
|
4422
|
+
|
|
4423
|
+
|
|
4424
|
+
|
|
4425
|
+
|
|
4426
|
+
|
|
4427
|
+
|
|
4428
|
+
|
|
4429
|
+
|
|
4430
|
+
|
|
4431
|
+
|
|
4432
|
+
|
|
4433
|
+
|
|
4434
|
+
|
|
4435
|
+
|
|
4436
|
+
|
|
4437
|
+
|
|
4438
|
+
|
|
4439
|
+
|
|
4440
|
+
|
|
4441
|
+
|
|
4442
|
+
|
|
4443
|
+
|
|
4444
|
+
|
|
4445
|
+
|
|
4446
|
+
|
|
4447
|
+
|
|
4448
|
+
|
|
4449
|
+
|
|
4450
|
+
|
|
4451
|
+
|
|
4452
|
+
|
|
4453
|
+
|
|
4454
|
+
|
|
4455
|
+
|
|
4456
|
+
|
|
4457
|
+
|
|
4458
|
+
|
|
4459
|
+
|
|
4460
|
+
|
|
4461
|
+
|
|
4462
|
+
|
|
4463
|
+
|
|
4464
|
+
|
|
4465
|
+
|
|
4466
|
+
|
|
4467
|
+
|
|
4468
|
+
|
|
4469
|
+
|
|
4470
|
+
|
|
4471
|
+
|
|
4472
|
+
|
|
4473
|
+
|
|
4474
|
+
|
|
4475
|
+
|
|
4476
|
+
|
|
4477
|
+
|
|
4478
|
+
|
|
4479
|
+
exports.GradientText = GradientText; exports.SlashCommands = SlashCommands; exports.TemplateSuggestions = TemplateSuggestions; exports.LoadingNode = LoadingNode; exports.SMILIE_REPLACEMENTS = SMILIE_REPLACEMENTS; exports.smilieAutocorrectRules = smilieAutocorrectRules; exports.SmilieReplacer = SmilieReplacer; exports.findHexColors = findHexColors; exports.ColorHighlighter = ColorHighlighter; exports.FontSize = FontSize; exports.Mention = Mention; exports.createMentionExtension = createMentionExtension; exports.Markdown = Markdown2; exports.imagePastePluginKey = imagePastePluginKey; exports.insertImageNode = insertImageNode; exports.updateImageSrc = updateImageSrc; exports.removeImageNode = removeImageNode; exports.handleImageInsertion = handleImageInsertion; exports.Image = Image2; exports.commentsPluginKey = commentsPluginKey; exports.COMMENT_MARK_NAME = COMMENT_MARK_NAME; exports.findCommentRanges = findCommentRanges; exports.getCommentAnchors = getCommentAnchors; exports.getCommentIdsAt = getCommentIdsAt; exports.getCommentStore = getCommentStore; exports.Comments = Comments; exports.getCommentAuthor = getCommentAuthor; exports.ImportError = ImportError; exports.createImportContext = createImportContext; exports.ImportAdapterRegistry = ImportAdapterRegistry; exports.markdownImportAdapter = markdownImportAdapter; exports.htmlImportAdapter = htmlImportAdapter; exports.plainTextImportAdapter = plainTextImportAdapter; exports.rtfImportAdapter = rtfImportAdapter; exports.BUILT_IN_IMPORT_ADAPTERS = BUILT_IN_IMPORT_ADAPTERS; exports.createImportAdapterRegistry = createImportAdapterRegistry; exports.defaultImportRegistry = defaultImportRegistry; exports.registerImportAdapter = registerImportAdapter; exports.unregisterImportAdapter = unregisterImportAdapter; exports.findImportAdapter = findImportAdapter; exports.importFile = importFile; exports.getImportAccept = getImportAccept; exports.htmlToSlice = htmlToSlice; exports.insertImportedDocument = insertImportedDocument; exports.importFilesIntoEditor = importFilesIntoEditor; exports.fileImportPluginKey = fileImportPluginKey; exports.FileImport = FileImport; exports.richClipboardPluginKey = richClipboardPluginKey; exports.writeRichClipboard = writeRichClipboard; exports.RichClipboard = RichClipboard; exports.smartQuoteRules = smartQuoteRules; exports.symbolRules = symbolRules; exports.fractionRules = fractionRules; exports.capitalizeSentenceRules = capitalizeSentenceRules; exports.twoInitialCapitalsRules = twoInitialCapitalsRules; exports.defaultAutocorrectRules = defaultAutocorrectRules; exports.DEFAULT_AUTOCORRECT_EXCEPTIONS = DEFAULT_AUTOCORRECT_EXCEPTIONS; exports.autocorrectPluginKey = autocorrectPluginKey; exports.findAutocorrection = findAutocorrection; exports.isInsidePromptToken = isInsidePromptToken; exports.Autocorrect = Autocorrect; exports.outlinePluginKey = outlinePluginKey; exports.computeOutline = computeOutline; exports.buildOutlineTree = buildOutlineTree; exports.getOutline = getOutline; exports.getActiveHeading = getActiveHeading; exports.createOutlineStore = createOutlineStore; exports.navigateToHeading = navigateToHeading; exports.Outline = Outline; exports.tableOfContentsMarkdownIt = tableOfContentsMarkdownIt; exports.footnotesMarkdownIt = footnotesMarkdownIt; exports.tableOfContentsPluginKey = tableOfContentsPluginKey; exports.getTableOfContentsEntries = getTableOfContentsEntries; exports.TableOfContents = TableOfContents; exports.footnotesPluginKey = footnotesPluginKey; exports.getFootnotes = getFootnotes; exports.syncFootnotes = syncFootnotes; exports.FootnoteReference = FootnoteReference; exports.Footnotes = Footnotes; exports.Footnote = Footnote; exports.getBookmarks = getBookmarks; exports.Bookmark = Bookmark; exports.crossReferencePluginKey = crossReferencePluginKey; exports.getCrossReferenceTargets = getCrossReferenceTargets; exports.CrossReference = CrossReference; exports.documentStructureCommandItems = documentStructureCommandItems; exports.getDocumentStructureCommandItems = getDocumentStructureCommandItems; exports.createRichTextPreset = createRichTextPreset;
|
|
4480
|
+
//# sourceMappingURL=chunk-4QPLEUL2.cjs.map
|