@pixerate/editor 0.7.0 → 0.8.1
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/extensions/index.cjs +1 -0
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.js +1 -0
- package/dist/extensions/index.js.map +1 -1
- package/dist/history/index.cjs +260 -0
- package/dist/history/index.cjs.map +1 -0
- package/dist/history/index.d.cts +109 -0
- package/dist/history/index.d.ts +109 -0
- package/dist/history/index.js +232 -0
- package/dist/history/index.js.map +1 -0
- package/dist/index.cjs +240 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +238 -0
- package/dist/index.js.map +1 -1
- package/dist/serializers/index.cjs +7 -0
- package/dist/serializers/index.cjs.map +1 -1
- package/dist/serializers/index.js +7 -0
- package/dist/serializers/index.js.map +1 -1
- package/package.json +6 -1
package/dist/index.d.cts
CHANGED
|
@@ -6,6 +6,7 @@ export { ExtractedMention, escapeHtml, extractMentionsFromDoc, getEditorMarkdown
|
|
|
6
6
|
import { Editor, EditorOptions, Content, Extensions } from '@tiptap/core';
|
|
7
7
|
export { Content, Editor, EditorOptions, Extensions } from '@tiptap/core';
|
|
8
8
|
export { ASTNode, BinaryOpNode, CellCoordinate, CellData, CellDep, CellFormat, CellRange, CellRefNode, ColumnBinding, ColumnType, DataSourceBinder, DependencyGraph, EvaluationContext, FormulaEvaluator, FormulaParser, FormulaToken, FormulaTokenType, FunctionCallNode, LiteralNode, PropertyRefNode, RangeNode, RowType, SpreadsheetColumn, SpreadsheetController, SpreadsheetControllerOptions, SpreadsheetDataSource, SpreadsheetDataSourceField, SpreadsheetDocument, SpreadsheetRow, UnaryOpNode, colNameToIndex, extractCellDependencies, indexToColName, parseCellReference, parseFormula, parseRange, tokenizeFormula } from './spreadsheet/index.cjs';
|
|
9
|
+
export { Command, HistoryManager, HistoryManagerOptions, HistoryState, MergedExecutionOptions, SnapshotCommandOptions, createHistoryManager } from './history/index.cjs';
|
|
9
10
|
export { MarkdownOptions } from 'tiptap-markdown';
|
|
10
11
|
import '@tiptap/pm/view';
|
|
11
12
|
import '@tiptap/pm/model';
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export { ExtractedMention, escapeHtml, extractMentionsFromDoc, getEditorMarkdown
|
|
|
6
6
|
import { Editor, EditorOptions, Content, Extensions } from '@tiptap/core';
|
|
7
7
|
export { Content, Editor, EditorOptions, Extensions } from '@tiptap/core';
|
|
8
8
|
export { ASTNode, BinaryOpNode, CellCoordinate, CellData, CellDep, CellFormat, CellRange, CellRefNode, ColumnBinding, ColumnType, DataSourceBinder, DependencyGraph, EvaluationContext, FormulaEvaluator, FormulaParser, FormulaToken, FormulaTokenType, FunctionCallNode, LiteralNode, PropertyRefNode, RangeNode, RowType, SpreadsheetColumn, SpreadsheetController, SpreadsheetControllerOptions, SpreadsheetDataSource, SpreadsheetDataSourceField, SpreadsheetDocument, SpreadsheetRow, UnaryOpNode, colNameToIndex, extractCellDependencies, indexToColName, parseCellReference, parseFormula, parseRange, tokenizeFormula } from './spreadsheet/index.js';
|
|
9
|
+
export { Command, HistoryManager, HistoryManagerOptions, HistoryState, MergedExecutionOptions, SnapshotCommandOptions, createHistoryManager } from './history/index.js';
|
|
9
10
|
export { MarkdownOptions } from 'tiptap-markdown';
|
|
10
11
|
import '@tiptap/pm/view';
|
|
11
12
|
import '@tiptap/pm/model';
|
package/dist/index.js
CHANGED
|
@@ -2115,6 +2115,7 @@ function createRichTextPreset(options = {}) {
|
|
|
2115
2115
|
openOnClick: openLinksOnClick,
|
|
2116
2116
|
autolink: true,
|
|
2117
2117
|
defaultProtocol: "https",
|
|
2118
|
+
protocols: ["file", "vscode", "cursor"],
|
|
2118
2119
|
HTMLAttributes: {
|
|
2119
2120
|
target: "_blank",
|
|
2120
2121
|
rel: "noopener noreferrer",
|
|
@@ -2335,6 +2336,13 @@ var md2 = new MarkdownIt({
|
|
|
2335
2336
|
linkify: true,
|
|
2336
2337
|
breaks: true
|
|
2337
2338
|
}).use(taskLists);
|
|
2339
|
+
var defaultValidateLink = md2.validateLink;
|
|
2340
|
+
md2.validateLink = (url) => {
|
|
2341
|
+
if (url.startsWith("file://") || url.startsWith("vscode://") || url.startsWith("cursor://")) {
|
|
2342
|
+
return true;
|
|
2343
|
+
}
|
|
2344
|
+
return defaultValidateLink.call(md2, url);
|
|
2345
|
+
};
|
|
2338
2346
|
function markdownToTipTapHtml(markdown) {
|
|
2339
2347
|
if (!markdown) return "<p></p>";
|
|
2340
2348
|
return md2.render(markdown);
|
|
@@ -3834,6 +3842,234 @@ var DirtyTracker = class {
|
|
|
3834
3842
|
function createDirtyTracker(initialBaseline, options) {
|
|
3835
3843
|
return new DirtyTracker(initialBaseline, options);
|
|
3836
3844
|
}
|
|
3845
|
+
|
|
3846
|
+
// src/history/HistoryManager.ts
|
|
3847
|
+
var HistoryManager = class {
|
|
3848
|
+
undoStack = [];
|
|
3849
|
+
redoStack = [];
|
|
3850
|
+
maxDepth;
|
|
3851
|
+
isApplying = false;
|
|
3852
|
+
batchDepth = 0;
|
|
3853
|
+
currentBatch = null;
|
|
3854
|
+
listeners = /* @__PURE__ */ new Set();
|
|
3855
|
+
onStateChange;
|
|
3856
|
+
cachedState;
|
|
3857
|
+
constructor(options = {}) {
|
|
3858
|
+
this.maxDepth = options.maxDepth ?? 50;
|
|
3859
|
+
this.onStateChange = options.onStateChange;
|
|
3860
|
+
this.cachedState = this.computeState();
|
|
3861
|
+
}
|
|
3862
|
+
computeState() {
|
|
3863
|
+
const canUndo = this.undoStack.length > 0;
|
|
3864
|
+
const canRedo = this.redoStack.length > 0;
|
|
3865
|
+
return {
|
|
3866
|
+
canUndo,
|
|
3867
|
+
canRedo,
|
|
3868
|
+
undoName: canUndo ? this.undoStack[this.undoStack.length - 1].name : "",
|
|
3869
|
+
redoName: canRedo ? this.redoStack[this.redoStack.length - 1].name : "",
|
|
3870
|
+
undoCount: this.undoStack.length,
|
|
3871
|
+
redoCount: this.redoStack.length
|
|
3872
|
+
};
|
|
3873
|
+
}
|
|
3874
|
+
/**
|
|
3875
|
+
* Returns a snapshot of the current history state.
|
|
3876
|
+
* Cached to maintain referential equality across renders for useSyncExternalStore.
|
|
3877
|
+
*/
|
|
3878
|
+
getState() {
|
|
3879
|
+
return this.cachedState;
|
|
3880
|
+
}
|
|
3881
|
+
notify() {
|
|
3882
|
+
this.cachedState = this.computeState();
|
|
3883
|
+
const state = this.cachedState;
|
|
3884
|
+
this.onStateChange?.(state);
|
|
3885
|
+
this.listeners.forEach((listener) => {
|
|
3886
|
+
try {
|
|
3887
|
+
listener(state);
|
|
3888
|
+
} catch (err) {
|
|
3889
|
+
console.error("[HistoryManager] Error in state listener:", err);
|
|
3890
|
+
}
|
|
3891
|
+
});
|
|
3892
|
+
}
|
|
3893
|
+
/**
|
|
3894
|
+
* Executes a command and pushes it onto the undo stack.
|
|
3895
|
+
* Clears the redo stack.
|
|
3896
|
+
*/
|
|
3897
|
+
execute(command) {
|
|
3898
|
+
if (this.isApplying) {
|
|
3899
|
+
command.execute();
|
|
3900
|
+
return;
|
|
3901
|
+
}
|
|
3902
|
+
if (this.batchDepth > 0 && this.currentBatch) {
|
|
3903
|
+
command.execute();
|
|
3904
|
+
this.currentBatch.push({
|
|
3905
|
+
...command,
|
|
3906
|
+
timestamp: command.timestamp ?? Date.now()
|
|
3907
|
+
});
|
|
3908
|
+
return;
|
|
3909
|
+
}
|
|
3910
|
+
command.execute();
|
|
3911
|
+
this.undoStack.push({
|
|
3912
|
+
...command,
|
|
3913
|
+
timestamp: command.timestamp ?? Date.now()
|
|
3914
|
+
});
|
|
3915
|
+
if (this.undoStack.length > this.maxDepth) {
|
|
3916
|
+
this.undoStack.shift();
|
|
3917
|
+
}
|
|
3918
|
+
this.redoStack = [];
|
|
3919
|
+
this.notify();
|
|
3920
|
+
}
|
|
3921
|
+
/**
|
|
3922
|
+
* Executes a command, coalescing it with the previous command if they share
|
|
3923
|
+
* the same `tag` and occurred within `windowMs` (default: 300ms).
|
|
3924
|
+
* Useful for high-frequency interactions like slider scrubs or node drags.
|
|
3925
|
+
*/
|
|
3926
|
+
executeMerged(command, options = {}) {
|
|
3927
|
+
const windowMs = options.windowMs ?? 300;
|
|
3928
|
+
const now = Date.now();
|
|
3929
|
+
if (command.tag && this.undoStack.length > 0 && this.batchDepth === 0 && !this.isApplying) {
|
|
3930
|
+
const top = this.undoStack[this.undoStack.length - 1];
|
|
3931
|
+
const elapsed = top.timestamp ? now - top.timestamp : Infinity;
|
|
3932
|
+
if (top.tag === command.tag && elapsed <= windowMs) {
|
|
3933
|
+
command.execute();
|
|
3934
|
+
const initialUndo = top.undo;
|
|
3935
|
+
this.undoStack[this.undoStack.length - 1] = {
|
|
3936
|
+
name: command.name,
|
|
3937
|
+
tag: command.tag,
|
|
3938
|
+
timestamp: now,
|
|
3939
|
+
execute: command.execute,
|
|
3940
|
+
undo: initialUndo,
|
|
3941
|
+
redo: command.redo ?? command.execute
|
|
3942
|
+
};
|
|
3943
|
+
this.redoStack = [];
|
|
3944
|
+
this.notify();
|
|
3945
|
+
return;
|
|
3946
|
+
}
|
|
3947
|
+
}
|
|
3948
|
+
this.execute({ ...command, timestamp: now });
|
|
3949
|
+
}
|
|
3950
|
+
/**
|
|
3951
|
+
* Batches multiple commands executed within `fn` into a single atomic undo entry.
|
|
3952
|
+
*/
|
|
3953
|
+
batch(name, fn) {
|
|
3954
|
+
if (this.isApplying) {
|
|
3955
|
+
fn();
|
|
3956
|
+
return;
|
|
3957
|
+
}
|
|
3958
|
+
if (this.batchDepth > 0) {
|
|
3959
|
+
fn();
|
|
3960
|
+
return;
|
|
3961
|
+
}
|
|
3962
|
+
this.batchDepth++;
|
|
3963
|
+
this.currentBatch = [];
|
|
3964
|
+
try {
|
|
3965
|
+
fn();
|
|
3966
|
+
} finally {
|
|
3967
|
+
this.batchDepth--;
|
|
3968
|
+
const batchCommands = this.currentBatch;
|
|
3969
|
+
this.currentBatch = null;
|
|
3970
|
+
if (batchCommands && batchCommands.length > 0) {
|
|
3971
|
+
const compoundCommand = {
|
|
3972
|
+
name,
|
|
3973
|
+
timestamp: Date.now(),
|
|
3974
|
+
execute: () => {
|
|
3975
|
+
for (let i = 0; i < batchCommands.length; i++) {
|
|
3976
|
+
(batchCommands[i].redo ?? batchCommands[i].execute)();
|
|
3977
|
+
}
|
|
3978
|
+
},
|
|
3979
|
+
undo: () => {
|
|
3980
|
+
for (let i = batchCommands.length - 1; i >= 0; i--) {
|
|
3981
|
+
batchCommands[i].undo();
|
|
3982
|
+
}
|
|
3983
|
+
},
|
|
3984
|
+
redo: () => {
|
|
3985
|
+
for (let i = 0; i < batchCommands.length; i++) {
|
|
3986
|
+
(batchCommands[i].redo ?? batchCommands[i].execute)();
|
|
3987
|
+
}
|
|
3988
|
+
}
|
|
3989
|
+
};
|
|
3990
|
+
this.undoStack.push(compoundCommand);
|
|
3991
|
+
if (this.undoStack.length > this.maxDepth) {
|
|
3992
|
+
this.undoStack.shift();
|
|
3993
|
+
}
|
|
3994
|
+
this.redoStack = [];
|
|
3995
|
+
this.notify();
|
|
3996
|
+
}
|
|
3997
|
+
}
|
|
3998
|
+
}
|
|
3999
|
+
/**
|
|
4000
|
+
* Reverts the most recent command on the undo stack.
|
|
4001
|
+
* Returns true if a command was undone, false otherwise.
|
|
4002
|
+
*/
|
|
4003
|
+
undo() {
|
|
4004
|
+
if (this.undoStack.length === 0 || this.isApplying || this.batchDepth > 0) {
|
|
4005
|
+
return false;
|
|
4006
|
+
}
|
|
4007
|
+
this.isApplying = true;
|
|
4008
|
+
try {
|
|
4009
|
+
const command = this.undoStack.pop();
|
|
4010
|
+
command.undo();
|
|
4011
|
+
this.redoStack.push(command);
|
|
4012
|
+
return true;
|
|
4013
|
+
} finally {
|
|
4014
|
+
this.isApplying = false;
|
|
4015
|
+
this.notify();
|
|
4016
|
+
}
|
|
4017
|
+
}
|
|
4018
|
+
/**
|
|
4019
|
+
* Re-applies the most recent undone command on the redo stack.
|
|
4020
|
+
* Returns true if a command was redone, false otherwise.
|
|
4021
|
+
*/
|
|
4022
|
+
redo() {
|
|
4023
|
+
if (this.redoStack.length === 0 || this.isApplying || this.batchDepth > 0) {
|
|
4024
|
+
return false;
|
|
4025
|
+
}
|
|
4026
|
+
this.isApplying = true;
|
|
4027
|
+
try {
|
|
4028
|
+
const command = this.redoStack.pop();
|
|
4029
|
+
(command.redo ?? command.execute)();
|
|
4030
|
+
this.undoStack.push(command);
|
|
4031
|
+
return true;
|
|
4032
|
+
} finally {
|
|
4033
|
+
this.isApplying = false;
|
|
4034
|
+
this.notify();
|
|
4035
|
+
}
|
|
4036
|
+
}
|
|
4037
|
+
/**
|
|
4038
|
+
* Clears both undo and redo stacks.
|
|
4039
|
+
*/
|
|
4040
|
+
clear() {
|
|
4041
|
+
this.undoStack = [];
|
|
4042
|
+
this.redoStack = [];
|
|
4043
|
+
this.notify();
|
|
4044
|
+
}
|
|
4045
|
+
/**
|
|
4046
|
+
* Subscribes to history state changes.
|
|
4047
|
+
* The listener is immediately invoked with the current state.
|
|
4048
|
+
* Returns an unsubscribe function.
|
|
4049
|
+
*/
|
|
4050
|
+
subscribe(listener) {
|
|
4051
|
+
this.listeners.add(listener);
|
|
4052
|
+
listener(this.getState());
|
|
4053
|
+
return () => {
|
|
4054
|
+
this.listeners.delete(listener);
|
|
4055
|
+
};
|
|
4056
|
+
}
|
|
4057
|
+
/**
|
|
4058
|
+
* Utility helper to create a Command from before/after state snapshots.
|
|
4059
|
+
*/
|
|
4060
|
+
static createSnapshotCommand(options) {
|
|
4061
|
+
return {
|
|
4062
|
+
name: options.name,
|
|
4063
|
+
tag: options.tag,
|
|
4064
|
+
execute: () => options.apply(options.after),
|
|
4065
|
+
undo: () => options.apply(options.before),
|
|
4066
|
+
redo: () => options.apply(options.after)
|
|
4067
|
+
};
|
|
4068
|
+
}
|
|
4069
|
+
};
|
|
4070
|
+
function createHistoryManager(options = {}) {
|
|
4071
|
+
return new HistoryManager(options);
|
|
4072
|
+
}
|
|
3837
4073
|
export {
|
|
3838
4074
|
ColorHighlighter,
|
|
3839
4075
|
DataSourceBinder,
|
|
@@ -3844,6 +4080,7 @@ export {
|
|
|
3844
4080
|
FormulaEvaluator,
|
|
3845
4081
|
FormulaParser,
|
|
3846
4082
|
GradientText,
|
|
4083
|
+
HistoryManager,
|
|
3847
4084
|
INSTRUCTION_REGEX,
|
|
3848
4085
|
Image2 as Image,
|
|
3849
4086
|
LoadingNode,
|
|
@@ -3858,6 +4095,7 @@ export {
|
|
|
3858
4095
|
colNameToIndex,
|
|
3859
4096
|
createDirtyTracker,
|
|
3860
4097
|
createEditor,
|
|
4098
|
+
createHistoryManager,
|
|
3861
4099
|
createMentionExtension,
|
|
3862
4100
|
createRichTextPreset,
|
|
3863
4101
|
defaultIsEqual,
|