@pixerate/editor 0.47.0 → 0.49.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/agent/index.cjs +248 -29
- package/dist/agent/index.cjs.map +1 -1
- package/dist/agent/index.d.cts +18 -6
- package/dist/agent/index.d.ts +18 -6
- package/dist/agent/index.js +228 -9
- package/dist/agent/index.js.map +1 -1
- package/dist/{builtins-xs7rK6ys.d.cts → builtins-1kqwLUnb.d.cts} +1 -1
- package/dist/{builtins-D2nMtw2W.d.ts → builtins-BKYlHH1s.d.ts} +1 -1
- package/dist/chart/index.cjs +216 -3541
- package/dist/chart/index.cjs.map +1 -1
- package/dist/chart/index.d.cts +4 -494
- package/dist/chart/index.d.ts +4 -494
- package/dist/chart/index.js +155 -3480
- package/dist/chart/index.js.map +1 -1
- package/dist/{chunk-5VXI5GED.js → chunk-2CJ3LPYQ.js} +3 -3
- package/dist/{chunk-TXXNBDQX.cjs → chunk-2Q46FKZK.cjs} +113 -34
- package/dist/chunk-2Q46FKZK.cjs.map +1 -0
- package/dist/chunk-3JNRQVTS.cjs +521 -0
- package/dist/chunk-3JNRQVTS.cjs.map +1 -0
- package/dist/chunk-5TWIN7ZJ.js +113 -0
- package/dist/chunk-5TWIN7ZJ.js.map +1 -0
- package/dist/{chunk-PQFAHT5O.js → chunk-DQPBQXKG.js} +27 -94
- package/dist/chunk-DQPBQXKG.js.map +1 -0
- package/dist/{chunk-ZFBBVGCI.js → chunk-EKYHKQPG.js} +243 -243
- package/dist/{chunk-ZFBBVGCI.js.map → chunk-EKYHKQPG.js.map} +1 -1
- package/dist/{chunk-J3R2OWOE.cjs → chunk-FEMIVHN3.cjs} +610 -15
- package/dist/chunk-FEMIVHN3.cjs.map +1 -0
- package/dist/{chunk-C3NWJE3K.js → chunk-GJBIVWB2.js} +11 -672
- package/dist/chunk-GJBIVWB2.js.map +1 -0
- package/dist/chunk-GTZXF4BI.cjs +3424 -0
- package/dist/chunk-GTZXF4BI.cjs.map +1 -0
- package/dist/chunk-JOX6MJW4.cjs +674 -0
- package/dist/chunk-JOX6MJW4.cjs.map +1 -0
- package/dist/{chunk-REAGGLXS.js → chunk-JQ3BB3E6.js} +2 -2
- package/dist/{chunk-H4PICYNL.cjs → chunk-LNKZPIQD.cjs} +113 -180
- package/dist/chunk-LNKZPIQD.cjs.map +1 -0
- package/dist/chunk-OV7UAKIY.js +674 -0
- package/dist/chunk-OV7UAKIY.js.map +1 -0
- package/dist/{chunk-TK2XZK6Z.js → chunk-QFTVLEVN.js} +596 -1
- package/dist/chunk-QFTVLEVN.js.map +1 -0
- package/dist/{chunk-KRGXUQ2Y.js → chunk-T6XU4B54.js} +82 -3
- package/dist/chunk-T6XU4B54.js.map +1 -0
- package/dist/chunk-TGBCBQFV.cjs +113 -0
- package/dist/chunk-TGBCBQFV.cjs.map +1 -0
- package/dist/{chunk-SQC26VQV.cjs → chunk-UN33YOXW.cjs} +191 -191
- package/dist/{chunk-SQC26VQV.cjs.map → chunk-UN33YOXW.cjs.map} +1 -1
- package/dist/chunk-WBOAXDKD.js +3424 -0
- package/dist/chunk-WBOAXDKD.js.map +1 -0
- package/dist/{chunk-LYGEEDNR.cjs → chunk-XP5IUZUO.cjs} +242 -242
- package/dist/chunk-XP5IUZUO.cjs.map +1 -0
- package/dist/{chunk-BBRK6MOI.cjs → chunk-YU4WQE5M.cjs} +100 -100
- package/dist/{chunk-BBRK6MOI.cjs.map → chunk-YU4WQE5M.cjs.map} +1 -1
- package/dist/commands/index.d.cts +1 -1
- package/dist/commands/index.d.ts +1 -1
- package/dist/controller-ChjCCMLl.d.cts +822 -0
- package/dist/controller-DtbEo3om.d.ts +822 -0
- package/dist/export/index.cjs +4 -2
- package/dist/export/index.cjs.map +1 -1
- package/dist/export/index.d.cts +5 -1
- package/dist/export/index.d.ts +5 -1
- package/dist/export/index.js +3 -1
- package/dist/extensions/index.cjs +33 -4
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.d.cts +4 -2
- package/dist/extensions/index.d.ts +4 -2
- package/dist/extensions/index.js +32 -3
- package/dist/{index-QrqMmZ75.d.cts → index-DoHqT1mq.d.cts} +203 -7
- package/dist/{index-CSUCQYAH.d.ts → index-YLZ0fKqE.d.ts} +203 -7
- package/dist/index.cjs +39 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -7
- package/dist/index.d.ts +9 -7
- package/dist/index.js +33 -7
- package/dist/index.js.map +1 -1
- package/dist/spreadsheet/index.cjs +4 -4
- package/dist/spreadsheet/index.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-C3NWJE3K.js.map +0 -1
- package/dist/chunk-H4PICYNL.cjs.map +0 -1
- package/dist/chunk-J3R2OWOE.cjs.map +0 -1
- package/dist/chunk-KRGXUQ2Y.js.map +0 -1
- package/dist/chunk-LYGEEDNR.cjs.map +0 -1
- package/dist/chunk-NEOO6QJD.cjs +0 -1182
- package/dist/chunk-NEOO6QJD.cjs.map +0 -1
- package/dist/chunk-PQFAHT5O.js.map +0 -1
- package/dist/chunk-TK2XZK6Z.js.map +0 -1
- package/dist/chunk-TXXNBDQX.cjs.map +0 -1
- package/dist/types-BVqWm3d1.d.cts +0 -320
- package/dist/types-BVqWm3d1.d.ts +0 -320
- /package/dist/{chunk-5VXI5GED.js.map → chunk-2CJ3LPYQ.js.map} +0 -0
- /package/dist/{chunk-REAGGLXS.js.map → chunk-JQ3BB3E6.js.map} +0 -0
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ChartController,
|
|
3
|
+
chartFromMermaid,
|
|
4
|
+
chartSceneToDomSpec,
|
|
5
|
+
chartToMermaid,
|
|
6
|
+
describeChart,
|
|
7
|
+
layoutChart,
|
|
8
|
+
layoutSparkline
|
|
9
|
+
} from "./chunk-WBOAXDKD.js";
|
|
10
|
+
import {
|
|
11
|
+
DEFAULT_CHART_THEME,
|
|
12
|
+
normalizeChartSpec
|
|
13
|
+
} from "./chunk-OV7UAKIY.js";
|
|
1
14
|
import {
|
|
2
15
|
isTrackChangesEnabled
|
|
3
16
|
} from "./chunk-SWE3NPOU.js";
|
|
@@ -1174,6 +1187,570 @@ function createTableExtensions(options = {}) {
|
|
|
1174
1187
|
];
|
|
1175
1188
|
}
|
|
1176
1189
|
|
|
1190
|
+
// src/extensions/chart/node-view.ts
|
|
1191
|
+
import { DOMSerializer } from "@tiptap/pm/model";
|
|
1192
|
+
import { NodeSelection } from "@tiptap/pm/state";
|
|
1193
|
+
var specKey = (spec) => JSON.stringify(spec);
|
|
1194
|
+
var ChartNodeView = class {
|
|
1195
|
+
constructor(props, mount, renderStatic) {
|
|
1196
|
+
this.renderStatic = renderStatic;
|
|
1197
|
+
this.editor = props.editor;
|
|
1198
|
+
this.node = props.node;
|
|
1199
|
+
this.getPos = typeof props.getPos === "function" ? props.getPos : () => void 0;
|
|
1200
|
+
this.editable = this.editor.isEditable;
|
|
1201
|
+
this.dom = document.createElement("div");
|
|
1202
|
+
this.dom.className = "pixerate-chart-node";
|
|
1203
|
+
this.dom.setAttribute("data-type", "chart");
|
|
1204
|
+
this.dom.contentEditable = "false";
|
|
1205
|
+
this.syncAttributes();
|
|
1206
|
+
this.key = specKey(this.node.attrs.spec);
|
|
1207
|
+
this.controller = new ChartController({ spec: this.node.attrs.spec });
|
|
1208
|
+
this.unsubscribe = this.controller.subscribe((state) => {
|
|
1209
|
+
if (!state.gesture) this.writeBack();
|
|
1210
|
+
});
|
|
1211
|
+
this.editor.on("update", this.onEditorUpdate);
|
|
1212
|
+
this.renderer = mount ? mount(this.dom, this.viewState()) : null;
|
|
1213
|
+
if (!mount) this.drawStatic();
|
|
1214
|
+
}
|
|
1215
|
+
renderStatic;
|
|
1216
|
+
dom;
|
|
1217
|
+
node;
|
|
1218
|
+
editor;
|
|
1219
|
+
getPos;
|
|
1220
|
+
controller;
|
|
1221
|
+
renderer;
|
|
1222
|
+
unsubscribe;
|
|
1223
|
+
editing = false;
|
|
1224
|
+
selected = false;
|
|
1225
|
+
editable;
|
|
1226
|
+
key;
|
|
1227
|
+
viewState() {
|
|
1228
|
+
return {
|
|
1229
|
+
id: this.node.attrs.id ?? null,
|
|
1230
|
+
controller: this.controller,
|
|
1231
|
+
width: this.node.attrs.width ?? null,
|
|
1232
|
+
height: this.node.attrs.height,
|
|
1233
|
+
editable: this.editable,
|
|
1234
|
+
selected: this.selected,
|
|
1235
|
+
editing: this.editing,
|
|
1236
|
+
setEditing: this.setEditing,
|
|
1237
|
+
setSize: this.setSize
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1240
|
+
render() {
|
|
1241
|
+
if (this.renderer) this.renderer.update(this.viewState());
|
|
1242
|
+
else this.drawStatic();
|
|
1243
|
+
this.dom.toggleAttribute("data-editing", this.editing);
|
|
1244
|
+
}
|
|
1245
|
+
drawStatic() {
|
|
1246
|
+
const { dom } = DOMSerializer.renderSpec(document, this.renderStatic(this.node));
|
|
1247
|
+
this.dom.replaceChildren(dom);
|
|
1248
|
+
}
|
|
1249
|
+
syncAttributes() {
|
|
1250
|
+
if (this.node.attrs.id) this.dom.setAttribute("data-chart-id", this.node.attrs.id);
|
|
1251
|
+
else this.dom.removeAttribute("data-chart-id");
|
|
1252
|
+
}
|
|
1253
|
+
onEditorUpdate = () => {
|
|
1254
|
+
if (this.editor.isEditable === this.editable) return;
|
|
1255
|
+
this.editable = this.editor.isEditable;
|
|
1256
|
+
if (!this.editable) this.editing = false;
|
|
1257
|
+
this.render();
|
|
1258
|
+
};
|
|
1259
|
+
/** Writes the controller's spec into the node, if it changed. */
|
|
1260
|
+
writeBack() {
|
|
1261
|
+
const spec = this.controller.toJSON();
|
|
1262
|
+
const key = specKey(spec);
|
|
1263
|
+
if (key === this.key) return;
|
|
1264
|
+
const pos = this.getPos();
|
|
1265
|
+
if (typeof pos !== "number" || this.editor.isDestroyed) return;
|
|
1266
|
+
this.key = key;
|
|
1267
|
+
this.editor.view.dispatch(this.editor.state.tr.setNodeMarkup(pos, void 0, { ...this.node.attrs, spec }));
|
|
1268
|
+
}
|
|
1269
|
+
setEditing = (editing) => {
|
|
1270
|
+
if (editing && !this.editor.isEditable) return;
|
|
1271
|
+
if (editing && !this.selected) {
|
|
1272
|
+
const pos = this.getPos();
|
|
1273
|
+
if (typeof pos === "number") {
|
|
1274
|
+
this.editor.view.dispatch(this.editor.state.tr.setSelection(NodeSelection.create(this.editor.state.doc, pos)));
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
if (this.editing === editing) return;
|
|
1278
|
+
this.editing = editing;
|
|
1279
|
+
this.render();
|
|
1280
|
+
};
|
|
1281
|
+
setSize = (size) => {
|
|
1282
|
+
const pos = this.getPos();
|
|
1283
|
+
if (typeof pos !== "number" || !this.editor.isEditable) return;
|
|
1284
|
+
this.editor.view.dispatch(this.editor.state.tr.setNodeMarkup(pos, void 0, { ...this.node.attrs, ...size }));
|
|
1285
|
+
};
|
|
1286
|
+
update(node) {
|
|
1287
|
+
if (node.type !== this.node.type) return false;
|
|
1288
|
+
this.node = node;
|
|
1289
|
+
this.syncAttributes();
|
|
1290
|
+
const key = specKey(node.attrs.spec);
|
|
1291
|
+
if (key !== this.key) {
|
|
1292
|
+
this.key = key;
|
|
1293
|
+
if (specKey(this.controller.toJSON()) !== key) this.controller.load(node.attrs.spec, { clearHistory: true });
|
|
1294
|
+
}
|
|
1295
|
+
this.render();
|
|
1296
|
+
return true;
|
|
1297
|
+
}
|
|
1298
|
+
selectNode() {
|
|
1299
|
+
this.selected = true;
|
|
1300
|
+
this.dom.classList.add("ProseMirror-selectednode");
|
|
1301
|
+
this.render();
|
|
1302
|
+
}
|
|
1303
|
+
deselectNode() {
|
|
1304
|
+
this.selected = false;
|
|
1305
|
+
this.editing = false;
|
|
1306
|
+
this.dom.classList.remove("ProseMirror-selectednode");
|
|
1307
|
+
this.render();
|
|
1308
|
+
}
|
|
1309
|
+
/** The inspector's inputs, buttons and chart gestures keep their events while it is open. */
|
|
1310
|
+
stopEvent(event) {
|
|
1311
|
+
if (!this.editing) return false;
|
|
1312
|
+
return !(event.type === "dragstart" && event.target === this.dom);
|
|
1313
|
+
}
|
|
1314
|
+
ignoreMutation() {
|
|
1315
|
+
return true;
|
|
1316
|
+
}
|
|
1317
|
+
destroy() {
|
|
1318
|
+
this.editor.off("update", this.onEditorUpdate);
|
|
1319
|
+
this.unsubscribe();
|
|
1320
|
+
this.renderer?.destroy();
|
|
1321
|
+
this.controller.destroy();
|
|
1322
|
+
}
|
|
1323
|
+
};
|
|
1324
|
+
function createChartNodeView(mount, renderStatic) {
|
|
1325
|
+
return (props) => new ChartNodeView(props, mount, renderStatic);
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
// src/extensions/chart/chart-node.ts
|
|
1329
|
+
import { Node, mergeAttributes } from "@tiptap/core";
|
|
1330
|
+
import { Plugin as Plugin2, PluginKey as PluginKey2 } from "@tiptap/pm/state";
|
|
1331
|
+
|
|
1332
|
+
// src/extensions/document-structure/utils.ts
|
|
1333
|
+
import { createDocument } from "@tiptap/core";
|
|
1334
|
+
import { EditorState } from "@tiptap/pm/state";
|
|
1335
|
+
import { ReplaceAroundStep, ReplaceStep } from "@tiptap/pm/transform";
|
|
1336
|
+
var idCounter = 0;
|
|
1337
|
+
function generateStructureId(prefix) {
|
|
1338
|
+
idCounter = (idCounter + 1) % 1296;
|
|
1339
|
+
const random = Math.random().toString(36).slice(2, 8).padEnd(6, "0");
|
|
1340
|
+
return `${prefix}-${random}${idCounter.toString(36).padStart(2, "0")}`;
|
|
1341
|
+
}
|
|
1342
|
+
function transactionsInsert(transactions, typeNames) {
|
|
1343
|
+
for (const tr of transactions) {
|
|
1344
|
+
for (const step of tr.steps) {
|
|
1345
|
+
if (!(step instanceof ReplaceStep || step instanceof ReplaceAroundStep)) {
|
|
1346
|
+
const mark = step.mark;
|
|
1347
|
+
if (mark && typeNames.includes(mark.type.name)) return true;
|
|
1348
|
+
continue;
|
|
1349
|
+
}
|
|
1350
|
+
let found = false;
|
|
1351
|
+
step.slice.content.descendants((node) => {
|
|
1352
|
+
if (found) return false;
|
|
1353
|
+
if (typeNames.includes(node.type.name) || node.marks.some((m) => typeNames.includes(m.type.name))) {
|
|
1354
|
+
found = true;
|
|
1355
|
+
}
|
|
1356
|
+
return !found;
|
|
1357
|
+
});
|
|
1358
|
+
if (found) return true;
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
return false;
|
|
1362
|
+
}
|
|
1363
|
+
function docContains(doc, typeNames) {
|
|
1364
|
+
let found = false;
|
|
1365
|
+
doc.descendants((node) => {
|
|
1366
|
+
if (found) return false;
|
|
1367
|
+
if (typeNames.includes(node.type.name) || node.marks.some((m) => typeNames.includes(m.type.name))) {
|
|
1368
|
+
found = true;
|
|
1369
|
+
}
|
|
1370
|
+
return !found;
|
|
1371
|
+
});
|
|
1372
|
+
return found;
|
|
1373
|
+
}
|
|
1374
|
+
function presenceStateSpec(typeNames) {
|
|
1375
|
+
return {
|
|
1376
|
+
init: (_config, state) => docContains(state.doc, typeNames),
|
|
1377
|
+
apply: (tr, present, _oldState, newState) => {
|
|
1378
|
+
if (!tr.docChanged) return present;
|
|
1379
|
+
if (!present && !transactionsInsert([tr], typeNames)) return false;
|
|
1380
|
+
return docContains(newState.doc, typeNames);
|
|
1381
|
+
}
|
|
1382
|
+
};
|
|
1383
|
+
}
|
|
1384
|
+
function arraysEqual(a, b, eq) {
|
|
1385
|
+
if (a.length !== b.length) return false;
|
|
1386
|
+
for (let i = 0; i < a.length; i++) {
|
|
1387
|
+
if (!eq(a[i], b[i])) return false;
|
|
1388
|
+
}
|
|
1389
|
+
return true;
|
|
1390
|
+
}
|
|
1391
|
+
function scrollDomAtPos(view, pos, behavior = "smooth") {
|
|
1392
|
+
try {
|
|
1393
|
+
const dom = view?.nodeDOM?.(pos);
|
|
1394
|
+
if (dom && typeof dom.scrollIntoView === "function") {
|
|
1395
|
+
dom.scrollIntoView({ block: "start", behavior });
|
|
1396
|
+
}
|
|
1397
|
+
} catch {
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
function syncInitialContent(editor, sync) {
|
|
1401
|
+
const { content } = editor.options;
|
|
1402
|
+
if (content == null || content === "") return;
|
|
1403
|
+
try {
|
|
1404
|
+
const doc = createDocument(content, editor.schema, editor.options.parseOptions, {
|
|
1405
|
+
errorOnInvalidContent: false
|
|
1406
|
+
});
|
|
1407
|
+
const tr = sync(EditorState.create({ doc }));
|
|
1408
|
+
if (tr?.docChanged) editor.options.content = tr.doc;
|
|
1409
|
+
} catch {
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
var STRUCTURE_PRIORITY = 45;
|
|
1413
|
+
|
|
1414
|
+
// src/extensions/chart/chart-node.ts
|
|
1415
|
+
var chartPluginKey = new PluginKey2("chartNode");
|
|
1416
|
+
function getDocumentCharts(doc, typeName = "chart") {
|
|
1417
|
+
const charts = [];
|
|
1418
|
+
doc.descendants((node, pos) => {
|
|
1419
|
+
if (node.type.name === typeName) {
|
|
1420
|
+
charts.push({ id: node.attrs.id ?? null, pos, node, spec: node.attrs.spec });
|
|
1421
|
+
return false;
|
|
1422
|
+
}
|
|
1423
|
+
return !node.isTextblock;
|
|
1424
|
+
});
|
|
1425
|
+
return charts;
|
|
1426
|
+
}
|
|
1427
|
+
function isChartEnabled(editor) {
|
|
1428
|
+
return !!editor?.schema?.nodes?.chart;
|
|
1429
|
+
}
|
|
1430
|
+
function readSpec(value) {
|
|
1431
|
+
let input = value;
|
|
1432
|
+
if (typeof value === "string") {
|
|
1433
|
+
try {
|
|
1434
|
+
input = JSON.parse(value);
|
|
1435
|
+
} catch {
|
|
1436
|
+
return null;
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) return null;
|
|
1440
|
+
return normalizeChartSpec(input).spec;
|
|
1441
|
+
}
|
|
1442
|
+
var readSize = (value) => {
|
|
1443
|
+
const n = value === null ? NaN : Number(value);
|
|
1444
|
+
return Number.isFinite(n) && n >= 50 && n <= 4096 ? n : null;
|
|
1445
|
+
};
|
|
1446
|
+
function syncChartIds(state, typeName, generateId) {
|
|
1447
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1448
|
+
let tr = null;
|
|
1449
|
+
for (const chart of getDocumentCharts(state.doc, typeName)) {
|
|
1450
|
+
if (chart.id && !seen.has(chart.id)) {
|
|
1451
|
+
seen.add(chart.id);
|
|
1452
|
+
continue;
|
|
1453
|
+
}
|
|
1454
|
+
let id = generateId();
|
|
1455
|
+
while (seen.has(id)) id = generateId();
|
|
1456
|
+
seen.add(id);
|
|
1457
|
+
tr = tr ?? state.tr;
|
|
1458
|
+
tr.setNodeMarkup(chart.pos, void 0, { ...chart.node.attrs, id });
|
|
1459
|
+
}
|
|
1460
|
+
return tr?.setMeta("addToHistory", false) ?? null;
|
|
1461
|
+
}
|
|
1462
|
+
function staticChartSvg(node, options) {
|
|
1463
|
+
const spec = node.attrs.spec;
|
|
1464
|
+
const width = node.attrs.width ?? options.defaultWidth;
|
|
1465
|
+
const height = node.attrs.height ?? options.defaultHeight;
|
|
1466
|
+
const scene = layoutChart(spec, { width, height, theme: options.theme, selection: null });
|
|
1467
|
+
return chartSceneToDomSpec(scene, {
|
|
1468
|
+
ariaLabel: spec.title || "Chart",
|
|
1469
|
+
description: describeChart(spec),
|
|
1470
|
+
attrs: { style: "max-width: 100%; height: auto; display: block" }
|
|
1471
|
+
});
|
|
1472
|
+
}
|
|
1473
|
+
var longestBacktickRun = (text) => Math.max(0, ...Array.from(text.matchAll(/`+/g), (m) => m[0].length));
|
|
1474
|
+
var Chart = Node.create({
|
|
1475
|
+
name: "chart",
|
|
1476
|
+
priority: STRUCTURE_PRIORITY,
|
|
1477
|
+
group: "block",
|
|
1478
|
+
atom: true,
|
|
1479
|
+
selectable: true,
|
|
1480
|
+
draggable: true,
|
|
1481
|
+
addOptions() {
|
|
1482
|
+
return {
|
|
1483
|
+
HTMLAttributes: {},
|
|
1484
|
+
nodeView: null,
|
|
1485
|
+
theme: DEFAULT_CHART_THEME,
|
|
1486
|
+
defaultWidth: 640,
|
|
1487
|
+
defaultHeight: 320,
|
|
1488
|
+
generateId: () => generateStructureId("chart")
|
|
1489
|
+
};
|
|
1490
|
+
},
|
|
1491
|
+
addAttributes() {
|
|
1492
|
+
return {
|
|
1493
|
+
id: {
|
|
1494
|
+
default: null,
|
|
1495
|
+
parseHTML: (element) => element.getAttribute("data-chart-id") || null,
|
|
1496
|
+
renderHTML: (attributes) => attributes.id ? { "data-chart-id": attributes.id } : {}
|
|
1497
|
+
},
|
|
1498
|
+
spec: {
|
|
1499
|
+
default: normalizeChartSpec({}).spec,
|
|
1500
|
+
// null (no `data-chart`) keeps what the parse rule found, e.g. a mermaid block's spec.
|
|
1501
|
+
parseHTML: (element) => readSpec(element.getAttribute("data-chart")),
|
|
1502
|
+
renderHTML: (attributes) => ({
|
|
1503
|
+
"data-chart": JSON.stringify(attributes.spec)
|
|
1504
|
+
})
|
|
1505
|
+
},
|
|
1506
|
+
width: {
|
|
1507
|
+
default: null,
|
|
1508
|
+
parseHTML: (element) => readSize(element.getAttribute("data-width")),
|
|
1509
|
+
renderHTML: (attributes) => attributes.width ? { "data-width": String(attributes.width) } : {}
|
|
1510
|
+
},
|
|
1511
|
+
height: {
|
|
1512
|
+
default: this.options.defaultHeight,
|
|
1513
|
+
parseHTML: (element) => readSize(element.getAttribute("data-height")),
|
|
1514
|
+
renderHTML: (attributes) => ({
|
|
1515
|
+
"data-height": String(attributes.height)
|
|
1516
|
+
})
|
|
1517
|
+
}
|
|
1518
|
+
};
|
|
1519
|
+
},
|
|
1520
|
+
parseHTML() {
|
|
1521
|
+
return [
|
|
1522
|
+
{
|
|
1523
|
+
tag: 'div[data-type="chart"]',
|
|
1524
|
+
priority: 60,
|
|
1525
|
+
// A missing or broken spec falls through, so the fallback content inside (e.g. a
|
|
1526
|
+
// DOCX import's caption and data table) is kept instead.
|
|
1527
|
+
getAttrs: (element) => readSpec(element.getAttribute("data-chart")) ? null : false
|
|
1528
|
+
},
|
|
1529
|
+
{
|
|
1530
|
+
// ```mermaid blocks (from markdown) that hold a chart; other diagrams stay code.
|
|
1531
|
+
tag: "pre",
|
|
1532
|
+
priority: 60,
|
|
1533
|
+
getAttrs: (element) => {
|
|
1534
|
+
const code = element.querySelector("code");
|
|
1535
|
+
const language = code?.getAttribute("class") ?? element.getAttribute("data-language") ?? "";
|
|
1536
|
+
if (!/(?:^|\s)language-mermaid(?:\s|$)/.test(language) && language !== "mermaid") return false;
|
|
1537
|
+
const result = chartFromMermaid((code ?? element).textContent ?? "");
|
|
1538
|
+
return result.family ? { spec: result.spec } : false;
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
];
|
|
1542
|
+
},
|
|
1543
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
1544
|
+
const svg = staticChartSvg(node, this.options);
|
|
1545
|
+
return [
|
|
1546
|
+
"div",
|
|
1547
|
+
mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {
|
|
1548
|
+
"data-type": "chart",
|
|
1549
|
+
class: "pixerate-chart"
|
|
1550
|
+
}),
|
|
1551
|
+
svg
|
|
1552
|
+
];
|
|
1553
|
+
},
|
|
1554
|
+
renderText({ node }) {
|
|
1555
|
+
return `[Chart: ${node.attrs.spec?.title || "untitled"}]`;
|
|
1556
|
+
},
|
|
1557
|
+
addStorage() {
|
|
1558
|
+
return {
|
|
1559
|
+
markdown: {
|
|
1560
|
+
serialize(state, node) {
|
|
1561
|
+
const text = chartToMermaid(node.attrs.spec);
|
|
1562
|
+
const fence = "`".repeat(Math.max(3, longestBacktickRun(text) + 1));
|
|
1563
|
+
state.write(`${fence}mermaid
|
|
1564
|
+
`);
|
|
1565
|
+
state.text(text, false);
|
|
1566
|
+
state.ensureNewLine();
|
|
1567
|
+
state.write(fence);
|
|
1568
|
+
state.closeBlock(node);
|
|
1569
|
+
},
|
|
1570
|
+
parse: {
|
|
1571
|
+
// markdown-it renders ```mermaid as <pre><code class="language-mermaid">, which
|
|
1572
|
+
// `parseHTML` reads.
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
};
|
|
1576
|
+
},
|
|
1577
|
+
addCommands() {
|
|
1578
|
+
return {
|
|
1579
|
+
insertChart: (options) => ({ commands }) => commands.insertContent({
|
|
1580
|
+
type: this.name,
|
|
1581
|
+
attrs: {
|
|
1582
|
+
id: options.id ?? this.options.generateId(),
|
|
1583
|
+
spec: normalizeChartSpec(options.spec ?? {}).spec,
|
|
1584
|
+
width: options.width ?? null,
|
|
1585
|
+
height: options.height ?? this.options.defaultHeight
|
|
1586
|
+
}
|
|
1587
|
+
}),
|
|
1588
|
+
updateChart: (id, changes) => ({ state, tr, dispatch }) => {
|
|
1589
|
+
const chart = getDocumentCharts(state.doc, this.name).find((c) => c.id === id);
|
|
1590
|
+
if (!chart) return false;
|
|
1591
|
+
if (dispatch) {
|
|
1592
|
+
tr.setNodeMarkup(chart.pos, void 0, {
|
|
1593
|
+
...chart.node.attrs,
|
|
1594
|
+
...changes.spec !== void 0 ? { spec: normalizeChartSpec(changes.spec).spec } : {},
|
|
1595
|
+
...changes.width !== void 0 ? { width: changes.width } : {},
|
|
1596
|
+
...changes.height !== void 0 ? { height: changes.height } : {}
|
|
1597
|
+
});
|
|
1598
|
+
}
|
|
1599
|
+
return true;
|
|
1600
|
+
}
|
|
1601
|
+
};
|
|
1602
|
+
},
|
|
1603
|
+
addNodeView() {
|
|
1604
|
+
return createChartNodeView(this.options.nodeView, (node) => staticChartSvg(node, this.options));
|
|
1605
|
+
},
|
|
1606
|
+
addProseMirrorPlugins() {
|
|
1607
|
+
const { name } = this;
|
|
1608
|
+
const { generateId } = this.options;
|
|
1609
|
+
return [
|
|
1610
|
+
new Plugin2({
|
|
1611
|
+
key: chartPluginKey,
|
|
1612
|
+
appendTransaction: (transactions, _oldState, newState) => {
|
|
1613
|
+
if (!transactions.some((tr) => tr.docChanged)) return null;
|
|
1614
|
+
if (!transactionsInsert(transactions, [name])) return null;
|
|
1615
|
+
return syncChartIds(newState, name, generateId);
|
|
1616
|
+
}
|
|
1617
|
+
})
|
|
1618
|
+
];
|
|
1619
|
+
},
|
|
1620
|
+
onBeforeCreate() {
|
|
1621
|
+
const { generateId } = this.options;
|
|
1622
|
+
syncInitialContent(this.editor, (state) => syncChartIds(state, this.name, generateId));
|
|
1623
|
+
}
|
|
1624
|
+
});
|
|
1625
|
+
|
|
1626
|
+
// src/extensions/chart/sparkline-node.ts
|
|
1627
|
+
import { Node as Node2, mergeAttributes as mergeAttributes2 } from "@tiptap/core";
|
|
1628
|
+
var SPARKLINE_KINDS = ["line", "column", "win-loss"];
|
|
1629
|
+
var MAX_SPARKLINE_VALUES = 1e3;
|
|
1630
|
+
function normalizeSparklineValues(values) {
|
|
1631
|
+
if (!Array.isArray(values)) return [];
|
|
1632
|
+
return values.slice(0, MAX_SPARKLINE_VALUES).map((v) => typeof v === "number" && Number.isFinite(v) ? v : null);
|
|
1633
|
+
}
|
|
1634
|
+
function readValues(text) {
|
|
1635
|
+
if (!text) return [];
|
|
1636
|
+
try {
|
|
1637
|
+
return normalizeSparklineValues(JSON.parse(text));
|
|
1638
|
+
} catch {
|
|
1639
|
+
return normalizeSparklineValues(text.split(/[\s,]+/).filter(Boolean).map(Number));
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
var readNumber = (text, fallback, max) => {
|
|
1643
|
+
const n = text === null ? NaN : Number(text);
|
|
1644
|
+
return Number.isFinite(n) && n >= 4 && n <= max ? n : fallback;
|
|
1645
|
+
};
|
|
1646
|
+
function sparklineLabel(node) {
|
|
1647
|
+
if (node.attrs.label) return node.attrs.label;
|
|
1648
|
+
const present = node.attrs.values.filter((v) => v !== null);
|
|
1649
|
+
return present.length ? `Trend from ${present[0]} to ${present[present.length - 1]}` : "No data";
|
|
1650
|
+
}
|
|
1651
|
+
var Sparkline = Node2.create({
|
|
1652
|
+
name: "sparkline",
|
|
1653
|
+
group: "inline",
|
|
1654
|
+
inline: true,
|
|
1655
|
+
atom: true,
|
|
1656
|
+
selectable: true,
|
|
1657
|
+
addOptions() {
|
|
1658
|
+
return { HTMLAttributes: {}, color: "#4269d0", negativeColor: "#e5484d" };
|
|
1659
|
+
},
|
|
1660
|
+
addAttributes() {
|
|
1661
|
+
return {
|
|
1662
|
+
values: {
|
|
1663
|
+
default: [],
|
|
1664
|
+
parseHTML: (element) => readValues(element.getAttribute("data-values")),
|
|
1665
|
+
renderHTML: (attributes) => ({ "data-values": JSON.stringify(attributes.values ?? []) })
|
|
1666
|
+
},
|
|
1667
|
+
kind: {
|
|
1668
|
+
default: "line",
|
|
1669
|
+
parseHTML: (element) => {
|
|
1670
|
+
const kind = element.getAttribute("data-kind");
|
|
1671
|
+
return SPARKLINE_KINDS.includes(kind) ? kind : "line";
|
|
1672
|
+
},
|
|
1673
|
+
renderHTML: (attributes) => ({ "data-kind": attributes.kind })
|
|
1674
|
+
},
|
|
1675
|
+
width: {
|
|
1676
|
+
default: 80,
|
|
1677
|
+
parseHTML: (element) => readNumber(element.getAttribute("data-width"), 80, 1e3),
|
|
1678
|
+
renderHTML: (attributes) => ({ "data-width": String(attributes.width) })
|
|
1679
|
+
},
|
|
1680
|
+
height: {
|
|
1681
|
+
default: 18,
|
|
1682
|
+
parseHTML: (element) => readNumber(element.getAttribute("data-height"), 18, 200),
|
|
1683
|
+
renderHTML: (attributes) => ({ "data-height": String(attributes.height) })
|
|
1684
|
+
},
|
|
1685
|
+
color: {
|
|
1686
|
+
default: null,
|
|
1687
|
+
parseHTML: (element) => element.getAttribute("data-color") || null,
|
|
1688
|
+
renderHTML: (attributes) => attributes.color ? { "data-color": attributes.color } : {}
|
|
1689
|
+
},
|
|
1690
|
+
label: {
|
|
1691
|
+
default: null,
|
|
1692
|
+
parseHTML: (element) => element.getAttribute("data-label") || null,
|
|
1693
|
+
renderHTML: (attributes) => attributes.label ? { "data-label": attributes.label } : {}
|
|
1694
|
+
}
|
|
1695
|
+
};
|
|
1696
|
+
},
|
|
1697
|
+
parseHTML() {
|
|
1698
|
+
return [{ tag: 'span[data-type="sparkline"]', priority: 60 }];
|
|
1699
|
+
},
|
|
1700
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
1701
|
+
const scene = layoutSparkline(node.attrs.values, {
|
|
1702
|
+
kind: node.attrs.kind,
|
|
1703
|
+
width: node.attrs.width,
|
|
1704
|
+
height: node.attrs.height,
|
|
1705
|
+
color: node.attrs.color ?? this.options.color,
|
|
1706
|
+
negativeColor: this.options.negativeColor
|
|
1707
|
+
});
|
|
1708
|
+
const svg = chartSceneToDomSpec(scene, {
|
|
1709
|
+
ariaLabel: sparklineLabel(node),
|
|
1710
|
+
attrs: { style: "display: inline-block; vertical-align: middle" }
|
|
1711
|
+
});
|
|
1712
|
+
return [
|
|
1713
|
+
"span",
|
|
1714
|
+
mergeAttributes2(this.options.HTMLAttributes, HTMLAttributes, {
|
|
1715
|
+
"data-type": "sparkline",
|
|
1716
|
+
class: "pixerate-sparkline"
|
|
1717
|
+
}),
|
|
1718
|
+
svg
|
|
1719
|
+
];
|
|
1720
|
+
},
|
|
1721
|
+
renderText({ node }) {
|
|
1722
|
+
return `[${sparklineLabel(node)}]`;
|
|
1723
|
+
},
|
|
1724
|
+
addStorage() {
|
|
1725
|
+
return {
|
|
1726
|
+
markdown: {
|
|
1727
|
+
serialize(state, node) {
|
|
1728
|
+
const attr = (name, value) => value === null || value === void 0 ? "" : ` ${name}="${String(value).replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<")}"`;
|
|
1729
|
+
state.write(
|
|
1730
|
+
`<span data-type="sparkline"${attr("data-values", JSON.stringify(node.attrs.values))}${attr("data-kind", node.attrs.kind)}${attr("data-width", node.attrs.width)}${attr("data-height", node.attrs.height)}${attr("data-color", node.attrs.color)}${attr("data-label", node.attrs.label)}></span>`
|
|
1731
|
+
);
|
|
1732
|
+
},
|
|
1733
|
+
parse: {}
|
|
1734
|
+
}
|
|
1735
|
+
};
|
|
1736
|
+
},
|
|
1737
|
+
addCommands() {
|
|
1738
|
+
return {
|
|
1739
|
+
insertSparkline: (options) => ({ commands }) => commands.insertContent({
|
|
1740
|
+
type: this.name,
|
|
1741
|
+
attrs: {
|
|
1742
|
+
values: normalizeSparklineValues(options.values),
|
|
1743
|
+
kind: options.kind && SPARKLINE_KINDS.includes(options.kind) ? options.kind : "line",
|
|
1744
|
+
width: options.width ?? 80,
|
|
1745
|
+
height: options.height ?? 18,
|
|
1746
|
+
color: options.color ?? null,
|
|
1747
|
+
label: options.label ?? null
|
|
1748
|
+
}
|
|
1749
|
+
})
|
|
1750
|
+
};
|
|
1751
|
+
}
|
|
1752
|
+
});
|
|
1753
|
+
|
|
1177
1754
|
// src/extensions/table/actions.ts
|
|
1178
1755
|
import { CellSelection as CellSelection2, isInTable, selectedRect } from "@tiptap/pm/tables";
|
|
1179
1756
|
var TABLE_ACTIONS = [
|
|
@@ -1430,6 +2007,12 @@ export {
|
|
|
1430
2007
|
handleTablePasteWithoutNesting,
|
|
1431
2008
|
unnestTables,
|
|
1432
2009
|
createTableNestingPlugin,
|
|
2010
|
+
generateStructureId,
|
|
2011
|
+
presenceStateSpec,
|
|
2012
|
+
arraysEqual,
|
|
2013
|
+
scrollDomAtPos,
|
|
2014
|
+
syncInitialContent,
|
|
2015
|
+
STRUCTURE_PRIORITY,
|
|
1433
2016
|
FIND_PARAGRAPH_MARK,
|
|
1434
2017
|
MAX_FIND_PATTERN_LENGTH,
|
|
1435
2018
|
createSearchBudget,
|
|
@@ -1449,6 +2032,18 @@ export {
|
|
|
1449
2032
|
TableCell,
|
|
1450
2033
|
TableHeader,
|
|
1451
2034
|
createTableExtensions,
|
|
2035
|
+
ChartNodeView,
|
|
2036
|
+
createChartNodeView,
|
|
2037
|
+
chartPluginKey,
|
|
2038
|
+
getDocumentCharts,
|
|
2039
|
+
isChartEnabled,
|
|
2040
|
+
staticChartSvg,
|
|
2041
|
+
Chart,
|
|
2042
|
+
SPARKLINE_KINDS,
|
|
2043
|
+
MAX_SPARKLINE_VALUES,
|
|
2044
|
+
normalizeSparklineValues,
|
|
2045
|
+
sparklineLabel,
|
|
2046
|
+
Sparkline,
|
|
1452
2047
|
TABLE_ACTIONS,
|
|
1453
2048
|
DEFAULT_TABLE_TOOLBAR,
|
|
1454
2049
|
MAX_TABLE_ROWS,
|
|
@@ -1462,4 +2057,4 @@ export {
|
|
|
1462
2057
|
getTableState,
|
|
1463
2058
|
createTableStore
|
|
1464
2059
|
};
|
|
1465
|
-
//# sourceMappingURL=chunk-
|
|
2060
|
+
//# sourceMappingURL=chunk-QFTVLEVN.js.map
|