@blankdotpage/cake 0.1.1 → 0.1.2
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/cake/clipboard.d.ts +1 -1
- package/dist/cake/core/runtime.d.ts +1 -0
- package/dist/cake/dom/render.d.ts +1 -1
- package/dist/cake/engine/selection/selection-geometry.d.ts +1 -0
- package/dist/index.cjs +803 -246
- package/dist/index.js +803 -246
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,42 +1,51 @@
|
|
|
1
1
|
import require$$0, { useRef, useState, useCallback, useEffect, forwardRef, useImperativeHandle, Fragment } from "react";
|
|
2
|
-
import { createPortal } from "react-dom";
|
|
3
2
|
import { Pencil, ExternalLink, Unlink } from "lucide-react";
|
|
4
3
|
import TurndownService from "turndown";
|
|
5
4
|
import { EditorSelection, Transaction } from "@codemirror/state";
|
|
6
|
-
var
|
|
7
|
-
var
|
|
5
|
+
var jsxRuntime = { exports: {} };
|
|
6
|
+
var reactJsxRuntime_production_min = {};
|
|
8
7
|
/**
|
|
9
8
|
* @license React
|
|
10
|
-
* react-jsx-
|
|
9
|
+
* react-jsx-runtime.production.min.js
|
|
11
10
|
*
|
|
12
11
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
13
12
|
*
|
|
14
13
|
* This source code is licensed under the MIT license found in the
|
|
15
14
|
* LICENSE file in the root directory of this source tree.
|
|
16
15
|
*/
|
|
17
|
-
var
|
|
18
|
-
function
|
|
19
|
-
if (
|
|
20
|
-
|
|
21
|
-
var
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
16
|
+
var hasRequiredReactJsxRuntime_production_min;
|
|
17
|
+
function requireReactJsxRuntime_production_min() {
|
|
18
|
+
if (hasRequiredReactJsxRuntime_production_min) return reactJsxRuntime_production_min;
|
|
19
|
+
hasRequiredReactJsxRuntime_production_min = 1;
|
|
20
|
+
var f = require$$0, k = Symbol.for("react.element"), l = Symbol.for("react.fragment"), m = Object.prototype.hasOwnProperty, n = f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner, p = { key: true, ref: true, __self: true, __source: true };
|
|
21
|
+
function q(c, a, g) {
|
|
22
|
+
var b, d = {}, e = null, h = null;
|
|
23
|
+
void 0 !== g && (e = "" + g);
|
|
24
|
+
void 0 !== a.key && (e = "" + a.key);
|
|
25
|
+
void 0 !== a.ref && (h = a.ref);
|
|
26
|
+
for (b in a) m.call(a, b) && !p.hasOwnProperty(b) && (d[b] = a[b]);
|
|
27
|
+
if (c && c.defaultProps) for (b in a = c.defaultProps, a) void 0 === d[b] && (d[b] = a[b]);
|
|
28
|
+
return { $$typeof: k, type: c, key: e, ref: h, props: d, _owner: n.current };
|
|
29
|
+
}
|
|
30
|
+
reactJsxRuntime_production_min.Fragment = l;
|
|
31
|
+
reactJsxRuntime_production_min.jsx = q;
|
|
32
|
+
reactJsxRuntime_production_min.jsxs = q;
|
|
33
|
+
return reactJsxRuntime_production_min;
|
|
34
|
+
}
|
|
35
|
+
var reactJsxRuntime_development = {};
|
|
27
36
|
/**
|
|
28
37
|
* @license React
|
|
29
|
-
* react-jsx-
|
|
38
|
+
* react-jsx-runtime.development.js
|
|
30
39
|
*
|
|
31
40
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
32
41
|
*
|
|
33
42
|
* This source code is licensed under the MIT license found in the
|
|
34
43
|
* LICENSE file in the root directory of this source tree.
|
|
35
44
|
*/
|
|
36
|
-
var
|
|
37
|
-
function
|
|
38
|
-
if (
|
|
39
|
-
|
|
45
|
+
var hasRequiredReactJsxRuntime_development;
|
|
46
|
+
function requireReactJsxRuntime_development() {
|
|
47
|
+
if (hasRequiredReactJsxRuntime_development) return reactJsxRuntime_development;
|
|
48
|
+
hasRequiredReactJsxRuntime_development = 1;
|
|
40
49
|
if (process.env.NODE_ENV !== "production") {
|
|
41
50
|
(function() {
|
|
42
51
|
var React = require$$0;
|
|
@@ -523,10 +532,6 @@ function requireReactJsxDevRuntime_development() {
|
|
|
523
532
|
};
|
|
524
533
|
var specialPropKeyWarningShown;
|
|
525
534
|
var specialPropRefWarningShown;
|
|
526
|
-
var didWarnAboutStringRefs;
|
|
527
|
-
{
|
|
528
|
-
didWarnAboutStringRefs = {};
|
|
529
|
-
}
|
|
530
535
|
function hasValidRef(config) {
|
|
531
536
|
{
|
|
532
537
|
if (hasOwnProperty.call(config, "ref")) {
|
|
@@ -551,13 +556,7 @@ function requireReactJsxDevRuntime_development() {
|
|
|
551
556
|
}
|
|
552
557
|
function warnIfStringRefCannotBeAutoConverted(config, self) {
|
|
553
558
|
{
|
|
554
|
-
if (typeof config.ref === "string" && ReactCurrentOwner.current && self
|
|
555
|
-
var componentName = getComponentNameFromType(ReactCurrentOwner.current.type);
|
|
556
|
-
if (!didWarnAboutStringRefs[componentName]) {
|
|
557
|
-
error('Component "%s" contains the string ref "%s". Support for string refs will be removed in a future major release. This case cannot be automatically converted to an arrow function. We ask you to manually fix this case by using useRef() or createRef() instead. Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref', getComponentNameFromType(ReactCurrentOwner.current.type), config.ref);
|
|
558
|
-
didWarnAboutStringRefs[componentName] = true;
|
|
559
|
-
}
|
|
560
|
-
}
|
|
559
|
+
if (typeof config.ref === "string" && ReactCurrentOwner.current && self) ;
|
|
561
560
|
}
|
|
562
561
|
}
|
|
563
562
|
function defineKeyPropWarningGetter(props, displayName) {
|
|
@@ -711,11 +710,6 @@ function requireReactJsxDevRuntime_development() {
|
|
|
711
710
|
}
|
|
712
711
|
function getSourceInfoErrorAddendum(source) {
|
|
713
712
|
{
|
|
714
|
-
if (source !== void 0) {
|
|
715
|
-
var fileName = source.fileName.replace(/^.*[\\\/]/, "");
|
|
716
|
-
var lineNumber = source.lineNumber;
|
|
717
|
-
return "\n\nCheck your code at " + fileName + ":" + lineNumber + ".";
|
|
718
|
-
}
|
|
719
713
|
return "";
|
|
720
714
|
}
|
|
721
715
|
}
|
|
@@ -841,7 +835,7 @@ function requireReactJsxDevRuntime_development() {
|
|
|
841
835
|
if (type === void 0 || typeof type === "object" && type !== null && Object.keys(type).length === 0) {
|
|
842
836
|
info += " You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.";
|
|
843
837
|
}
|
|
844
|
-
var sourceInfo = getSourceInfoErrorAddendum(
|
|
838
|
+
var sourceInfo = getSourceInfoErrorAddendum();
|
|
845
839
|
if (sourceInfo) {
|
|
846
840
|
info += sourceInfo;
|
|
847
841
|
} else {
|
|
@@ -905,19 +899,31 @@ function requireReactJsxDevRuntime_development() {
|
|
|
905
899
|
return element;
|
|
906
900
|
}
|
|
907
901
|
}
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
902
|
+
function jsxWithValidationStatic(type, props, key) {
|
|
903
|
+
{
|
|
904
|
+
return jsxWithValidation(type, props, key, true);
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
function jsxWithValidationDynamic(type, props, key) {
|
|
908
|
+
{
|
|
909
|
+
return jsxWithValidation(type, props, key, false);
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
var jsx = jsxWithValidationDynamic;
|
|
913
|
+
var jsxs = jsxWithValidationStatic;
|
|
914
|
+
reactJsxRuntime_development.Fragment = REACT_FRAGMENT_TYPE;
|
|
915
|
+
reactJsxRuntime_development.jsx = jsx;
|
|
916
|
+
reactJsxRuntime_development.jsxs = jsxs;
|
|
911
917
|
})();
|
|
912
918
|
}
|
|
913
|
-
return
|
|
919
|
+
return reactJsxRuntime_development;
|
|
914
920
|
}
|
|
915
921
|
if (process.env.NODE_ENV === "production") {
|
|
916
|
-
|
|
922
|
+
jsxRuntime.exports = requireReactJsxRuntime_production_min();
|
|
917
923
|
} else {
|
|
918
|
-
|
|
924
|
+
jsxRuntime.exports = requireReactJsxRuntime_development();
|
|
919
925
|
}
|
|
920
|
-
var
|
|
926
|
+
var jsxRuntimeExports = jsxRuntime.exports;
|
|
921
927
|
const graphemeSegmenter = new Intl.Segmenter(void 0, {
|
|
922
928
|
granularity: "grapheme"
|
|
923
929
|
});
|
|
@@ -2409,13 +2415,150 @@ function createRuntime(extensions) {
|
|
|
2409
2415
|
const endInLine = lineIndex === endLoc.lineIndex ? endLoc.offsetInLine : line.cursorLength;
|
|
2410
2416
|
const selectedRuns = sliceRuns(runs, startInLine, endInLine).selected;
|
|
2411
2417
|
const content = runsToInlines(normalizeRuns(selectedRuns));
|
|
2412
|
-
|
|
2418
|
+
const paragraph = { type: "paragraph", content };
|
|
2419
|
+
if (line.path.length > 1) {
|
|
2420
|
+
const wrapperPath = line.path.slice(0, -1);
|
|
2421
|
+
const wrapper = getBlockAtPath(state.doc.blocks, wrapperPath);
|
|
2422
|
+
if (wrapper && wrapper.type === "block-wrapper") {
|
|
2423
|
+
blocks.push({
|
|
2424
|
+
type: "block-wrapper",
|
|
2425
|
+
kind: wrapper.kind,
|
|
2426
|
+
data: wrapper.data,
|
|
2427
|
+
blocks: [paragraph]
|
|
2428
|
+
});
|
|
2429
|
+
continue;
|
|
2430
|
+
}
|
|
2431
|
+
}
|
|
2432
|
+
blocks.push(paragraph);
|
|
2413
2433
|
}
|
|
2414
2434
|
const sliceDoc = {
|
|
2415
2435
|
blocks: blocks.length > 0 ? blocks : [{ type: "paragraph", content: [] }]
|
|
2416
2436
|
};
|
|
2417
2437
|
return serialize(normalize(sliceDoc)).source;
|
|
2418
2438
|
}
|
|
2439
|
+
function escapeHtml(text) {
|
|
2440
|
+
return text.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2441
|
+
}
|
|
2442
|
+
function runsToHtml(runs) {
|
|
2443
|
+
var _a;
|
|
2444
|
+
let html = "";
|
|
2445
|
+
for (const run of runs) {
|
|
2446
|
+
let content = escapeHtml(run.text);
|
|
2447
|
+
const sortedMarks = [...run.marks].reverse();
|
|
2448
|
+
for (const mark of sortedMarks) {
|
|
2449
|
+
if (mark.kind === "bold") {
|
|
2450
|
+
content = `<strong>${content}</strong>`;
|
|
2451
|
+
} else if (mark.kind === "italic") {
|
|
2452
|
+
content = `<em>${content}</em>`;
|
|
2453
|
+
} else if (mark.kind === "strikethrough") {
|
|
2454
|
+
content = `<s>${content}</s>`;
|
|
2455
|
+
} else if (mark.kind === "link") {
|
|
2456
|
+
const url = ((_a = mark.data) == null ? void 0 : _a.url) ?? "";
|
|
2457
|
+
content = `<a href="${escapeHtml(url)}">${content}</a>`;
|
|
2458
|
+
}
|
|
2459
|
+
}
|
|
2460
|
+
html += content;
|
|
2461
|
+
}
|
|
2462
|
+
return html;
|
|
2463
|
+
}
|
|
2464
|
+
function serializeSelectionToHtml(state, selection) {
|
|
2465
|
+
const normalized = normalizeSelection$1(selection);
|
|
2466
|
+
const lines = flattenDocToLines(state.doc);
|
|
2467
|
+
const docCursorLength = cursorLengthForLines(lines);
|
|
2468
|
+
const cursorStart = Math.max(
|
|
2469
|
+
0,
|
|
2470
|
+
Math.min(docCursorLength, Math.min(normalized.start, normalized.end))
|
|
2471
|
+
);
|
|
2472
|
+
const cursorEnd = Math.max(
|
|
2473
|
+
0,
|
|
2474
|
+
Math.min(docCursorLength, Math.max(normalized.start, normalized.end))
|
|
2475
|
+
);
|
|
2476
|
+
if (cursorStart === cursorEnd) {
|
|
2477
|
+
return "";
|
|
2478
|
+
}
|
|
2479
|
+
const startLoc = resolveCursorToLine(lines, cursorStart);
|
|
2480
|
+
const endLoc = resolveCursorToLine(lines, cursorEnd);
|
|
2481
|
+
let html = "";
|
|
2482
|
+
let activeList = null;
|
|
2483
|
+
const closeList = () => {
|
|
2484
|
+
if (activeList) {
|
|
2485
|
+
html += `</${activeList.type}>`;
|
|
2486
|
+
activeList = null;
|
|
2487
|
+
}
|
|
2488
|
+
};
|
|
2489
|
+
const openList = (type, indent) => {
|
|
2490
|
+
if (activeList && activeList.type === type && activeList.indent === indent) {
|
|
2491
|
+
return;
|
|
2492
|
+
}
|
|
2493
|
+
closeList();
|
|
2494
|
+
html += `<${type}>`;
|
|
2495
|
+
activeList = { type, indent };
|
|
2496
|
+
};
|
|
2497
|
+
for (let lineIndex = startLoc.lineIndex; lineIndex <= endLoc.lineIndex; lineIndex += 1) {
|
|
2498
|
+
const line = lines[lineIndex];
|
|
2499
|
+
if (!line) {
|
|
2500
|
+
continue;
|
|
2501
|
+
}
|
|
2502
|
+
const block = getBlockAtPath(state.doc.blocks, line.path);
|
|
2503
|
+
if (!block || block.type !== "paragraph") {
|
|
2504
|
+
continue;
|
|
2505
|
+
}
|
|
2506
|
+
const runs = paragraphToRuns(block);
|
|
2507
|
+
const startInLine = lineIndex === startLoc.lineIndex ? startLoc.offsetInLine : 0;
|
|
2508
|
+
const endInLine = lineIndex === endLoc.lineIndex ? endLoc.offsetInLine : line.cursorLength;
|
|
2509
|
+
const selectedRuns = sliceRuns(runs, startInLine, endInLine).selected;
|
|
2510
|
+
let wrapperKind = null;
|
|
2511
|
+
let wrapperData;
|
|
2512
|
+
if (line.path.length > 1) {
|
|
2513
|
+
const wrapperPath = line.path.slice(0, -1);
|
|
2514
|
+
const wrapper = getBlockAtPath(state.doc.blocks, wrapperPath);
|
|
2515
|
+
if (wrapper && wrapper.type === "block-wrapper") {
|
|
2516
|
+
wrapperKind = wrapper.kind;
|
|
2517
|
+
wrapperData = wrapper.data;
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
2520
|
+
const plainText = runs.map((r) => r.text).join("");
|
|
2521
|
+
const listMatch = plainText.match(/^(\s*)([-*+]|\d+\.)( )(.*)$/);
|
|
2522
|
+
let lineHtml;
|
|
2523
|
+
if (listMatch && !wrapperKind) {
|
|
2524
|
+
const prefixLength = listMatch[1].length + listMatch[2].length + listMatch[3].length;
|
|
2525
|
+
const contentRuns = sliceRuns(runs, prefixLength, runs.reduce((sum, r) => sum + r.text.length, 0)).selected;
|
|
2526
|
+
lineHtml = runsToHtml(normalizeRuns(contentRuns));
|
|
2527
|
+
} else {
|
|
2528
|
+
lineHtml = runsToHtml(normalizeRuns(selectedRuns));
|
|
2529
|
+
}
|
|
2530
|
+
if (wrapperKind === "heading") {
|
|
2531
|
+
closeList();
|
|
2532
|
+
const level = Math.min(
|
|
2533
|
+
(wrapperData == null ? void 0 : wrapperData.level) ?? 1,
|
|
2534
|
+
6
|
|
2535
|
+
);
|
|
2536
|
+
html += `<h${level} style="margin:0">${lineHtml}</h${level}>`;
|
|
2537
|
+
} else if (wrapperKind === "bullet-list") {
|
|
2538
|
+
openList("ul", 0);
|
|
2539
|
+
html += `<li>${lineHtml}</li>`;
|
|
2540
|
+
} else if (wrapperKind === "numbered-list") {
|
|
2541
|
+
openList("ol", 0);
|
|
2542
|
+
html += `<li>${lineHtml}</li>`;
|
|
2543
|
+
} else if (wrapperKind === "blockquote") {
|
|
2544
|
+
closeList();
|
|
2545
|
+
html += `<blockquote>${lineHtml}</blockquote>`;
|
|
2546
|
+
} else if (listMatch) {
|
|
2547
|
+
const isNumbered = /^\d+\.$/.test(listMatch[2]);
|
|
2548
|
+
const indent = Math.floor(listMatch[1].length / 2);
|
|
2549
|
+
openList(isNumbered ? "ol" : "ul", indent);
|
|
2550
|
+
html += `<li>${lineHtml}</li>`;
|
|
2551
|
+
} else {
|
|
2552
|
+
closeList();
|
|
2553
|
+
html += `<div>${lineHtml}</div>`;
|
|
2554
|
+
}
|
|
2555
|
+
}
|
|
2556
|
+
closeList();
|
|
2557
|
+
if (!html) {
|
|
2558
|
+
return "";
|
|
2559
|
+
}
|
|
2560
|
+
return `<div>${html}</div>`;
|
|
2561
|
+
}
|
|
2419
2562
|
const runtime = {
|
|
2420
2563
|
extensions,
|
|
2421
2564
|
parse,
|
|
@@ -2423,6 +2566,7 @@ function createRuntime(extensions) {
|
|
|
2423
2566
|
createState,
|
|
2424
2567
|
updateSelection,
|
|
2425
2568
|
serializeSelection,
|
|
2569
|
+
serializeSelectionToHtml,
|
|
2426
2570
|
applyEdit
|
|
2427
2571
|
};
|
|
2428
2572
|
return runtime;
|
|
@@ -2577,7 +2721,7 @@ function normalizeNodes(result) {
|
|
|
2577
2721
|
}
|
|
2578
2722
|
return Array.isArray(result) ? result : [result];
|
|
2579
2723
|
}
|
|
2580
|
-
function renderDocContent(doc, extensions,
|
|
2724
|
+
function renderDocContent(doc, extensions, root) {
|
|
2581
2725
|
const runs = [];
|
|
2582
2726
|
let cursorOffset = 0;
|
|
2583
2727
|
let lineIndex = 0;
|
|
@@ -2597,7 +2741,60 @@ function renderDocContent(doc, extensions, _root) {
|
|
|
2597
2741
|
lineIndex += 1;
|
|
2598
2742
|
}
|
|
2599
2743
|
};
|
|
2600
|
-
function
|
|
2744
|
+
function getBlockKey(block) {
|
|
2745
|
+
if (block.type === "paragraph") {
|
|
2746
|
+
return "paragraph";
|
|
2747
|
+
}
|
|
2748
|
+
if (block.type === "block-wrapper") {
|
|
2749
|
+
return `block-wrapper:${block.kind}`;
|
|
2750
|
+
}
|
|
2751
|
+
if (block.type === "block-atom") {
|
|
2752
|
+
return `block-atom:${block.kind}`;
|
|
2753
|
+
}
|
|
2754
|
+
return "unknown";
|
|
2755
|
+
}
|
|
2756
|
+
function getElementKey(element) {
|
|
2757
|
+
if (element.hasAttribute("data-block")) {
|
|
2758
|
+
const blockType = element.getAttribute("data-block") ?? "unknown";
|
|
2759
|
+
const lineKind = element instanceof HTMLElement ? element.dataset.lineKind : null;
|
|
2760
|
+
if (lineKind && lineKind !== blockType) {
|
|
2761
|
+
return lineKind;
|
|
2762
|
+
}
|
|
2763
|
+
return blockType;
|
|
2764
|
+
}
|
|
2765
|
+
if (element.hasAttribute("data-block-wrapper")) {
|
|
2766
|
+
return `block-wrapper:${element.getAttribute("data-block-wrapper")}`;
|
|
2767
|
+
}
|
|
2768
|
+
if (element.hasAttribute("data-block-atom")) {
|
|
2769
|
+
return `block-atom:${element.getAttribute("data-block-atom")}`;
|
|
2770
|
+
}
|
|
2771
|
+
return "unknown";
|
|
2772
|
+
}
|
|
2773
|
+
function getInlineKey(inline) {
|
|
2774
|
+
if (inline.type === "text") {
|
|
2775
|
+
return "text";
|
|
2776
|
+
}
|
|
2777
|
+
if (inline.type === "inline-wrapper") {
|
|
2778
|
+
return `inline-wrapper:${inline.kind}`;
|
|
2779
|
+
}
|
|
2780
|
+
if (inline.type === "inline-atom") {
|
|
2781
|
+
return `inline-atom:${inline.kind}`;
|
|
2782
|
+
}
|
|
2783
|
+
return "unknown";
|
|
2784
|
+
}
|
|
2785
|
+
function getInlineElementKey(element) {
|
|
2786
|
+
if (element.classList.contains("cake-text")) {
|
|
2787
|
+
return "text";
|
|
2788
|
+
}
|
|
2789
|
+
if (element.hasAttribute("data-inline")) {
|
|
2790
|
+
return `inline-wrapper:${element.getAttribute("data-inline")}`;
|
|
2791
|
+
}
|
|
2792
|
+
if (element.hasAttribute("data-inline-atom")) {
|
|
2793
|
+
return `inline-atom:${element.getAttribute("data-inline-atom")}`;
|
|
2794
|
+
}
|
|
2795
|
+
return "unknown";
|
|
2796
|
+
}
|
|
2797
|
+
function reconcileInline(inline, existing) {
|
|
2601
2798
|
for (const extension of extensions) {
|
|
2602
2799
|
const render = extension.renderInline;
|
|
2603
2800
|
if (!render) {
|
|
@@ -2609,6 +2806,17 @@ function renderDocContent(doc, extensions, _root) {
|
|
|
2609
2806
|
}
|
|
2610
2807
|
}
|
|
2611
2808
|
if (inline.type === "text") {
|
|
2809
|
+
const canReuse = existing && existing instanceof HTMLSpanElement && getInlineElementKey(existing) === "text";
|
|
2810
|
+
if (canReuse) {
|
|
2811
|
+
const textNode = existing.firstChild;
|
|
2812
|
+
if (textNode instanceof Text) {
|
|
2813
|
+
if (textNode.textContent !== inline.text) {
|
|
2814
|
+
textNode.textContent = inline.text;
|
|
2815
|
+
}
|
|
2816
|
+
createTextRun$1(textNode);
|
|
2817
|
+
return [existing];
|
|
2818
|
+
}
|
|
2819
|
+
}
|
|
2612
2820
|
const element = document.createElement("span");
|
|
2613
2821
|
element.className = "cake-text";
|
|
2614
2822
|
const node = document.createTextNode(inline.text);
|
|
@@ -2617,16 +2825,29 @@ function renderDocContent(doc, extensions, _root) {
|
|
|
2617
2825
|
return [element];
|
|
2618
2826
|
}
|
|
2619
2827
|
if (inline.type === "inline-wrapper") {
|
|
2828
|
+
const canReuse = existing && existing instanceof HTMLSpanElement && getInlineElementKey(existing) === getInlineKey(inline);
|
|
2829
|
+
if (canReuse) {
|
|
2830
|
+
reconcileInlineChildren(existing, inline.children);
|
|
2831
|
+
return [existing];
|
|
2832
|
+
}
|
|
2620
2833
|
const element = document.createElement("span");
|
|
2621
2834
|
element.setAttribute("data-inline", inline.kind);
|
|
2622
2835
|
for (const child of inline.children) {
|
|
2623
|
-
for (const node of
|
|
2836
|
+
for (const node of reconcileInline(child, null)) {
|
|
2624
2837
|
element.append(node);
|
|
2625
2838
|
}
|
|
2626
2839
|
}
|
|
2627
2840
|
return [element];
|
|
2628
2841
|
}
|
|
2629
2842
|
if (inline.type === "inline-atom") {
|
|
2843
|
+
const canReuse = existing && existing instanceof HTMLSpanElement && getInlineElementKey(existing) === getInlineKey(inline);
|
|
2844
|
+
if (canReuse) {
|
|
2845
|
+
const textNode = existing.firstChild;
|
|
2846
|
+
if (textNode instanceof Text) {
|
|
2847
|
+
createTextRun$1(textNode);
|
|
2848
|
+
return [existing];
|
|
2849
|
+
}
|
|
2850
|
+
}
|
|
2630
2851
|
const element = document.createElement("span");
|
|
2631
2852
|
element.setAttribute("data-inline-atom", inline.kind);
|
|
2632
2853
|
const node = document.createTextNode(" ");
|
|
@@ -2636,7 +2857,25 @@ function renderDocContent(doc, extensions, _root) {
|
|
|
2636
2857
|
}
|
|
2637
2858
|
return [];
|
|
2638
2859
|
}
|
|
2639
|
-
function
|
|
2860
|
+
function reconcileInlineChildren(parent, inlines) {
|
|
2861
|
+
const mergedInlines = mergeInlineForRender(inlines);
|
|
2862
|
+
const existingChildren2 = Array.from(parent.children);
|
|
2863
|
+
const newChildren = [];
|
|
2864
|
+
mergedInlines.forEach((inline, i) => {
|
|
2865
|
+
const existingChild = existingChildren2[i] ?? null;
|
|
2866
|
+
const canReuse = existingChild && getInlineElementKey(existingChild) === getInlineKey(inline);
|
|
2867
|
+
const nodes = reconcileInline(inline, canReuse ? existingChild : null);
|
|
2868
|
+
newChildren.push(...nodes);
|
|
2869
|
+
});
|
|
2870
|
+
if (newChildren.length === existingChildren2.length && newChildren.every((node, i) => node === existingChildren2[i])) {
|
|
2871
|
+
return;
|
|
2872
|
+
}
|
|
2873
|
+
parent.replaceChildren(...newChildren);
|
|
2874
|
+
}
|
|
2875
|
+
function renderInline(inline) {
|
|
2876
|
+
return reconcileInline(inline, null);
|
|
2877
|
+
}
|
|
2878
|
+
function reconcileBlock(block, existing) {
|
|
2640
2879
|
for (const extension of extensions) {
|
|
2641
2880
|
const render = extension.renderBlock;
|
|
2642
2881
|
if (!render) {
|
|
@@ -2648,12 +2887,35 @@ function renderDocContent(doc, extensions, _root) {
|
|
|
2648
2887
|
}
|
|
2649
2888
|
}
|
|
2650
2889
|
if (block.type === "paragraph") {
|
|
2890
|
+
const canReuse = existing && existing instanceof HTMLDivElement && getElementKey(existing) === "paragraph";
|
|
2891
|
+
const currentLineIndex = context.getLineIndex();
|
|
2892
|
+
context.incrementLineIndex();
|
|
2893
|
+
if (canReuse) {
|
|
2894
|
+
existing.setAttribute("data-line-index", String(currentLineIndex));
|
|
2895
|
+
if (block.content.length === 0) {
|
|
2896
|
+
const firstChild = existing.firstChild;
|
|
2897
|
+
if (firstChild instanceof Text && existing.querySelector("br")) {
|
|
2898
|
+
if (firstChild.textContent !== "") {
|
|
2899
|
+
firstChild.textContent = "";
|
|
2900
|
+
}
|
|
2901
|
+
createTextRun$1(firstChild);
|
|
2902
|
+
return [existing];
|
|
2903
|
+
}
|
|
2904
|
+
existing.replaceChildren();
|
|
2905
|
+
const textNode = document.createTextNode("");
|
|
2906
|
+
createTextRun$1(textNode);
|
|
2907
|
+
existing.append(textNode);
|
|
2908
|
+
existing.append(document.createElement("br"));
|
|
2909
|
+
return [existing];
|
|
2910
|
+
}
|
|
2911
|
+
reconcileInlineChildren(existing, block.content);
|
|
2912
|
+
return [existing];
|
|
2913
|
+
}
|
|
2651
2914
|
const element = document.createElement("div");
|
|
2652
2915
|
element.setAttribute("data-block", "paragraph");
|
|
2653
|
-
element.setAttribute("data-line-index", String(
|
|
2916
|
+
element.setAttribute("data-line-index", String(currentLineIndex));
|
|
2654
2917
|
element.classList.add("cake-line");
|
|
2655
2918
|
element.dataset.lineKind = "paragraph";
|
|
2656
|
-
context.incrementLineIndex();
|
|
2657
2919
|
if (block.content.length === 0) {
|
|
2658
2920
|
const textNode = document.createTextNode("");
|
|
2659
2921
|
createTextRun$1(textNode);
|
|
@@ -2662,7 +2924,7 @@ function renderDocContent(doc, extensions, _root) {
|
|
|
2662
2924
|
} else {
|
|
2663
2925
|
const mergedContent = mergeInlineForRender(block.content);
|
|
2664
2926
|
for (const inline of mergedContent) {
|
|
2665
|
-
for (const node of
|
|
2927
|
+
for (const node of reconcileInline(inline, null)) {
|
|
2666
2928
|
element.append(node);
|
|
2667
2929
|
}
|
|
2668
2930
|
}
|
|
@@ -2670,6 +2932,11 @@ function renderDocContent(doc, extensions, _root) {
|
|
|
2670
2932
|
return [element];
|
|
2671
2933
|
}
|
|
2672
2934
|
if (block.type === "block-wrapper") {
|
|
2935
|
+
const canReuse = existing && existing instanceof HTMLDivElement && getElementKey(existing) === getBlockKey(block);
|
|
2936
|
+
if (canReuse) {
|
|
2937
|
+
reconcileBlockChildren(existing, block.blocks);
|
|
2938
|
+
return [existing];
|
|
2939
|
+
}
|
|
2673
2940
|
const element = document.createElement("div");
|
|
2674
2941
|
element.setAttribute("data-block-wrapper", block.kind);
|
|
2675
2942
|
for (const node of renderBlocks(block.blocks)) {
|
|
@@ -2678,15 +2945,41 @@ function renderDocContent(doc, extensions, _root) {
|
|
|
2678
2945
|
return [element];
|
|
2679
2946
|
}
|
|
2680
2947
|
if (block.type === "block-atom") {
|
|
2948
|
+
const canReuse = existing && existing instanceof HTMLDivElement && getElementKey(existing) === getBlockKey(block);
|
|
2949
|
+
const currentLineIndex = context.getLineIndex();
|
|
2950
|
+
context.incrementLineIndex();
|
|
2951
|
+
if (canReuse) {
|
|
2952
|
+
existing.setAttribute("data-line-index", String(currentLineIndex));
|
|
2953
|
+
return [existing];
|
|
2954
|
+
}
|
|
2681
2955
|
const element = document.createElement("div");
|
|
2682
2956
|
element.setAttribute("data-block-atom", block.kind);
|
|
2683
|
-
element.setAttribute("data-line-index", String(
|
|
2957
|
+
element.setAttribute("data-line-index", String(currentLineIndex));
|
|
2684
2958
|
element.classList.add("cake-line");
|
|
2685
|
-
context.incrementLineIndex();
|
|
2686
2959
|
return [element];
|
|
2687
2960
|
}
|
|
2688
2961
|
return [];
|
|
2689
2962
|
}
|
|
2963
|
+
function reconcileBlockChildren(parent, blocks) {
|
|
2964
|
+
const existingChildren2 = Array.from(parent.children);
|
|
2965
|
+
const newChildren = [];
|
|
2966
|
+
blocks.forEach((block, index) => {
|
|
2967
|
+
const existingChild = existingChildren2[index] ?? null;
|
|
2968
|
+
const canReuse = existingChild && getElementKey(existingChild) === getBlockKey(block);
|
|
2969
|
+
const nodes = reconcileBlock(block, canReuse ? existingChild : null);
|
|
2970
|
+
newChildren.push(...nodes);
|
|
2971
|
+
if (index < blocks.length - 1) {
|
|
2972
|
+
cursorOffset += 1;
|
|
2973
|
+
}
|
|
2974
|
+
});
|
|
2975
|
+
if (newChildren.length === existingChildren2.length && newChildren.every((node, i) => node === existingChildren2[i])) {
|
|
2976
|
+
return;
|
|
2977
|
+
}
|
|
2978
|
+
parent.replaceChildren(...newChildren);
|
|
2979
|
+
}
|
|
2980
|
+
function renderBlock(block) {
|
|
2981
|
+
return reconcileBlock(block, null);
|
|
2982
|
+
}
|
|
2690
2983
|
function renderBlocks(blocks) {
|
|
2691
2984
|
const nodes = [];
|
|
2692
2985
|
blocks.forEach((block, index) => {
|
|
@@ -2697,10 +2990,17 @@ function renderDocContent(doc, extensions, _root) {
|
|
|
2697
2990
|
});
|
|
2698
2991
|
return nodes;
|
|
2699
2992
|
}
|
|
2993
|
+
const existingChildren = root ? Array.from(root.children) : [];
|
|
2700
2994
|
const contentNodes = [];
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2995
|
+
doc.blocks.forEach((block, index) => {
|
|
2996
|
+
const existingChild = existingChildren[index] ?? null;
|
|
2997
|
+
const canReuse = existingChild && getElementKey(existingChild) === getBlockKey(block);
|
|
2998
|
+
const nodes = reconcileBlock(block, canReuse ? existingChild : null);
|
|
2999
|
+
contentNodes.push(...nodes);
|
|
3000
|
+
if (index < doc.blocks.length - 1) {
|
|
3001
|
+
cursorOffset += 1;
|
|
3002
|
+
}
|
|
3003
|
+
});
|
|
2704
3004
|
return { content: contentNodes, map: createDomMap(runs) };
|
|
2705
3005
|
}
|
|
2706
3006
|
function mergeInlineForRender(inlines) {
|
|
@@ -3222,13 +3522,13 @@ function CakeLinkPopover(params) {
|
|
|
3222
3522
|
if (state.status !== "open") {
|
|
3223
3523
|
return;
|
|
3224
3524
|
}
|
|
3225
|
-
container.addEventListener("scroll",
|
|
3525
|
+
container.addEventListener("scroll", close, { passive: true });
|
|
3226
3526
|
window.addEventListener("resize", reposition);
|
|
3227
3527
|
return () => {
|
|
3228
|
-
container.removeEventListener("scroll",
|
|
3528
|
+
container.removeEventListener("scroll", close);
|
|
3229
3529
|
window.removeEventListener("resize", reposition);
|
|
3230
3530
|
};
|
|
3231
|
-
}, [container, reposition, state.status]);
|
|
3531
|
+
}, [close, container, reposition, state.status]);
|
|
3232
3532
|
const handleMouseDown = useCallback(
|
|
3233
3533
|
(event) => {
|
|
3234
3534
|
event.stopPropagation();
|
|
@@ -3297,7 +3597,7 @@ function CakeLinkPopover(params) {
|
|
|
3297
3597
|
handleCancel();
|
|
3298
3598
|
}
|
|
3299
3599
|
};
|
|
3300
|
-
return /* @__PURE__ */
|
|
3600
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3301
3601
|
"div",
|
|
3302
3602
|
{
|
|
3303
3603
|
className: "cake-link-popover",
|
|
@@ -3310,7 +3610,7 @@ function CakeLinkPopover(params) {
|
|
|
3310
3610
|
},
|
|
3311
3611
|
onMouseDown: handleMouseDown,
|
|
3312
3612
|
onClick: (event) => event.stopPropagation(),
|
|
3313
|
-
children: state.isEditing ? /* @__PURE__ */
|
|
3613
|
+
children: state.isEditing ? /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
3314
3614
|
"form",
|
|
3315
3615
|
{
|
|
3316
3616
|
className: "cake-link-editor",
|
|
@@ -3319,7 +3619,7 @@ function CakeLinkPopover(params) {
|
|
|
3319
3619
|
handleSave();
|
|
3320
3620
|
},
|
|
3321
3621
|
children: [
|
|
3322
|
-
/* @__PURE__ */
|
|
3622
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3323
3623
|
"input",
|
|
3324
3624
|
{
|
|
3325
3625
|
className: "cake-link-input",
|
|
@@ -3336,56 +3636,24 @@ function CakeLinkPopover(params) {
|
|
|
3336
3636
|
},
|
|
3337
3637
|
onKeyDown: handleInputKeyDown,
|
|
3338
3638
|
placeholder: "https://"
|
|
3339
|
-
}
|
|
3340
|
-
void 0,
|
|
3341
|
-
false,
|
|
3342
|
-
{
|
|
3343
|
-
fileName: "/Users/moboudra/dev/blankpage/cake/src/cake/extensions/link/link-popover.tsx",
|
|
3344
|
-
lineNumber: 281,
|
|
3345
|
-
columnNumber: 11
|
|
3346
|
-
},
|
|
3347
|
-
this
|
|
3639
|
+
}
|
|
3348
3640
|
),
|
|
3349
|
-
/* @__PURE__ */
|
|
3350
|
-
|
|
3351
|
-
lineNumber: 297,
|
|
3352
|
-
columnNumber: 11
|
|
3353
|
-
}, this),
|
|
3354
|
-
/* @__PURE__ */ jsxDevRuntimeExports.jsxDEV(
|
|
3641
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "submit", className: "cake-link-save", children: "Save" }),
|
|
3642
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3355
3643
|
"button",
|
|
3356
3644
|
{
|
|
3357
3645
|
type: "button",
|
|
3358
3646
|
className: "cake-link-cancel",
|
|
3359
3647
|
onClick: handleCancel,
|
|
3360
3648
|
children: "Cancel"
|
|
3361
|
-
}
|
|
3362
|
-
void 0,
|
|
3363
|
-
false,
|
|
3364
|
-
{
|
|
3365
|
-
fileName: "/Users/moboudra/dev/blankpage/cake/src/cake/extensions/link/link-popover.tsx",
|
|
3366
|
-
lineNumber: 300,
|
|
3367
|
-
columnNumber: 11
|
|
3368
|
-
},
|
|
3369
|
-
this
|
|
3649
|
+
}
|
|
3370
3650
|
)
|
|
3371
3651
|
]
|
|
3372
|
-
}
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
{
|
|
3376
|
-
|
|
3377
|
-
lineNumber: 274,
|
|
3378
|
-
columnNumber: 9
|
|
3379
|
-
},
|
|
3380
|
-
this
|
|
3381
|
-
) : /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV(jsxDevRuntimeExports.Fragment, { children: [
|
|
3382
|
-
/* @__PURE__ */ jsxDevRuntimeExports.jsxDEV("div", { className: "cake-link-url", title: displayUrl, children: displayUrl }, void 0, false, {
|
|
3383
|
-
fileName: "/Users/moboudra/dev/blankpage/cake/src/cake/extensions/link/link-popover.tsx",
|
|
3384
|
-
lineNumber: 310,
|
|
3385
|
-
columnNumber: 11
|
|
3386
|
-
}, this),
|
|
3387
|
-
/* @__PURE__ */ jsxDevRuntimeExports.jsxDEV("div", { className: "cake-link-actions", children: [
|
|
3388
|
-
/* @__PURE__ */ jsxDevRuntimeExports.jsxDEV(
|
|
3652
|
+
}
|
|
3653
|
+
) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
3654
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "cake-link-url", title: displayUrl, children: displayUrl }),
|
|
3655
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "cake-link-actions", children: [
|
|
3656
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3389
3657
|
"button",
|
|
3390
3658
|
{
|
|
3391
3659
|
type: "button",
|
|
@@ -3393,22 +3661,10 @@ function CakeLinkPopover(params) {
|
|
|
3393
3661
|
onClick: handleEdit,
|
|
3394
3662
|
title: "Edit link",
|
|
3395
3663
|
"aria-label": "Edit link",
|
|
3396
|
-
children: /* @__PURE__ */
|
|
3397
|
-
|
|
3398
|
-
lineNumber: 321,
|
|
3399
|
-
columnNumber: 15
|
|
3400
|
-
}, this)
|
|
3401
|
-
},
|
|
3402
|
-
void 0,
|
|
3403
|
-
false,
|
|
3404
|
-
{
|
|
3405
|
-
fileName: "/Users/moboudra/dev/blankpage/cake/src/cake/extensions/link/link-popover.tsx",
|
|
3406
|
-
lineNumber: 314,
|
|
3407
|
-
columnNumber: 13
|
|
3408
|
-
},
|
|
3409
|
-
this
|
|
3664
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(Pencil, { className: "cake-link-icon" })
|
|
3665
|
+
}
|
|
3410
3666
|
),
|
|
3411
|
-
/* @__PURE__ */
|
|
3667
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3412
3668
|
"button",
|
|
3413
3669
|
{
|
|
3414
3670
|
type: "button",
|
|
@@ -3416,22 +3672,10 @@ function CakeLinkPopover(params) {
|
|
|
3416
3672
|
onClick: handleOpen,
|
|
3417
3673
|
title: "Open link",
|
|
3418
3674
|
"aria-label": "Open link",
|
|
3419
|
-
children: /* @__PURE__ */
|
|
3420
|
-
|
|
3421
|
-
lineNumber: 330,
|
|
3422
|
-
columnNumber: 15
|
|
3423
|
-
}, this)
|
|
3424
|
-
},
|
|
3425
|
-
void 0,
|
|
3426
|
-
false,
|
|
3427
|
-
{
|
|
3428
|
-
fileName: "/Users/moboudra/dev/blankpage/cake/src/cake/extensions/link/link-popover.tsx",
|
|
3429
|
-
lineNumber: 323,
|
|
3430
|
-
columnNumber: 13
|
|
3431
|
-
},
|
|
3432
|
-
this
|
|
3675
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(ExternalLink, { className: "cake-link-icon" })
|
|
3676
|
+
}
|
|
3433
3677
|
),
|
|
3434
|
-
/* @__PURE__ */
|
|
3678
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3435
3679
|
"button",
|
|
3436
3680
|
{
|
|
3437
3681
|
type: "button",
|
|
@@ -3439,40 +3683,12 @@ function CakeLinkPopover(params) {
|
|
|
3439
3683
|
onClick: handleUnlink,
|
|
3440
3684
|
title: "Remove link",
|
|
3441
3685
|
"aria-label": "Remove link",
|
|
3442
|
-
children: /* @__PURE__ */
|
|
3443
|
-
|
|
3444
|
-
lineNumber: 339,
|
|
3445
|
-
columnNumber: 15
|
|
3446
|
-
}, this)
|
|
3447
|
-
},
|
|
3448
|
-
void 0,
|
|
3449
|
-
false,
|
|
3450
|
-
{
|
|
3451
|
-
fileName: "/Users/moboudra/dev/blankpage/cake/src/cake/extensions/link/link-popover.tsx",
|
|
3452
|
-
lineNumber: 332,
|
|
3453
|
-
columnNumber: 13
|
|
3454
|
-
},
|
|
3455
|
-
this
|
|
3686
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(Unlink, { className: "cake-link-icon" })
|
|
3687
|
+
}
|
|
3456
3688
|
)
|
|
3457
|
-
] }
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
columnNumber: 11
|
|
3461
|
-
}, this)
|
|
3462
|
-
] }, void 0, true, {
|
|
3463
|
-
fileName: "/Users/moboudra/dev/blankpage/cake/src/cake/extensions/link/link-popover.tsx",
|
|
3464
|
-
lineNumber: 309,
|
|
3465
|
-
columnNumber: 9
|
|
3466
|
-
}, this)
|
|
3467
|
-
},
|
|
3468
|
-
void 0,
|
|
3469
|
-
false,
|
|
3470
|
-
{
|
|
3471
|
-
fileName: "/Users/moboudra/dev/blankpage/cake/src/cake/extensions/link/link-popover.tsx",
|
|
3472
|
-
lineNumber: 261,
|
|
3473
|
-
columnNumber: 5
|
|
3474
|
-
},
|
|
3475
|
-
this
|
|
3689
|
+
] })
|
|
3690
|
+
] })
|
|
3691
|
+
}
|
|
3476
3692
|
);
|
|
3477
3693
|
}
|
|
3478
3694
|
function buildLayoutModel(lines, measurer) {
|
|
@@ -3821,21 +4037,13 @@ const linkExtension = {
|
|
|
3821
4037
|
if (!context.contentRoot || !context.toOverlayRect) {
|
|
3822
4038
|
return null;
|
|
3823
4039
|
}
|
|
3824
|
-
return /* @__PURE__ */
|
|
4040
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3825
4041
|
CakeLinkPopover,
|
|
3826
4042
|
{
|
|
3827
4043
|
container: context.container,
|
|
3828
4044
|
contentRoot: context.contentRoot,
|
|
3829
4045
|
toOverlayRect: context.toOverlayRect
|
|
3830
|
-
}
|
|
3831
|
-
void 0,
|
|
3832
|
-
false,
|
|
3833
|
-
{
|
|
3834
|
-
fileName: "/Users/moboudra/dev/blankpage/cake/src/cake/extensions/link/link.tsx",
|
|
3835
|
-
lineNumber: 179,
|
|
3836
|
-
columnNumber: 7
|
|
3837
|
-
},
|
|
3838
|
-
this
|
|
4046
|
+
}
|
|
3839
4047
|
);
|
|
3840
4048
|
}
|
|
3841
4049
|
};
|
|
@@ -5335,6 +5543,7 @@ function ScrollbarOverlay({ container }) {
|
|
|
5335
5543
|
const [isDragging, setIsDragging] = useState(false);
|
|
5336
5544
|
const [isHovered, setIsHovered] = useState(false);
|
|
5337
5545
|
const [isScrolling, setIsScrolling] = useState(false);
|
|
5546
|
+
const [isDarkMode, setIsDarkMode] = useState(false);
|
|
5338
5547
|
const dragStartRef = useRef(
|
|
5339
5548
|
null
|
|
5340
5549
|
);
|
|
@@ -5349,6 +5558,24 @@ function ScrollbarOverlay({ container }) {
|
|
|
5349
5558
|
);
|
|
5350
5559
|
const maxScrollTop = scrollHeight - clientHeight;
|
|
5351
5560
|
const thumbTop = maxScrollTop > 0 ? TRACK_PADDING + scrollTop / maxScrollTop * (trackHeight - thumbHeight) : TRACK_PADDING;
|
|
5561
|
+
useEffect(() => {
|
|
5562
|
+
function checkDarkMode() {
|
|
5563
|
+
const html = document.documentElement;
|
|
5564
|
+
setIsDarkMode(html.classList.contains("dark"));
|
|
5565
|
+
}
|
|
5566
|
+
checkDarkMode();
|
|
5567
|
+
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
5568
|
+
mediaQuery.addEventListener("change", checkDarkMode);
|
|
5569
|
+
const observer = new MutationObserver(checkDarkMode);
|
|
5570
|
+
observer.observe(document.documentElement, {
|
|
5571
|
+
attributes: true,
|
|
5572
|
+
attributeFilter: ["class"]
|
|
5573
|
+
});
|
|
5574
|
+
return () => {
|
|
5575
|
+
mediaQuery.removeEventListener("change", checkDarkMode);
|
|
5576
|
+
observer.disconnect();
|
|
5577
|
+
};
|
|
5578
|
+
}, []);
|
|
5352
5579
|
useEffect(() => {
|
|
5353
5580
|
function update() {
|
|
5354
5581
|
setState({
|
|
@@ -5486,6 +5713,13 @@ function ScrollbarOverlay({ container }) {
|
|
|
5486
5713
|
return null;
|
|
5487
5714
|
}
|
|
5488
5715
|
const isVisible = isDragging || isHovered || isScrolling;
|
|
5716
|
+
const wrapperStyle = {
|
|
5717
|
+
position: "absolute",
|
|
5718
|
+
inset: 0,
|
|
5719
|
+
pointerEvents: "none",
|
|
5720
|
+
overflow: "hidden",
|
|
5721
|
+
zIndex: 50
|
|
5722
|
+
};
|
|
5489
5723
|
const trackStyle = {
|
|
5490
5724
|
position: "absolute",
|
|
5491
5725
|
top: 0,
|
|
@@ -5495,6 +5729,12 @@ function ScrollbarOverlay({ container }) {
|
|
|
5495
5729
|
height: clientHeight,
|
|
5496
5730
|
pointerEvents: "auto"
|
|
5497
5731
|
};
|
|
5732
|
+
const getThumbColor = () => {
|
|
5733
|
+
if (isDarkMode) {
|
|
5734
|
+
return isDragging ? "rgba(255, 255, 255, 0.5)" : "rgba(255, 255, 255, 0.3)";
|
|
5735
|
+
}
|
|
5736
|
+
return isDragging ? "rgba(0, 0, 0, 0.5)" : "rgba(0, 0, 0, 0.3)";
|
|
5737
|
+
};
|
|
5498
5738
|
const thumbStyle = {
|
|
5499
5739
|
position: "absolute",
|
|
5500
5740
|
right: "2px",
|
|
@@ -5502,54 +5742,35 @@ function ScrollbarOverlay({ container }) {
|
|
|
5502
5742
|
borderRadius: "9999px",
|
|
5503
5743
|
height: thumbHeight,
|
|
5504
5744
|
top: thumbTop,
|
|
5505
|
-
opacity: isVisible ? 1 : 0
|
|
5745
|
+
opacity: isVisible ? 1 : 0,
|
|
5746
|
+
backgroundColor: getThumbColor(),
|
|
5747
|
+
transition: "opacity 150ms",
|
|
5748
|
+
cursor: "pointer"
|
|
5506
5749
|
};
|
|
5507
|
-
return /* @__PURE__ */
|
|
5750
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: wrapperStyle, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5508
5751
|
"div",
|
|
5509
5752
|
{
|
|
5510
5753
|
"data-testid": "custom-scrollbar",
|
|
5511
5754
|
"aria-hidden": "true",
|
|
5512
|
-
className: "pointer-events-auto absolute top-0 right-0 bottom-0 z-50 w-3",
|
|
5513
5755
|
style: trackStyle,
|
|
5514
5756
|
onClick: handleTrackClick,
|
|
5515
5757
|
onMouseEnter: () => setIsHovered(true),
|
|
5516
5758
|
onMouseLeave: () => setIsHovered(false),
|
|
5517
|
-
children: /* @__PURE__ */
|
|
5759
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5518
5760
|
"div",
|
|
5519
5761
|
{
|
|
5520
5762
|
"data-testid": "scrollbar-thumb",
|
|
5521
|
-
className: `absolute right-0.5 w-1.5 cursor-pointer rounded-full transition-opacity duration-150 ${isDragging ? "bg-black/50 dark:bg-white/50" : "bg-black/30 dark:bg-white/30"}`,
|
|
5522
5763
|
style: thumbStyle,
|
|
5523
5764
|
onMouseDown: handleThumbMouseDown
|
|
5524
|
-
}
|
|
5525
|
-
void 0,
|
|
5526
|
-
false,
|
|
5527
|
-
{
|
|
5528
|
-
fileName: "/Users/moboudra/dev/blankpage/cake/src/cake/extensions/scrollbar/index.tsx",
|
|
5529
|
-
lineNumber: 230,
|
|
5530
|
-
columnNumber: 7
|
|
5531
|
-
},
|
|
5532
|
-
this
|
|
5765
|
+
}
|
|
5533
5766
|
)
|
|
5534
|
-
}
|
|
5535
|
-
|
|
5536
|
-
false,
|
|
5537
|
-
{
|
|
5538
|
-
fileName: "/Users/moboudra/dev/blankpage/cake/src/cake/extensions/scrollbar/index.tsx",
|
|
5539
|
-
lineNumber: 221,
|
|
5540
|
-
columnNumber: 5
|
|
5541
|
-
},
|
|
5542
|
-
this
|
|
5543
|
-
);
|
|
5767
|
+
}
|
|
5768
|
+
) });
|
|
5544
5769
|
}
|
|
5545
5770
|
const scrollbarExtension = {
|
|
5546
5771
|
name: "scrollbar",
|
|
5547
5772
|
renderOverlay(context) {
|
|
5548
|
-
return /* @__PURE__ */
|
|
5549
|
-
fileName: "/Users/moboudra/dev/blankpage/cake/src/cake/extensions/scrollbar/index.tsx",
|
|
5550
|
-
lineNumber: 247,
|
|
5551
|
-
columnNumber: 12
|
|
5552
|
-
}, this);
|
|
5773
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(ScrollbarOverlay, { container: context.container });
|
|
5553
5774
|
}
|
|
5554
5775
|
};
|
|
5555
5776
|
const STRIKE_KIND = "strikethrough";
|
|
@@ -6067,7 +6288,7 @@ function computeSelectionRects(layout, selection, measurer) {
|
|
|
6067
6288
|
return rects;
|
|
6068
6289
|
}
|
|
6069
6290
|
function computeCaretRect(caret) {
|
|
6070
|
-
const height = caret.
|
|
6291
|
+
const height = caret.fontSize * 1.2;
|
|
6071
6292
|
const contentHeight = caret.lineRect.height > 0 ? Math.max(
|
|
6072
6293
|
0,
|
|
6073
6294
|
caret.lineRect.height - caret.padding.top - caret.padding.bottom
|
|
@@ -6121,6 +6342,7 @@ function getSelectionGeometry(params) {
|
|
|
6121
6342
|
scroll
|
|
6122
6343
|
}),
|
|
6123
6344
|
lineLength: lineInfo.cursorLength,
|
|
6345
|
+
fontSize: getComputedFontSize(lineElement),
|
|
6124
6346
|
padding: getComputedVerticalPadding(lineElement)
|
|
6125
6347
|
};
|
|
6126
6348
|
const caretRect = computeCaretRect(caretMeasurement);
|
|
@@ -6164,6 +6386,7 @@ function getSelectionGeometry(params) {
|
|
|
6164
6386
|
scroll
|
|
6165
6387
|
}),
|
|
6166
6388
|
lineLength: lineInfo.cursorLength,
|
|
6389
|
+
fontSize: getComputedFontSize(focusLineElement),
|
|
6167
6390
|
padding: getComputedVerticalPadding(focusLineElement)
|
|
6168
6391
|
};
|
|
6169
6392
|
focusRect = computeCaretRect(caretMeasurement);
|
|
@@ -6290,6 +6513,11 @@ function getComputedVerticalPadding(lineElement) {
|
|
|
6290
6513
|
bottom: Number.isFinite(bottom) ? bottom : 0
|
|
6291
6514
|
};
|
|
6292
6515
|
}
|
|
6516
|
+
function getComputedFontSize(lineElement) {
|
|
6517
|
+
const fontSize = window.getComputedStyle(lineElement).fontSize;
|
|
6518
|
+
const parsed = Number.parseFloat(fontSize);
|
|
6519
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : 16;
|
|
6520
|
+
}
|
|
6293
6521
|
function rectRight(rect) {
|
|
6294
6522
|
return rect.left + rect.width;
|
|
6295
6523
|
}
|
|
@@ -6687,6 +6915,36 @@ function nextWordBreak(text, offset) {
|
|
|
6687
6915
|
}
|
|
6688
6916
|
return text.length;
|
|
6689
6917
|
}
|
|
6918
|
+
const MAX_HTML_INPUT_LENGTH = 5e5;
|
|
6919
|
+
const MAX_MARKDOWN_OUTPUT_LENGTH = 1e5;
|
|
6920
|
+
function isHTMLElement(node) {
|
|
6921
|
+
return node !== null && node.nodeType === Node.ELEMENT_NODE;
|
|
6922
|
+
}
|
|
6923
|
+
function isElement(node) {
|
|
6924
|
+
return node !== null && node.nodeType === Node.ELEMENT_NODE;
|
|
6925
|
+
}
|
|
6926
|
+
const CLEANUP_PATTERNS = {
|
|
6927
|
+
unescapeHeaders: /^\\(#{1,6})\s+/gm,
|
|
6928
|
+
unescapeBlockquote: /^\\>/gm,
|
|
6929
|
+
unescapeMarkdown: /\\([*_`~[\]])/g,
|
|
6930
|
+
unescapeListBullets: /^(\s*)\\([-*+])(\s+)/gm,
|
|
6931
|
+
unescapeListNumbers: /^(\s*)(\d+)\\\.(\s+)/gm,
|
|
6932
|
+
normalizeBullets: /^(\s*)[-*+](\s{2,})/gm,
|
|
6933
|
+
normalizeNumbers: /^[\s]*\d+\.[\s]+/gm,
|
|
6934
|
+
normalizeHeaders: /^(#{1,6})[\s]{2,}/gm,
|
|
6935
|
+
removeTrailingSpaces: /[ \t]+$/gm,
|
|
6936
|
+
headersInBlockquotes: /^>\s*(#{1,6}\s+.*)/gm,
|
|
6937
|
+
excessiveNewlines: /\n{3,}/g,
|
|
6938
|
+
interlacedTableGaps: /(\|[^\n]*\|)\s*\n\s*\n+\s*(\|[^\n]*\|)/g,
|
|
6939
|
+
complexTableGaps: /(\|[^\n]*\|)(\s*\n){2,}(\|[^\n]*\|)/g
|
|
6940
|
+
};
|
|
6941
|
+
const HTML_PREPROCESSING_PATTERNS = {
|
|
6942
|
+
removeStyleAndDataAttrs: /\s(?:style|data-[^=]*|id)="[^"]*"/gi,
|
|
6943
|
+
removeNonCodeClasses: /\sclass="(?![^"]*(?:language-|hljs))[^"]*"/gi,
|
|
6944
|
+
removeEmptyElements: /<(\w+)[^>]*>\s*<\/\1>/gi,
|
|
6945
|
+
normalizeSpaces: /[ \t]{2,}/g,
|
|
6946
|
+
reduceBlankLines: /\n\s*\n/g
|
|
6947
|
+
};
|
|
6690
6948
|
const turndownService = new TurndownService({
|
|
6691
6949
|
headingStyle: "atx",
|
|
6692
6950
|
bulletListMarker: "-",
|
|
@@ -6704,6 +6962,13 @@ turndownService.addRule("strikethrough", {
|
|
|
6704
6962
|
turndownService.addRule("codeBlock", {
|
|
6705
6963
|
filter: "pre",
|
|
6706
6964
|
replacement: (content, node) => {
|
|
6965
|
+
if (!isHTMLElement(node)) {
|
|
6966
|
+
return `
|
|
6967
|
+
\`\`\`
|
|
6968
|
+
${content}
|
|
6969
|
+
\`\`\`
|
|
6970
|
+
`;
|
|
6971
|
+
}
|
|
6707
6972
|
const codeElement = node.querySelector("code");
|
|
6708
6973
|
if (codeElement) {
|
|
6709
6974
|
const className = codeElement.className || "";
|
|
@@ -6722,12 +6987,308 @@ ${content}
|
|
|
6722
6987
|
`;
|
|
6723
6988
|
}
|
|
6724
6989
|
});
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
6990
|
+
turndownService.addRule("tableRow", {
|
|
6991
|
+
filter: "tr",
|
|
6992
|
+
replacement: (_content, node) => {
|
|
6993
|
+
var _a;
|
|
6994
|
+
if (!isHTMLElement(node)) {
|
|
6995
|
+
return "";
|
|
6996
|
+
}
|
|
6997
|
+
const isHeaderRow = ((_a = node.parentNode) == null ? void 0 : _a.nodeName) === "THEAD";
|
|
6998
|
+
const cells = Array.from(node.querySelectorAll("td, th"));
|
|
6999
|
+
const cellContents = cells.map((cell) => {
|
|
7000
|
+
const text = cell.textContent || "";
|
|
7001
|
+
return text.replace(/\|/g, "\\|").trim();
|
|
7002
|
+
});
|
|
7003
|
+
let result = "| " + cellContents.join(" | ") + " |\n";
|
|
7004
|
+
if (isHeaderRow) {
|
|
7005
|
+
const separators = cells.map((cell) => {
|
|
7006
|
+
const align = cell.getAttribute("align");
|
|
7007
|
+
if (align === "center") {
|
|
7008
|
+
return ":-------------:";
|
|
7009
|
+
}
|
|
7010
|
+
if (align === "right") {
|
|
7011
|
+
return "-------------:";
|
|
7012
|
+
}
|
|
7013
|
+
return "-------------";
|
|
7014
|
+
});
|
|
7015
|
+
result += "| " + separators.join(" | ") + " |\n";
|
|
7016
|
+
}
|
|
7017
|
+
return result;
|
|
7018
|
+
}
|
|
7019
|
+
});
|
|
7020
|
+
turndownService.addRule("taskList", {
|
|
7021
|
+
filter: (node) => {
|
|
7022
|
+
if (!isHTMLElement(node)) {
|
|
7023
|
+
return false;
|
|
7024
|
+
}
|
|
7025
|
+
if (node.nodeName !== "LI") {
|
|
7026
|
+
return false;
|
|
7027
|
+
}
|
|
7028
|
+
if (node.querySelector('input[type="checkbox"]') !== null) {
|
|
7029
|
+
return true;
|
|
7030
|
+
}
|
|
7031
|
+
const textContent = node.textContent || "";
|
|
7032
|
+
const hasCheckboxSymbols = /^[\s]*[☐☑✓✗[\]]/m.test(textContent) || /^[\s]*\[[ x]\]/m.test(textContent);
|
|
7033
|
+
const hasCheckboxClass = Boolean(
|
|
7034
|
+
node.className && (node.className.includes("task") || node.className.includes("checkbox") || node.className.includes("todo"))
|
|
7035
|
+
);
|
|
7036
|
+
return hasCheckboxSymbols || hasCheckboxClass;
|
|
7037
|
+
},
|
|
7038
|
+
replacement: (content, node) => {
|
|
7039
|
+
if (!isHTMLElement(node)) {
|
|
7040
|
+
return content;
|
|
7041
|
+
}
|
|
7042
|
+
const checkbox = node.querySelector('input[type="checkbox"]');
|
|
7043
|
+
const isCheckbox = checkbox instanceof HTMLInputElement && checkbox.type === "checkbox";
|
|
7044
|
+
let isChecked = false;
|
|
7045
|
+
if (isCheckbox) {
|
|
7046
|
+
isChecked = checkbox.checked;
|
|
7047
|
+
} else {
|
|
7048
|
+
const textContent2 = node.textContent || "";
|
|
7049
|
+
isChecked = /^[\s]*[☑✓✗]/.test(textContent2) || /^[\s]*\[x\]/i.test(textContent2);
|
|
7050
|
+
}
|
|
7051
|
+
const prefix = isChecked ? "- [x] " : "- [ ] ";
|
|
7052
|
+
let textContent = content;
|
|
7053
|
+
textContent = textContent.replace(/^\s*\[[ x]\]\s*/gi, "");
|
|
7054
|
+
textContent = textContent.replace(/^\s*[☐☑✓✗]\s*/g, "");
|
|
7055
|
+
textContent = textContent.replace(/^\s*\[[x ]\]\s*/gi, "");
|
|
7056
|
+
textContent = textContent.replace(/^\s*\\?\[[ x]\\?\]\s*/gi, "");
|
|
7057
|
+
textContent = textContent.replace(/\\?\[\\?\s*\\?\]\\?\s*/g, "");
|
|
7058
|
+
return prefix + textContent.trim() + "\n";
|
|
7059
|
+
}
|
|
7060
|
+
});
|
|
7061
|
+
turndownService.addRule("list", {
|
|
7062
|
+
filter: ["ul", "ol"],
|
|
7063
|
+
replacement: (content, node) => {
|
|
7064
|
+
const parent = node.parentNode;
|
|
7065
|
+
const isNested = isElement(parent) && parent.tagName === "LI";
|
|
7066
|
+
if (isNested) {
|
|
7067
|
+
return "\n" + content;
|
|
7068
|
+
}
|
|
7069
|
+
return "\n" + content + "\n";
|
|
7070
|
+
}
|
|
7071
|
+
});
|
|
7072
|
+
turndownService.addRule("blockquote", {
|
|
7073
|
+
filter: "blockquote",
|
|
7074
|
+
replacement: (content) => {
|
|
7075
|
+
const lines = content.trim().split("\n");
|
|
7076
|
+
const processedLines = lines.map((line) => {
|
|
7077
|
+
const trimmed = line.trim();
|
|
7078
|
+
if (!trimmed) {
|
|
7079
|
+
return ">";
|
|
7080
|
+
}
|
|
7081
|
+
const existingQuotes = trimmed.match(/^(>\s*)+/);
|
|
7082
|
+
if (existingQuotes) {
|
|
7083
|
+
return existingQuotes[0] + " " + trimmed;
|
|
7084
|
+
}
|
|
7085
|
+
return "> " + trimmed;
|
|
7086
|
+
});
|
|
7087
|
+
return "\n" + processedLines.join("\n") + "\n";
|
|
7088
|
+
}
|
|
7089
|
+
});
|
|
7090
|
+
turndownService.addRule("horizontalRule", {
|
|
7091
|
+
filter: "hr",
|
|
7092
|
+
replacement: () => "\n---\n"
|
|
7093
|
+
});
|
|
7094
|
+
turndownService.addRule("inlineCode", {
|
|
7095
|
+
filter: (node) => {
|
|
7096
|
+
const parent = node.parentNode;
|
|
7097
|
+
return node.nodeName === "CODE" && !(isElement(parent) && parent.tagName === "PRE");
|
|
7098
|
+
},
|
|
7099
|
+
replacement: (content) => {
|
|
7100
|
+
const backtickCount = Math.max(
|
|
7101
|
+
1,
|
|
7102
|
+
(content.match(/`+/g) || []).reduce(
|
|
7103
|
+
(max, match) => Math.max(max, match.length),
|
|
7104
|
+
0
|
|
7105
|
+
) + 1
|
|
7106
|
+
);
|
|
7107
|
+
const delimiter = "`".repeat(backtickCount);
|
|
7108
|
+
return delimiter + content + delimiter;
|
|
7109
|
+
}
|
|
7110
|
+
});
|
|
7111
|
+
turndownService.addRule("image", {
|
|
7112
|
+
filter: "img",
|
|
7113
|
+
replacement: (_content, node) => {
|
|
7114
|
+
if (!isHTMLElement(node)) {
|
|
7115
|
+
return "";
|
|
7116
|
+
}
|
|
7117
|
+
const src = node.getAttribute("src") || "";
|
|
7118
|
+
const alt = node.getAttribute("alt") || "";
|
|
7119
|
+
const title = node.getAttribute("title");
|
|
7120
|
+
if (title) {
|
|
7121
|
+
return ``;
|
|
7122
|
+
}
|
|
7123
|
+
return ``;
|
|
7124
|
+
}
|
|
7125
|
+
});
|
|
7126
|
+
turndownService.addRule("highlight", {
|
|
7127
|
+
filter: (node) => {
|
|
7128
|
+
var _a, _b;
|
|
7129
|
+
if (!isHTMLElement(node)) {
|
|
7130
|
+
return false;
|
|
7131
|
+
}
|
|
7132
|
+
return node.nodeName === "MARK" || node.nodeName === "SPAN" && (((_a = node.style) == null ? void 0 : _a.backgroundColor) === "yellow" || ((_b = node.className) == null ? void 0 : _b.includes("highlight")));
|
|
7133
|
+
},
|
|
7134
|
+
replacement: (content) => `==${content}==`
|
|
7135
|
+
});
|
|
7136
|
+
turndownService.addRule("headerWithId", {
|
|
7137
|
+
filter: ["h1", "h2", "h3", "h4", "h5", "h6"],
|
|
7138
|
+
replacement: (content, node) => {
|
|
7139
|
+
if (!isHTMLElement(node)) {
|
|
7140
|
+
return content;
|
|
7141
|
+
}
|
|
7142
|
+
const rawLevel = parseInt(node.nodeName.charAt(1));
|
|
7143
|
+
const level = Math.min(rawLevel, 3);
|
|
7144
|
+
const hashes = "#".repeat(level);
|
|
7145
|
+
const id = node.getAttribute("id");
|
|
7146
|
+
if (id) {
|
|
7147
|
+
return `
|
|
7148
|
+
${hashes} ${content} {#${id}}
|
|
7149
|
+
`;
|
|
7150
|
+
}
|
|
7151
|
+
return `
|
|
7152
|
+
${hashes} ${content}
|
|
7153
|
+
`;
|
|
7154
|
+
}
|
|
7155
|
+
});
|
|
7156
|
+
function processTextNodes(element) {
|
|
7157
|
+
const spans = Array.from(element.querySelectorAll("span"));
|
|
7158
|
+
spans.forEach((span) => {
|
|
7159
|
+
var _a;
|
|
7160
|
+
const textContent = span.textContent || "";
|
|
7161
|
+
const textNode = document.createTextNode(textContent);
|
|
7162
|
+
(_a = span.parentNode) == null ? void 0 : _a.replaceChild(textNode, span);
|
|
7163
|
+
});
|
|
7164
|
+
}
|
|
7165
|
+
function detectSourceApp(html) {
|
|
7166
|
+
const detectionPatterns = {
|
|
7167
|
+
notion: ["notion-", "notranslate"],
|
|
7168
|
+
github: ["github.com", "js-file-line-container"],
|
|
7169
|
+
slack: ["slack-", "c-message"],
|
|
7170
|
+
"google-docs": ["docs.google.com", "kix-"]
|
|
7171
|
+
};
|
|
7172
|
+
for (const [app, patterns] of Object.entries(detectionPatterns)) {
|
|
7173
|
+
if (patterns.some((pattern) => html.includes(pattern))) {
|
|
7174
|
+
return app;
|
|
7175
|
+
}
|
|
7176
|
+
}
|
|
7177
|
+
return "unknown";
|
|
7178
|
+
}
|
|
7179
|
+
function preprocessForApp(html, app) {
|
|
7180
|
+
switch (app) {
|
|
7181
|
+
case "notion":
|
|
7182
|
+
return html.replace(/<div[^>]*class="[^"]*notion-[^"]*"[^>]*>/gi, "<div>").replace(/<span[^>]*class="[^"]*notion-[^"]*"[^>]*>/gi, "<span>").replace(/<details[^>]*>/gi, "<div>").replace(/<\/details>/gi, "</div>").replace(/<summary[^>]*>/gi, "<strong>").replace(/<\/summary>/gi, "</strong>");
|
|
7183
|
+
case "github":
|
|
7184
|
+
return html.replace(/<td[^>]*class="[^"]*blob-num[^"]*"[^>]*>.*?<\/td>/gi, "").replace(/<span[^>]*class="[^"]*pl-[^"]*"[^>]*>/gi, "<span>").replace(/<span[^>]*class="[^"]*highlight[^"]*"[^>]*>/gi, "<span>");
|
|
7185
|
+
case "slack":
|
|
7186
|
+
return html.replace(/<span[^>]*class="[^"]*c-member[^"]*"[^>]*>/gi, "<span>").replace(/<span[^>]*data-stringify-type="mention"[^>]*>/gi, "<span>").replace(
|
|
7187
|
+
/<span[^>]*class="[^"]*c-emoji[^"]*"[^>]*>([^<]*)<\/span>/gi,
|
|
7188
|
+
"$1"
|
|
7189
|
+
);
|
|
7190
|
+
case "google-docs":
|
|
7191
|
+
return html.replace(
|
|
7192
|
+
/<span[^>]*style="[^"]*font-weight:[^;"]*bold[^"]*"[^>]*>/gi,
|
|
7193
|
+
"<strong>"
|
|
7194
|
+
).replace(
|
|
7195
|
+
/<span[^>]*style="[^"]*font-style:[^;"]*italic[^"]*"[^>]*>/gi,
|
|
7196
|
+
"<em>"
|
|
7197
|
+
).replace(/<\/span>/gi, "").replace(/<p[^>]*style="[^"]*"[^>]*>/gi, "<p>");
|
|
7198
|
+
default:
|
|
7199
|
+
return html;
|
|
7200
|
+
}
|
|
7201
|
+
}
|
|
7202
|
+
function cleanupMarkdown(markdown) {
|
|
7203
|
+
return markdown.replace(CLEANUP_PATTERNS.unescapeHeaders, "$1 ").replace(CLEANUP_PATTERNS.unescapeBlockquote, ">").replace(CLEANUP_PATTERNS.unescapeMarkdown, "$1").replace(CLEANUP_PATTERNS.unescapeListBullets, "$1$2$3").replace(CLEANUP_PATTERNS.unescapeListNumbers, "$1$2.$3").replace(CLEANUP_PATTERNS.normalizeBullets, "$1- ").replace(CLEANUP_PATTERNS.normalizeNumbers, (match) => {
|
|
7204
|
+
var _a;
|
|
7205
|
+
const num = ((_a = match.match(/\d+/)) == null ? void 0 : _a[0]) || "1";
|
|
7206
|
+
return `${num}. `;
|
|
7207
|
+
}).replace(CLEANUP_PATTERNS.normalizeHeaders, "$1 ").replace(CLEANUP_PATTERNS.removeTrailingSpaces, "").replace(CLEANUP_PATTERNS.headersInBlockquotes, "\n$1").replace(CLEANUP_PATTERNS.excessiveNewlines, "\n\n").replace(CLEANUP_PATTERNS.interlacedTableGaps, "$1\n$2").replace(CLEANUP_PATTERNS.complexTableGaps, "$1\n$3").replace(/\*\*\[([^\]]+?)\]\(([^)]+?)\)\*\*/g, "[**$1**]($2)").replace(/__\[([^\]]+?)\]\(([^)]+?)\)__/g, "[**$1**]($2)").replace(/\*\[([^\]]+?)\]\(([^)]+?)\)\*/g, "[*$1*]($2)").replace(/_\[([^\]]+?)\]\(([^)]+?)\)_/g, "[*$1*]($2)").trim();
|
|
7208
|
+
}
|
|
7209
|
+
function preprocessHtml(html) {
|
|
7210
|
+
const sourceApp = detectSourceApp(html);
|
|
7211
|
+
let processedHtml = preprocessForApp(html, sourceApp);
|
|
7212
|
+
const parser = new DOMParser();
|
|
7213
|
+
const doc = parser.parseFromString(processedHtml, "text/html");
|
|
7214
|
+
if (doc.body) {
|
|
7215
|
+
processTextNodes(doc.body);
|
|
7216
|
+
processedHtml = doc.body.innerHTML;
|
|
7217
|
+
}
|
|
7218
|
+
return processedHtml.replace(HTML_PREPROCESSING_PATTERNS.removeStyleAndDataAttrs, "").replace(HTML_PREPROCESSING_PATTERNS.removeNonCodeClasses, "").replace(HTML_PREPROCESSING_PATTERNS.removeEmptyElements, "").replace(HTML_PREPROCESSING_PATTERNS.normalizeSpaces, " ").replace(HTML_PREPROCESSING_PATTERNS.reduceBlankLines, "\n\n").trim();
|
|
7219
|
+
}
|
|
7220
|
+
function sanitizeContent(content) {
|
|
7221
|
+
return content.replace(/<script[^>]*>.*?<\/script>/gi, "").replace(
|
|
7222
|
+
/<(?:iframe|object|embed)[^>]*>.*?<\/(?:iframe|object|embed)>/gi,
|
|
7223
|
+
""
|
|
7224
|
+
);
|
|
7225
|
+
}
|
|
7226
|
+
function limitContentLength(content, maxLength = MAX_MARKDOWN_OUTPUT_LENGTH) {
|
|
7227
|
+
return content.substring(0, maxLength);
|
|
7228
|
+
}
|
|
7229
|
+
function sanitizeMarkdown(markdown) {
|
|
7230
|
+
return limitContentLength(sanitizeContent(markdown));
|
|
7231
|
+
}
|
|
7232
|
+
function shouldProcessPaste(htmlContent) {
|
|
7233
|
+
if (htmlContent.length > MAX_HTML_INPUT_LENGTH) {
|
|
7234
|
+
console.warn("HTML content too large for paste processing");
|
|
7235
|
+
return false;
|
|
7236
|
+
}
|
|
7237
|
+
const hasFormatting = /<(?:strong|b|em|i|u|s|del|strike|code|pre|h[1-6]|blockquote|ul|ol|li|table|tr|td|th|a|img|mark|span|div)[\s>]/i.test(
|
|
7238
|
+
htmlContent
|
|
7239
|
+
);
|
|
7240
|
+
if (!hasFormatting) {
|
|
7241
|
+
return false;
|
|
7242
|
+
}
|
|
7243
|
+
if (/<img\s/i.test(htmlContent)) {
|
|
7244
|
+
return true;
|
|
7245
|
+
}
|
|
7246
|
+
const strippedContent = htmlContent.replace(/<[^>]*>/g, "").trim();
|
|
7247
|
+
if (!strippedContent || strippedContent.length < 3) {
|
|
7248
|
+
return false;
|
|
7249
|
+
}
|
|
7250
|
+
return true;
|
|
7251
|
+
}
|
|
7252
|
+
function normalizeListPrefixes(content) {
|
|
7253
|
+
const lines = content.split("\n");
|
|
7254
|
+
let currentListType = null;
|
|
7255
|
+
let currentNumber = 1;
|
|
7256
|
+
return lines.map((line) => {
|
|
7257
|
+
const match = line.match(/^(\s*)([-*+]|\d+\.)( +)(.*)$/);
|
|
7258
|
+
if (match) {
|
|
7259
|
+
const [, indent, marker, , listContent] = match;
|
|
7260
|
+
if (currentListType === null) {
|
|
7261
|
+
currentListType = /\d+\./.test(marker) ? "numbered" : "bullet";
|
|
7262
|
+
}
|
|
7263
|
+
const newMarker = currentListType === "bullet" ? "-" : `${currentNumber}.`;
|
|
7264
|
+
if (currentListType === "numbered") {
|
|
7265
|
+
currentNumber += 1;
|
|
7266
|
+
}
|
|
7267
|
+
return `${indent}${newMarker} ${listContent}`;
|
|
7268
|
+
}
|
|
7269
|
+
return line;
|
|
7270
|
+
}).join("\n");
|
|
7271
|
+
}
|
|
7272
|
+
function convertHtmlToMarkdown(html) {
|
|
7273
|
+
try {
|
|
7274
|
+
const processedHtml = preprocessHtml(html);
|
|
7275
|
+
const markdown = turndownService.turndown(processedHtml);
|
|
7276
|
+
return cleanupMarkdown(markdown);
|
|
7277
|
+
} catch (error) {
|
|
7278
|
+
console.error("Error converting HTML to markdown:", error);
|
|
6728
7279
|
return "";
|
|
6729
7280
|
}
|
|
6730
|
-
|
|
7281
|
+
}
|
|
7282
|
+
function htmlToMarkdownForPaste(htmlContent) {
|
|
7283
|
+
if (!shouldProcessPaste(htmlContent)) {
|
|
7284
|
+
return null;
|
|
7285
|
+
}
|
|
7286
|
+
const markdown = convertHtmlToMarkdown(htmlContent);
|
|
7287
|
+
if (!markdown.trim()) {
|
|
7288
|
+
return null;
|
|
7289
|
+
}
|
|
7290
|
+
const normalizedMarkdown = normalizeListPrefixes(markdown);
|
|
7291
|
+
return sanitizeMarkdown(normalizedMarkdown).replace(/\r\n?/g, "\n");
|
|
6731
7292
|
}
|
|
6732
7293
|
const defaultSelection = { start: 0, end: 0, affinity: "forward" };
|
|
6733
7294
|
const COMPOSITION_COMMIT_CLEAR_DELAY_MS = 50;
|
|
@@ -6906,10 +7467,15 @@ class CakeEngine {
|
|
|
6906
7467
|
}
|
|
6907
7468
|
}
|
|
6908
7469
|
setValue({ value, selection }) {
|
|
6909
|
-
const
|
|
6910
|
-
if (
|
|
7470
|
+
const valueChanged = value !== this.state.source;
|
|
7471
|
+
if (!valueChanged && selection === void 0) {
|
|
6911
7472
|
return;
|
|
6912
7473
|
}
|
|
7474
|
+
if (!valueChanged && selection !== void 0) {
|
|
7475
|
+
this.setSelection(selection);
|
|
7476
|
+
return;
|
|
7477
|
+
}
|
|
7478
|
+
const nextSelection = selection ?? this.state.selection;
|
|
6913
7479
|
this.state = this.runtime.createState(value, nextSelection);
|
|
6914
7480
|
this.render();
|
|
6915
7481
|
}
|
|
@@ -7169,7 +7735,11 @@ class CakeEngine {
|
|
|
7169
7735
|
this.extensions,
|
|
7170
7736
|
this.contentRoot
|
|
7171
7737
|
);
|
|
7172
|
-
this.contentRoot.
|
|
7738
|
+
const existingChildren = Array.from(this.contentRoot.childNodes);
|
|
7739
|
+
const needsUpdate = content.length !== existingChildren.length || content.some((node, i) => node !== existingChildren[i]);
|
|
7740
|
+
if (needsUpdate) {
|
|
7741
|
+
this.contentRoot.replaceChildren(...content);
|
|
7742
|
+
}
|
|
7173
7743
|
this.domMap = map;
|
|
7174
7744
|
this.updateExtensionsOverlayPosition();
|
|
7175
7745
|
if (!this.isComposing) {
|
|
@@ -7765,6 +8335,13 @@ class CakeEngine {
|
|
|
7765
8335
|
}
|
|
7766
8336
|
event.preventDefault();
|
|
7767
8337
|
clipboardData.setData("text/plain", text);
|
|
8338
|
+
const html = this.runtime.serializeSelectionToHtml(
|
|
8339
|
+
this.state,
|
|
8340
|
+
this.state.selection
|
|
8341
|
+
);
|
|
8342
|
+
if (html) {
|
|
8343
|
+
clipboardData.setData("text/html", html);
|
|
8344
|
+
}
|
|
7768
8345
|
}
|
|
7769
8346
|
handleCut(event) {
|
|
7770
8347
|
if (this.readOnly) {
|
|
@@ -9074,8 +9651,8 @@ class CakeEngine {
|
|
|
9074
9651
|
if (!this.extensionsRoot) {
|
|
9075
9652
|
return;
|
|
9076
9653
|
}
|
|
9077
|
-
const scrollTop = this.container.scrollTop;
|
|
9078
|
-
const scrollLeft = this.container.scrollLeft;
|
|
9654
|
+
const scrollTop = Math.max(0, this.container.scrollTop);
|
|
9655
|
+
const scrollLeft = Math.max(0, this.container.scrollLeft);
|
|
9079
9656
|
if (scrollTop === 0 && scrollLeft === 0) {
|
|
9080
9657
|
this.extensionsRoot.style.transform = "";
|
|
9081
9658
|
return;
|
|
@@ -10738,10 +11315,10 @@ const CakeEditor = forwardRef(
|
|
|
10738
11315
|
containerStyle.position = "relative";
|
|
10739
11316
|
}
|
|
10740
11317
|
const containerClassName = props.className ? `cake ${props.className}` : "cake";
|
|
10741
|
-
const overlayContext =
|
|
11318
|
+
const overlayContext = containerRef.current && contentRoot ? {
|
|
10742
11319
|
container: containerRef.current,
|
|
10743
11320
|
contentRoot,
|
|
10744
|
-
overlayRoot,
|
|
11321
|
+
overlayRoot: overlayRoot ?? void 0,
|
|
10745
11322
|
toOverlayRect: (rect) => {
|
|
10746
11323
|
var _a;
|
|
10747
11324
|
const containerRect = (_a = containerRef.current) == null ? void 0 : _a.getBoundingClientRect();
|
|
@@ -10778,8 +11355,11 @@ const CakeEditor = forwardRef(
|
|
|
10778
11355
|
return { start: focus, end: focus };
|
|
10779
11356
|
}
|
|
10780
11357
|
} : null;
|
|
10781
|
-
|
|
10782
|
-
|
|
11358
|
+
const hasOverlayExtensions = allExtensionsRef.current.some(
|
|
11359
|
+
(ext) => ext.renderOverlay
|
|
11360
|
+
);
|
|
11361
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { position: "relative", height: "100%" }, children: [
|
|
11362
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10783
11363
|
"div",
|
|
10784
11364
|
{
|
|
10785
11365
|
ref: containerRef,
|
|
@@ -10790,35 +11370,12 @@ const CakeEditor = forwardRef(
|
|
|
10790
11370
|
var _a;
|
|
10791
11371
|
(_a = props.onBlur) == null ? void 0 : _a.call(props, event.nativeEvent);
|
|
10792
11372
|
}
|
|
10793
|
-
}
|
|
10794
|
-
void 0,
|
|
10795
|
-
false,
|
|
10796
|
-
{
|
|
10797
|
-
fileName: "/Users/moboudra/dev/blankpage/cake/src/cake/react/CakeEditor.tsx",
|
|
10798
|
-
lineNumber: 351,
|
|
10799
|
-
columnNumber: 9
|
|
10800
|
-
},
|
|
10801
|
-
this
|
|
11373
|
+
}
|
|
10802
11374
|
),
|
|
10803
|
-
|
|
10804
|
-
/* @__PURE__ */
|
|
10805
|
-
(extension) => extension.renderOverlay ? /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV(Fragment, { children: extension.renderOverlay(overlayContext) }, extension.name, false, {
|
|
10806
|
-
fileName: "/Users/moboudra/dev/blankpage/cake/src/cake/react/CakeEditor.tsx",
|
|
10807
|
-
lineNumber: 365,
|
|
10808
|
-
columnNumber: 21
|
|
10809
|
-
}, this) : null
|
|
10810
|
-
) }, void 0, false, {
|
|
10811
|
-
fileName: "/Users/moboudra/dev/blankpage/cake/src/cake/react/CakeEditor.tsx",
|
|
10812
|
-
lineNumber: 362,
|
|
10813
|
-
columnNumber: 15
|
|
10814
|
-
}, this),
|
|
10815
|
-
overlayRoot
|
|
11375
|
+
overlayContext && hasOverlayExtensions ? allExtensionsRef.current.map(
|
|
11376
|
+
(extension) => extension.renderOverlay ? /* @__PURE__ */ jsxRuntimeExports.jsx(Fragment, { children: extension.renderOverlay(overlayContext) }, extension.name) : null
|
|
10816
11377
|
) : null
|
|
10817
|
-
] }
|
|
10818
|
-
fileName: "/Users/moboudra/dev/blankpage/cake/src/cake/react/CakeEditor.tsx",
|
|
10819
|
-
lineNumber: 350,
|
|
10820
|
-
columnNumber: 7
|
|
10821
|
-
}, this);
|
|
11378
|
+
] });
|
|
10822
11379
|
}
|
|
10823
11380
|
);
|
|
10824
11381
|
CakeEditor.displayName = "CakeEditor";
|