@w100n/documents 0.16.4 → 0.18.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/dist/{Compare-M57FG4R3.js → Compare-RHAUAKUJ.js} +2 -2
- package/dist/{SheetView-OEKOHMKW.js → SheetView-43JDIP7D.js} +5 -5
- package/dist/{TextEditor-5S7FSLIZ.js → TextEditor-CYS4U5XA.js} +119 -27
- package/dist/TextEditor-CYS4U5XA.js.map +1 -0
- package/dist/{chunk-VNXZVOPN.js → chunk-BWU6FPPZ.js} +956 -1
- package/dist/chunk-BWU6FPPZ.js.map +1 -0
- package/dist/{chunk-3D2G5NBI.js → chunk-DATYTA4H.js} +2 -2
- package/dist/{chunk-EQLBYW42.js → chunk-GSIPTCQH.js} +9 -1
- package/dist/chunk-GSIPTCQH.js.map +1 -0
- package/dist/chunk-Z5STMOD6.js +39 -0
- package/dist/chunk-Z5STMOD6.js.map +1 -0
- package/dist/{chunk-AKJGYZME.js → chunk-ZCSHH24C.js} +67 -832
- package/dist/chunk-ZCSHH24C.js.map +1 -0
- package/dist/collab.cjs +197 -2
- package/dist/collab.cjs.map +1 -1
- package/dist/collab.d.cts +1 -1
- package/dist/collab.d.ts +1 -1
- package/dist/collab.js +3 -3
- package/dist/index.cjs +1437 -543
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +330 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1080 -497
- package/dist/index.js.map +1 -1
- package/dist/kinds.d.cts +1 -1
- package/dist/kinds.d.ts +1 -1
- package/dist/memory.cjs +34 -5
- package/dist/memory.cjs.map +1 -1
- package/dist/memory.d.cts +1 -1
- package/dist/memory.d.ts +1 -1
- package/dist/memory.js +34 -5
- package/dist/memory.js.map +1 -1
- package/dist/{types-BUO0OzOl.d.cts → types-DyonaPQf.d.cts} +12 -1
- package/dist/{types-BUO0OzOl.d.ts → types-DyonaPQf.d.ts} +12 -1
- package/package.json +1 -1
- package/dist/TextEditor-5S7FSLIZ.js.map +0 -1
- package/dist/chunk-AKJGYZME.js.map +0 -1
- package/dist/chunk-EQLBYW42.js.map +0 -1
- package/dist/chunk-VNXZVOPN.js.map +0 -1
- /package/dist/{Compare-M57FG4R3.js.map → Compare-RHAUAKUJ.js.map} +0 -0
- /package/dist/{SheetView-OEKOHMKW.js.map → SheetView-43JDIP7D.js.map} +0 -0
- /package/dist/{chunk-3D2G5NBI.js.map → chunk-DATYTA4H.js.map} +0 -0
|
@@ -1,7 +1,879 @@
|
|
|
1
1
|
'use client';
|
|
2
|
+
import {
|
|
3
|
+
mathml
|
|
4
|
+
} from "./chunk-ZAVXCH7V.js";
|
|
5
|
+
|
|
6
|
+
// src/editor/pager.ts
|
|
7
|
+
import { Extension } from "@tiptap/core";
|
|
8
|
+
import { Plugin, PluginKey } from "@tiptap/pm/state";
|
|
9
|
+
import { Decoration, DecorationSet } from "@tiptap/pm/view";
|
|
10
|
+
var a4 = { width: 793.73, height: 1122.53, margins: [96, 96, 96, 96] };
|
|
11
|
+
var letter = { width: 816, height: 1056 };
|
|
12
|
+
var paging = new PluginKey("w100n-pager");
|
|
13
|
+
var skip = (el) => el.classList.contains("w100n-text-gap") || el.classList.contains("ProseMirror-gapcursor");
|
|
14
|
+
function measure(view) {
|
|
15
|
+
const { page } = paging.getState(view.state);
|
|
16
|
+
const [top, , bottom] = page.margins;
|
|
17
|
+
const room = page.height - top - bottom;
|
|
18
|
+
const els = [...view.dom.children];
|
|
19
|
+
const gaps = [];
|
|
20
|
+
const line = page.width - page.margins[1] - page.margins[3];
|
|
21
|
+
const area = (list) => list.length ? 14 + list.reduce((h, text) => h + 15 * Math.max(1, Math.ceil(text.length * 5.6 / line)), 0) : 0;
|
|
22
|
+
let notes2 = [];
|
|
23
|
+
let count = 0;
|
|
24
|
+
let i = 0;
|
|
25
|
+
let shift = 0;
|
|
26
|
+
let start = 0;
|
|
27
|
+
let last = 0;
|
|
28
|
+
view.state.doc.forEach((node, offset) => {
|
|
29
|
+
let el = els[i++];
|
|
30
|
+
while (el && skip(el)) {
|
|
31
|
+
if (el.classList.contains("w100n-text-gap")) shift += el.offsetHeight;
|
|
32
|
+
el = els[i++];
|
|
33
|
+
}
|
|
34
|
+
if (!el) return;
|
|
35
|
+
const y = el.offsetTop - shift;
|
|
36
|
+
const end = y + el.offsetHeight;
|
|
37
|
+
const mine = [];
|
|
38
|
+
node.descendants((d) => {
|
|
39
|
+
if (d.type.name === "footnote") mine.push(`${count + mine.length + 1} ${d.attrs.text}`);
|
|
40
|
+
});
|
|
41
|
+
if (node.type.name === "pageBreak") {
|
|
42
|
+
gaps.push({ pos: offset + node.nodeSize, height: start + room - end + bottom + 24 + top, page: gaps.length + 1, notes: notes2 });
|
|
43
|
+
notes2 = [];
|
|
44
|
+
start = end;
|
|
45
|
+
} else if (end > start + room - area([...notes2, ...mine]) && y > start) {
|
|
46
|
+
gaps.push({ pos: offset, height: start + room - y + bottom + 24 + top, page: gaps.length + 1, notes: notes2 });
|
|
47
|
+
notes2 = [];
|
|
48
|
+
start = y;
|
|
49
|
+
}
|
|
50
|
+
notes2.push(...mine);
|
|
51
|
+
count += mine.length;
|
|
52
|
+
while (end > start + room) start += room;
|
|
53
|
+
last = end;
|
|
54
|
+
});
|
|
55
|
+
gaps.push({ pos: view.state.doc.content.size, height: Math.max(0, start + room - last), page: gaps.length + 1, end: true, notes: notes2 });
|
|
56
|
+
return gaps.map((g) => ({ ...g, height: Math.max(0, Math.round(g.height)) }));
|
|
57
|
+
}
|
|
58
|
+
var Pager = Extension.create({
|
|
59
|
+
name: "pager",
|
|
60
|
+
addProseMirrorPlugins: () => [new Plugin({
|
|
61
|
+
key: paging,
|
|
62
|
+
state: {
|
|
63
|
+
init: () => ({ set: DecorationSet.empty, page: a4, marks: { header: "", footer: "" }, flow: false }),
|
|
64
|
+
apply(tr, value) {
|
|
65
|
+
const next = tr.getMeta(paging);
|
|
66
|
+
return { set: next?.set ?? value.set.map(tr.mapping, tr.doc), page: next?.page ?? value.page, marks: next?.marks ?? value.marks, flow: next?.flow ?? value.flow };
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
props: { decorations: (state) => paging.getState(state).set },
|
|
70
|
+
view(view) {
|
|
71
|
+
let timer = 0;
|
|
72
|
+
let sig = "";
|
|
73
|
+
const run = () => {
|
|
74
|
+
if (!view.dom.isConnected) return;
|
|
75
|
+
const { marks, flow } = paging.getState(view.state);
|
|
76
|
+
if (flow) {
|
|
77
|
+
if (sig !== "flow") view.dispatch(view.state.tr.setMeta(paging, { set: DecorationSet.empty }).setMeta("addToHistory", false));
|
|
78
|
+
sig = "flow";
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const gaps = measure(view);
|
|
82
|
+
const next = gaps.map((g) => `${g.pos}:${g.height}:${g.notes.join("\n")}`).join() + `|${marks.header}|${marks.footer}`;
|
|
83
|
+
if (next === sig) return;
|
|
84
|
+
sig = next;
|
|
85
|
+
const line = (parent, cls, text) => {
|
|
86
|
+
if (!text) return;
|
|
87
|
+
const span = document.createElement("span");
|
|
88
|
+
span.className = cls;
|
|
89
|
+
span.textContent = text;
|
|
90
|
+
parent.append(span);
|
|
91
|
+
};
|
|
92
|
+
const first = Decoration.widget(0, () => {
|
|
93
|
+
const el = document.createElement("div");
|
|
94
|
+
el.className = "w100n-text-first";
|
|
95
|
+
el.contentEditable = "false";
|
|
96
|
+
line(el, "w100n-text-head", marks.header);
|
|
97
|
+
return el;
|
|
98
|
+
}, { key: `first:${marks.header}`, side: -1, ignoreSelection: true });
|
|
99
|
+
const set = DecorationSet.create(view.state.doc, [first, ...gaps.map((g) => Decoration.widget(g.pos, () => {
|
|
100
|
+
const el = document.createElement("div");
|
|
101
|
+
el.className = g.end ? "w100n-text-gap is-end" : "w100n-text-gap";
|
|
102
|
+
el.style.height = `${g.height}px`;
|
|
103
|
+
el.dataset.page = String(g.page);
|
|
104
|
+
el.contentEditable = "false";
|
|
105
|
+
line(el, "w100n-text-foot", marks.footer);
|
|
106
|
+
if (!g.end) line(el, "w100n-text-head", marks.header);
|
|
107
|
+
if (g.notes.length) {
|
|
108
|
+
const list = document.createElement("div");
|
|
109
|
+
list.className = "w100n-text-footnotes";
|
|
110
|
+
for (const note of g.notes) {
|
|
111
|
+
const p = document.createElement("p");
|
|
112
|
+
const n = document.createElement("sup");
|
|
113
|
+
n.textContent = note.slice(0, note.indexOf(" "));
|
|
114
|
+
p.append(n, note.slice(note.indexOf(" ")));
|
|
115
|
+
list.append(p);
|
|
116
|
+
}
|
|
117
|
+
el.append(list);
|
|
118
|
+
}
|
|
119
|
+
return el;
|
|
120
|
+
}, { key: `${g.pos}:${g.height}:${g.page}:${marks.header}:${marks.footer}:${g.notes.join("\n")}`, side: -1, ignoreSelection: true }))]);
|
|
121
|
+
view.dispatch(view.state.tr.setMeta(paging, { set }).setMeta("addToHistory", false));
|
|
122
|
+
};
|
|
123
|
+
const later = (ms) => {
|
|
124
|
+
clearTimeout(timer);
|
|
125
|
+
timer = window.setTimeout(run, ms);
|
|
126
|
+
};
|
|
127
|
+
const watch = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(() => later(200));
|
|
128
|
+
watch?.observe(view.dom);
|
|
129
|
+
later(0);
|
|
130
|
+
return {
|
|
131
|
+
update: (next, prev) => {
|
|
132
|
+
const now = paging.getState(next.state), was = paging.getState(prev);
|
|
133
|
+
if (now.page !== was.page || now.marks !== was.marks || now.flow !== was.flow) later(0);
|
|
134
|
+
else if (next.state.doc !== prev.doc) later(400);
|
|
135
|
+
},
|
|
136
|
+
destroy: () => {
|
|
137
|
+
clearTimeout(timer);
|
|
138
|
+
watch?.disconnect();
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
})]
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// src/editor/extensions.ts
|
|
146
|
+
import { Extension as Extension2, Mark, Node } from "@tiptap/core";
|
|
147
|
+
import Collaboration from "@tiptap/extension-collaboration";
|
|
148
|
+
import CollaborationCaret from "@tiptap/extension-collaboration-caret";
|
|
149
|
+
import Highlight from "@tiptap/extension-highlight";
|
|
150
|
+
import Image from "@tiptap/extension-image";
|
|
151
|
+
import { TaskItem, TaskList } from "@tiptap/extension-list";
|
|
152
|
+
import { TableKit } from "@tiptap/extension-table";
|
|
153
|
+
import { Color, FontFamily, FontSize, TextStyle } from "@tiptap/extension-text-style";
|
|
154
|
+
import { Plugin as Plugin2, PluginKey as PluginKey2, TextSelection } from "@tiptap/pm/state";
|
|
155
|
+
import { StepMap } from "@tiptap/pm/transform";
|
|
156
|
+
import { Decoration as Decoration2, DecorationSet as DecorationSet2 } from "@tiptap/pm/view";
|
|
157
|
+
import StarterKit from "@tiptap/starter-kit";
|
|
158
|
+
import { ySyncPluginKey } from "@tiptap/y-tiptap";
|
|
159
|
+
var notes = new PluginKey2("w100n-notes");
|
|
160
|
+
var blocks = [
|
|
161
|
+
"paragraph",
|
|
162
|
+
"heading",
|
|
163
|
+
"bulletList",
|
|
164
|
+
"orderedList",
|
|
165
|
+
"listItem",
|
|
166
|
+
"taskList",
|
|
167
|
+
"taskItem",
|
|
168
|
+
"blockquote",
|
|
169
|
+
"codeBlock",
|
|
170
|
+
"horizontalRule",
|
|
171
|
+
"table",
|
|
172
|
+
"tableRow",
|
|
173
|
+
"tableHeader",
|
|
174
|
+
"tableCell",
|
|
175
|
+
"pageBreak",
|
|
176
|
+
"toc"
|
|
177
|
+
];
|
|
178
|
+
var changed = (trs) => {
|
|
179
|
+
const ranges = [];
|
|
180
|
+
trs.forEach((tr, n) => tr.steps.forEach((step, i) => {
|
|
181
|
+
const slice = step.slice;
|
|
182
|
+
if (!slice || !slice.openStart && !slice.openEnd && !slice.content.firstChild?.isBlock) return;
|
|
183
|
+
const after = tr.mapping.slice(i + 1);
|
|
184
|
+
for (const later of trs.slice(n + 1)) after.appendMapping(later.mapping);
|
|
185
|
+
step.getMap().forEach((_a, _b, from, to) => ranges.push([after.map(from, -1), after.map(to, 1)]));
|
|
186
|
+
}));
|
|
187
|
+
return ranges;
|
|
188
|
+
};
|
|
189
|
+
var Cells = Extension2.create({
|
|
190
|
+
name: "cells",
|
|
191
|
+
addGlobalAttributes: () => [
|
|
192
|
+
{ types: ["tableCell", "tableHeader"], attributes: { background: { default: null, parseHTML: (el) => el.dataset.fill ?? null, renderHTML: (attrs) => attrs.background ? { "data-fill": attrs.background, style: `background-color: ${attrs.background}` } : {} } } },
|
|
193
|
+
{ types: ["table"], attributes: { borders: { default: null, parseHTML: (el) => el.dataset.borders ?? null, renderHTML: (attrs) => attrs.borders ? { "data-borders": attrs.borders } : {} } } }
|
|
194
|
+
]
|
|
195
|
+
});
|
|
196
|
+
var searching = new PluginKey2("w100n-search");
|
|
197
|
+
var lookup = (doc, query, matchCase) => {
|
|
198
|
+
const hits = [];
|
|
199
|
+
if (!query) return hits;
|
|
200
|
+
const needle = matchCase ? query : query.toLowerCase();
|
|
201
|
+
doc.descendants((node, pos) => {
|
|
202
|
+
if (!node.isTextblock) return true;
|
|
203
|
+
let text = "";
|
|
204
|
+
const at = [];
|
|
205
|
+
node.forEach((child, offset) => {
|
|
206
|
+
const part = child.isText ? child.text : "\uFFFC";
|
|
207
|
+
for (let i = 0; i < part.length; i++) at.push(pos + 1 + offset + i);
|
|
208
|
+
text += part;
|
|
209
|
+
});
|
|
210
|
+
const hay = matchCase ? text : text.toLowerCase();
|
|
211
|
+
for (let i = hay.indexOf(needle); i >= 0; i = hay.indexOf(needle, i + needle.length)) hits.push({ from: at[i], to: at[i + needle.length - 1] + 1 });
|
|
212
|
+
return false;
|
|
213
|
+
});
|
|
214
|
+
return hits;
|
|
215
|
+
};
|
|
216
|
+
var Search = Extension2.create({
|
|
217
|
+
name: "search",
|
|
218
|
+
addProseMirrorPlugins: () => [new Plugin2({
|
|
219
|
+
key: searching,
|
|
220
|
+
state: {
|
|
221
|
+
init: () => ({ query: "", matchCase: false, hits: [], at: 0, set: DecorationSet2.empty }),
|
|
222
|
+
apply(tr, value) {
|
|
223
|
+
const meta = tr.getMeta(searching);
|
|
224
|
+
if (!meta && !tr.docChanged) return value;
|
|
225
|
+
const next = { ...value, ...meta };
|
|
226
|
+
const hits = lookup(tr.doc, next.query, next.matchCase);
|
|
227
|
+
const at = hits.length ? (next.at % hits.length + hits.length) % hits.length : 0;
|
|
228
|
+
return { ...next, hits, at, set: DecorationSet2.create(tr.doc, hits.map((h, i) => Decoration2.inline(h.from, h.to, { class: i === at ? "w100n-found is-current" : "w100n-found" }))) };
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
props: { decorations: (state) => searching.getState(state).set }
|
|
232
|
+
})]
|
|
233
|
+
});
|
|
234
|
+
var replace = (editor, text, all) => {
|
|
235
|
+
const { hits, at } = searching.getState(editor.state);
|
|
236
|
+
if (!hits.length) return 0;
|
|
237
|
+
const tr = editor.state.tr;
|
|
238
|
+
for (const hit of all ? [...hits].reverse() : [hits[at]]) tr.insertText(text, hit.from, hit.to);
|
|
239
|
+
editor.view.dispatch(tr);
|
|
240
|
+
return all ? hits.length : 1;
|
|
241
|
+
};
|
|
242
|
+
var cleanPaste = (html) => html.replace(/<!--\[if[\s\S]*?<!\[endif\]-->/g, "").replace(/<o:p>[\s\S]*?<\/o:p>/g, "").replace(/\sclass=("|')?Mso[^"'\s>]*\1?/g, "").replace(/<img\b[^>]*\ssrc=("|')file:[^"']*\1[^>]*>/gi, "").replace(/\sstyle=("|')([^"']*)\1/g, (_, q, css) => {
|
|
243
|
+
const kept = css.split(";").map((x) => x.trim()).filter((x) => x && !/^mso-|^tab-stops|^font-family:\s*["']?(Symbol|Wingdings)/i.test(x)).join("; ");
|
|
244
|
+
return kept ? ` style=${q}${kept}${q}` : "";
|
|
245
|
+
});
|
|
246
|
+
var Blocks = Extension2.create({
|
|
247
|
+
name: "blocks",
|
|
248
|
+
addGlobalAttributes: () => [{
|
|
249
|
+
types: blocks,
|
|
250
|
+
attributes: {
|
|
251
|
+
align: { default: null, parseHTML: (el) => el.style.textAlign || null, renderHTML: (attrs) => attrs.align ? { style: `text-align: ${attrs.align}` } : {} },
|
|
252
|
+
indent: { default: 0, parseHTML: (el) => Number(el.dataset.indent) || 0, renderHTML: (attrs) => attrs.indent ? { "data-indent": attrs.indent, style: `margin-left: ${attrs.indent * 0.5}in` } : {} },
|
|
253
|
+
line: { default: null, parseHTML: (el) => Number(el.dataset.line) || null, renderHTML: (attrs) => attrs.line ? { "data-line": attrs.line, style: `line-height: ${attrs.line * 1.15}` } : {} },
|
|
254
|
+
after: { default: null, parseHTML: (el) => el.dataset.after ? Number(el.dataset.after) : null, renderHTML: (attrs) => attrs.after === null || attrs.after === void 0 ? {} : { "data-after": attrs.after, style: `margin-bottom: ${attrs.after}pt` } },
|
|
255
|
+
ref: { default: null, rendered: false, keepOnSplit: false }
|
|
256
|
+
}
|
|
257
|
+
}],
|
|
258
|
+
addProseMirrorPlugins: () => [new Plugin2({
|
|
259
|
+
appendTransaction(trs, _old, state) {
|
|
260
|
+
const ranges = changed(trs);
|
|
261
|
+
if (!ranges.length) return null;
|
|
262
|
+
const seen2 = /* @__PURE__ */ new Map();
|
|
263
|
+
const drop = [];
|
|
264
|
+
const visit = (node, pos2) => {
|
|
265
|
+
const ref = node.attrs.ref;
|
|
266
|
+
if (!ref) return;
|
|
267
|
+
const first = seen2.get(ref);
|
|
268
|
+
if (!first) seen2.set(ref, { pos: pos2, node });
|
|
269
|
+
else if (!first.node.textContent && node.textContent) {
|
|
270
|
+
drop.push(first.pos);
|
|
271
|
+
seen2.set(ref, { pos: pos2, node });
|
|
272
|
+
} else drop.push(pos2);
|
|
273
|
+
};
|
|
274
|
+
const from = Math.max(0, Math.min(...ranges.map((r) => r[0])));
|
|
275
|
+
const to = Math.min(state.doc.content.size, Math.max(...ranges.map((r) => r[1])));
|
|
276
|
+
const $from = state.doc.resolve(from);
|
|
277
|
+
const $to = state.doc.resolve(to);
|
|
278
|
+
const start = Math.max(0, $from.index(0) - 1);
|
|
279
|
+
const end = Math.min(state.doc.childCount, $to.index(0) + 2);
|
|
280
|
+
let pos = 0;
|
|
281
|
+
for (let i = 0; i < start; i++) pos += state.doc.child(i).nodeSize;
|
|
282
|
+
for (let i = start; i < end; i++) {
|
|
283
|
+
const top = state.doc.child(i);
|
|
284
|
+
visit(top, pos);
|
|
285
|
+
top.descendants((node, at) => visit(node, pos + 1 + at));
|
|
286
|
+
pos += top.nodeSize;
|
|
287
|
+
}
|
|
288
|
+
if (!drop.length) return null;
|
|
289
|
+
const tr = state.tr;
|
|
290
|
+
for (const at of drop) tr.setNodeAttribute(at, "ref", null);
|
|
291
|
+
return tr;
|
|
292
|
+
}
|
|
293
|
+
})]
|
|
294
|
+
});
|
|
295
|
+
var PageBreak = Node.create({
|
|
296
|
+
name: "pageBreak",
|
|
297
|
+
group: "block",
|
|
298
|
+
atom: true,
|
|
299
|
+
selectable: true,
|
|
300
|
+
addOptions: () => ({ label: "" }),
|
|
301
|
+
parseHTML: () => [{ tag: "div[data-page-break]" }],
|
|
302
|
+
renderHTML() {
|
|
303
|
+
return ["div", { "data-page-break": "", "data-label": this.options.label, class: "w100n-text-break", contenteditable: "false" }];
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
var Formula = Node.create({
|
|
307
|
+
name: "math",
|
|
308
|
+
group: "inline",
|
|
309
|
+
inline: true,
|
|
310
|
+
atom: true,
|
|
311
|
+
selectable: true,
|
|
312
|
+
addAttributes: () => ({ latex: { default: "", parseHTML: (el) => el.getAttribute("data-math") ?? "" } }),
|
|
313
|
+
parseHTML: () => [{ tag: "span[data-math]" }],
|
|
314
|
+
renderHTML: ({ node }) => ["span", { "data-math": node.attrs.latex, class: "w100n-math" }],
|
|
315
|
+
addNodeView: () => ({ node }) => {
|
|
316
|
+
const dom = document.createElement("span");
|
|
317
|
+
dom.className = "w100n-math";
|
|
318
|
+
dom.dataset.math = node.attrs.latex;
|
|
319
|
+
dom.contentEditable = "false";
|
|
320
|
+
dom.innerHTML = mathml(node.attrs.latex);
|
|
321
|
+
return { dom };
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
var Footnote = Node.create({
|
|
325
|
+
name: "footnote",
|
|
326
|
+
group: "inline",
|
|
327
|
+
inline: true,
|
|
328
|
+
atom: true,
|
|
329
|
+
selectable: true,
|
|
330
|
+
addAttributes: () => ({
|
|
331
|
+
id: { default: null, parseHTML: (el) => el.getAttribute("data-note-id") },
|
|
332
|
+
text: { default: "", parseHTML: (el) => el.getAttribute("title") ?? "" }
|
|
333
|
+
}),
|
|
334
|
+
parseHTML: () => [{ tag: "sup[data-footnote]" }],
|
|
335
|
+
renderHTML: ({ node }) => ["sup", { "data-footnote": "", "data-note-id": node.attrs.id ?? void 0, title: node.attrs.text, class: "w100n-fn", contenteditable: "false" }]
|
|
336
|
+
});
|
|
337
|
+
var wikiName = (target) => target.split("#")[0].trim().replace(/\.md$/i, "");
|
|
338
|
+
var WikiLink = Node.create({
|
|
339
|
+
name: "wikilink",
|
|
340
|
+
group: "inline",
|
|
341
|
+
inline: true,
|
|
342
|
+
atom: true,
|
|
343
|
+
selectable: true,
|
|
344
|
+
addOptions: () => ({ known: () => true }),
|
|
345
|
+
addAttributes: () => ({
|
|
346
|
+
target: { default: "", parseHTML: (el) => el.getAttribute("data-wiki") ?? "" },
|
|
347
|
+
alias: { default: null, parseHTML: (el) => el.getAttribute("data-alias") }
|
|
348
|
+
}),
|
|
349
|
+
parseHTML: () => [{ tag: "span[data-wiki]" }],
|
|
350
|
+
renderHTML: ({ node }) => [
|
|
351
|
+
"span",
|
|
352
|
+
{ "data-wiki": node.attrs.target, "data-alias": node.attrs.alias ?? void 0, class: "w100n-wiki", contenteditable: "false" },
|
|
353
|
+
node.attrs.alias || wikiName(node.attrs.target) || node.attrs.target
|
|
354
|
+
],
|
|
355
|
+
addProseMirrorPlugins() {
|
|
356
|
+
const known = this.options.known;
|
|
357
|
+
return [new Plugin2({
|
|
358
|
+
props: {
|
|
359
|
+
decorations(state) {
|
|
360
|
+
const found = [];
|
|
361
|
+
state.doc.descendants((node, pos) => {
|
|
362
|
+
if (node.type.name === "wikilink" && !known(node.attrs.target)) found.push(Decoration2.node(pos, pos + node.nodeSize, { class: "is-missing" }));
|
|
363
|
+
});
|
|
364
|
+
return DecorationSet2.create(state.doc, found);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
})];
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
var wikiAsk = new PluginKey2("wikiAsk");
|
|
371
|
+
var WikiAsk = Extension2.create({
|
|
372
|
+
name: "wikiAsk",
|
|
373
|
+
addProseMirrorPlugins() {
|
|
374
|
+
return [new Plugin2({
|
|
375
|
+
key: wikiAsk,
|
|
376
|
+
state: {
|
|
377
|
+
init: () => null,
|
|
378
|
+
apply(tr, _old, _before, state) {
|
|
379
|
+
const { $from, empty } = state.selection;
|
|
380
|
+
if (!empty || !$from.parent.isTextblock || $from.parent.type.spec.code) return null;
|
|
381
|
+
const before = $from.parent.textBetween(0, $from.parentOffset, void 0, "\uFFFC");
|
|
382
|
+
const m = /\[\[([^[\]\n|\ufffc]*)$/.exec(before);
|
|
383
|
+
return m ? { from: $from.pos - m[0].length, query: m[1] } : null;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
})];
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
var signs = { bold: "**", italic: "*", strike: "~~", code: "`" };
|
|
390
|
+
var syntax = (text, pos, side) => Decoration2.widget(pos, () => {
|
|
391
|
+
const el = document.createElement("span");
|
|
392
|
+
el.className = "w100n-syntax";
|
|
393
|
+
el.textContent = text;
|
|
394
|
+
return el;
|
|
395
|
+
}, { side, key: `${text}:${pos}:${side}` });
|
|
396
|
+
var Reveal = Extension2.create({
|
|
397
|
+
name: "reveal",
|
|
398
|
+
addProseMirrorPlugins: () => [new Plugin2({
|
|
399
|
+
props: {
|
|
400
|
+
decorations(state) {
|
|
401
|
+
const { $from, empty } = state.selection;
|
|
402
|
+
if (!empty || !$from.parent.isTextblock) return null;
|
|
403
|
+
const found = [];
|
|
404
|
+
const start = $from.start();
|
|
405
|
+
if ($from.parent.type.name === "heading") found.push(syntax(`${"#".repeat($from.parent.attrs.level)} `, start, -1));
|
|
406
|
+
const at = $from.parentOffset;
|
|
407
|
+
for (const [name, sign] of Object.entries(signs)) {
|
|
408
|
+
let from = -1;
|
|
409
|
+
let offset = 0;
|
|
410
|
+
$from.parent.forEach((child) => {
|
|
411
|
+
const end = offset + child.nodeSize;
|
|
412
|
+
if (child.marks.some((m) => m.type.name === name)) {
|
|
413
|
+
if (from < 0) from = offset;
|
|
414
|
+
if (from <= at && at <= end && (end === $from.parent.content.size || !$from.parent.childAfter(end).node?.marks.some((m) => m.type.name === name))) {
|
|
415
|
+
found.push(syntax(sign, start + from, -1), syntax(sign, start + end, 1));
|
|
416
|
+
}
|
|
417
|
+
} else from = -1;
|
|
418
|
+
offset = end;
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
return DecorationSet2.create(state.doc, found);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
})]
|
|
425
|
+
});
|
|
426
|
+
var EndNotes = Extension2.create({
|
|
427
|
+
name: "endNotes",
|
|
428
|
+
addProseMirrorPlugins: () => [new Plugin2({
|
|
429
|
+
props: {
|
|
430
|
+
decorations(state) {
|
|
431
|
+
const notes2 = [];
|
|
432
|
+
state.doc.descendants((n) => {
|
|
433
|
+
if (n.type.name === "footnote") notes2.push(n.attrs.text);
|
|
434
|
+
});
|
|
435
|
+
if (!notes2.length) return null;
|
|
436
|
+
return DecorationSet2.create(state.doc, [Decoration2.widget(state.doc.content.size, () => {
|
|
437
|
+
const list = document.createElement("div");
|
|
438
|
+
list.className = "w100n-text-endnotes";
|
|
439
|
+
list.contentEditable = "false";
|
|
440
|
+
notes2.forEach((text, i) => {
|
|
441
|
+
const p = list.appendChild(document.createElement("p"));
|
|
442
|
+
p.appendChild(document.createElement("sup")).textContent = String(i + 1);
|
|
443
|
+
p.append(text);
|
|
444
|
+
});
|
|
445
|
+
return list;
|
|
446
|
+
}, { key: notes2.join("\n"), side: 1, ignoreSelection: true })]);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
})]
|
|
450
|
+
});
|
|
451
|
+
var headings = (doc, after) => {
|
|
452
|
+
const found = [];
|
|
453
|
+
doc.descendants((node, pos) => {
|
|
454
|
+
if (pos > after && node.type.name === "heading" && node.attrs.level <= 3 && node.textContent.trim()) found.push({ pos, level: node.attrs.level, text: node.textContent.trim() });
|
|
455
|
+
return !node.isTextblock;
|
|
456
|
+
});
|
|
457
|
+
return found;
|
|
458
|
+
};
|
|
459
|
+
function entries(doc, relative, after) {
|
|
460
|
+
const list = headings(doc, after).map((h) => [h.level, h.text]);
|
|
461
|
+
const top = relative && list.length ? Math.min(...list.map(([level]) => level)) - 1 : 0;
|
|
462
|
+
return list.map(([level, text]) => [level - top, text]);
|
|
463
|
+
}
|
|
464
|
+
var Toc = Node.create({
|
|
465
|
+
name: "toc",
|
|
466
|
+
group: "block",
|
|
467
|
+
atom: true,
|
|
468
|
+
selectable: true,
|
|
469
|
+
addOptions: () => ({ relative: false, label: "", empty: "" }),
|
|
470
|
+
addAttributes: () => ({ entries: { default: "[]" }, title: { default: null } }),
|
|
471
|
+
parseHTML: () => [{ tag: "nav[data-toc]" }],
|
|
472
|
+
renderHTML() {
|
|
473
|
+
return ["nav", { "data-toc": "", class: "w100n-text-toc" }];
|
|
474
|
+
},
|
|
475
|
+
addNodeView() {
|
|
476
|
+
return ({ editor, getPos }) => {
|
|
477
|
+
const dom = document.createElement("nav");
|
|
478
|
+
dom.className = "w100n-text-toc";
|
|
479
|
+
dom.contentEditable = "false";
|
|
480
|
+
const paint2 = () => {
|
|
481
|
+
const at = getPos() ?? 0;
|
|
482
|
+
const list = entries(editor.state.doc, this.options.relative, at);
|
|
483
|
+
const head = document.createElement("b");
|
|
484
|
+
head.textContent = this.options.label;
|
|
485
|
+
const items = list.map(([level, text], i) => {
|
|
486
|
+
const go = document.createElement("button");
|
|
487
|
+
go.type = "button";
|
|
488
|
+
go.textContent = text;
|
|
489
|
+
go.dataset.level = String(level);
|
|
490
|
+
go.onclick = () => {
|
|
491
|
+
const hit = headings(editor.state.doc, getPos() ?? 0)[i];
|
|
492
|
+
if (hit) editor.view.nodeDOM(hit.pos)?.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
493
|
+
};
|
|
494
|
+
return go;
|
|
495
|
+
});
|
|
496
|
+
const empty = document.createElement("small");
|
|
497
|
+
empty.textContent = this.options.empty;
|
|
498
|
+
dom.replaceChildren(head, ...items.length ? items : [empty]);
|
|
499
|
+
};
|
|
500
|
+
paint2();
|
|
501
|
+
return {
|
|
502
|
+
dom,
|
|
503
|
+
update: (node) => {
|
|
504
|
+
if (node.type.name !== "toc") return false;
|
|
505
|
+
paint2();
|
|
506
|
+
return true;
|
|
507
|
+
},
|
|
508
|
+
ignoreMutation: () => true
|
|
509
|
+
};
|
|
510
|
+
};
|
|
511
|
+
},
|
|
512
|
+
addProseMirrorPlugins() {
|
|
513
|
+
const relative = this.options.relative;
|
|
514
|
+
return [new Plugin2({
|
|
515
|
+
appendTransaction(trs, _old, state) {
|
|
516
|
+
if (!trs.some((tr2) => tr2.docChanged && !tr2.getMeta(ySyncPluginKey))) return null;
|
|
517
|
+
const at = [];
|
|
518
|
+
state.doc.forEach((node, pos) => {
|
|
519
|
+
if (node.type.name === "toc") at.push(pos);
|
|
520
|
+
});
|
|
521
|
+
if (!at.length) return null;
|
|
522
|
+
const tr = state.tr;
|
|
523
|
+
for (const pos of at) {
|
|
524
|
+
const fresh = JSON.stringify(entries(state.doc, relative, pos));
|
|
525
|
+
if (state.doc.nodeAt(pos).attrs.entries !== fresh) tr.setNodeAttribute(pos, "entries", fresh);
|
|
526
|
+
}
|
|
527
|
+
return tr.docChanged ? tr : null;
|
|
528
|
+
}
|
|
529
|
+
})];
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
var revision = (name, tag) => Mark.create({
|
|
533
|
+
name,
|
|
534
|
+
inclusive: false,
|
|
535
|
+
excludes: "insertion deletion",
|
|
536
|
+
addAttributes: () => ({ id: { default: null }, author: { default: "" }, date: { default: "" } }),
|
|
537
|
+
parseHTML: () => [{ tag: `${tag}[data-rev]` }],
|
|
538
|
+
renderHTML: ({ HTMLAttributes }) => [tag, { "data-rev": HTMLAttributes.id, class: "w100n-text-rev", title: HTMLAttributes.author }, 0]
|
|
539
|
+
});
|
|
540
|
+
var seen = /* @__PURE__ */ new WeakMap();
|
|
541
|
+
function changes(doc) {
|
|
542
|
+
const hit = seen.get(doc);
|
|
543
|
+
if (hit) return hit;
|
|
544
|
+
const out = [];
|
|
545
|
+
doc.descendants((node, pos) => {
|
|
546
|
+
if (!node.isText) return;
|
|
547
|
+
const mark = node.marks.find((m) => m.type.name === "insertion" || m.type.name === "deletion");
|
|
548
|
+
if (!mark) return;
|
|
549
|
+
const last = out[out.length - 1];
|
|
550
|
+
if (last && last.id === mark.attrs.id && last.kind === mark.type.name && last.to === pos) Object.assign(last, { text: last.text + node.text, to: pos + node.nodeSize });
|
|
551
|
+
else out.push({ id: mark.attrs.id, kind: mark.type.name, author: mark.attrs.author, date: mark.attrs.date, text: node.text, from: pos, to: pos + node.nodeSize });
|
|
552
|
+
});
|
|
553
|
+
seen.set(doc, out);
|
|
554
|
+
return out;
|
|
555
|
+
}
|
|
556
|
+
function decide(editor, accept, id) {
|
|
557
|
+
const { state } = editor;
|
|
558
|
+
const tr = state.tr;
|
|
559
|
+
for (const c of changes(state.doc).filter((c2) => !id || c2.id === id).reverse()) {
|
|
560
|
+
if (c.kind === "insertion" === accept) tr.removeMark(c.from, c.to, state.schema.marks[c.kind].create({ id: c.id, author: c.author, date: c.date }));
|
|
561
|
+
else tr.delete(c.from, c.to);
|
|
562
|
+
}
|
|
563
|
+
if (tr.docChanged) editor.view.dispatch(tr);
|
|
564
|
+
}
|
|
565
|
+
var suggesting = new PluginKey2("w100n-suggest");
|
|
566
|
+
var Suggest = Extension2.create({
|
|
567
|
+
name: "suggest",
|
|
568
|
+
addProseMirrorPlugins() {
|
|
569
|
+
const stamp = (state, kind, from, to) => {
|
|
570
|
+
const me = suggesting.getState(state).me;
|
|
571
|
+
const own = [state.doc.resolve(from).nodeBefore, state.doc.resolve(to).nodeAfter].flatMap((n) => n?.marks ?? []).find((m) => m.type.name === kind && m.attrs.author === me);
|
|
572
|
+
return state.schema.marks[kind].create(own ? own.attrs : { id: Math.random().toString(36).slice(2, 10), author: me, date: (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d+Z$/, "Z") });
|
|
573
|
+
};
|
|
574
|
+
const strike = (tr, state, from, to) => {
|
|
575
|
+
const parts = [];
|
|
576
|
+
state.doc.nodesBetween(from, to, (node, pos) => {
|
|
577
|
+
if (!node.isText) return;
|
|
578
|
+
const a = Math.max(from, pos), b = Math.min(to, pos + node.nodeSize);
|
|
579
|
+
if (b > a && !node.marks.some((m) => m.type.name === "deletion")) parts.push({ from: a, to: b, added: node.marks.some((m) => m.type.name === "insertion") });
|
|
580
|
+
});
|
|
581
|
+
const mark = stamp(state, "deletion", from, to);
|
|
582
|
+
for (const p of parts.reverse()) {
|
|
583
|
+
if (p.added) tr.delete(p.from, p.to);
|
|
584
|
+
else tr.addMark(p.from, p.to, mark);
|
|
585
|
+
}
|
|
586
|
+
};
|
|
587
|
+
const type = (view, from, to, text) => {
|
|
588
|
+
const { state } = view;
|
|
589
|
+
const tr = state.tr;
|
|
590
|
+
if (to > from) strike(tr, state, from, to);
|
|
591
|
+
const at = tr.mapping.map(to);
|
|
592
|
+
const kept = (state.storedMarks ?? state.doc.resolve(from).marks()).filter((m) => m.type.name !== "insertion" && m.type.name !== "deletion");
|
|
593
|
+
tr.insert(at, state.schema.text(text, [...kept, stamp(state, "insertion", from, to)]));
|
|
594
|
+
tr.setSelection(TextSelection.create(tr.doc, at + text.length));
|
|
595
|
+
view.dispatch(tr.scrollIntoView());
|
|
596
|
+
return true;
|
|
597
|
+
};
|
|
598
|
+
return [new Plugin2({
|
|
599
|
+
key: suggesting,
|
|
600
|
+
state: {
|
|
601
|
+
init: () => ({ on: false, me: "" }),
|
|
602
|
+
apply: (tr, value) => tr.getMeta(suggesting) ?? value
|
|
603
|
+
},
|
|
604
|
+
props: {
|
|
605
|
+
handleTextInput(view, from, to, text) {
|
|
606
|
+
return suggesting.getState(view.state).on && type(view, from, to, text);
|
|
607
|
+
},
|
|
608
|
+
handlePaste(view, _event, slice) {
|
|
609
|
+
if (!suggesting.getState(view.state).on) return false;
|
|
610
|
+
const { from, to } = view.state.selection;
|
|
611
|
+
return type(view, from, to, slice.content.textBetween(0, slice.content.size, "\n"));
|
|
612
|
+
},
|
|
613
|
+
handleKeyDown(view, event) {
|
|
614
|
+
const { state } = view;
|
|
615
|
+
if (!suggesting.getState(state).on || event.key !== "Backspace" && event.key !== "Delete" || event.metaKey || event.ctrlKey || event.altKey) return false;
|
|
616
|
+
const { from, to, empty, $from } = state.selection;
|
|
617
|
+
const back = event.key === "Backspace";
|
|
618
|
+
let at = from;
|
|
619
|
+
if (empty) {
|
|
620
|
+
const skip2 = (pos) => state.doc.resolve(pos)[back ? "nodeBefore" : "nodeAfter"]?.marks.some((m) => m.type.name === "deletion");
|
|
621
|
+
while (skip2(at)) at += back ? -1 : 1;
|
|
622
|
+
if (back ? at <= $from.start() : at >= $from.end()) return false;
|
|
623
|
+
}
|
|
624
|
+
const tr = state.tr;
|
|
625
|
+
if (empty) strike(tr, state, back ? at - 1 : at, back ? at : at + 1);
|
|
626
|
+
else strike(tr, state, from, to);
|
|
627
|
+
const caret = empty ? tr.mapping.map(back ? at - 1 : at + 1, back ? -1 : 1) : tr.mapping.map(back ? from : to);
|
|
628
|
+
tr.setSelection(TextSelection.create(tr.doc, caret));
|
|
629
|
+
view.dispatch(tr.scrollIntoView());
|
|
630
|
+
return true;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
})];
|
|
634
|
+
}
|
|
635
|
+
});
|
|
636
|
+
var Note = Mark.create({
|
|
637
|
+
name: "comment",
|
|
638
|
+
inclusive: false,
|
|
639
|
+
excludes: "",
|
|
640
|
+
addAttributes: () => ({ id: { default: null, renderHTML: (attrs) => ({ "data-comment": attrs.id }) } }),
|
|
641
|
+
renderHTML: ({ HTMLAttributes }) => ["span", HTMLAttributes, 0]
|
|
642
|
+
});
|
|
643
|
+
var locks = new PluginKey2("w100n-locks");
|
|
644
|
+
var locked = (node) => node.type.name === "paragraph" && String(node.attrs.ref ?? "").startsWith("lock:");
|
|
645
|
+
var scan = (doc) => {
|
|
646
|
+
const spans = [];
|
|
647
|
+
doc.descendants((node, pos) => {
|
|
648
|
+
if (!locked(node)) return true;
|
|
649
|
+
spans.push({ from: pos, to: pos + node.nodeSize });
|
|
650
|
+
return false;
|
|
651
|
+
});
|
|
652
|
+
return spans;
|
|
653
|
+
};
|
|
654
|
+
var Locks = Extension2.create({
|
|
655
|
+
name: "locks",
|
|
656
|
+
addOptions: () => ({ label: "" }),
|
|
657
|
+
addProseMirrorPlugins() {
|
|
658
|
+
const shade = (doc, spans) => DecorationSet2.create(doc, spans.map((s) => Decoration2.node(s.from, s.to, { class: "w100n-text-lock", contenteditable: "false", "data-label": this.options.label })));
|
|
659
|
+
return [new Plugin2({
|
|
660
|
+
key: locks,
|
|
661
|
+
state: {
|
|
662
|
+
init: (_config, state) => {
|
|
663
|
+
const spans = scan(state.doc);
|
|
664
|
+
return { spans, set: shade(state.doc, spans) };
|
|
665
|
+
},
|
|
666
|
+
apply(tr, value) {
|
|
667
|
+
if (!tr.docChanged) return value;
|
|
668
|
+
const fresh = tr.steps.some((step) => {
|
|
669
|
+
let found = false;
|
|
670
|
+
step.slice?.content.descendants((node) => {
|
|
671
|
+
found || (found = locked(node));
|
|
672
|
+
return !found;
|
|
673
|
+
});
|
|
674
|
+
return found;
|
|
675
|
+
});
|
|
676
|
+
const spans = fresh ? scan(tr.doc) : value.spans.map((s) => ({ from: tr.mapping.map(s.from, 1), to: tr.mapping.map(s.to, -1) })).filter((s) => s.to > s.from);
|
|
677
|
+
return { spans, set: spans.length ? shade(tr.doc, spans) : DecorationSet2.empty };
|
|
678
|
+
}
|
|
679
|
+
},
|
|
680
|
+
filterTransaction(tr, state) {
|
|
681
|
+
let spans = locks.getState(state).spans;
|
|
682
|
+
if (!spans.length || !tr.docChanged) return true;
|
|
683
|
+
return tr.mapping.maps.every((map) => {
|
|
684
|
+
let ok = true;
|
|
685
|
+
map.forEach((from, to) => {
|
|
686
|
+
for (const s of spans) if ((from < s.to && to > s.from || from > s.from && from < s.to) && !(from <= s.from && to >= s.to)) ok = false;
|
|
687
|
+
});
|
|
688
|
+
spans = spans.map((s) => ({ from: map.map(s.from, 1), to: map.map(s.to, -1) }));
|
|
689
|
+
return ok;
|
|
690
|
+
});
|
|
691
|
+
},
|
|
692
|
+
props: {
|
|
693
|
+
decorations: (state) => locks.getState(state).set,
|
|
694
|
+
handleKeyDown(view, event) {
|
|
695
|
+
const back = event.key === "Backspace";
|
|
696
|
+
const { $from, empty } = view.state.selection;
|
|
697
|
+
if (!back && event.key !== "Delete" || !empty || $from.depth < 1) return false;
|
|
698
|
+
if (back ? $from.parentOffset !== 0 : $from.parentOffset !== $from.parent.content.size) return false;
|
|
699
|
+
const at = back ? $from.before() : $from.after();
|
|
700
|
+
const node = back ? view.state.doc.resolve(at).nodeBefore : view.state.doc.resolve(at).nodeAfter;
|
|
701
|
+
if (!node || !locked(node)) return false;
|
|
702
|
+
view.dispatch(view.state.tr.delete(back ? at - node.nodeSize : at, back ? at : at + node.nodeSize));
|
|
703
|
+
return true;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
})];
|
|
707
|
+
}
|
|
708
|
+
});
|
|
709
|
+
var paint = (doc, spots, active, pending) => DecorationSet2.create(doc, [
|
|
710
|
+
...spots.filter((s) => s.to > s.from).map((s) => Decoration2.inline(s.from, s.to, { class: s.id === active ? "w100n-text-note is-active" : "w100n-text-note", "data-note": s.id })),
|
|
711
|
+
...pending && pending.to > pending.from ? [Decoration2.inline(pending.from, pending.to, { class: "w100n-text-note is-active" })] : []
|
|
712
|
+
]);
|
|
713
|
+
var remap = (tr) => {
|
|
714
|
+
const start = tr.before.content.findDiffStart(tr.doc.content);
|
|
715
|
+
if (!tr.getMeta(ySyncPluginKey) || start === null) return tr.mapping;
|
|
716
|
+
let { a, b } = tr.before.content.findDiffEnd(tr.doc.content);
|
|
717
|
+
if (a < start) [a, b] = [start, b + start - a];
|
|
718
|
+
if (b < start) [a, b] = [a + start - b, start];
|
|
719
|
+
return new StepMap([start, a - start, b - start]);
|
|
720
|
+
};
|
|
721
|
+
var Notes = Extension2.create({
|
|
722
|
+
name: "notes",
|
|
723
|
+
addProseMirrorPlugins: () => [new Plugin2({
|
|
724
|
+
key: notes,
|
|
725
|
+
state: {
|
|
726
|
+
init: (_config, state) => ({ spots: [], active: null, pending: null, set: DecorationSet2.create(state.doc, []) }),
|
|
727
|
+
apply(tr, value) {
|
|
728
|
+
const next = tr.getMeta(notes);
|
|
729
|
+
if (!next && (!tr.docChanged || !value.spots.length && !value.pending)) return value;
|
|
730
|
+
const by = remap(tr);
|
|
731
|
+
const map = (r) => ({ ...r, from: by.map(r.from, 1), to: by.map(r.to, -1) });
|
|
732
|
+
const merged = { ...value, spots: value.spots.map(map), pending: value.pending && map(value.pending), ...next };
|
|
733
|
+
return { ...merged, set: paint(tr.doc, merged.spots, merged.active, merged.pending) };
|
|
734
|
+
}
|
|
735
|
+
},
|
|
736
|
+
props: { decorations: (state) => notes.getState(state).set }
|
|
737
|
+
})]
|
|
738
|
+
});
|
|
739
|
+
var script = (name, tag, other) => Mark.create({
|
|
740
|
+
name,
|
|
741
|
+
excludes: other,
|
|
742
|
+
parseHTML: () => [{ tag }, { style: `vertical-align=${name === "superscript" ? "super" : "sub"}` }],
|
|
743
|
+
renderHTML: () => [tag, 0],
|
|
744
|
+
addKeyboardShortcuts() {
|
|
745
|
+
return { [name === "superscript" ? "Mod-." : "Mod-,"]: () => this.editor.commands.toggleMark(name) };
|
|
746
|
+
}
|
|
747
|
+
});
|
|
748
|
+
function kit(kind, t, live, wiki) {
|
|
749
|
+
return [
|
|
750
|
+
StarterKit.configure({ trailingNode: false, link: { openOnClick: false, autolink: true, defaultProtocol: "https" }, dropcursor: { color: "#8b5cf6", width: 2 }, ...live ? { undoRedo: false } : {} }),
|
|
751
|
+
TaskList,
|
|
752
|
+
TaskItem.configure({ nested: true, a11y: { checkboxLabel: (node) => node.textContent || t.tasks } }),
|
|
753
|
+
TableKit.configure({ table: { resizable: true, cellMinWidth: 32 } }),
|
|
754
|
+
Cells,
|
|
755
|
+
Search,
|
|
756
|
+
Image.extend({
|
|
757
|
+
addAttributes() {
|
|
758
|
+
return { ...this.parent?.(), wrap: { default: null, parseHTML: (el) => el.dataset.wrap ?? null, renderHTML: (attrs) => attrs.wrap ? { "data-wrap": attrs.wrap } : {} } };
|
|
759
|
+
}
|
|
760
|
+
}).configure({ inline: true, allowBase64: true, resize: { enabled: true, directions: ["top-left", "top-right", "bottom-left", "bottom-right"], minWidth: 24, minHeight: 24, alwaysPreserveAspectRatio: true } }),
|
|
761
|
+
Highlight.configure({ multicolor: true }),
|
|
762
|
+
TextStyle,
|
|
763
|
+
Color,
|
|
764
|
+
FontSize,
|
|
765
|
+
FontFamily,
|
|
766
|
+
script("superscript", "sup", "subscript"),
|
|
767
|
+
script("subscript", "sub", "superscript"),
|
|
768
|
+
Blocks,
|
|
769
|
+
PageBreak.configure({ label: t.pageBreak }),
|
|
770
|
+
Toc.configure({ relative: kind === "markdown", label: t.toc, empty: t.tocEmpty }),
|
|
771
|
+
Note,
|
|
772
|
+
Notes,
|
|
773
|
+
Formula,
|
|
774
|
+
Footnote,
|
|
775
|
+
EndNotes,
|
|
776
|
+
WikiLink.configure({ known: wiki?.known ?? (() => true) }),
|
|
777
|
+
...kind === "markdown" && wiki ? [WikiAsk, Reveal] : [],
|
|
778
|
+
...kind === "docx" ? [Pager, Locks.configure({ label: t.locked }), revision("insertion", "ins"), revision("deletion", "del"), Suggest] : [],
|
|
779
|
+
...live ? [Collaboration.configure({ document: live.doc }), CollaborationCaret.configure({ provider: live.link, user: live.user })] : []
|
|
780
|
+
];
|
|
781
|
+
}
|
|
782
|
+
var textblocks = (editor, change) => editor.chain().focus().command(({ tr, state }) => {
|
|
783
|
+
state.doc.nodesBetween(state.selection.from, state.selection.to, (node, pos) => {
|
|
784
|
+
if (!node.isTextblock) return true;
|
|
785
|
+
for (const [key, value] of Object.entries(change(node.attrs))) if (node.attrs[key] !== value) tr.setNodeAttribute(pos, key, value);
|
|
786
|
+
return false;
|
|
787
|
+
});
|
|
788
|
+
return true;
|
|
789
|
+
}).run();
|
|
790
|
+
var align = (editor, value) => textblocks(editor, () => ({ align: value === "left" ? null : value }));
|
|
791
|
+
var spacing = (editor, change) => textblocks(editor, () => change);
|
|
792
|
+
var indent = (editor, step) => {
|
|
793
|
+
const type = editor.isActive("taskItem") ? "taskItem" : editor.isActive("listItem") ? "listItem" : null;
|
|
794
|
+
if (type) return step > 0 ? editor.chain().focus().sinkListItem(type).run() : editor.chain().focus().liftListItem(type).run();
|
|
795
|
+
return textblocks(editor, (attrs) => ({ indent: Math.min(8, Math.max(0, Number(attrs.indent) + step)) }));
|
|
796
|
+
};
|
|
797
|
+
var clear = (editor) => {
|
|
798
|
+
const chain = editor.chain().focus();
|
|
799
|
+
for (const mark of ["bold", "italic", "underline", "strike", "code", "highlight", "textStyle"]) chain.unsetMark(mark);
|
|
800
|
+
chain.run();
|
|
801
|
+
return textblocks(editor, () => ({ align: null, indent: 0 }));
|
|
802
|
+
};
|
|
803
|
+
function locate(doc, list) {
|
|
804
|
+
if (!list.length) return [];
|
|
805
|
+
const marked = /* @__PURE__ */ new Map();
|
|
806
|
+
doc.descendants((node, pos) => {
|
|
807
|
+
if (!node.isText) return;
|
|
808
|
+
for (const mark of node.marks) {
|
|
809
|
+
if (mark.type.name !== "comment") continue;
|
|
810
|
+
const found = marked.get(mark.attrs.id);
|
|
811
|
+
if (found) Object.assign(found, { to: pos + node.nodeSize, text: found.text + node.text });
|
|
812
|
+
else marked.set(mark.attrs.id, { from: pos, to: pos + node.nodeSize, text: node.text });
|
|
813
|
+
}
|
|
814
|
+
});
|
|
815
|
+
const claimed = /* @__PURE__ */ new Set();
|
|
816
|
+
const search = (quote) => {
|
|
817
|
+
const line = quote.split("\n").find((part) => part.trim())?.trim();
|
|
818
|
+
let hit = null;
|
|
819
|
+
if (line) doc.descendants((node, pos) => {
|
|
820
|
+
if (hit) return false;
|
|
821
|
+
if (!node.isTextblock) return true;
|
|
822
|
+
const at = node.textBetween(0, node.content.size, void 0, "\uFFFC").indexOf(line);
|
|
823
|
+
if (at >= 0) hit = { from: pos + 1 + at, to: pos + 1 + at + line.length };
|
|
824
|
+
return false;
|
|
825
|
+
});
|
|
826
|
+
return hit;
|
|
827
|
+
};
|
|
828
|
+
return list.flatMap((c) => {
|
|
829
|
+
const own = [c.anchor, c.id].find((id) => id && marked.has(id));
|
|
830
|
+
let range = own ? marked.get(own) : void 0;
|
|
831
|
+
if (!range) {
|
|
832
|
+
const twin = [...marked].find(([id, m]) => !claimed.has(id) && m.text === c.quote);
|
|
833
|
+
if (twin) {
|
|
834
|
+
claimed.add(twin[0]);
|
|
835
|
+
range = twin[1];
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
range ?? (range = search(c.quote));
|
|
839
|
+
return range ? [{ id: c.id, from: range.from, to: range.to }] : [];
|
|
840
|
+
});
|
|
841
|
+
}
|
|
2
842
|
|
|
3
843
|
// src/text.ts
|
|
4
844
|
var en = {
|
|
845
|
+
elsewhere: "Other",
|
|
846
|
+
newFolder: "New folder",
|
|
847
|
+
newNoteHere: "New note here",
|
|
848
|
+
renameFolder: "Rename folder",
|
|
849
|
+
trashFolder: "Move folder to trash",
|
|
850
|
+
folderTrashAsk: "Move {name} and everything in it to trash?",
|
|
851
|
+
moveTo: "Move to",
|
|
852
|
+
folderActions: "Folder actions",
|
|
853
|
+
folderName: "Folder name",
|
|
854
|
+
topLevel: "Top level",
|
|
855
|
+
wikiCreate: "Create \u201C{name}\u201D",
|
|
856
|
+
wikiNew: "new note",
|
|
857
|
+
wikiKeys: "\u2191\u2193 pick \xB7 \u21B5 link \xB7 | alias",
|
|
858
|
+
tree: "Tree",
|
|
859
|
+
cards: "Cards",
|
|
860
|
+
openNote: "Open note",
|
|
861
|
+
findNote: "Type a note name",
|
|
862
|
+
createNote: "Create note \u201C{name}\u201D",
|
|
863
|
+
noNote: "No notes match",
|
|
864
|
+
keysOpen: "\u2191\u2193 move \xB7 \u21B5 open \xB7 esc close",
|
|
865
|
+
commands: "Commands",
|
|
866
|
+
newNote: "New note",
|
|
867
|
+
searchAll: "Search in all notes",
|
|
868
|
+
showOutline: "Show outline",
|
|
869
|
+
showLinks: "Show backlinks",
|
|
870
|
+
showVersions: "Show versions",
|
|
871
|
+
showComments: "Show comments",
|
|
872
|
+
keysRun: "\u2191\u2193 move \xB7 \u21B5 run \xB7 esc close",
|
|
873
|
+
links: "Links",
|
|
874
|
+
linked: "Linked mentions",
|
|
875
|
+
unlinked: "Unlinked mentions",
|
|
876
|
+
noBacklinks: "Nothing links here yet",
|
|
5
877
|
documents: "Documents",
|
|
6
878
|
hint: "Files of your projects: read, edit and comment in one place",
|
|
7
879
|
loose: "Without a folder",
|
|
@@ -355,6 +1227,38 @@ var en = {
|
|
|
355
1227
|
uploadFailed: "Could not upload the file"
|
|
356
1228
|
};
|
|
357
1229
|
var pl = {
|
|
1230
|
+
elsewhere: "Inne",
|
|
1231
|
+
newFolder: "Nowy folder",
|
|
1232
|
+
newNoteHere: "Nowa notatka tutaj",
|
|
1233
|
+
renameFolder: "Zmie\u0144 nazw\u0119 folderu",
|
|
1234
|
+
trashFolder: "Przenie\u015B folder do kosza",
|
|
1235
|
+
folderTrashAsk: "Przenie\u015B\u0107 {name} z ca\u0142\u0105 zawarto\u015Bci\u0105 do kosza?",
|
|
1236
|
+
moveTo: "Przenie\u015B do",
|
|
1237
|
+
folderActions: "Dzia\u0142ania na folderze",
|
|
1238
|
+
folderName: "Nazwa folderu",
|
|
1239
|
+
topLevel: "Najwy\u017Cszy poziom",
|
|
1240
|
+
wikiCreate: "Utw\xF3rz \u201E{name}\u201D",
|
|
1241
|
+
wikiNew: "nowa notatka",
|
|
1242
|
+
wikiKeys: "\u2191\u2193 wyb\xF3r \xB7 \u21B5 link \xB7 | alias",
|
|
1243
|
+
tree: "Drzewo",
|
|
1244
|
+
cards: "Karty",
|
|
1245
|
+
openNote: "Otw\xF3rz notatk\u0119",
|
|
1246
|
+
findNote: "Wpisz nazw\u0119 notatki",
|
|
1247
|
+
createNote: "Utw\xF3rz notatk\u0119 \u201E{name}\u201D",
|
|
1248
|
+
noNote: "Brak pasuj\u0105cych notatek",
|
|
1249
|
+
keysOpen: "\u2191\u2193 ruch \xB7 \u21B5 otw\xF3rz \xB7 esc zamknij",
|
|
1250
|
+
commands: "Polecenia",
|
|
1251
|
+
newNote: "Nowa notatka",
|
|
1252
|
+
searchAll: "Szukaj we wszystkich notatkach",
|
|
1253
|
+
showOutline: "Poka\u017C spis",
|
|
1254
|
+
showLinks: "Poka\u017C odno\u015Bniki",
|
|
1255
|
+
showVersions: "Poka\u017C wersje",
|
|
1256
|
+
showComments: "Poka\u017C komentarze",
|
|
1257
|
+
keysRun: "\u2191\u2193 ruch \xB7 \u21B5 uruchom \xB7 esc zamknij",
|
|
1258
|
+
links: "Odno\u015Bniki",
|
|
1259
|
+
linked: "Linki do tej notatki",
|
|
1260
|
+
unlinked: "Wzmianki bez linku",
|
|
1261
|
+
noBacklinks: "Nic tu jeszcze nie linkuje",
|
|
358
1262
|
documents: "Dokumenty",
|
|
359
1263
|
hint: "Pliki Twoich projekt\xF3w: czytaj, edytuj i komentuj w jednym miejscu",
|
|
360
1264
|
loose: "Bez folderu",
|
|
@@ -708,6 +1612,38 @@ var pl = {
|
|
|
708
1612
|
uploadFailed: "Nie uda\u0142o si\u0119 wgra\u0107 pliku"
|
|
709
1613
|
};
|
|
710
1614
|
var uk = {
|
|
1615
|
+
elsewhere: "\u0406\u043D\u0448\u0435",
|
|
1616
|
+
newFolder: "\u041D\u043E\u0432\u0430 \u043F\u0430\u043F\u043A\u0430",
|
|
1617
|
+
newNoteHere: "\u041D\u043E\u0432\u0430 \u043D\u043E\u0442\u0430\u0442\u043A\u0430 \u0442\u0443\u0442",
|
|
1618
|
+
renameFolder: "\u041F\u0435\u0440\u0435\u0439\u043C\u0435\u043D\u0443\u0432\u0430\u0442\u0438 \u043F\u0430\u043F\u043A\u0443",
|
|
1619
|
+
trashFolder: "\u041F\u0430\u043F\u043A\u0443 \u0432 \u043A\u043E\u0448\u0438\u043A",
|
|
1620
|
+
folderTrashAsk: "\u041F\u0435\u0440\u0435\u043C\u0456\u0441\u0442\u0438\u0442\u0438 {name} \u0437 \u0443\u0441\u0456\u043C \u0432\u043C\u0456\u0441\u0442\u043E\u043C \u0443 \u043A\u043E\u0448\u0438\u043A?",
|
|
1621
|
+
moveTo: "\u041F\u0435\u0440\u0435\u043D\u0435\u0441\u0442\u0438 \u0432",
|
|
1622
|
+
folderActions: "\u0414\u0456\u0457 \u0437 \u043F\u0430\u043F\u043A\u043E\u044E",
|
|
1623
|
+
folderName: "\u041D\u0430\u0437\u0432\u0430 \u043F\u0430\u043F\u043A\u0438",
|
|
1624
|
+
topLevel: "\u0412\u0435\u0440\u0445\u043D\u0456\u0439 \u0440\u0456\u0432\u0435\u043D\u044C",
|
|
1625
|
+
wikiCreate: "\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \xAB{name}\xBB",
|
|
1626
|
+
wikiNew: "\u043D\u043E\u0432\u0430 \u043D\u043E\u0442\u0430\u0442\u043A\u0430",
|
|
1627
|
+
wikiKeys: "\u2191\u2193 \u0432\u0438\u0431\u0456\u0440 \xB7 \u21B5 \u043F\u043E\u0441\u0438\u043B\u0430\u043D\u043D\u044F \xB7 | \u043F\u0456\u0434\u043F\u0438\u0441",
|
|
1628
|
+
tree: "\u0414\u0435\u0440\u0435\u0432\u043E",
|
|
1629
|
+
cards: "\u041A\u0430\u0440\u0442\u043A\u0438",
|
|
1630
|
+
openNote: "\u0412\u0456\u0434\u043A\u0440\u0438\u0442\u0438 \u043D\u043E\u0442\u0430\u0442\u043A\u0443",
|
|
1631
|
+
findNote: "\u0412\u0432\u0435\u0434\u0456\u0442\u044C \u043D\u0430\u0437\u0432\u0443 \u043D\u043E\u0442\u0430\u0442\u043A\u0438",
|
|
1632
|
+
createNote: "\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u043D\u043E\u0442\u0430\u0442\u043A\u0443 \xAB{name}\xBB",
|
|
1633
|
+
noNote: "\u041D\u0435\u043C\u0430\u0454 \u0442\u0430\u043A\u0438\u0445 \u043D\u043E\u0442\u0430\u0442\u043E\u043A",
|
|
1634
|
+
keysOpen: "\u2191\u2193 \u0440\u0443\u0445 \xB7 \u21B5 \u0432\u0456\u0434\u043A\u0440\u0438\u0442\u0438 \xB7 esc \u0437\u0430\u043A\u0440\u0438\u0442\u0438",
|
|
1635
|
+
commands: "\u041A\u043E\u043C\u0430\u043D\u0434\u0438",
|
|
1636
|
+
newNote: "\u041D\u043E\u0432\u0430 \u043D\u043E\u0442\u0430\u0442\u043A\u0430",
|
|
1637
|
+
searchAll: "\u0428\u0443\u043A\u0430\u0442\u0438 \u0432 \u0443\u0441\u0456\u0445 \u043D\u043E\u0442\u0430\u0442\u043A\u0430\u0445",
|
|
1638
|
+
showOutline: "\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u0437\u043C\u0456\u0441\u0442",
|
|
1639
|
+
showLinks: "\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u043F\u043E\u0441\u0438\u043B\u0430\u043D\u043D\u044F",
|
|
1640
|
+
showVersions: "\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u0432\u0435\u0440\u0441\u0456\u0457",
|
|
1641
|
+
showComments: "\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u043A\u043E\u043C\u0435\u043D\u0442\u0430\u0440\u0456",
|
|
1642
|
+
keysRun: "\u2191\u2193 \u0440\u0443\u0445 \xB7 \u21B5 \u0432\u0438\u043A\u043E\u043D\u0430\u0442\u0438 \xB7 esc \u0437\u0430\u043A\u0440\u0438\u0442\u0438",
|
|
1643
|
+
links: "\u041F\u043E\u0441\u0438\u043B\u0430\u043D\u043D\u044F",
|
|
1644
|
+
linked: "\u041F\u043E\u0441\u0438\u043B\u0430\u044E\u0442\u044C\u0441\u044F \u0441\u044E\u0434\u0438",
|
|
1645
|
+
unlinked: "\u0417\u0433\u0430\u0434\u043A\u0438 \u0431\u0435\u0437 \u043F\u043E\u0441\u0438\u043B\u0430\u043D\u043D\u044F",
|
|
1646
|
+
noBacklinks: "\u0421\u044E\u0434\u0438 \u0449\u0435 \u043D\u0456\u0449\u043E \u043D\u0435 \u043F\u043E\u0441\u0438\u043B\u0430\u0454\u0442\u044C\u0441\u044F",
|
|
711
1647
|
documents: "\u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0438",
|
|
712
1648
|
hint: "\u0424\u0430\u0439\u043B\u0438 \u0432\u0430\u0448\u0438\u0445 \u043F\u0440\u043E\u0454\u043A\u0442\u0456\u0432: \u0447\u0438\u0442\u0430\u0439\u0442\u0435, \u0440\u0435\u0434\u0430\u0433\u0443\u0439\u0442\u0435 \u0439 \u043A\u043E\u043C\u0435\u043D\u0442\u0443\u0439\u0442\u0435 \u0432 \u043E\u0434\u043D\u043E\u043C\u0443 \u043C\u0456\u0441\u0446\u0456",
|
|
713
1649
|
loose: "\u0411\u0435\u0437 \u0442\u0435\u043A\u0438",
|
|
@@ -1063,6 +1999,25 @@ var uk = {
|
|
|
1063
1999
|
var texts = { en, pl, uk };
|
|
1064
2000
|
|
|
1065
2001
|
export {
|
|
2002
|
+
a4,
|
|
2003
|
+
letter,
|
|
2004
|
+
paging,
|
|
2005
|
+
notes,
|
|
2006
|
+
searching,
|
|
2007
|
+
replace,
|
|
2008
|
+
cleanPaste,
|
|
2009
|
+
wikiName,
|
|
2010
|
+
wikiAsk,
|
|
2011
|
+
entries,
|
|
2012
|
+
changes,
|
|
2013
|
+
decide,
|
|
2014
|
+
suggesting,
|
|
2015
|
+
kit,
|
|
2016
|
+
align,
|
|
2017
|
+
spacing,
|
|
2018
|
+
indent,
|
|
2019
|
+
clear,
|
|
2020
|
+
locate,
|
|
1066
2021
|
texts
|
|
1067
2022
|
};
|
|
1068
|
-
//# sourceMappingURL=chunk-
|
|
2023
|
+
//# sourceMappingURL=chunk-BWU6FPPZ.js.map
|