draftly 2.0.0 → 2.1.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/{chunk-BWJLMREN.cjs → chunk-EQUQHE2E.cjs} +26 -24
- package/dist/chunk-EQUQHE2E.cjs.map +1 -0
- package/dist/{chunk-L2XSK57Y.js → chunk-NRPI5O6Y.js} +1267 -551
- package/dist/chunk-NRPI5O6Y.js.map +1 -0
- package/dist/{chunk-W5ALMXG2.cjs → chunk-OMFUE4AQ.cjs} +1304 -588
- package/dist/chunk-OMFUE4AQ.cjs.map +1 -0
- package/dist/{chunk-EEHILRG5.js → chunk-TD3L5C45.js} +13 -11
- package/dist/chunk-TD3L5C45.js.map +1 -0
- package/dist/{chunk-ZUI3GI3W.js → chunk-UCHBDJ4R.js} +22 -20
- package/dist/chunk-UCHBDJ4R.js.map +1 -0
- package/dist/{chunk-TBVZEK2H.cjs → chunk-W75QUUQC.cjs} +13 -11
- package/dist/chunk-W75QUUQC.cjs.map +1 -0
- package/dist/editor/index.cjs +16 -16
- package/dist/editor/index.js +2 -2
- package/dist/index.cjs +33 -33
- package/dist/index.js +3 -3
- package/dist/plugins/index.cjs +19 -19
- package/dist/plugins/index.d.cts +77 -42
- package/dist/plugins/index.d.ts +77 -42
- package/dist/plugins/index.js +3 -3
- package/dist/preview/index.cjs +1 -1
- package/dist/preview/index.js +1 -1
- package/package.json +1 -1
- package/src/editor/draftly.ts +29 -27
- package/src/editor/utils.ts +13 -11
- package/src/plugins/table-plugin.ts +1759 -900
- package/dist/chunk-BWJLMREN.cjs.map +0 -1
- package/dist/chunk-EEHILRG5.js.map +0 -1
- package/dist/chunk-L2XSK57Y.js.map +0 -1
- package/dist/chunk-TBVZEK2H.cjs.map +0 -1
- package/dist/chunk-W5ALMXG2.cjs.map +0 -1
- package/dist/chunk-ZUI3GI3W.js.map +0 -1
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkEQUQHE2E_cjs = require('./chunk-EQUQHE2E.cjs');
|
|
4
4
|
var chunk3T55CBNZ_cjs = require('./chunk-3T55CBNZ.cjs');
|
|
5
5
|
var chunkCLW73JRX_cjs = require('./chunk-CLW73JRX.cjs');
|
|
6
|
-
var
|
|
6
|
+
var chunkW75QUUQC_cjs = require('./chunk-W75QUUQC.cjs');
|
|
7
7
|
var view = require('@codemirror/view');
|
|
8
8
|
var language = require('@codemirror/language');
|
|
9
9
|
var highlight = require('@lezer/highlight');
|
|
10
|
+
var state = require('@codemirror/state');
|
|
11
|
+
var markdown = require('@lezer/markdown');
|
|
10
12
|
var DOMPurify = require('dompurify');
|
|
11
13
|
var katex = require('katex');
|
|
12
14
|
var katexCss = require('katex/dist/katex.min.css?raw');
|
|
@@ -41,7 +43,7 @@ var mermaid__default = /*#__PURE__*/_interopDefault(mermaid);
|
|
|
41
43
|
var emoji__namespace = /*#__PURE__*/_interopNamespace(emoji);
|
|
42
44
|
|
|
43
45
|
// src/plugins/paragraph-plugin.ts
|
|
44
|
-
var ParagraphPlugin = class extends
|
|
46
|
+
var ParagraphPlugin = class extends chunkEQUQHE2E_cjs.DraftlyPlugin {
|
|
45
47
|
name = "paragraph";
|
|
46
48
|
version = "1.0.0";
|
|
47
49
|
requiredNodes = ["Paragraph"];
|
|
@@ -58,7 +60,7 @@ var ParagraphPlugin = class extends chunkBWJLMREN_cjs.DraftlyPlugin {
|
|
|
58
60
|
return `<p class="cm-draftly-paragraph">${children}</p>`;
|
|
59
61
|
}
|
|
60
62
|
};
|
|
61
|
-
var theme =
|
|
63
|
+
var theme = chunkW75QUUQC_cjs.createTheme({
|
|
62
64
|
default: {
|
|
63
65
|
".cm-draftly-paragraph": {
|
|
64
66
|
paddingTop: "0.5em",
|
|
@@ -85,7 +87,7 @@ var headingLineDecorations = {
|
|
|
85
87
|
"heading-5": view.Decoration.line({ class: "cm-draftly-line-h5" }),
|
|
86
88
|
"heading-6": view.Decoration.line({ class: "cm-draftly-line-h6" })
|
|
87
89
|
};
|
|
88
|
-
var HeadingPlugin = class extends
|
|
90
|
+
var HeadingPlugin = class extends chunkEQUQHE2E_cjs.DecorationPlugin {
|
|
89
91
|
name = "heading";
|
|
90
92
|
version = "1.0.0";
|
|
91
93
|
decorationPriority = 10;
|
|
@@ -157,7 +159,7 @@ var HeadingPlugin = class extends chunkBWJLMREN_cjs.DecorationPlugin {
|
|
|
157
159
|
`;
|
|
158
160
|
}
|
|
159
161
|
};
|
|
160
|
-
var theme2 =
|
|
162
|
+
var theme2 = chunkW75QUUQC_cjs.createTheme({
|
|
161
163
|
default: {
|
|
162
164
|
".cm-draftly-h1": {
|
|
163
165
|
fontSize: "2em",
|
|
@@ -256,7 +258,7 @@ var highlightParser = {
|
|
|
256
258
|
);
|
|
257
259
|
}
|
|
258
260
|
};
|
|
259
|
-
var InlinePlugin = class extends
|
|
261
|
+
var InlinePlugin = class extends chunkEQUQHE2E_cjs.DecorationPlugin {
|
|
260
262
|
name = "inline";
|
|
261
263
|
version = "1.0.0";
|
|
262
264
|
decorationPriority = 20;
|
|
@@ -293,32 +295,32 @@ var InlinePlugin = class extends chunkBWJLMREN_cjs.DecorationPlugin {
|
|
|
293
295
|
return [
|
|
294
296
|
{
|
|
295
297
|
key: "Mod-b",
|
|
296
|
-
run:
|
|
298
|
+
run: chunkW75QUUQC_cjs.toggleMarkdownStyle("**"),
|
|
297
299
|
preventDefault: true
|
|
298
300
|
},
|
|
299
301
|
{
|
|
300
302
|
key: "Mod-i",
|
|
301
|
-
run:
|
|
303
|
+
run: chunkW75QUUQC_cjs.toggleMarkdownStyle("*"),
|
|
302
304
|
preventDefault: true
|
|
303
305
|
},
|
|
304
306
|
{
|
|
305
307
|
key: "Mod-Shift-s",
|
|
306
|
-
run:
|
|
308
|
+
run: chunkW75QUUQC_cjs.toggleMarkdownStyle("~~"),
|
|
307
309
|
preventDefault: true
|
|
308
310
|
},
|
|
309
311
|
{
|
|
310
312
|
key: "Mod-,",
|
|
311
|
-
run:
|
|
313
|
+
run: chunkW75QUUQC_cjs.toggleMarkdownStyle("~"),
|
|
312
314
|
preventDefault: true
|
|
313
315
|
},
|
|
314
316
|
{
|
|
315
317
|
key: "Mod-.",
|
|
316
|
-
run:
|
|
318
|
+
run: chunkW75QUUQC_cjs.toggleMarkdownStyle("^"),
|
|
317
319
|
preventDefault: true
|
|
318
320
|
},
|
|
319
321
|
{
|
|
320
322
|
key: "Mod-Shift-h",
|
|
321
|
-
run:
|
|
323
|
+
run: chunkW75QUUQC_cjs.toggleMarkdownStyle("=="),
|
|
322
324
|
preventDefault: true
|
|
323
325
|
}
|
|
324
326
|
];
|
|
@@ -405,7 +407,7 @@ var InlinePlugin = class extends chunkBWJLMREN_cjs.DecorationPlugin {
|
|
|
405
407
|
return `<span class="${className}">${children}</span>`;
|
|
406
408
|
}
|
|
407
409
|
};
|
|
408
|
-
var theme3 =
|
|
410
|
+
var theme3 = chunkW75QUUQC_cjs.createTheme({
|
|
409
411
|
default: {
|
|
410
412
|
// Emphasis (italic)
|
|
411
413
|
".cm-draftly-emphasis": {
|
|
@@ -501,7 +503,7 @@ var LinkTooltipWidget = class extends view.WidgetType {
|
|
|
501
503
|
return event.type !== "click" && event.type !== "mouseenter" && event.type !== "mouseleave";
|
|
502
504
|
}
|
|
503
505
|
};
|
|
504
|
-
var LinkPlugin = class extends
|
|
506
|
+
var LinkPlugin = class extends chunkEQUQHE2E_cjs.DecorationPlugin {
|
|
505
507
|
name = "link";
|
|
506
508
|
version = "1.0.0";
|
|
507
509
|
decorationPriority = 22;
|
|
@@ -705,7 +707,7 @@ var LinkTextWidget = class extends view.WidgetType {
|
|
|
705
707
|
return event.type !== "click" && event.type !== "mouseenter" && event.type !== "mouseleave";
|
|
706
708
|
}
|
|
707
709
|
};
|
|
708
|
-
var theme4 =
|
|
710
|
+
var theme4 = chunkW75QUUQC_cjs.createTheme({
|
|
709
711
|
default: {
|
|
710
712
|
// Link text
|
|
711
713
|
".cm-draftly-link-text": {
|
|
@@ -851,7 +853,7 @@ var TaskCheckboxWidget = class extends view.WidgetType {
|
|
|
851
853
|
}
|
|
852
854
|
}
|
|
853
855
|
};
|
|
854
|
-
var ListPlugin = class extends
|
|
856
|
+
var ListPlugin = class extends chunkEQUQHE2E_cjs.DecorationPlugin {
|
|
855
857
|
name = "list";
|
|
856
858
|
version = "1.0.0";
|
|
857
859
|
decorationPriority = 20;
|
|
@@ -1054,7 +1056,7 @@ var ListPlugin = class extends chunkBWJLMREN_cjs.DecorationPlugin {
|
|
|
1054
1056
|
}
|
|
1055
1057
|
}
|
|
1056
1058
|
};
|
|
1057
|
-
var theme5 =
|
|
1059
|
+
var theme5 = chunkW75QUUQC_cjs.createTheme({
|
|
1058
1060
|
default: {
|
|
1059
1061
|
// Indentation marker positioning
|
|
1060
1062
|
".cm-draftly-list-indent": {
|
|
@@ -1152,6 +1154,130 @@ var theme5 = chunkTBVZEK2H_cjs.createTheme({
|
|
|
1152
1154
|
}
|
|
1153
1155
|
}
|
|
1154
1156
|
});
|
|
1157
|
+
var BREAK_TAG = "<br />";
|
|
1158
|
+
var BREAK_TAG_REGEX = /<br\s*\/?>/gi;
|
|
1159
|
+
var DELIMITER_CELL_PATTERN = /^:?-{3,}:?$/;
|
|
1160
|
+
var TABLE_SUB_NODE_NAMES = /* @__PURE__ */ new Set(["TableHeader", "TableDelimiter", "TableRow", "TableCell"]);
|
|
1161
|
+
var TABLE_TEMPLATE = {
|
|
1162
|
+
headers: ["Header 1", "Header 2", "Header 3"],
|
|
1163
|
+
alignments: ["left", "left", "left"],
|
|
1164
|
+
rows: [["", "", ""]]
|
|
1165
|
+
};
|
|
1166
|
+
var normalizeAnnotation = state.Annotation.define();
|
|
1167
|
+
var repairSelectionAnnotation = state.Annotation.define();
|
|
1168
|
+
var pipeReplace = view.Decoration.replace({});
|
|
1169
|
+
var delimiterReplace = view.Decoration.replace({});
|
|
1170
|
+
var tableBlockWrapper = view.BlockWrapper.create({
|
|
1171
|
+
tagName: "div",
|
|
1172
|
+
attributes: { class: "cm-draftly-table-wrapper" }
|
|
1173
|
+
});
|
|
1174
|
+
var TableBreakWidget = class extends view.WidgetType {
|
|
1175
|
+
/** Reuses the same widget instance for identical break markers. */
|
|
1176
|
+
eq() {
|
|
1177
|
+
return true;
|
|
1178
|
+
}
|
|
1179
|
+
/** Renders an inline `<br />` placeholder inside a table cell. */
|
|
1180
|
+
toDOM() {
|
|
1181
|
+
const span = document.createElement("span");
|
|
1182
|
+
span.className = "cm-draftly-table-break";
|
|
1183
|
+
span.setAttribute("aria-label", "line break");
|
|
1184
|
+
span.appendChild(document.createElement("br"));
|
|
1185
|
+
return span;
|
|
1186
|
+
}
|
|
1187
|
+
/** Allows the editor to observe events on the rendered break widget. */
|
|
1188
|
+
ignoreEvent() {
|
|
1189
|
+
return false;
|
|
1190
|
+
}
|
|
1191
|
+
};
|
|
1192
|
+
var TableControlsWidget = class extends view.WidgetType {
|
|
1193
|
+
constructor(onAddRow, onAddColumn) {
|
|
1194
|
+
super();
|
|
1195
|
+
this.onAddRow = onAddRow;
|
|
1196
|
+
this.onAddColumn = onAddColumn;
|
|
1197
|
+
}
|
|
1198
|
+
/** Forces the control widget to be recreated so handlers stay current. */
|
|
1199
|
+
eq() {
|
|
1200
|
+
return false;
|
|
1201
|
+
}
|
|
1202
|
+
/** Renders the hover controls used to append rows and columns. */
|
|
1203
|
+
toDOM(view) {
|
|
1204
|
+
const anchor = document.createElement("span");
|
|
1205
|
+
anchor.className = "cm-draftly-table-controls-anchor";
|
|
1206
|
+
anchor.setAttribute("aria-hidden", "true");
|
|
1207
|
+
const rightButton = this.createButton("Add column", "cm-draftly-table-control cm-draftly-table-control-column");
|
|
1208
|
+
rightButton.addEventListener("mousedown", (event) => {
|
|
1209
|
+
event.preventDefault();
|
|
1210
|
+
event.stopPropagation();
|
|
1211
|
+
this.onAddColumn(view);
|
|
1212
|
+
});
|
|
1213
|
+
const bottomButton = this.createButton("Add row", "cm-draftly-table-control cm-draftly-table-control-row");
|
|
1214
|
+
bottomButton.addEventListener("mousedown", (event) => {
|
|
1215
|
+
event.preventDefault();
|
|
1216
|
+
event.stopPropagation();
|
|
1217
|
+
this.onAddRow(view);
|
|
1218
|
+
});
|
|
1219
|
+
anchor.append(rightButton, bottomButton);
|
|
1220
|
+
return anchor;
|
|
1221
|
+
}
|
|
1222
|
+
/** Lets button events bubble through the widget. */
|
|
1223
|
+
ignoreEvent() {
|
|
1224
|
+
return false;
|
|
1225
|
+
}
|
|
1226
|
+
/** Builds a single control button with the provided label and class. */
|
|
1227
|
+
createButton(label, className) {
|
|
1228
|
+
const button = document.createElement("button");
|
|
1229
|
+
button.type = "button";
|
|
1230
|
+
button.className = className;
|
|
1231
|
+
button.setAttribute("tabindex", "-1");
|
|
1232
|
+
button.setAttribute("aria-label", label);
|
|
1233
|
+
button.textContent = "+";
|
|
1234
|
+
return button;
|
|
1235
|
+
}
|
|
1236
|
+
};
|
|
1237
|
+
function isEscaped(text, index) {
|
|
1238
|
+
let slashCount = 0;
|
|
1239
|
+
for (let i = index - 1; i >= 0 && text[i] === "\\"; i--) {
|
|
1240
|
+
slashCount++;
|
|
1241
|
+
}
|
|
1242
|
+
return slashCount % 2 === 1;
|
|
1243
|
+
}
|
|
1244
|
+
function getPipePositions(lineText) {
|
|
1245
|
+
const positions = [];
|
|
1246
|
+
for (let index = 0; index < lineText.length; index++) {
|
|
1247
|
+
if (lineText[index] === "|" && !isEscaped(lineText, index)) {
|
|
1248
|
+
positions.push(index);
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
return positions;
|
|
1252
|
+
}
|
|
1253
|
+
function splitTableLine(lineText) {
|
|
1254
|
+
const cells = [];
|
|
1255
|
+
const trimmed = lineText.trim();
|
|
1256
|
+
if (!trimmed.includes("|")) {
|
|
1257
|
+
return [trimmed];
|
|
1258
|
+
}
|
|
1259
|
+
let current = "";
|
|
1260
|
+
for (let index = 0; index < trimmed.length; index++) {
|
|
1261
|
+
const char = trimmed[index];
|
|
1262
|
+
if (char === "|" && !isEscaped(trimmed, index)) {
|
|
1263
|
+
cells.push(current);
|
|
1264
|
+
current = "";
|
|
1265
|
+
continue;
|
|
1266
|
+
}
|
|
1267
|
+
current += char;
|
|
1268
|
+
}
|
|
1269
|
+
cells.push(current);
|
|
1270
|
+
if (trimmed.startsWith("|")) {
|
|
1271
|
+
cells.shift();
|
|
1272
|
+
}
|
|
1273
|
+
if (trimmed.endsWith("|")) {
|
|
1274
|
+
cells.pop();
|
|
1275
|
+
}
|
|
1276
|
+
return cells;
|
|
1277
|
+
}
|
|
1278
|
+
function isTableRowLine(lineText) {
|
|
1279
|
+
return getPipePositions(lineText.trim()).length > 0;
|
|
1280
|
+
}
|
|
1155
1281
|
function parseAlignment(cell) {
|
|
1156
1282
|
const trimmed = cell.trim();
|
|
1157
1283
|
const left = trimmed.startsWith(":");
|
|
@@ -1160,642 +1286,1232 @@ function parseAlignment(cell) {
|
|
|
1160
1286
|
if (right) return "right";
|
|
1161
1287
|
return "left";
|
|
1162
1288
|
}
|
|
1163
|
-
function
|
|
1164
|
-
const
|
|
1165
|
-
if (
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1289
|
+
function parseDelimiterAlignments(lineText) {
|
|
1290
|
+
const cells = splitTableLine(lineText).map((cell) => cell.trim());
|
|
1291
|
+
if (cells.length === 0 || !cells.every((cell) => DELIMITER_CELL_PATTERN.test(cell))) {
|
|
1292
|
+
return null;
|
|
1293
|
+
}
|
|
1294
|
+
return cells.map(parseAlignment);
|
|
1295
|
+
}
|
|
1296
|
+
function splitTableAndTrailingMarkdown(markdown) {
|
|
1297
|
+
const lines = markdown.split("\n");
|
|
1298
|
+
if (lines.length < 2) {
|
|
1299
|
+
return { tableMarkdown: markdown, trailingMarkdown: "" };
|
|
1300
|
+
}
|
|
1301
|
+
const headerLine = lines[0] || "";
|
|
1302
|
+
const delimiterLine = lines[1] || "";
|
|
1303
|
+
if (!isTableRowLine(headerLine) || !parseDelimiterAlignments(delimiterLine)) {
|
|
1304
|
+
return { tableMarkdown: markdown, trailingMarkdown: "" };
|
|
1305
|
+
}
|
|
1306
|
+
let endIndex = 1;
|
|
1307
|
+
for (let index = 2; index < lines.length; index++) {
|
|
1308
|
+
if (!isTableRowLine(lines[index] || "")) {
|
|
1309
|
+
break;
|
|
1310
|
+
}
|
|
1311
|
+
endIndex = index;
|
|
1312
|
+
}
|
|
1313
|
+
return {
|
|
1314
|
+
tableMarkdown: lines.slice(0, endIndex + 1).join("\n"),
|
|
1315
|
+
trailingMarkdown: lines.slice(endIndex + 1).join("\n")
|
|
1171
1316
|
};
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
for (let
|
|
1179
|
-
|
|
1317
|
+
}
|
|
1318
|
+
function canonicalizeBreakTags(text) {
|
|
1319
|
+
return text.replace(BREAK_TAG_REGEX, BREAK_TAG);
|
|
1320
|
+
}
|
|
1321
|
+
function escapeUnescapedPipes(text) {
|
|
1322
|
+
let result = "";
|
|
1323
|
+
for (let index = 0; index < text.length; index++) {
|
|
1324
|
+
const char = text[index];
|
|
1325
|
+
if (char === "|" && !isEscaped(text, index)) {
|
|
1326
|
+
result += "\\|";
|
|
1327
|
+
continue;
|
|
1328
|
+
}
|
|
1329
|
+
result += char;
|
|
1180
1330
|
}
|
|
1181
|
-
return
|
|
1331
|
+
return result;
|
|
1332
|
+
}
|
|
1333
|
+
function normalizeCellContent(text) {
|
|
1334
|
+
const normalizedBreaks = canonicalizeBreakTags(text.trim());
|
|
1335
|
+
if (!normalizedBreaks) {
|
|
1336
|
+
return "";
|
|
1337
|
+
}
|
|
1338
|
+
const parts = normalizedBreaks.split(BREAK_TAG_REGEX).map((part) => escapeUnescapedPipes(part.trim()));
|
|
1339
|
+
if (parts.length === 1) {
|
|
1340
|
+
return parts[0] || "";
|
|
1341
|
+
}
|
|
1342
|
+
return parts.join(` ${BREAK_TAG} `).trim();
|
|
1182
1343
|
}
|
|
1183
|
-
function
|
|
1184
|
-
|
|
1185
|
-
if (!trimmed.startsWith("|")) return false;
|
|
1186
|
-
let inner = trimmed;
|
|
1187
|
-
if (inner.startsWith("|")) inner = inner.slice(1);
|
|
1188
|
-
if (inner.endsWith("|")) inner = inner.slice(0, -1);
|
|
1189
|
-
return inner.split("|").every((cell) => cell.trim() === "");
|
|
1344
|
+
function renderWidth(text) {
|
|
1345
|
+
return canonicalizeBreakTags(text).replace(BREAK_TAG, " ").replace(/\\\|/g, "|").length;
|
|
1190
1346
|
}
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1347
|
+
function padCell(text, width, alignment) {
|
|
1348
|
+
const safeWidth = Math.max(width, renderWidth(text));
|
|
1349
|
+
const difference = safeWidth - renderWidth(text);
|
|
1350
|
+
if (difference <= 0) {
|
|
1351
|
+
return text;
|
|
1194
1352
|
}
|
|
1195
|
-
|
|
1196
|
-
text
|
|
1197
|
-
config?.plugins || [],
|
|
1198
|
-
config?.markdown || [],
|
|
1199
|
-
config?.theme || "auto" /* AUTO */,
|
|
1200
|
-
true
|
|
1201
|
-
);
|
|
1202
|
-
const html = await renderer.render();
|
|
1203
|
-
const paragraphMatch = html.match(/^\s*<p>([\s\S]*)<\/p>\s*$/i);
|
|
1204
|
-
if (paragraphMatch && paragraphMatch[1] !== void 0) {
|
|
1205
|
-
return paragraphMatch[1];
|
|
1353
|
+
if (alignment === "right") {
|
|
1354
|
+
return " ".repeat(difference) + text;
|
|
1206
1355
|
}
|
|
1207
|
-
|
|
1356
|
+
if (alignment === "center") {
|
|
1357
|
+
const left = Math.floor(difference / 2);
|
|
1358
|
+
const right = difference - left;
|
|
1359
|
+
return " ".repeat(left) + text + " ".repeat(right);
|
|
1360
|
+
}
|
|
1361
|
+
return text + " ".repeat(difference);
|
|
1362
|
+
}
|
|
1363
|
+
function delimiterCell(width, alignment) {
|
|
1364
|
+
const hyphenCount = Math.max(width, 3);
|
|
1365
|
+
if (alignment === "center") {
|
|
1366
|
+
return ":" + "-".repeat(Math.max(1, hyphenCount - 2)) + ":";
|
|
1367
|
+
}
|
|
1368
|
+
if (alignment === "right") {
|
|
1369
|
+
return "-".repeat(Math.max(2, hyphenCount - 1)) + ":";
|
|
1370
|
+
}
|
|
1371
|
+
return "-".repeat(hyphenCount);
|
|
1372
|
+
}
|
|
1373
|
+
function parseTableMarkdown(markdown) {
|
|
1374
|
+
const { tableMarkdown } = splitTableAndTrailingMarkdown(markdown);
|
|
1375
|
+
const lines = tableMarkdown.split("\n");
|
|
1376
|
+
if (lines.length < 2) {
|
|
1377
|
+
return null;
|
|
1378
|
+
}
|
|
1379
|
+
const headers = splitTableLine(lines[0] || "").map((cell) => cell.trim());
|
|
1380
|
+
const alignments = parseDelimiterAlignments(lines[1] || "");
|
|
1381
|
+
if (!alignments) {
|
|
1382
|
+
return null;
|
|
1383
|
+
}
|
|
1384
|
+
const rows = lines.slice(2).filter((line) => isTableRowLine(line)).map((line) => splitTableLine(line).map((cell) => cell.trim()));
|
|
1385
|
+
return { headers, alignments, rows };
|
|
1208
1386
|
}
|
|
1209
|
-
function
|
|
1210
|
-
|
|
1387
|
+
function normalizeParsedTable(parsed) {
|
|
1388
|
+
const columnCount = Math.max(
|
|
1389
|
+
parsed.headers.length,
|
|
1390
|
+
parsed.alignments.length,
|
|
1391
|
+
...parsed.rows.map((row) => row.length),
|
|
1392
|
+
1
|
|
1393
|
+
);
|
|
1394
|
+
const headers = Array.from({ length: columnCount }, (_, index) => normalizeCellContent(parsed.headers[index] || ""));
|
|
1395
|
+
const alignments = Array.from({ length: columnCount }, (_, index) => parsed.alignments[index] || "left");
|
|
1396
|
+
const rows = parsed.rows.map(
|
|
1397
|
+
(row) => Array.from({ length: columnCount }, (_, index) => normalizeCellContent(row[index] || ""))
|
|
1398
|
+
);
|
|
1399
|
+
return { headers, alignments, rows };
|
|
1400
|
+
}
|
|
1401
|
+
function formatTableMarkdown(parsed) {
|
|
1402
|
+
const normalized = normalizeParsedTable(parsed);
|
|
1403
|
+
const widths = normalized.headers.map(
|
|
1404
|
+
(header, index) => Math.max(renderWidth(header), ...normalized.rows.map((row) => renderWidth(row[index] || "")), 3)
|
|
1405
|
+
);
|
|
1406
|
+
const formatRow = (cells) => `| ${cells.map((cell, index) => padCell(cell, widths[index] || 3, normalized.alignments[index] || "left")).join(" | ")} |`;
|
|
1407
|
+
const headerLine = formatRow(normalized.headers);
|
|
1408
|
+
const delimiterLine = `| ${normalized.alignments.map((alignment, index) => delimiterCell(widths[index] || 3, alignment)).join(" | ")} |`;
|
|
1409
|
+
const bodyLines = normalized.rows.map((row) => formatRow(row));
|
|
1410
|
+
return [headerLine, delimiterLine, ...bodyLines].join("\n");
|
|
1411
|
+
}
|
|
1412
|
+
function buildEmptyRow(columnCount) {
|
|
1413
|
+
return Array.from({ length: columnCount }, () => "");
|
|
1414
|
+
}
|
|
1415
|
+
function createPreviewRenderer(markdown, config) {
|
|
1416
|
+
const plugins = (config?.plugins || []).filter((plugin) => plugin.name !== "paragraph");
|
|
1417
|
+
return new chunkCLW73JRX_cjs.PreviewRenderer(markdown, plugins, config?.markdown || [], config?.theme || "auto" /* AUTO */, true);
|
|
1418
|
+
}
|
|
1419
|
+
function stripSingleParagraph(html) {
|
|
1420
|
+
const trimmed = html.trim();
|
|
1421
|
+
const match = trimmed.match(/^<p\b[^>]*>([\s\S]*)<\/p>$/i);
|
|
1422
|
+
return match?.[1] || trimmed;
|
|
1211
1423
|
}
|
|
1212
|
-
function
|
|
1213
|
-
|
|
1424
|
+
async function renderCellToHtml(text, config) {
|
|
1425
|
+
if (!text.trim()) {
|
|
1426
|
+
return " ";
|
|
1427
|
+
}
|
|
1428
|
+
return stripSingleParagraph(await createPreviewRenderer(text, config).render());
|
|
1214
1429
|
}
|
|
1215
1430
|
async function renderTableToHtml(parsed, config) {
|
|
1216
|
-
const
|
|
1217
|
-
let html = '<div class="cm-draftly-table-widget">';
|
|
1218
|
-
html += '<
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
const
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
const align = getColumnAlignment(alignments, i);
|
|
1233
|
-
const cell = row[i] || "";
|
|
1234
|
-
const rendered = await renderCellWithPreviewRenderer(cell, config);
|
|
1235
|
-
html += `<td style="text-align: ${align}">${rendered}</td>`;
|
|
1431
|
+
const normalized = normalizeParsedTable(parsed);
|
|
1432
|
+
let html = '<div class="cm-draftly-table-widget"><table class="cm-draftly-table cm-draftly-table-preview">';
|
|
1433
|
+
html += '<thead><tr class="cm-draftly-table-row cm-draftly-table-header-row">';
|
|
1434
|
+
for (let index = 0; index < normalized.headers.length; index++) {
|
|
1435
|
+
const alignment = normalized.alignments[index] || "left";
|
|
1436
|
+
const content = await renderCellToHtml(normalized.headers[index] || "", config);
|
|
1437
|
+
html += `<th class="cm-draftly-table-cell cm-draftly-table-th${alignment === "center" ? " cm-draftly-table-cell-center" : alignment === "right" ? " cm-draftly-table-cell-right" : ""}${index === normalized.headers.length - 1 ? " cm-draftly-table-cell-last" : ""}">${content}</th>`;
|
|
1438
|
+
}
|
|
1439
|
+
html += "</tr></thead><tbody>";
|
|
1440
|
+
for (let rowIndex = 0; rowIndex < normalized.rows.length; rowIndex++) {
|
|
1441
|
+
const row = normalized.rows[rowIndex] || [];
|
|
1442
|
+
html += `<tr class="cm-draftly-table-row cm-draftly-table-body-row${rowIndex % 2 === 1 ? " cm-draftly-table-row-even" : ""}${rowIndex === normalized.rows.length - 1 ? " cm-draftly-table-row-last" : ""}">`;
|
|
1443
|
+
for (let index = 0; index < normalized.headers.length; index++) {
|
|
1444
|
+
const alignment = normalized.alignments[index] || "left";
|
|
1445
|
+
const content = await renderCellToHtml(row[index] || "", config);
|
|
1446
|
+
html += `<td class="cm-draftly-table-cell${alignment === "center" ? " cm-draftly-table-cell-center" : alignment === "right" ? " cm-draftly-table-cell-right" : ""}${index === normalized.headers.length - 1 ? " cm-draftly-table-cell-last" : ""}">${content}</td>`;
|
|
1236
1447
|
}
|
|
1237
1448
|
html += "</tr>";
|
|
1238
1449
|
}
|
|
1239
|
-
html += "</tbody>";
|
|
1240
|
-
html += "</table></div>";
|
|
1450
|
+
html += "</tbody></table></div>";
|
|
1241
1451
|
return html;
|
|
1242
1452
|
}
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1453
|
+
function getVisibleBounds(rawCellText) {
|
|
1454
|
+
const leading = rawCellText.length - rawCellText.trimStart().length;
|
|
1455
|
+
const trailing = rawCellText.length - rawCellText.trimEnd().length;
|
|
1456
|
+
const trimmedLength = rawCellText.trim().length;
|
|
1457
|
+
if (trimmedLength === 0) {
|
|
1458
|
+
const placeholderOffset = Math.min(Math.floor(rawCellText.length / 2), Math.max(rawCellText.length - 1, 0));
|
|
1459
|
+
return {
|
|
1460
|
+
startOffset: placeholderOffset,
|
|
1461
|
+
endOffset: Math.min(placeholderOffset + 1, rawCellText.length)
|
|
1462
|
+
};
|
|
1250
1463
|
}
|
|
1251
|
-
|
|
1252
|
-
|
|
1464
|
+
return {
|
|
1465
|
+
startOffset: leading,
|
|
1466
|
+
endOffset: rawCellText.length - trailing
|
|
1467
|
+
};
|
|
1468
|
+
}
|
|
1469
|
+
function isBodyRowEmpty(row) {
|
|
1470
|
+
return row.every((cell) => normalizeCellContent(cell.rawText) === "");
|
|
1471
|
+
}
|
|
1472
|
+
function buildTableFromInfo(tableInfo) {
|
|
1473
|
+
return {
|
|
1474
|
+
headers: tableInfo.headerCells.map((cell) => normalizeCellContent(cell.rawText)),
|
|
1475
|
+
alignments: [...tableInfo.alignments],
|
|
1476
|
+
rows: tableInfo.bodyCells.map((row) => row.map((cell) => normalizeCellContent(cell.rawText)))
|
|
1477
|
+
};
|
|
1478
|
+
}
|
|
1479
|
+
function getRowLineIndex(rowIndex) {
|
|
1480
|
+
return rowIndex === 0 ? 0 : rowIndex + 1;
|
|
1481
|
+
}
|
|
1482
|
+
function getCellAnchorInFormattedTable(formattedTable, rowIndex, columnIndex, offset = 0) {
|
|
1483
|
+
const lines = formattedTable.split("\n");
|
|
1484
|
+
const lineIndex = getRowLineIndex(rowIndex);
|
|
1485
|
+
const lineText = lines[lineIndex] || "";
|
|
1486
|
+
const pipes = getPipePositions(lineText);
|
|
1487
|
+
if (pipes.length < columnIndex + 2) {
|
|
1488
|
+
return formattedTable.length;
|
|
1489
|
+
}
|
|
1490
|
+
const rawFrom = pipes[columnIndex] + 1;
|
|
1491
|
+
const rawTo = pipes[columnIndex + 1];
|
|
1492
|
+
const visible = getVisibleBounds(lineText.slice(rawFrom, rawTo));
|
|
1493
|
+
const lineOffset = lines.slice(0, lineIndex).reduce((sum, line) => sum + line.length + 1, 0);
|
|
1494
|
+
return lineOffset + Math.min(rawFrom + visible.startOffset + offset, rawFrom + Math.max(visible.endOffset - 1, visible.startOffset));
|
|
1495
|
+
}
|
|
1496
|
+
function createTableInsert(state, from, to, tableMarkdown) {
|
|
1497
|
+
let insert = tableMarkdown;
|
|
1498
|
+
let prefixLength = 0;
|
|
1499
|
+
const startLine = state.doc.lineAt(from);
|
|
1500
|
+
if (startLine.number === 1 || state.doc.line(startLine.number - 1).text.trim() !== "") {
|
|
1501
|
+
insert = "\n" + insert;
|
|
1502
|
+
prefixLength = 1;
|
|
1503
|
+
}
|
|
1504
|
+
const endLine = state.doc.lineAt(Math.max(from, to));
|
|
1505
|
+
if (endLine.number === state.doc.lines || state.doc.line(endLine.number + 1).text.trim() !== "") {
|
|
1506
|
+
insert += "\n";
|
|
1507
|
+
}
|
|
1508
|
+
return { from, to, insert, prefixLength };
|
|
1509
|
+
}
|
|
1510
|
+
function readTableInfo(state, nodeFrom, nodeTo) {
|
|
1511
|
+
const startLine = state.doc.lineAt(nodeFrom);
|
|
1512
|
+
const endLine = state.doc.lineAt(nodeTo);
|
|
1513
|
+
const delimiterLineNumber = startLine.number + 1;
|
|
1514
|
+
if (delimiterLineNumber > endLine.number) {
|
|
1515
|
+
return null;
|
|
1253
1516
|
}
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
const
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
view.dispatch({
|
|
1297
|
-
selection: { anchor: this.from },
|
|
1298
|
-
scrollIntoView: true
|
|
1517
|
+
const delimiterLine = state.doc.line(delimiterLineNumber);
|
|
1518
|
+
const alignments = parseDelimiterAlignments(delimiterLine.text);
|
|
1519
|
+
if (!alignments) {
|
|
1520
|
+
return null;
|
|
1521
|
+
}
|
|
1522
|
+
let effectiveEndLineNumber = delimiterLineNumber;
|
|
1523
|
+
for (let lineNumber = delimiterLineNumber + 1; lineNumber <= endLine.number; lineNumber++) {
|
|
1524
|
+
const line = state.doc.line(lineNumber);
|
|
1525
|
+
if (!isTableRowLine(line.text)) {
|
|
1526
|
+
break;
|
|
1527
|
+
}
|
|
1528
|
+
effectiveEndLineNumber = lineNumber;
|
|
1529
|
+
}
|
|
1530
|
+
const cellsByRow = [];
|
|
1531
|
+
for (let lineNumber = startLine.number; lineNumber <= effectiveEndLineNumber; lineNumber++) {
|
|
1532
|
+
if (lineNumber === delimiterLineNumber) {
|
|
1533
|
+
continue;
|
|
1534
|
+
}
|
|
1535
|
+
const line = state.doc.line(lineNumber);
|
|
1536
|
+
const pipes = getPipePositions(line.text);
|
|
1537
|
+
if (pipes.length < 2) {
|
|
1538
|
+
return null;
|
|
1539
|
+
}
|
|
1540
|
+
const isHeader = lineNumber === startLine.number;
|
|
1541
|
+
const rowIndex = isHeader ? 0 : cellsByRow.length;
|
|
1542
|
+
const cells = [];
|
|
1543
|
+
for (let columnIndex = 0; columnIndex < pipes.length - 1; columnIndex++) {
|
|
1544
|
+
const from = line.from + pipes[columnIndex] + 1;
|
|
1545
|
+
const to = line.from + pipes[columnIndex + 1];
|
|
1546
|
+
const rawText = line.text.slice(pipes[columnIndex] + 1, pipes[columnIndex + 1]);
|
|
1547
|
+
const visible = getVisibleBounds(rawText);
|
|
1548
|
+
cells.push({
|
|
1549
|
+
rowKind: isHeader ? "header" : "body",
|
|
1550
|
+
rowIndex,
|
|
1551
|
+
columnIndex,
|
|
1552
|
+
from,
|
|
1553
|
+
to,
|
|
1554
|
+
contentFrom: from + visible.startOffset,
|
|
1555
|
+
contentTo: from + visible.endOffset,
|
|
1556
|
+
lineFrom: line.from,
|
|
1557
|
+
lineNumber,
|
|
1558
|
+
rawText
|
|
1299
1559
|
});
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
return wrapper;
|
|
1560
|
+
}
|
|
1561
|
+
cellsByRow.push(cells);
|
|
1303
1562
|
}
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1563
|
+
if (cellsByRow.length === 0) {
|
|
1564
|
+
return null;
|
|
1565
|
+
}
|
|
1566
|
+
return {
|
|
1567
|
+
from: startLine.from,
|
|
1568
|
+
to: state.doc.line(effectiveEndLineNumber).to,
|
|
1569
|
+
startLineNumber: startLine.number,
|
|
1570
|
+
delimiterLineNumber,
|
|
1571
|
+
endLineNumber: effectiveEndLineNumber,
|
|
1572
|
+
columnCount: cellsByRow[0].length,
|
|
1573
|
+
alignments: Array.from({ length: cellsByRow[0].length }, (_, index) => alignments[index] || "left"),
|
|
1574
|
+
cellsByRow,
|
|
1575
|
+
headerCells: cellsByRow[0],
|
|
1576
|
+
bodyCells: cellsByRow.slice(1)
|
|
1577
|
+
};
|
|
1578
|
+
}
|
|
1579
|
+
function getTableInfoAtPosition(state, position) {
|
|
1580
|
+
let resolved = null;
|
|
1581
|
+
language.syntaxTree(state).iterate({
|
|
1582
|
+
enter: (node) => {
|
|
1583
|
+
if (resolved || node.name !== "Table") {
|
|
1584
|
+
return;
|
|
1585
|
+
}
|
|
1586
|
+
const info = readTableInfo(state, node.from, node.to);
|
|
1587
|
+
if (info && position >= info.from && position <= info.to) {
|
|
1588
|
+
resolved = info;
|
|
1589
|
+
}
|
|
1311
1590
|
}
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1591
|
+
});
|
|
1592
|
+
return resolved;
|
|
1593
|
+
}
|
|
1594
|
+
function findCellAtPosition(tableInfo, position) {
|
|
1595
|
+
for (const row of tableInfo.cellsByRow) {
|
|
1596
|
+
for (const cell of row) {
|
|
1597
|
+
if (position >= cell.from && position <= cell.to) {
|
|
1598
|
+
return cell;
|
|
1599
|
+
}
|
|
1317
1600
|
}
|
|
1318
1601
|
}
|
|
1319
|
-
|
|
1320
|
-
|
|
1602
|
+
for (const row of tableInfo.cellsByRow) {
|
|
1603
|
+
for (const cell of row) {
|
|
1604
|
+
if (position >= cell.from - 1 && position <= cell.to + 1) {
|
|
1605
|
+
return cell;
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
let nearestCell = null;
|
|
1610
|
+
let nearestDistance = Number.POSITIVE_INFINITY;
|
|
1611
|
+
for (const row of tableInfo.cellsByRow) {
|
|
1612
|
+
for (const cell of row) {
|
|
1613
|
+
const distance = Math.min(Math.abs(position - cell.from), Math.abs(position - cell.to));
|
|
1614
|
+
if (distance < nearestDistance) {
|
|
1615
|
+
nearestCell = cell;
|
|
1616
|
+
nearestDistance = distance;
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
}
|
|
1620
|
+
return nearestCell;
|
|
1621
|
+
}
|
|
1622
|
+
function clampCellPosition(cell, position) {
|
|
1623
|
+
const cellEnd = Math.max(cell.contentFrom, cell.contentTo);
|
|
1624
|
+
return Math.max(cell.contentFrom, Math.min(position, cellEnd));
|
|
1625
|
+
}
|
|
1626
|
+
function collectBreakRanges(tableInfo) {
|
|
1627
|
+
const ranges = [];
|
|
1628
|
+
for (const row of tableInfo.cellsByRow) {
|
|
1629
|
+
for (const cell of row) {
|
|
1630
|
+
let match;
|
|
1631
|
+
const regex = new RegExp(BREAK_TAG_REGEX);
|
|
1632
|
+
while ((match = regex.exec(cell.rawText)) !== null) {
|
|
1633
|
+
ranges.push({
|
|
1634
|
+
from: cell.from + match.index,
|
|
1635
|
+
to: cell.from + match.index + match[0].length
|
|
1636
|
+
});
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1321
1639
|
}
|
|
1640
|
+
return ranges;
|
|
1641
|
+
}
|
|
1642
|
+
var lineDecorations = {
|
|
1643
|
+
header: view.Decoration.line({ class: "cm-draftly-table-row cm-draftly-table-header-row" }),
|
|
1644
|
+
delimiter: view.Decoration.line({ class: "cm-draftly-table-row cm-draftly-table-delimiter-row" }),
|
|
1645
|
+
body: view.Decoration.line({ class: "cm-draftly-table-row cm-draftly-table-body-row" }),
|
|
1646
|
+
even: view.Decoration.line({ class: "cm-draftly-table-row cm-draftly-table-body-row cm-draftly-table-row-even" }),
|
|
1647
|
+
last: view.Decoration.line({ class: "cm-draftly-table-row-last" })
|
|
1322
1648
|
};
|
|
1323
|
-
var
|
|
1324
|
-
"
|
|
1325
|
-
"
|
|
1326
|
-
"
|
|
1327
|
-
"
|
|
1328
|
-
"
|
|
1329
|
-
|
|
1330
|
-
|
|
1649
|
+
var cellDecorations = {
|
|
1650
|
+
"th-left": view.Decoration.mark({ class: "cm-draftly-table-cell cm-draftly-table-th" }),
|
|
1651
|
+
"th-center": view.Decoration.mark({ class: "cm-draftly-table-cell cm-draftly-table-th cm-draftly-table-cell-center" }),
|
|
1652
|
+
"th-right": view.Decoration.mark({ class: "cm-draftly-table-cell cm-draftly-table-th cm-draftly-table-cell-right" }),
|
|
1653
|
+
"th-left-last": view.Decoration.mark({ class: "cm-draftly-table-cell cm-draftly-table-th cm-draftly-table-cell-last" }),
|
|
1654
|
+
"th-center-last": view.Decoration.mark({
|
|
1655
|
+
class: "cm-draftly-table-cell cm-draftly-table-th cm-draftly-table-cell-center cm-draftly-table-cell-last"
|
|
1656
|
+
}),
|
|
1657
|
+
"th-right-last": view.Decoration.mark({
|
|
1658
|
+
class: "cm-draftly-table-cell cm-draftly-table-th cm-draftly-table-cell-right cm-draftly-table-cell-last"
|
|
1659
|
+
}),
|
|
1660
|
+
"td-left": view.Decoration.mark({ class: "cm-draftly-table-cell" }),
|
|
1661
|
+
"td-center": view.Decoration.mark({ class: "cm-draftly-table-cell cm-draftly-table-cell-center" }),
|
|
1662
|
+
"td-right": view.Decoration.mark({ class: "cm-draftly-table-cell cm-draftly-table-cell-right" }),
|
|
1663
|
+
"td-left-last": view.Decoration.mark({ class: "cm-draftly-table-cell cm-draftly-table-cell-last" }),
|
|
1664
|
+
"td-center-last": view.Decoration.mark({
|
|
1665
|
+
class: "cm-draftly-table-cell cm-draftly-table-cell-center cm-draftly-table-cell-last"
|
|
1666
|
+
}),
|
|
1667
|
+
"td-right-last": view.Decoration.mark({
|
|
1668
|
+
class: "cm-draftly-table-cell cm-draftly-table-cell-right cm-draftly-table-cell-last"
|
|
1669
|
+
})
|
|
1331
1670
|
};
|
|
1332
|
-
|
|
1671
|
+
function getCellDecoration(isHeader, alignment, isLastCell) {
|
|
1672
|
+
const key = `${isHeader ? "th" : "td"}-${alignment}${isLastCell ? "-last" : ""}`;
|
|
1673
|
+
return cellDecorations[key];
|
|
1674
|
+
}
|
|
1675
|
+
var TablePlugin = class extends chunkEQUQHE2E_cjs.DecorationPlugin {
|
|
1333
1676
|
name = "table";
|
|
1334
|
-
version = "
|
|
1677
|
+
version = "2.0.0";
|
|
1335
1678
|
decorationPriority = 20;
|
|
1336
1679
|
requiredNodes = ["Table", "TableHeader", "TableDelimiter", "TableRow", "TableCell"];
|
|
1337
|
-
/** Configuration stored from onRegister */
|
|
1338
1680
|
draftlyConfig;
|
|
1681
|
+
pendingNormalizationView = null;
|
|
1682
|
+
pendingPaddingView = null;
|
|
1683
|
+
pendingSelectionRepairView = null;
|
|
1684
|
+
/** Stores the editor config for preview rendering and shared behavior. */
|
|
1339
1685
|
onRegister(context) {
|
|
1340
1686
|
super.onRegister(context);
|
|
1341
1687
|
this.draftlyConfig = context.config;
|
|
1342
1688
|
}
|
|
1689
|
+
/** Exposes the plugin theme used for editor and preview styling. */
|
|
1343
1690
|
get theme() {
|
|
1344
1691
|
return theme6;
|
|
1345
1692
|
}
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1693
|
+
/** Enables GFM table parsing for the editor and preview renderer. */
|
|
1694
|
+
getMarkdownConfig() {
|
|
1695
|
+
return markdown.Table;
|
|
1696
|
+
}
|
|
1697
|
+
/** Registers block wrappers and atomic ranges for the table UI. */
|
|
1698
|
+
getExtensions() {
|
|
1699
|
+
return [
|
|
1700
|
+
state.Prec.highest(view.keymap.of(this.buildTableKeymap())),
|
|
1701
|
+
view.EditorView.blockWrappers.of((view) => this.computeBlockWrappers(view)),
|
|
1702
|
+
view.EditorView.atomicRanges.of((view) => this.computeAtomicRanges(view)),
|
|
1703
|
+
view.EditorView.domEventHandlers({
|
|
1704
|
+
keydown: (event, view) => this.handleDomKeydown(view, event)
|
|
1705
|
+
})
|
|
1706
|
+
];
|
|
1707
|
+
}
|
|
1708
|
+
/** Provides the table-specific keyboard shortcuts and navigation. */
|
|
1349
1709
|
getKeymap() {
|
|
1710
|
+
return [];
|
|
1711
|
+
}
|
|
1712
|
+
/** Builds the high-priority key bindings used inside tables. */
|
|
1713
|
+
buildTableKeymap() {
|
|
1350
1714
|
return [
|
|
1351
|
-
{
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
},
|
|
1356
|
-
{
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
},
|
|
1361
|
-
{
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
}
|
|
1366
|
-
{
|
|
1367
|
-
key: "Enter",
|
|
1368
|
-
run: (view) => this.handleEnter(view)
|
|
1369
|
-
},
|
|
1370
|
-
{
|
|
1371
|
-
key: "Tab",
|
|
1372
|
-
run: (view) => this.handleTab(view, false)
|
|
1373
|
-
},
|
|
1374
|
-
{
|
|
1375
|
-
key: "Shift-Tab",
|
|
1376
|
-
run: (view) => this.handleTab(view, true)
|
|
1377
|
-
}
|
|
1715
|
+
{ key: "Mod-Shift-t", run: (view) => this.insertTable(view), preventDefault: true },
|
|
1716
|
+
{ key: "Mod-Alt-ArrowDown", run: (view) => this.addRow(view), preventDefault: true },
|
|
1717
|
+
{ key: "Mod-Alt-ArrowRight", run: (view) => this.addColumn(view), preventDefault: true },
|
|
1718
|
+
{ key: "Mod-Alt-Backspace", run: (view) => this.removeRow(view), preventDefault: true },
|
|
1719
|
+
{ key: "Mod-Alt-Delete", run: (view) => this.removeColumn(view), preventDefault: true },
|
|
1720
|
+
{ key: "Tab", run: (view) => this.handleTab(view, false) },
|
|
1721
|
+
{ key: "Shift-Tab", run: (view) => this.handleTab(view, true) },
|
|
1722
|
+
{ key: "ArrowLeft", run: (view) => this.handleArrowHorizontal(view, false) },
|
|
1723
|
+
{ key: "ArrowRight", run: (view) => this.handleArrowHorizontal(view, true) },
|
|
1724
|
+
{ key: "ArrowUp", run: (view) => this.handleArrowVertical(view, false) },
|
|
1725
|
+
{ key: "ArrowDown", run: (view) => this.handleArrowVertical(view, true) },
|
|
1726
|
+
{ key: "Enter", run: (view) => this.handleEnter(view) },
|
|
1727
|
+
{ key: "Shift-Enter", run: (view) => this.insertBreakTag(view), preventDefault: true },
|
|
1728
|
+
{ key: "Backspace", run: (view) => this.handleBreakDeletion(view, false) },
|
|
1729
|
+
{ key: "Delete", run: (view) => this.handleBreakDeletion(view, true) }
|
|
1378
1730
|
];
|
|
1379
1731
|
}
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1732
|
+
/** Schedules an initial normalization pass once the view is ready. */
|
|
1733
|
+
onViewReady(view) {
|
|
1734
|
+
this.scheduleNormalization(view);
|
|
1735
|
+
}
|
|
1736
|
+
/** Re-schedules normalization after user-driven document changes. */
|
|
1737
|
+
onViewUpdate(update) {
|
|
1738
|
+
if (update.docChanged && !update.transactions.some((transaction) => transaction.annotation(normalizeAnnotation))) {
|
|
1739
|
+
this.schedulePadding(update.view);
|
|
1740
|
+
}
|
|
1741
|
+
if (update.selectionSet && !update.transactions.some((transaction) => transaction.annotation(repairSelectionAnnotation))) {
|
|
1742
|
+
this.scheduleSelectionRepair(update.view);
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
/** Intercepts table-specific DOM key handling before browser defaults run. */
|
|
1746
|
+
handleDomKeydown(view, event) {
|
|
1747
|
+
if (event.defaultPrevented || event.isComposing || event.altKey || event.metaKey || event.ctrlKey) {
|
|
1748
|
+
return false;
|
|
1749
|
+
}
|
|
1750
|
+
let handled = false;
|
|
1751
|
+
if (event.key === "Tab") {
|
|
1752
|
+
handled = this.handleTab(view, event.shiftKey);
|
|
1753
|
+
} else if (event.key === "Enter" && event.shiftKey) {
|
|
1754
|
+
handled = this.insertBreakTag(view);
|
|
1755
|
+
} else if (event.key === "Enter") {
|
|
1756
|
+
handled = this.handleEnter(view);
|
|
1757
|
+
} else if (event.key === "ArrowLeft") {
|
|
1758
|
+
handled = this.handleArrowHorizontal(view, false);
|
|
1759
|
+
} else if (event.key === "ArrowRight") {
|
|
1760
|
+
handled = this.handleArrowHorizontal(view, true);
|
|
1761
|
+
} else if (event.key === "ArrowUp") {
|
|
1762
|
+
handled = this.handleArrowVertical(view, false);
|
|
1763
|
+
} else if (event.key === "ArrowDown") {
|
|
1764
|
+
handled = this.handleArrowVertical(view, true);
|
|
1765
|
+
} else if (event.key === "Backspace") {
|
|
1766
|
+
handled = this.handleBreakDeletion(view, false);
|
|
1767
|
+
} else if (event.key === "Delete") {
|
|
1768
|
+
handled = this.handleBreakDeletion(view, true);
|
|
1769
|
+
}
|
|
1770
|
+
if (handled) {
|
|
1771
|
+
event.preventDefault();
|
|
1772
|
+
event.stopPropagation();
|
|
1773
|
+
}
|
|
1774
|
+
return handled;
|
|
1775
|
+
}
|
|
1776
|
+
/** Builds the visual table decorations for every parsed table block. */
|
|
1383
1777
|
buildDecorations(ctx) {
|
|
1384
|
-
const { view
|
|
1385
|
-
|
|
1386
|
-
tree.iterate({
|
|
1778
|
+
const { view, decorations } = ctx;
|
|
1779
|
+
language.syntaxTree(view.state).iterate({
|
|
1387
1780
|
enter: (node) => {
|
|
1388
|
-
if (node.name !== "Table")
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
const
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
for (let i = nodeLineStart.number; i <= nodeLineEnd.number; i++) {
|
|
1395
|
-
const line = view$1.state.doc.line(i);
|
|
1396
|
-
decorations.push(tableMarkDecorations["table-line"].range(line.from));
|
|
1397
|
-
if (i === nodeLineStart.number) {
|
|
1398
|
-
decorations.push(tableMarkDecorations["table-line-start"].range(line.from));
|
|
1399
|
-
}
|
|
1400
|
-
if (i === nodeLineEnd.number) {
|
|
1401
|
-
decorations.push(tableMarkDecorations["table-line-end"].range(line.from));
|
|
1402
|
-
}
|
|
1403
|
-
if (i === nodeLineStart.number + 1) {
|
|
1404
|
-
decorations.push(tableMarkDecorations["table-delimiter"].range(line.from));
|
|
1405
|
-
}
|
|
1406
|
-
}
|
|
1407
|
-
} else {
|
|
1408
|
-
const tableContent = view$1.state.sliceDoc(from, to);
|
|
1409
|
-
for (let i = nodeLineStart.number; i <= nodeLineEnd.number; i++) {
|
|
1410
|
-
const line = view$1.state.doc.line(i);
|
|
1411
|
-
decorations.push(tableMarkDecorations["table-rendered"].range(line.from));
|
|
1412
|
-
decorations.push(tableMarkDecorations["table-hidden"].range(line.from, line.to));
|
|
1413
|
-
}
|
|
1414
|
-
decorations.push(
|
|
1415
|
-
view.Decoration.widget({
|
|
1416
|
-
widget: new TableWidget(tableContent, from, to, this.draftlyConfig),
|
|
1417
|
-
side: 1,
|
|
1418
|
-
block: false
|
|
1419
|
-
}).range(to)
|
|
1420
|
-
);
|
|
1781
|
+
if (node.name !== "Table") {
|
|
1782
|
+
return;
|
|
1783
|
+
}
|
|
1784
|
+
const tableInfo = readTableInfo(view.state, node.from, node.to);
|
|
1785
|
+
if (tableInfo) {
|
|
1786
|
+
this.decorateTable(view, decorations, tableInfo);
|
|
1421
1787
|
}
|
|
1422
1788
|
}
|
|
1423
1789
|
});
|
|
1424
1790
|
}
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1791
|
+
/** Renders the full table node to semantic preview HTML. */
|
|
1792
|
+
async renderToHTML(node, _children, ctx) {
|
|
1793
|
+
if (node.name === "Table") {
|
|
1794
|
+
const content = ctx.sliceDoc(node.from, node.to);
|
|
1795
|
+
const { tableMarkdown, trailingMarkdown } = splitTableAndTrailingMarkdown(content);
|
|
1796
|
+
const parsed = parseTableMarkdown(tableMarkdown);
|
|
1797
|
+
if (!parsed) {
|
|
1798
|
+
return null;
|
|
1799
|
+
}
|
|
1800
|
+
const tableHtml = await renderTableToHtml(parsed, this.draftlyConfig);
|
|
1801
|
+
if (!trailingMarkdown.trim()) {
|
|
1802
|
+
return tableHtml;
|
|
1803
|
+
}
|
|
1804
|
+
return tableHtml + await createPreviewRenderer(trailingMarkdown, this.draftlyConfig).render();
|
|
1805
|
+
}
|
|
1806
|
+
if (TABLE_SUB_NODE_NAMES.has(node.name)) {
|
|
1807
|
+
return "";
|
|
1808
|
+
}
|
|
1809
|
+
return null;
|
|
1810
|
+
}
|
|
1811
|
+
/** Computes the block wrapper ranges used to group table lines. */
|
|
1812
|
+
computeBlockWrappers(view$1) {
|
|
1813
|
+
const wrappers = [];
|
|
1814
|
+
language.syntaxTree(view$1.state).iterate({
|
|
1815
|
+
enter: (node) => {
|
|
1816
|
+
if (node.name !== "Table") {
|
|
1817
|
+
return;
|
|
1818
|
+
}
|
|
1819
|
+
const tableInfo = readTableInfo(view$1.state, node.from, node.to);
|
|
1820
|
+
if (tableInfo) {
|
|
1821
|
+
wrappers.push(tableBlockWrapper.range(tableInfo.from, tableInfo.to));
|
|
1822
|
+
}
|
|
1451
1823
|
}
|
|
1452
1824
|
});
|
|
1453
|
-
return true;
|
|
1825
|
+
return view.BlockWrapper.set(wrappers, true);
|
|
1454
1826
|
}
|
|
1455
|
-
/**
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1827
|
+
/** Computes atomic ranges for delimiters and inline break tags. */
|
|
1828
|
+
computeAtomicRanges(view$1) {
|
|
1829
|
+
const ranges = [];
|
|
1830
|
+
language.syntaxTree(view$1.state).iterate({
|
|
1831
|
+
enter: (node) => {
|
|
1832
|
+
if (node.name !== "Table") {
|
|
1833
|
+
return;
|
|
1834
|
+
}
|
|
1835
|
+
const tableInfo = readTableInfo(view$1.state, node.from, node.to);
|
|
1836
|
+
if (!tableInfo) {
|
|
1837
|
+
return;
|
|
1838
|
+
}
|
|
1839
|
+
for (let lineNumber = tableInfo.startLineNumber; lineNumber <= tableInfo.endLineNumber; lineNumber++) {
|
|
1840
|
+
const line = view$1.state.doc.line(lineNumber);
|
|
1841
|
+
if (lineNumber === tableInfo.delimiterLineNumber) {
|
|
1842
|
+
ranges.push(delimiterReplace.range(line.from, line.to));
|
|
1843
|
+
continue;
|
|
1844
|
+
}
|
|
1845
|
+
const pipes = getPipePositions(line.text);
|
|
1846
|
+
for (const pipe of pipes) {
|
|
1847
|
+
ranges.push(pipeReplace.range(line.from + pipe, line.from + pipe + 1));
|
|
1848
|
+
}
|
|
1849
|
+
for (let columnIndex = 0; columnIndex < pipes.length - 1; columnIndex++) {
|
|
1850
|
+
const rawFrom = pipes[columnIndex] + 1;
|
|
1851
|
+
const rawTo = pipes[columnIndex + 1];
|
|
1852
|
+
const rawText = line.text.slice(rawFrom, rawTo);
|
|
1853
|
+
const visible = getVisibleBounds(rawText);
|
|
1854
|
+
if (visible.startOffset > 0) {
|
|
1855
|
+
ranges.push(pipeReplace.range(line.from + rawFrom, line.from + rawFrom + visible.startOffset));
|
|
1856
|
+
}
|
|
1857
|
+
if (visible.endOffset < rawText.length) {
|
|
1858
|
+
ranges.push(pipeReplace.range(line.from + rawFrom + visible.endOffset, line.from + rawTo));
|
|
1859
|
+
}
|
|
1860
|
+
let match;
|
|
1861
|
+
const regex = new RegExp(BREAK_TAG_REGEX);
|
|
1862
|
+
while ((match = regex.exec(rawText)) !== null) {
|
|
1863
|
+
ranges.push(
|
|
1864
|
+
view.Decoration.replace({ widget: new TableBreakWidget() }).range(
|
|
1865
|
+
line.from + rawFrom + match.index,
|
|
1866
|
+
line.from + rawFrom + match.index + match[0].length
|
|
1867
|
+
)
|
|
1868
|
+
);
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1476
1872
|
}
|
|
1477
1873
|
});
|
|
1478
|
-
return true;
|
|
1874
|
+
return state.RangeSet.of(ranges, true);
|
|
1479
1875
|
}
|
|
1480
|
-
/**
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
}
|
|
1495
|
-
colIndex = Math.max(0, colIndex);
|
|
1496
|
-
const tableText = state.sliceDoc(tableInfo.from, tableInfo.to);
|
|
1497
|
-
const lines = tableText.split("\n");
|
|
1498
|
-
const newLines = lines.map((line, lineIdx) => {
|
|
1499
|
-
const cells = this.splitLineToCells(line);
|
|
1500
|
-
const insertAfter = Math.min(colIndex, cells.length - 1);
|
|
1501
|
-
if (lineIdx === 1) {
|
|
1502
|
-
cells.splice(insertAfter + 1, 0, " -------- ");
|
|
1876
|
+
/** Applies row, cell, and control decorations for a single table. */
|
|
1877
|
+
decorateTable(view$1, decorations, tableInfo) {
|
|
1878
|
+
for (let lineNumber = tableInfo.startLineNumber; lineNumber <= tableInfo.endLineNumber; lineNumber++) {
|
|
1879
|
+
const line = view$1.state.doc.line(lineNumber);
|
|
1880
|
+
const isHeader = lineNumber === tableInfo.startLineNumber;
|
|
1881
|
+
const isDelimiter = lineNumber === tableInfo.delimiterLineNumber;
|
|
1882
|
+
const isLastBody = !isHeader && !isDelimiter && lineNumber === tableInfo.endLineNumber;
|
|
1883
|
+
const bodyIndex = isHeader || isDelimiter ? -1 : lineNumber - tableInfo.delimiterLineNumber - 1;
|
|
1884
|
+
if (isHeader) {
|
|
1885
|
+
decorations.push(lineDecorations.header.range(line.from));
|
|
1886
|
+
} else if (isDelimiter) {
|
|
1887
|
+
decorations.push(lineDecorations.delimiter.range(line.from));
|
|
1888
|
+
} else if (bodyIndex % 2 === 1) {
|
|
1889
|
+
decorations.push(lineDecorations.even.range(line.from));
|
|
1503
1890
|
} else {
|
|
1504
|
-
|
|
1891
|
+
decorations.push(lineDecorations.body.range(line.from));
|
|
1505
1892
|
}
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
view.dispatch({
|
|
1509
|
-
changes: {
|
|
1510
|
-
from: tableInfo.from,
|
|
1511
|
-
to: tableInfo.to,
|
|
1512
|
-
insert: newLines.join("\n")
|
|
1893
|
+
if (isLastBody) {
|
|
1894
|
+
decorations.push(lineDecorations.last.range(line.from));
|
|
1513
1895
|
}
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1896
|
+
if (isDelimiter) {
|
|
1897
|
+
decorations.push(delimiterReplace.range(line.from, line.to));
|
|
1898
|
+
continue;
|
|
1899
|
+
}
|
|
1900
|
+
this.decorateLine(decorations, line.from, line.text, tableInfo.alignments, isHeader);
|
|
1901
|
+
}
|
|
1902
|
+
decorations.push(
|
|
1903
|
+
view.Decoration.widget({
|
|
1904
|
+
widget: new TableControlsWidget(
|
|
1905
|
+
(view2) => {
|
|
1906
|
+
const liveTable = getTableInfoAtPosition(view2.state, tableInfo.from);
|
|
1907
|
+
if (liveTable) {
|
|
1908
|
+
this.appendRow(view2, liveTable, liveTable.columnCount - 1);
|
|
1909
|
+
}
|
|
1910
|
+
},
|
|
1911
|
+
(view2) => {
|
|
1912
|
+
const liveTable = getTableInfoAtPosition(view2.state, tableInfo.from);
|
|
1913
|
+
if (liveTable) {
|
|
1914
|
+
this.appendColumn(view2, liveTable);
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
),
|
|
1918
|
+
side: 1
|
|
1919
|
+
}).range(tableInfo.to)
|
|
1920
|
+
);
|
|
1921
|
+
}
|
|
1922
|
+
/** Applies the visual cell decorations for a single table row line. */
|
|
1923
|
+
decorateLine(decorations, lineFrom, lineText, alignments, isHeader) {
|
|
1924
|
+
const pipes = getPipePositions(lineText);
|
|
1925
|
+
if (pipes.length < 2) {
|
|
1926
|
+
return;
|
|
1927
|
+
}
|
|
1928
|
+
for (const pipe of pipes) {
|
|
1929
|
+
decorations.push(pipeReplace.range(lineFrom + pipe, lineFrom + pipe + 1));
|
|
1930
|
+
}
|
|
1931
|
+
for (let columnIndex = 0; columnIndex < pipes.length - 1; columnIndex++) {
|
|
1932
|
+
const rawFrom = pipes[columnIndex] + 1;
|
|
1933
|
+
const rawTo = pipes[columnIndex + 1];
|
|
1934
|
+
const rawText = lineText.slice(rawFrom, rawTo);
|
|
1935
|
+
const visible = getVisibleBounds(rawText);
|
|
1936
|
+
const absoluteFrom = lineFrom + rawFrom;
|
|
1937
|
+
const absoluteTo = lineFrom + rawTo;
|
|
1938
|
+
if (visible.startOffset > 0) {
|
|
1939
|
+
decorations.push(pipeReplace.range(absoluteFrom, absoluteFrom + visible.startOffset));
|
|
1940
|
+
}
|
|
1941
|
+
if (visible.endOffset < rawText.length) {
|
|
1942
|
+
decorations.push(pipeReplace.range(absoluteFrom + visible.endOffset, absoluteTo));
|
|
1943
|
+
}
|
|
1944
|
+
decorations.push(
|
|
1945
|
+
getCellDecoration(isHeader, alignments[columnIndex] || "left", columnIndex === pipes.length - 2).range(
|
|
1946
|
+
absoluteFrom,
|
|
1947
|
+
absoluteTo
|
|
1948
|
+
)
|
|
1949
|
+
);
|
|
1950
|
+
let match;
|
|
1951
|
+
const regex = new RegExp(BREAK_TAG_REGEX);
|
|
1952
|
+
while ((match = regex.exec(rawText)) !== null) {
|
|
1953
|
+
decorations.push(
|
|
1954
|
+
view.Decoration.replace({ widget: new TableBreakWidget() }).range(
|
|
1955
|
+
absoluteFrom + match.index,
|
|
1956
|
+
absoluteFrom + match.index + match[0].length
|
|
1957
|
+
)
|
|
1958
|
+
);
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
/** Normalizes every parsed table block back into canonical markdown. */
|
|
1963
|
+
normalizeTables(view) {
|
|
1964
|
+
const changes = [];
|
|
1965
|
+
language.syntaxTree(view.state).iterate({
|
|
1966
|
+
enter: (node) => {
|
|
1967
|
+
if (node.name !== "Table") {
|
|
1968
|
+
return;
|
|
1969
|
+
}
|
|
1970
|
+
const content = view.state.sliceDoc(node.from, node.to);
|
|
1971
|
+
const { tableMarkdown } = splitTableAndTrailingMarkdown(content);
|
|
1972
|
+
const parsed = parseTableMarkdown(tableMarkdown);
|
|
1973
|
+
if (!parsed) {
|
|
1974
|
+
return;
|
|
1546
1975
|
}
|
|
1976
|
+
const formatted = formatTableMarkdown(parsed);
|
|
1977
|
+
const change = createTableInsert(view.state, node.from, node.from + tableMarkdown.length, formatted);
|
|
1978
|
+
if (change.insert !== tableMarkdown || change.from !== node.from || change.to !== node.from + tableMarkdown.length) {
|
|
1979
|
+
changes.push({
|
|
1980
|
+
from: change.from,
|
|
1981
|
+
to: change.to,
|
|
1982
|
+
insert: change.insert
|
|
1983
|
+
});
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
});
|
|
1987
|
+
if (changes.length > 0) {
|
|
1988
|
+
view.dispatch({
|
|
1989
|
+
changes: changes.sort((left, right) => right.from - left.from),
|
|
1990
|
+
annotations: normalizeAnnotation.of(true)
|
|
1547
1991
|
});
|
|
1548
|
-
return true;
|
|
1549
1992
|
}
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
anchor: cursorLine.to + 3
|
|
1561
|
-
// Position in first cell of new row
|
|
1993
|
+
}
|
|
1994
|
+
/** Defers table normalization until the current update cycle is finished. */
|
|
1995
|
+
scheduleNormalization(view) {
|
|
1996
|
+
if (this.pendingNormalizationView === view) {
|
|
1997
|
+
return;
|
|
1998
|
+
}
|
|
1999
|
+
this.pendingNormalizationView = view;
|
|
2000
|
+
queueMicrotask(() => {
|
|
2001
|
+
if (this.pendingNormalizationView !== view) {
|
|
2002
|
+
return;
|
|
1562
2003
|
}
|
|
2004
|
+
this.pendingNormalizationView = null;
|
|
2005
|
+
this.normalizeTables(view);
|
|
1563
2006
|
});
|
|
1564
|
-
return true;
|
|
1565
2007
|
}
|
|
1566
|
-
/**
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
const
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
2008
|
+
/** Adds missing spacer lines above and below tables after edits. */
|
|
2009
|
+
ensureTablePadding(view) {
|
|
2010
|
+
const changes = [];
|
|
2011
|
+
language.syntaxTree(view.state).iterate({
|
|
2012
|
+
enter: (node) => {
|
|
2013
|
+
if (node.name !== "Table") {
|
|
2014
|
+
return;
|
|
2015
|
+
}
|
|
2016
|
+
const tableInfo = readTableInfo(view.state, node.from, node.to);
|
|
2017
|
+
if (!tableInfo) {
|
|
2018
|
+
return;
|
|
2019
|
+
}
|
|
2020
|
+
const startLine = view.state.doc.lineAt(tableInfo.from);
|
|
2021
|
+
if (startLine.number === 1) {
|
|
2022
|
+
changes.push({ from: startLine.from, to: startLine.from, insert: "\n" });
|
|
2023
|
+
} else {
|
|
2024
|
+
const previousLine = view.state.doc.line(startLine.number - 1);
|
|
2025
|
+
if (previousLine.text.trim() !== "") {
|
|
2026
|
+
changes.push({ from: startLine.from, to: startLine.from, insert: "\n" });
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
const endLine = view.state.doc.lineAt(tableInfo.to);
|
|
2030
|
+
if (endLine.number === view.state.doc.lines) {
|
|
2031
|
+
changes.push({ from: endLine.to, to: endLine.to, insert: "\n" });
|
|
2032
|
+
} else {
|
|
2033
|
+
const nextLine = view.state.doc.line(endLine.number + 1);
|
|
2034
|
+
if (nextLine.text.trim() !== "") {
|
|
2035
|
+
changes.push({ from: endLine.to, to: endLine.to, insert: "\n" });
|
|
2036
|
+
}
|
|
2037
|
+
}
|
|
1593
2038
|
}
|
|
2039
|
+
});
|
|
2040
|
+
if (changes.length > 0) {
|
|
2041
|
+
view.dispatch({
|
|
2042
|
+
changes: changes.sort((left, right) => right.from - left.from),
|
|
2043
|
+
annotations: normalizeAnnotation.of(true)
|
|
2044
|
+
});
|
|
1594
2045
|
}
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
2046
|
+
}
|
|
2047
|
+
/** Schedules a padding-only pass after the current update cycle finishes. */
|
|
2048
|
+
schedulePadding(view) {
|
|
2049
|
+
if (this.pendingPaddingView === view) {
|
|
2050
|
+
return;
|
|
2051
|
+
}
|
|
2052
|
+
this.pendingPaddingView = view;
|
|
2053
|
+
queueMicrotask(() => {
|
|
2054
|
+
if (this.pendingPaddingView !== view) {
|
|
2055
|
+
return;
|
|
1603
2056
|
}
|
|
2057
|
+
this.pendingPaddingView = null;
|
|
2058
|
+
this.ensureTablePadding(view);
|
|
2059
|
+
});
|
|
2060
|
+
}
|
|
2061
|
+
/** Repairs carets that land in hidden table markup instead of editable cell content. */
|
|
2062
|
+
ensureTableSelection(view) {
|
|
2063
|
+
const selection = view.state.selection.main;
|
|
2064
|
+
if (!selection.empty) {
|
|
2065
|
+
return;
|
|
2066
|
+
}
|
|
2067
|
+
const tableInfo = getTableInfoAtPosition(view.state, selection.head);
|
|
2068
|
+
if (!tableInfo) {
|
|
2069
|
+
return;
|
|
2070
|
+
}
|
|
2071
|
+
const cell = findCellAtPosition(tableInfo, selection.head);
|
|
2072
|
+
if (!cell) {
|
|
2073
|
+
return;
|
|
2074
|
+
}
|
|
2075
|
+
const anchor = clampCellPosition(cell, selection.head);
|
|
2076
|
+
if (anchor === selection.head) {
|
|
2077
|
+
return;
|
|
1604
2078
|
}
|
|
1605
|
-
if (currentCellIdx === -1) return false;
|
|
1606
|
-
const nextIdx = backwards ? currentCellIdx - 1 : currentCellIdx + 1;
|
|
1607
|
-
if (nextIdx < 0 || nextIdx >= cellPositions.length) return false;
|
|
1608
|
-
const nextCell = cellPositions[nextIdx];
|
|
1609
|
-
const cellText = state.sliceDoc(nextCell.lineFrom + nextCell.start, nextCell.lineFrom + nextCell.end);
|
|
1610
|
-
const trimStart = cellText.length - cellText.trimStart().length;
|
|
1611
|
-
const trimEnd = cellText.length - cellText.trimEnd().length;
|
|
1612
|
-
const selectFrom = nextCell.lineFrom + nextCell.start + (trimStart > 0 ? 1 : 0);
|
|
1613
|
-
const selectTo = nextCell.lineFrom + nextCell.end - (trimEnd > 0 ? 1 : 0);
|
|
1614
2079
|
view.dispatch({
|
|
1615
|
-
selection: {
|
|
1616
|
-
|
|
1617
|
-
head: selectTo
|
|
1618
|
-
},
|
|
2080
|
+
selection: { anchor },
|
|
2081
|
+
annotations: repairSelectionAnnotation.of(true),
|
|
1619
2082
|
scrollIntoView: true
|
|
1620
2083
|
});
|
|
2084
|
+
}
|
|
2085
|
+
/** Schedules table selection repair after the current update finishes. */
|
|
2086
|
+
scheduleSelectionRepair(view) {
|
|
2087
|
+
if (this.pendingSelectionRepairView === view) {
|
|
2088
|
+
return;
|
|
2089
|
+
}
|
|
2090
|
+
this.pendingSelectionRepairView = view;
|
|
2091
|
+
queueMicrotask(() => {
|
|
2092
|
+
if (this.pendingSelectionRepairView !== view) {
|
|
2093
|
+
return;
|
|
2094
|
+
}
|
|
2095
|
+
this.pendingSelectionRepairView = null;
|
|
2096
|
+
this.ensureTableSelection(view);
|
|
2097
|
+
});
|
|
2098
|
+
}
|
|
2099
|
+
/** Rewrites a table block and restores the caret to a target cell position. */
|
|
2100
|
+
replaceTable(view, tableInfo, parsed, targetRowIndex, targetColumnIndex, offset = 0) {
|
|
2101
|
+
const formatted = formatTableMarkdown(parsed);
|
|
2102
|
+
const change = createTableInsert(view.state, tableInfo.from, tableInfo.to, formatted);
|
|
2103
|
+
const selection = change.from + change.prefixLength + getCellAnchorInFormattedTable(
|
|
2104
|
+
formatted,
|
|
2105
|
+
Math.max(0, targetRowIndex),
|
|
2106
|
+
Math.max(0, Math.min(targetColumnIndex, Math.max(parsed.headers.length - 1, 0))),
|
|
2107
|
+
Math.max(0, offset)
|
|
2108
|
+
);
|
|
2109
|
+
view.dispatch({
|
|
2110
|
+
changes: { from: change.from, to: change.to, insert: change.insert },
|
|
2111
|
+
selection: { anchor: selection }
|
|
2112
|
+
});
|
|
2113
|
+
}
|
|
2114
|
+
/** Inserts an empty body row below the given logical row index. */
|
|
2115
|
+
insertRowBelow(view, tableInfo, afterRowIndex, targetColumn) {
|
|
2116
|
+
const parsed = normalizeParsedTable(buildTableFromInfo(tableInfo));
|
|
2117
|
+
const insertBodyIndex = Math.max(0, Math.min(afterRowIndex, parsed.rows.length));
|
|
2118
|
+
parsed.rows.splice(insertBodyIndex, 0, buildEmptyRow(tableInfo.columnCount));
|
|
2119
|
+
this.replaceTable(view, tableInfo, parsed, insertBodyIndex + 1, targetColumn);
|
|
2120
|
+
}
|
|
2121
|
+
/** Inserts a starter table near the current cursor line. */
|
|
2122
|
+
insertTable(view) {
|
|
2123
|
+
const { state } = view;
|
|
2124
|
+
const cursor = state.selection.main.head;
|
|
2125
|
+
const line = state.doc.lineAt(cursor);
|
|
2126
|
+
const insertAt = line.text.trim() ? line.to : line.from;
|
|
2127
|
+
const formatted = formatTableMarkdown(TABLE_TEMPLATE);
|
|
2128
|
+
const change = createTableInsert(state, insertAt, insertAt, formatted);
|
|
2129
|
+
const selection = change.from + change.prefixLength + getCellAnchorInFormattedTable(formatted, 0, 0);
|
|
2130
|
+
view.dispatch({
|
|
2131
|
+
changes: { from: change.from, to: change.to, insert: change.insert },
|
|
2132
|
+
selection: { anchor: selection }
|
|
2133
|
+
});
|
|
1621
2134
|
return true;
|
|
1622
2135
|
}
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
2136
|
+
/** Adds a new empty body row to the active table. */
|
|
2137
|
+
addRow(view) {
|
|
2138
|
+
const tableInfo = this.getTableAtCursor(view);
|
|
2139
|
+
if (!tableInfo) {
|
|
2140
|
+
return false;
|
|
2141
|
+
}
|
|
2142
|
+
const cell = this.getCurrentCell(view, tableInfo);
|
|
2143
|
+
this.appendRow(view, tableInfo, cell?.columnIndex || 0);
|
|
2144
|
+
return true;
|
|
2145
|
+
}
|
|
2146
|
+
/** Appends a row and keeps the caret in the requested column. */
|
|
2147
|
+
appendRow(view, tableInfo, targetColumn) {
|
|
2148
|
+
this.insertRowBelow(view, tableInfo, tableInfo.bodyCells.length, targetColumn);
|
|
2149
|
+
}
|
|
2150
|
+
/** Inserts a new column after the current column. */
|
|
2151
|
+
addColumn(view) {
|
|
2152
|
+
const tableInfo = this.getTableAtCursor(view);
|
|
2153
|
+
if (!tableInfo) {
|
|
2154
|
+
return false;
|
|
2155
|
+
}
|
|
2156
|
+
const cell = this.getCurrentCell(view, tableInfo);
|
|
2157
|
+
const insertAfter = cell?.columnIndex ?? tableInfo.columnCount - 1;
|
|
2158
|
+
const parsed = normalizeParsedTable(buildTableFromInfo(tableInfo));
|
|
2159
|
+
parsed.headers.splice(insertAfter + 1, 0, "");
|
|
2160
|
+
parsed.alignments.splice(insertAfter + 1, 0, "left");
|
|
2161
|
+
for (const row of parsed.rows) {
|
|
2162
|
+
row.splice(insertAfter + 1, 0, "");
|
|
2163
|
+
}
|
|
2164
|
+
this.replaceTable(view, tableInfo, parsed, cell?.rowIndex || 0, insertAfter + 1);
|
|
2165
|
+
return true;
|
|
2166
|
+
}
|
|
2167
|
+
/** Appends a new column at the far right of the table. */
|
|
2168
|
+
appendColumn(view, tableInfo) {
|
|
2169
|
+
const parsed = normalizeParsedTable(buildTableFromInfo(tableInfo));
|
|
2170
|
+
parsed.headers.push("");
|
|
2171
|
+
parsed.alignments.push("left");
|
|
2172
|
+
for (const row of parsed.rows) {
|
|
2173
|
+
row.push("");
|
|
2174
|
+
}
|
|
2175
|
+
this.replaceTable(view, tableInfo, parsed, 0, parsed.headers.length - 1);
|
|
2176
|
+
}
|
|
2177
|
+
/** Removes the current body row or clears the last remaining row. */
|
|
2178
|
+
removeRow(view) {
|
|
2179
|
+
const tableInfo = this.getTableAtCursor(view);
|
|
2180
|
+
if (!tableInfo) {
|
|
2181
|
+
return false;
|
|
2182
|
+
}
|
|
2183
|
+
const cell = this.getCurrentCell(view, tableInfo);
|
|
2184
|
+
if (!cell || cell.rowKind !== "body") {
|
|
2185
|
+
return false;
|
|
2186
|
+
}
|
|
2187
|
+
const parsed = normalizeParsedTable(buildTableFromInfo(tableInfo));
|
|
2188
|
+
const bodyIndex = cell.rowIndex - 1;
|
|
2189
|
+
if (bodyIndex < 0 || bodyIndex >= parsed.rows.length) {
|
|
2190
|
+
return false;
|
|
2191
|
+
}
|
|
2192
|
+
if (parsed.rows.length === 1) {
|
|
2193
|
+
parsed.rows[0] = buildEmptyRow(tableInfo.columnCount);
|
|
2194
|
+
} else {
|
|
2195
|
+
parsed.rows.splice(bodyIndex, 1);
|
|
2196
|
+
}
|
|
2197
|
+
const nextRowIndex = Math.max(1, Math.min(cell.rowIndex, parsed.rows.length));
|
|
2198
|
+
this.replaceTable(view, tableInfo, parsed, nextRowIndex, Math.min(cell.columnIndex, tableInfo.columnCount - 1));
|
|
2199
|
+
return true;
|
|
2200
|
+
}
|
|
2201
|
+
/** Removes the current column when the table has more than one column. */
|
|
2202
|
+
removeColumn(view) {
|
|
2203
|
+
const tableInfo = this.getTableAtCursor(view);
|
|
2204
|
+
if (!tableInfo || tableInfo.columnCount <= 1) {
|
|
2205
|
+
return false;
|
|
2206
|
+
}
|
|
2207
|
+
const cell = this.getCurrentCell(view, tableInfo);
|
|
2208
|
+
const removeAt = cell?.columnIndex ?? tableInfo.columnCount - 1;
|
|
2209
|
+
const parsed = normalizeParsedTable(buildTableFromInfo(tableInfo));
|
|
2210
|
+
parsed.headers.splice(removeAt, 1);
|
|
2211
|
+
parsed.alignments.splice(removeAt, 1);
|
|
2212
|
+
for (const row of parsed.rows) {
|
|
2213
|
+
row.splice(removeAt, 1);
|
|
2214
|
+
}
|
|
2215
|
+
this.replaceTable(view, tableInfo, parsed, cell?.rowIndex || 0, Math.min(removeAt, parsed.headers.length - 1));
|
|
2216
|
+
return true;
|
|
2217
|
+
}
|
|
2218
|
+
/** Moves to the next or previous logical cell with Tab navigation. */
|
|
2219
|
+
handleTab(view, backwards) {
|
|
2220
|
+
const tableInfo = this.getTableAtCursor(view);
|
|
2221
|
+
if (!tableInfo) {
|
|
2222
|
+
return false;
|
|
2223
|
+
}
|
|
2224
|
+
const cell = this.getCurrentCell(view, tableInfo);
|
|
2225
|
+
if (!cell) {
|
|
2226
|
+
return false;
|
|
2227
|
+
}
|
|
2228
|
+
const cells = tableInfo.cellsByRow.flat();
|
|
2229
|
+
const currentIndex = cells.findIndex((candidate) => candidate.from === cell.from && candidate.to === cell.to);
|
|
2230
|
+
if (currentIndex < 0) {
|
|
2231
|
+
return false;
|
|
2232
|
+
}
|
|
2233
|
+
const nextIndex = backwards ? currentIndex - 1 : currentIndex + 1;
|
|
2234
|
+
if (nextIndex < 0) {
|
|
2235
|
+
return true;
|
|
2236
|
+
}
|
|
2237
|
+
if (nextIndex >= cells.length) {
|
|
2238
|
+
this.appendRow(view, tableInfo, 0);
|
|
2239
|
+
return true;
|
|
2240
|
+
}
|
|
2241
|
+
this.moveSelectionToCell(view, cells[nextIndex]);
|
|
2242
|
+
return true;
|
|
2243
|
+
}
|
|
2244
|
+
/** Moves horizontally between adjacent cells when the caret hits an edge. */
|
|
2245
|
+
handleArrowHorizontal(view, forward) {
|
|
2246
|
+
const tableInfo = this.getTableAtCursor(view);
|
|
2247
|
+
if (!tableInfo) {
|
|
2248
|
+
return false;
|
|
2249
|
+
}
|
|
2250
|
+
const cell = this.getCurrentCell(view, tableInfo);
|
|
2251
|
+
if (!cell) {
|
|
2252
|
+
return false;
|
|
2253
|
+
}
|
|
1631
2254
|
const cursor = view.state.selection.main.head;
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
2255
|
+
const rightEdge = Math.max(cell.contentFrom, cell.contentTo);
|
|
2256
|
+
if (forward && cursor < rightEdge) {
|
|
2257
|
+
return false;
|
|
2258
|
+
}
|
|
2259
|
+
if (!forward && cursor > cell.contentFrom) {
|
|
2260
|
+
return false;
|
|
2261
|
+
}
|
|
2262
|
+
const row = tableInfo.cellsByRow[cell.rowIndex] || [];
|
|
2263
|
+
const nextCell = row[cell.columnIndex + (forward ? 1 : -1)];
|
|
2264
|
+
if (!nextCell) {
|
|
2265
|
+
return false;
|
|
2266
|
+
}
|
|
2267
|
+
this.moveSelectionToCell(view, nextCell);
|
|
2268
|
+
return true;
|
|
2269
|
+
}
|
|
2270
|
+
/** Moves vertically between rows while keeping the current column. */
|
|
2271
|
+
handleArrowVertical(view, forward) {
|
|
2272
|
+
const tableInfo = this.getTableAtCursor(view);
|
|
2273
|
+
if (!tableInfo) {
|
|
2274
|
+
return false;
|
|
2275
|
+
}
|
|
2276
|
+
const cell = this.getCurrentCell(view, tableInfo);
|
|
2277
|
+
if (!cell) {
|
|
2278
|
+
return false;
|
|
2279
|
+
}
|
|
2280
|
+
const nextRow = tableInfo.cellsByRow[cell.rowIndex + (forward ? 1 : -1)];
|
|
2281
|
+
if (!nextRow) {
|
|
2282
|
+
return false;
|
|
2283
|
+
}
|
|
2284
|
+
const nextCell = nextRow[cell.columnIndex];
|
|
2285
|
+
if (!nextCell) {
|
|
2286
|
+
return false;
|
|
2287
|
+
}
|
|
2288
|
+
this.moveSelectionToCell(view, nextCell);
|
|
2289
|
+
return true;
|
|
2290
|
+
}
|
|
2291
|
+
/** Advances downward on Enter and manages the trailing empty row behavior. */
|
|
2292
|
+
handleEnter(view) {
|
|
2293
|
+
const tableInfo = this.getTableAtCursor(view);
|
|
2294
|
+
if (!tableInfo) {
|
|
2295
|
+
return false;
|
|
2296
|
+
}
|
|
2297
|
+
const cell = this.getCurrentCell(view, tableInfo);
|
|
2298
|
+
if (!cell) {
|
|
2299
|
+
return false;
|
|
2300
|
+
}
|
|
2301
|
+
if (cell.rowKind === "body") {
|
|
2302
|
+
const currentRow = tableInfo.bodyCells[cell.rowIndex - 1];
|
|
2303
|
+
if (currentRow && isBodyRowEmpty(currentRow)) {
|
|
2304
|
+
const parsed = normalizeParsedTable(buildTableFromInfo(tableInfo));
|
|
2305
|
+
parsed.rows.splice(cell.rowIndex - 1, 1);
|
|
2306
|
+
const formatted = formatTableMarkdown(parsed);
|
|
2307
|
+
const change = createTableInsert(view.state, tableInfo.from, tableInfo.to, formatted);
|
|
2308
|
+
const anchor = Math.min(change.from + change.insert.length, view.state.doc.length + change.insert.length);
|
|
2309
|
+
view.dispatch({
|
|
2310
|
+
changes: { from: change.from, to: change.to, insert: change.insert },
|
|
2311
|
+
selection: { anchor }
|
|
2312
|
+
});
|
|
2313
|
+
return true;
|
|
1638
2314
|
}
|
|
2315
|
+
}
|
|
2316
|
+
if (cell.rowKind === "body" && cell.rowIndex === tableInfo.cellsByRow.length - 1) {
|
|
2317
|
+
const parsed = normalizeParsedTable(buildTableFromInfo(tableInfo));
|
|
2318
|
+
parsed.rows.push(buildEmptyRow(tableInfo.columnCount));
|
|
2319
|
+
this.replaceTable(view, tableInfo, parsed, parsed.rows.length, cell.columnIndex);
|
|
2320
|
+
return true;
|
|
2321
|
+
}
|
|
2322
|
+
this.insertRowBelow(view, tableInfo, cell.rowIndex, cell.columnIndex);
|
|
2323
|
+
return true;
|
|
2324
|
+
}
|
|
2325
|
+
/** Inserts a canonical `<br />` token inside the current table cell. */
|
|
2326
|
+
insertBreakTag(view) {
|
|
2327
|
+
const tableInfo = this.getTableAtCursor(view);
|
|
2328
|
+
if (!tableInfo) {
|
|
2329
|
+
return false;
|
|
2330
|
+
}
|
|
2331
|
+
const selection = view.state.selection.main;
|
|
2332
|
+
view.dispatch({
|
|
2333
|
+
changes: { from: selection.from, to: selection.to, insert: BREAK_TAG },
|
|
2334
|
+
selection: { anchor: selection.from + BREAK_TAG.length }
|
|
1639
2335
|
});
|
|
1640
|
-
return
|
|
2336
|
+
return true;
|
|
1641
2337
|
}
|
|
1642
|
-
/**
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
if (trimmed.startsWith("|")) trimmed = trimmed.slice(1);
|
|
1648
|
-
if (trimmed.endsWith("|")) trimmed = trimmed.slice(0, -1);
|
|
1649
|
-
return trimmed.split("|");
|
|
1650
|
-
}
|
|
1651
|
-
// ============================================
|
|
1652
|
-
// Preview Rendering
|
|
1653
|
-
// ============================================
|
|
1654
|
-
async renderToHTML(node, _children, _ctx) {
|
|
1655
|
-
if (node.name === "Table") {
|
|
1656
|
-
const content = _ctx.sliceDoc(node.from, node.to);
|
|
1657
|
-
const parsed = parseTableMarkdown(content);
|
|
1658
|
-
if (!parsed) return null;
|
|
1659
|
-
return await renderTableToHtml(parsed, this.draftlyConfig);
|
|
2338
|
+
/** Deletes a whole `<br />` token when backspace or delete hits it. */
|
|
2339
|
+
handleBreakDeletion(view, forward) {
|
|
2340
|
+
const tableInfo = this.getTableAtCursor(view);
|
|
2341
|
+
if (!tableInfo) {
|
|
2342
|
+
return false;
|
|
1660
2343
|
}
|
|
1661
|
-
|
|
1662
|
-
|
|
2344
|
+
const selection = view.state.selection.main;
|
|
2345
|
+
const cursor = selection.head;
|
|
2346
|
+
for (const range of collectBreakRanges(tableInfo)) {
|
|
2347
|
+
const within = cursor > range.from && cursor < range.to;
|
|
2348
|
+
const matchesBackspace = !forward && cursor === range.to;
|
|
2349
|
+
const matchesDelete = forward && cursor === range.from;
|
|
2350
|
+
const overlapsSelection = !selection.empty && selection.from <= range.from && selection.to >= range.to;
|
|
2351
|
+
if (within || matchesBackspace || matchesDelete || overlapsSelection) {
|
|
2352
|
+
view.dispatch({
|
|
2353
|
+
changes: { from: range.from, to: range.to, insert: "" },
|
|
2354
|
+
selection: { anchor: range.from }
|
|
2355
|
+
});
|
|
2356
|
+
return true;
|
|
2357
|
+
}
|
|
1663
2358
|
}
|
|
1664
|
-
return
|
|
2359
|
+
return false;
|
|
2360
|
+
}
|
|
2361
|
+
/** Moves the current selection anchor into a target cell. */
|
|
2362
|
+
moveSelectionToCell(view, cell, offset = 0) {
|
|
2363
|
+
const end = Math.max(cell.contentFrom, cell.contentTo);
|
|
2364
|
+
view.dispatch({
|
|
2365
|
+
selection: { anchor: Math.min(cell.contentFrom + offset, end) },
|
|
2366
|
+
scrollIntoView: true
|
|
2367
|
+
});
|
|
2368
|
+
}
|
|
2369
|
+
/** Returns the table currently containing the editor cursor. */
|
|
2370
|
+
getTableAtCursor(view) {
|
|
2371
|
+
return getTableInfoAtPosition(view.state, view.state.selection.main.head);
|
|
2372
|
+
}
|
|
2373
|
+
/** Returns the active cell under the current selection head. */
|
|
2374
|
+
getCurrentCell(view, tableInfo) {
|
|
2375
|
+
return findCellAtPosition(tableInfo, view.state.selection.main.head);
|
|
1665
2376
|
}
|
|
1666
2377
|
};
|
|
1667
|
-
var theme6 =
|
|
2378
|
+
var theme6 = chunkW75QUUQC_cjs.createTheme({
|
|
1668
2379
|
default: {
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
"--radius": "0.375rem",
|
|
1672
|
-
fontFamily: "var(--font-jetbrains-mono, monospace)",
|
|
1673
|
-
fontSize: "0.9rem",
|
|
1674
|
-
backgroundColor: "rgba(0, 0, 0, 0.02)",
|
|
1675
|
-
padding: "0 0.75rem !important",
|
|
1676
|
-
lineHeight: "1.6",
|
|
1677
|
-
borderLeft: "1px solid var(--color-border, #e2e8f0)",
|
|
1678
|
-
borderRight: "1px solid var(--color-border, #e2e8f0)"
|
|
1679
|
-
},
|
|
1680
|
-
".cm-draftly-table-line-start": {
|
|
1681
|
-
borderTopLeftRadius: "var(--radius)",
|
|
1682
|
-
borderTopRightRadius: "var(--radius)",
|
|
1683
|
-
borderTop: "1px solid var(--color-border, #e2e8f0)"
|
|
1684
|
-
},
|
|
1685
|
-
".cm-draftly-table-line-end": {
|
|
1686
|
-
borderBottomLeftRadius: "var(--radius)",
|
|
1687
|
-
borderBottomRightRadius: "var(--radius)",
|
|
1688
|
-
borderBottom: "1px solid var(--color-border, #e2e8f0)"
|
|
1689
|
-
},
|
|
1690
|
-
".cm-draftly-table-delimiter-line": {
|
|
1691
|
-
opacity: "0.5"
|
|
1692
|
-
},
|
|
1693
|
-
// Hidden table text (when cursor is not in range)
|
|
1694
|
-
".cm-draftly-table-hidden": {
|
|
1695
|
-
display: "none"
|
|
1696
|
-
},
|
|
1697
|
-
// Line decoration for rendered state — hide line breaks
|
|
1698
|
-
".cm-draftly-table-rendered": {
|
|
1699
|
-
padding: "0 !important"
|
|
1700
|
-
},
|
|
1701
|
-
".cm-draftly-table-rendered br": {
|
|
1702
|
-
display: "none"
|
|
1703
|
-
},
|
|
1704
|
-
// Rendered table widget container
|
|
1705
|
-
".cm-draftly-table-widget": {
|
|
1706
|
-
cursor: "pointer",
|
|
1707
|
-
overflow: "auto",
|
|
1708
|
-
padding: "0.5rem 0"
|
|
1709
|
-
},
|
|
1710
|
-
// Table element
|
|
1711
|
-
".cm-draftly-table": {
|
|
2380
|
+
".cm-draftly-table-wrapper, .cm-draftly-table-widget": {
|
|
2381
|
+
display: "table",
|
|
1712
2382
|
width: "100%",
|
|
1713
2383
|
borderCollapse: "separate",
|
|
1714
2384
|
borderSpacing: "0",
|
|
1715
|
-
|
|
1716
|
-
overflow: "
|
|
1717
|
-
border: "1px solid var(--color-border, #
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
2385
|
+
position: "relative",
|
|
2386
|
+
overflow: "visible",
|
|
2387
|
+
border: "1px solid var(--color-border, #d7dee7)",
|
|
2388
|
+
borderRadius: "0.75rem",
|
|
2389
|
+
backgroundColor: "var(--color-background, #ffffff)",
|
|
2390
|
+
"& .cm-draftly-table": {
|
|
2391
|
+
width: "100%",
|
|
2392
|
+
borderCollapse: "separate",
|
|
2393
|
+
borderSpacing: "0",
|
|
2394
|
+
tableLayout: "auto"
|
|
2395
|
+
},
|
|
2396
|
+
"& .cm-draftly-table-row": {
|
|
2397
|
+
display: "table-row !important"
|
|
2398
|
+
},
|
|
2399
|
+
"& .cm-draftly-table-header-row": {
|
|
2400
|
+
backgroundColor: "rgba(15, 23, 42, 0.04)"
|
|
2401
|
+
},
|
|
2402
|
+
"& .cm-draftly-table-row-even": {
|
|
2403
|
+
backgroundColor: "rgba(15, 23, 42, 0.02)"
|
|
2404
|
+
},
|
|
2405
|
+
"& .cm-draftly-table-delimiter-row": {
|
|
2406
|
+
display: "none !important"
|
|
2407
|
+
},
|
|
2408
|
+
"& .cm-draftly-table-cell": {
|
|
2409
|
+
display: "table-cell",
|
|
2410
|
+
minWidth: "4rem",
|
|
2411
|
+
minHeight: "2.5rem",
|
|
2412
|
+
height: "2.75rem",
|
|
2413
|
+
padding: "0.5rem 0.875rem",
|
|
2414
|
+
verticalAlign: "top",
|
|
2415
|
+
borderRight: "1px solid var(--color-border, #d7dee7)",
|
|
2416
|
+
borderBottom: "1px solid var(--color-border, #d7dee7)",
|
|
2417
|
+
whiteSpace: "normal",
|
|
2418
|
+
overflowWrap: "break-word",
|
|
2419
|
+
wordBreak: "normal",
|
|
2420
|
+
lineHeight: "1.6"
|
|
2421
|
+
},
|
|
2422
|
+
"& .cm-draftly-table-body-row": {
|
|
2423
|
+
minHeight: "2.75rem"
|
|
2424
|
+
},
|
|
2425
|
+
"& .cm-draftly-table-cell .cm-draftly-code-inline": {
|
|
2426
|
+
whiteSpace: "normal",
|
|
2427
|
+
overflowWrap: "anywhere"
|
|
2428
|
+
},
|
|
2429
|
+
"& .cm-draftly-table-th": {
|
|
2430
|
+
fontWeight: "600",
|
|
2431
|
+
borderBottomWidth: "2px"
|
|
2432
|
+
},
|
|
2433
|
+
"& .cm-draftly-table-cell-last": {
|
|
2434
|
+
borderRight: "none"
|
|
2435
|
+
},
|
|
2436
|
+
"& .cm-draftly-table-row-last .cm-draftly-table-cell": {
|
|
2437
|
+
borderBottom: "none"
|
|
2438
|
+
},
|
|
2439
|
+
"& .cm-draftly-table-cell-center": {
|
|
2440
|
+
textAlign: "center"
|
|
2441
|
+
},
|
|
2442
|
+
"& .cm-draftly-table-cell-right": {
|
|
2443
|
+
textAlign: "right"
|
|
2444
|
+
},
|
|
2445
|
+
"& .cm-draftly-table-break": {
|
|
2446
|
+
display: "inline"
|
|
2447
|
+
},
|
|
2448
|
+
"& .cm-draftly-table-controls-anchor": {
|
|
2449
|
+
position: "absolute",
|
|
2450
|
+
inset: "0",
|
|
2451
|
+
pointerEvents: "none"
|
|
2452
|
+
},
|
|
2453
|
+
"& .cm-draftly-table-control": {
|
|
2454
|
+
position: "absolute",
|
|
2455
|
+
width: "1.75rem",
|
|
2456
|
+
height: "1.75rem",
|
|
2457
|
+
border: "1px solid var(--color-border, #d7dee7)",
|
|
2458
|
+
borderRadius: "999px",
|
|
2459
|
+
backgroundColor: "var(--color-background, #ffffff)",
|
|
2460
|
+
color: "var(--color-text, #0f172a)",
|
|
2461
|
+
boxShadow: "0 10px 24px rgba(15, 23, 42, 0.12)",
|
|
2462
|
+
display: "inline-flex",
|
|
2463
|
+
alignItems: "center",
|
|
2464
|
+
justifyContent: "center",
|
|
2465
|
+
opacity: "0",
|
|
2466
|
+
pointerEvents: "auto",
|
|
2467
|
+
transition: "opacity 120ms ease, transform 120ms ease, background-color 120ms ease"
|
|
2468
|
+
},
|
|
2469
|
+
"& .cm-draftly-table-control:hover": {
|
|
2470
|
+
backgroundColor: "rgba(15, 23, 42, 0.05)"
|
|
2471
|
+
},
|
|
2472
|
+
"& .cm-draftly-table-control-column": {
|
|
2473
|
+
top: "50%",
|
|
2474
|
+
right: "-0.95rem",
|
|
2475
|
+
transform: "translate(0.35rem, -50%)"
|
|
2476
|
+
},
|
|
2477
|
+
"& .cm-draftly-table-control-row": {
|
|
2478
|
+
left: "50%",
|
|
2479
|
+
bottom: "-0.95rem",
|
|
2480
|
+
transform: "translate(-50%, 0.35rem)"
|
|
2481
|
+
},
|
|
2482
|
+
"&:hover .cm-draftly-table-control, &:focus-within .cm-draftly-table-control": {
|
|
2483
|
+
opacity: "1"
|
|
2484
|
+
},
|
|
2485
|
+
"&:hover .cm-draftly-table-control-column, &:focus-within .cm-draftly-table-control-column": {
|
|
2486
|
+
transform: "translate(0, -50%)"
|
|
2487
|
+
},
|
|
2488
|
+
"&:hover .cm-draftly-table-control-row, &:focus-within .cm-draftly-table-control-row": {
|
|
2489
|
+
transform: "translate(-50%, 0)"
|
|
2490
|
+
}
|
|
1776
2491
|
}
|
|
1777
2492
|
},
|
|
1778
2493
|
dark: {
|
|
1779
|
-
".cm-draftly-table-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
2494
|
+
".cm-draftly-table-wrapper, .cm-draftly-table-widget": {
|
|
2495
|
+
borderColor: "var(--color-border, #30363d)",
|
|
2496
|
+
backgroundColor: "var(--color-background, #0d1117)",
|
|
2497
|
+
"& .cm-draftly-table-header-row": {
|
|
2498
|
+
backgroundColor: "rgba(255, 255, 255, 0.05)"
|
|
2499
|
+
},
|
|
2500
|
+
"& .cm-draftly-table-row-even": {
|
|
2501
|
+
backgroundColor: "rgba(255, 255, 255, 0.025)"
|
|
2502
|
+
},
|
|
2503
|
+
"& .cm-draftly-table-cell": {
|
|
2504
|
+
borderColor: "var(--color-border, #30363d)"
|
|
2505
|
+
},
|
|
2506
|
+
"& .cm-draftly-table-control": {
|
|
2507
|
+
borderColor: "var(--color-border, #30363d)",
|
|
2508
|
+
backgroundColor: "var(--color-background, #161b22)",
|
|
2509
|
+
color: "var(--color-text, #e6edf3)",
|
|
2510
|
+
boxShadow: "0 12px 28px rgba(0, 0, 0, 0.35)"
|
|
2511
|
+
},
|
|
2512
|
+
"& .cm-draftly-table-control:hover": {
|
|
2513
|
+
backgroundColor: "rgba(255, 255, 255, 0.08)"
|
|
2514
|
+
}
|
|
1799
2515
|
}
|
|
1800
2516
|
}
|
|
1801
2517
|
});
|
|
@@ -1854,7 +2570,7 @@ function parseHTMLTag(content) {
|
|
|
1854
2570
|
)
|
|
1855
2571
|
};
|
|
1856
2572
|
}
|
|
1857
|
-
var HTMLPlugin = class extends
|
|
2573
|
+
var HTMLPlugin = class extends chunkEQUQHE2E_cjs.DecorationPlugin {
|
|
1858
2574
|
name = "html";
|
|
1859
2575
|
version = "1.0.0";
|
|
1860
2576
|
decorationPriority = 30;
|
|
@@ -2005,7 +2721,7 @@ var HTMLPlugin = class extends chunkBWJLMREN_cjs.DecorationPlugin {
|
|
|
2005
2721
|
}
|
|
2006
2722
|
}
|
|
2007
2723
|
};
|
|
2008
|
-
var theme7 =
|
|
2724
|
+
var theme7 = chunkW75QUUQC_cjs.createTheme({
|
|
2009
2725
|
default: {
|
|
2010
2726
|
".cm-draftly-html-tag": {
|
|
2011
2727
|
color: "#6a737d",
|
|
@@ -2123,7 +2839,7 @@ var ImageWidget = class extends view.WidgetType {
|
|
|
2123
2839
|
return event.type !== "click";
|
|
2124
2840
|
}
|
|
2125
2841
|
};
|
|
2126
|
-
var ImagePlugin = class extends
|
|
2842
|
+
var ImagePlugin = class extends chunkEQUQHE2E_cjs.DecorationPlugin {
|
|
2127
2843
|
name = "image";
|
|
2128
2844
|
version = "1.0.0";
|
|
2129
2845
|
decorationPriority = 25;
|
|
@@ -2290,7 +3006,7 @@ var ImagePlugin = class extends chunkBWJLMREN_cjs.DecorationPlugin {
|
|
|
2290
3006
|
return html;
|
|
2291
3007
|
}
|
|
2292
3008
|
};
|
|
2293
|
-
var theme8 =
|
|
3009
|
+
var theme8 = chunkW75QUUQC_cjs.createTheme({
|
|
2294
3010
|
default: {
|
|
2295
3011
|
".cm-draftly-image-block br": {
|
|
2296
3012
|
display: "none"
|
|
@@ -2527,7 +3243,7 @@ var mathBlockParser = {
|
|
|
2527
3243
|
return true;
|
|
2528
3244
|
}
|
|
2529
3245
|
};
|
|
2530
|
-
var MathPlugin = class extends
|
|
3246
|
+
var MathPlugin = class extends chunkEQUQHE2E_cjs.DecorationPlugin {
|
|
2531
3247
|
name = "math";
|
|
2532
3248
|
version = "1.0.0";
|
|
2533
3249
|
decorationPriority = 25;
|
|
@@ -2656,7 +3372,7 @@ var MathPlugin = class extends chunkBWJLMREN_cjs.DecorationPlugin {
|
|
|
2656
3372
|
return null;
|
|
2657
3373
|
}
|
|
2658
3374
|
};
|
|
2659
|
-
var theme9 =
|
|
3375
|
+
var theme9 = chunkW75QUUQC_cjs.createTheme({
|
|
2660
3376
|
default: {
|
|
2661
3377
|
".cm-draftly-math-block": {
|
|
2662
3378
|
fontFamily: "var(--font-jetbrains-mono, monospace)"
|
|
@@ -2843,7 +3559,7 @@ var mermaidBlockParser = {
|
|
|
2843
3559
|
return true;
|
|
2844
3560
|
}
|
|
2845
3561
|
};
|
|
2846
|
-
var MermaidPlugin = class extends
|
|
3562
|
+
var MermaidPlugin = class extends chunkEQUQHE2E_cjs.DecorationPlugin {
|
|
2847
3563
|
name = "mermaid";
|
|
2848
3564
|
version = "1.0.0";
|
|
2849
3565
|
decorationPriority = 25;
|
|
@@ -2963,7 +3679,7 @@ var MermaidPlugin = class extends chunkBWJLMREN_cjs.DecorationPlugin {
|
|
|
2963
3679
|
return null;
|
|
2964
3680
|
}
|
|
2965
3681
|
};
|
|
2966
|
-
var theme10 =
|
|
3682
|
+
var theme10 = chunkW75QUUQC_cjs.createTheme({
|
|
2967
3683
|
default: {
|
|
2968
3684
|
// Raw mermaid block lines (monospace)
|
|
2969
3685
|
".cm-draftly-mermaid-block:not(.cm-draftly-mermaid-block-rendered)": {
|
|
@@ -3069,7 +3785,7 @@ var theme10 = chunkTBVZEK2H_cjs.createTheme({
|
|
|
3069
3785
|
});
|
|
3070
3786
|
|
|
3071
3787
|
// src/plugins/code-plugin.theme.ts
|
|
3072
|
-
var codePluginTheme =
|
|
3788
|
+
var codePluginTheme = chunkW75QUUQC_cjs.createTheme({
|
|
3073
3789
|
default: {
|
|
3074
3790
|
// Inline code
|
|
3075
3791
|
".cm-draftly-code-inline": {
|
|
@@ -3536,7 +4252,7 @@ var CodeBlockCaptionWidget = class extends view.WidgetType {
|
|
|
3536
4252
|
return false;
|
|
3537
4253
|
}
|
|
3538
4254
|
};
|
|
3539
|
-
var CodePlugin = class extends
|
|
4255
|
+
var CodePlugin = class extends chunkEQUQHE2E_cjs.DecorationPlugin {
|
|
3540
4256
|
name = "code";
|
|
3541
4257
|
version = "1.0.0";
|
|
3542
4258
|
decorationPriority = 25;
|
|
@@ -3555,7 +4271,7 @@ var CodePlugin = class extends chunkBWJLMREN_cjs.DecorationPlugin {
|
|
|
3555
4271
|
return [
|
|
3556
4272
|
{
|
|
3557
4273
|
key: "Mod-e",
|
|
3558
|
-
run:
|
|
4274
|
+
run: chunkW75QUUQC_cjs.toggleMarkdownStyle("`"),
|
|
3559
4275
|
preventDefault: true
|
|
3560
4276
|
},
|
|
3561
4277
|
{
|
|
@@ -4392,7 +5108,7 @@ var quoteLineDecorations = {
|
|
|
4392
5108
|
/** Decoration for blockquote lines */
|
|
4393
5109
|
"quote-line": view.Decoration.line({ class: "cm-draftly-quote-line" })
|
|
4394
5110
|
};
|
|
4395
|
-
var QuotePlugin = class extends
|
|
5111
|
+
var QuotePlugin = class extends chunkEQUQHE2E_cjs.DecorationPlugin {
|
|
4396
5112
|
name = "quote";
|
|
4397
5113
|
version = "1.0.0";
|
|
4398
5114
|
decorationPriority = 10;
|
|
@@ -4463,7 +5179,7 @@ var QuotePlugin = class extends chunkBWJLMREN_cjs.DecorationPlugin {
|
|
|
4463
5179
|
`;
|
|
4464
5180
|
}
|
|
4465
5181
|
};
|
|
4466
|
-
var theme11 =
|
|
5182
|
+
var theme11 = chunkW75QUUQC_cjs.createTheme({
|
|
4467
5183
|
default: {
|
|
4468
5184
|
// Line styling with left border
|
|
4469
5185
|
".cm-draftly-quote-line": {
|
|
@@ -4482,7 +5198,7 @@ var theme11 = chunkTBVZEK2H_cjs.createTheme({
|
|
|
4482
5198
|
});
|
|
4483
5199
|
var hrLineDecoration = view.Decoration.line({ class: "cm-draftly-hr-line" });
|
|
4484
5200
|
var hrMarkDecoration = view.Decoration.replace({});
|
|
4485
|
-
var HRPlugin = class extends
|
|
5201
|
+
var HRPlugin = class extends chunkEQUQHE2E_cjs.DecorationPlugin {
|
|
4486
5202
|
name = "hr";
|
|
4487
5203
|
version = "1.0.0";
|
|
4488
5204
|
decorationPriority = 10;
|
|
@@ -4530,7 +5246,7 @@ var HRPlugin = class extends chunkBWJLMREN_cjs.DecorationPlugin {
|
|
|
4530
5246
|
`;
|
|
4531
5247
|
}
|
|
4532
5248
|
};
|
|
4533
|
-
var theme12 =
|
|
5249
|
+
var theme12 = chunkW75QUUQC_cjs.createTheme({
|
|
4534
5250
|
default: {
|
|
4535
5251
|
// Line styling — displays a centered horizontal line
|
|
4536
5252
|
".cm-draftly-hr-line": {
|
|
@@ -4574,7 +5290,7 @@ var EmojiWidget = class extends view.WidgetType {
|
|
|
4574
5290
|
var emojiMarkDecorations = {
|
|
4575
5291
|
"emoji-source": view.Decoration.mark({ class: "cm-draftly-emoji-source" })
|
|
4576
5292
|
};
|
|
4577
|
-
var EmojiPlugin = class extends
|
|
5293
|
+
var EmojiPlugin = class extends chunkEQUQHE2E_cjs.DecorationPlugin {
|
|
4578
5294
|
name = "emoji";
|
|
4579
5295
|
version = "1.0.0";
|
|
4580
5296
|
decorationPriority = 20;
|
|
@@ -4633,7 +5349,7 @@ var EmojiPlugin = class extends chunkBWJLMREN_cjs.DecorationPlugin {
|
|
|
4633
5349
|
return `<span class="cm-draftly-emoji">${rendered}</span>`;
|
|
4634
5350
|
}
|
|
4635
5351
|
};
|
|
4636
|
-
var theme13 =
|
|
5352
|
+
var theme13 = chunkW75QUUQC_cjs.createTheme({
|
|
4637
5353
|
default: {
|
|
4638
5354
|
".cm-draftly-emoji": {
|
|
4639
5355
|
fontFamily: '"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", "Segoe UI Symbol", sans-serif',
|
|
@@ -4682,5 +5398,5 @@ exports.QuotePlugin = QuotePlugin;
|
|
|
4682
5398
|
exports.TablePlugin = TablePlugin;
|
|
4683
5399
|
exports.allPlugins = allPlugins;
|
|
4684
5400
|
exports.essentialPlugins = essentialPlugins;
|
|
4685
|
-
//# sourceMappingURL=chunk-
|
|
4686
|
-
//# sourceMappingURL=chunk-
|
|
5401
|
+
//# sourceMappingURL=chunk-OMFUE4AQ.cjs.map
|
|
5402
|
+
//# sourceMappingURL=chunk-OMFUE4AQ.cjs.map
|