@kedataindo/docflow-plugins 0.0.88 → 0.0.90
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/index.cjs +441 -26
- package/dist/index.d.cts +54 -2
- package/dist/index.d.ts +54 -2
- package/dist/index.js +423 -22
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -47,10 +47,18 @@ __export(index_exports, {
|
|
|
47
47
|
LocationChipNode: () => LocationChipNode,
|
|
48
48
|
PageBreak: () => PageBreak,
|
|
49
49
|
PeopleChipNode: () => PeopleChipNode,
|
|
50
|
+
SUGGESTION_DELETE: () => SUGGESTION_DELETE,
|
|
51
|
+
SUGGESTION_FORMAT: () => SUGGESTION_FORMAT,
|
|
52
|
+
SUGGESTION_INSERT: () => SUGGESTION_INSERT,
|
|
50
53
|
SlashMenuExtension: () => SlashMenuExtension,
|
|
54
|
+
SuggestionDeleteMark: () => SuggestionDeleteMark,
|
|
55
|
+
SuggestionFormatMark: () => SuggestionFormatMark,
|
|
56
|
+
SuggestionInsertMark: () => SuggestionInsertMark,
|
|
51
57
|
TocEntryNode: () => TocEntryNode,
|
|
52
58
|
TocNode: () => TocNode,
|
|
53
59
|
TocPageNumNode: () => TocPageNumNode,
|
|
60
|
+
acceptAllSuggestions: () => acceptAllSuggestions,
|
|
61
|
+
acceptSuggestion: () => acceptSuggestion,
|
|
54
62
|
aiPlugin: () => aiPlugin,
|
|
55
63
|
aiPluginKey: () => aiPluginKey,
|
|
56
64
|
alignmentPlugin: () => alignmentPlugin,
|
|
@@ -67,6 +75,7 @@ __export(index_exports, {
|
|
|
67
75
|
formattingPlugin: () => formattingPlugin,
|
|
68
76
|
getAIPreview: () => getAIPreview,
|
|
69
77
|
getCitationEngine: () => getCitationEngine,
|
|
78
|
+
getSuggestions: () => getSuggestions,
|
|
70
79
|
headingsPlugin: () => headingsPlugin,
|
|
71
80
|
highlightPlugin: () => highlightPlugin,
|
|
72
81
|
imagePlugin: () => imagePlugin,
|
|
@@ -80,10 +89,15 @@ __export(index_exports, {
|
|
|
80
89
|
placeholderPlugin: () => placeholderPlugin,
|
|
81
90
|
regenerateToc: () => regenerateToc,
|
|
82
91
|
registerSlashCommands: () => registerSlashCommands,
|
|
92
|
+
rejectAllSuggestions: () => rejectAllSuggestions,
|
|
93
|
+
rejectSuggestion: () => rejectSuggestion,
|
|
83
94
|
sanitizeCiteprocHtml: () => sanitizeCiteprocHtml,
|
|
95
|
+
setDocumentMode: () => setDocumentMode,
|
|
96
|
+
setSuggestionAuthor: () => setSuggestionAuthor,
|
|
84
97
|
slashMenuPlugin: () => slashMenuPlugin,
|
|
85
98
|
slashState: () => slashState,
|
|
86
99
|
smartElementsPlugin: () => smartElementsPlugin,
|
|
100
|
+
suggestChangesPlugin: () => suggestChangesPlugin,
|
|
87
101
|
tablePageSplitPlugin: () => tablePageSplitPlugin,
|
|
88
102
|
tablePlugin: () => tablePlugin,
|
|
89
103
|
textColorPlugin: () => textColorPlugin,
|
|
@@ -2883,9 +2897,394 @@ var commentPlugin = {
|
|
|
2883
2897
|
commands: {}
|
|
2884
2898
|
};
|
|
2885
2899
|
|
|
2886
|
-
// src/
|
|
2900
|
+
// src/suggestChanges.ts
|
|
2887
2901
|
var import_core11 = require("@tiptap/core");
|
|
2902
|
+
var import_state3 = require("@tiptap/pm/state");
|
|
2903
|
+
var import_transform2 = require("@tiptap/pm/transform");
|
|
2888
2904
|
var import_docflow_core19 = require("@kedataindo/docflow-core");
|
|
2905
|
+
var SUGGESTION_INSERT = "suggestionInsert";
|
|
2906
|
+
var SUGGESTION_DELETE = "suggestionDelete";
|
|
2907
|
+
var SUGGESTION_FORMAT = "suggestionFormat";
|
|
2908
|
+
var FORMAT_MARKS = /* @__PURE__ */ new Set(["bold", "italic", "underline", "strike", "highlight"]);
|
|
2909
|
+
var SUGGEST_APPLIED_META = "suggestChanges:applied";
|
|
2910
|
+
var suggestChangesKey = new import_state3.PluginKey("suggestChanges");
|
|
2911
|
+
var suggestionAttributes = () => ({
|
|
2912
|
+
suggestionId: {
|
|
2913
|
+
default: null,
|
|
2914
|
+
parseHTML: (el) => el.getAttribute("data-suggestion-id"),
|
|
2915
|
+
renderHTML: (attrs) => attrs.suggestionId ? { "data-suggestion-id": attrs.suggestionId } : {}
|
|
2916
|
+
},
|
|
2917
|
+
authorId: {
|
|
2918
|
+
default: null,
|
|
2919
|
+
parseHTML: (el) => el.getAttribute("data-suggestion-author"),
|
|
2920
|
+
renderHTML: (attrs) => attrs.authorId ? { "data-suggestion-author": attrs.authorId } : {}
|
|
2921
|
+
},
|
|
2922
|
+
authorName: { default: null },
|
|
2923
|
+
createdAt: { default: null }
|
|
2924
|
+
});
|
|
2925
|
+
var SuggestionInsertMark = import_core11.Mark.create({
|
|
2926
|
+
name: SUGGESTION_INSERT,
|
|
2927
|
+
addAttributes() {
|
|
2928
|
+
return suggestionAttributes();
|
|
2929
|
+
},
|
|
2930
|
+
parseHTML() {
|
|
2931
|
+
return [{ tag: 'span[data-suggestion="insert"]' }];
|
|
2932
|
+
},
|
|
2933
|
+
renderHTML({ HTMLAttributes }) {
|
|
2934
|
+
return [
|
|
2935
|
+
"span",
|
|
2936
|
+
(0, import_core11.mergeAttributes)(HTMLAttributes, {
|
|
2937
|
+
"data-suggestion": "insert",
|
|
2938
|
+
class: "docflow-suggestion docflow-suggestion--insert"
|
|
2939
|
+
}),
|
|
2940
|
+
0
|
|
2941
|
+
];
|
|
2942
|
+
}
|
|
2943
|
+
});
|
|
2944
|
+
var SuggestionDeleteMark = import_core11.Mark.create({
|
|
2945
|
+
name: SUGGESTION_DELETE,
|
|
2946
|
+
addAttributes() {
|
|
2947
|
+
return suggestionAttributes();
|
|
2948
|
+
},
|
|
2949
|
+
parseHTML() {
|
|
2950
|
+
return [{ tag: 'span[data-suggestion="delete"]' }];
|
|
2951
|
+
},
|
|
2952
|
+
renderHTML({ HTMLAttributes }) {
|
|
2953
|
+
return [
|
|
2954
|
+
"span",
|
|
2955
|
+
(0, import_core11.mergeAttributes)(HTMLAttributes, {
|
|
2956
|
+
"data-suggestion": "delete",
|
|
2957
|
+
class: "docflow-suggestion docflow-suggestion--delete"
|
|
2958
|
+
}),
|
|
2959
|
+
0
|
|
2960
|
+
];
|
|
2961
|
+
}
|
|
2962
|
+
});
|
|
2963
|
+
var SuggestionFormatMark = import_core11.Mark.create({
|
|
2964
|
+
name: SUGGESTION_FORMAT,
|
|
2965
|
+
addAttributes() {
|
|
2966
|
+
return {
|
|
2967
|
+
...suggestionAttributes(),
|
|
2968
|
+
format: {
|
|
2969
|
+
default: null,
|
|
2970
|
+
parseHTML: (el) => el.getAttribute("data-suggestion-format"),
|
|
2971
|
+
renderHTML: (attrs) => attrs.format ? { "data-suggestion-format": attrs.format } : {}
|
|
2972
|
+
},
|
|
2973
|
+
delta: { default: "add" }
|
|
2974
|
+
};
|
|
2975
|
+
},
|
|
2976
|
+
parseHTML() {
|
|
2977
|
+
return [{ tag: 'span[data-suggestion="format"]' }];
|
|
2978
|
+
},
|
|
2979
|
+
renderHTML({ HTMLAttributes }) {
|
|
2980
|
+
return [
|
|
2981
|
+
"span",
|
|
2982
|
+
(0, import_core11.mergeAttributes)(HTMLAttributes, {
|
|
2983
|
+
"data-suggestion": "format",
|
|
2984
|
+
class: "docflow-suggestion docflow-suggestion--format"
|
|
2985
|
+
}),
|
|
2986
|
+
0
|
|
2987
|
+
];
|
|
2988
|
+
}
|
|
2989
|
+
});
|
|
2990
|
+
var suggestionSeq = 0;
|
|
2991
|
+
var newSuggestionId = () => {
|
|
2992
|
+
suggestionSeq += 1;
|
|
2993
|
+
return `sug-${Date.now().toString(36)}-${suggestionSeq.toString(36)}`;
|
|
2994
|
+
};
|
|
2995
|
+
var adjacentRunId = (editorState, pos, markName) => {
|
|
2996
|
+
if (pos <= 0) return null;
|
|
2997
|
+
const before = editorState.doc.resolve(pos).nodeBefore;
|
|
2998
|
+
if (!before || !before.isText) return null;
|
|
2999
|
+
const mark = before.marks.find((m) => m.type.name === markName);
|
|
3000
|
+
return mark?.attrs.suggestionId ?? null;
|
|
3001
|
+
};
|
|
3002
|
+
var markAttrs = (id, author) => ({
|
|
3003
|
+
suggestionId: id,
|
|
3004
|
+
authorId: author.id ?? null,
|
|
3005
|
+
authorName: author.name ?? null,
|
|
3006
|
+
createdAt: Date.now()
|
|
3007
|
+
});
|
|
3008
|
+
var collectRanges = (doc, markName, id) => {
|
|
3009
|
+
const out = [];
|
|
3010
|
+
doc.descendants((node, pos) => {
|
|
3011
|
+
if (!node.isText || node.marks.length === 0) return;
|
|
3012
|
+
for (const mark of node.marks) {
|
|
3013
|
+
if (mark.type.name !== markName) continue;
|
|
3014
|
+
if (id && mark.attrs.suggestionId !== id) continue;
|
|
3015
|
+
out.push({ from: pos, to: pos + node.nodeSize, attrs: mark.attrs });
|
|
3016
|
+
}
|
|
3017
|
+
});
|
|
3018
|
+
return out;
|
|
3019
|
+
};
|
|
3020
|
+
var SuggestChanges = import_core11.Extension.create({
|
|
3021
|
+
name: "suggestChanges",
|
|
3022
|
+
addStorage() {
|
|
3023
|
+
return { suggestions: [] };
|
|
3024
|
+
},
|
|
3025
|
+
addProseMirrorPlugins() {
|
|
3026
|
+
const editor = this.editor;
|
|
3027
|
+
const syncStorage = () => {
|
|
3028
|
+
const storage = editor.storage.suggestChanges;
|
|
3029
|
+
if (storage) storage.suggestions = getSuggestions(editor);
|
|
3030
|
+
};
|
|
3031
|
+
return [
|
|
3032
|
+
new import_state3.Plugin({
|
|
3033
|
+
key: suggestChangesKey,
|
|
3034
|
+
state: {
|
|
3035
|
+
init: () => ({ mode: "editing", author: {} }),
|
|
3036
|
+
apply: (tr, value) => {
|
|
3037
|
+
const meta = tr.getMeta(suggestChangesKey);
|
|
3038
|
+
if (!meta) return value;
|
|
3039
|
+
return {
|
|
3040
|
+
mode: meta.mode ?? value.mode,
|
|
3041
|
+
author: meta.author ?? value.author
|
|
3042
|
+
};
|
|
3043
|
+
}
|
|
3044
|
+
},
|
|
3045
|
+
view: () => {
|
|
3046
|
+
syncStorage();
|
|
3047
|
+
return { update: syncStorage };
|
|
3048
|
+
},
|
|
3049
|
+
appendTransaction: (transactions, _oldState, newState) => {
|
|
3050
|
+
if (transactions.some((tr2) => tr2.getMeta(SUGGEST_APPLIED_META))) return null;
|
|
3051
|
+
const current = suggestChangesKey.getState(newState);
|
|
3052
|
+
if (current?.mode !== "suggesting") return null;
|
|
3053
|
+
const formatMark = newState.schema.marks[SUGGESTION_FORMAT];
|
|
3054
|
+
if (!formatMark) return null;
|
|
3055
|
+
const changes = [];
|
|
3056
|
+
for (const tr2 of transactions) {
|
|
3057
|
+
for (const step of tr2.steps) {
|
|
3058
|
+
if (step instanceof import_transform2.AddMarkStep || step instanceof import_transform2.RemoveMarkStep) {
|
|
3059
|
+
if (!FORMAT_MARKS.has(step.mark.type.name)) continue;
|
|
3060
|
+
changes.push({ from: step.from, to: step.to, name: step.mark.type.name, add: step instanceof import_transform2.AddMarkStep });
|
|
3061
|
+
}
|
|
3062
|
+
}
|
|
3063
|
+
}
|
|
3064
|
+
if (changes.length === 0) return null;
|
|
3065
|
+
const tr = newState.tr;
|
|
3066
|
+
for (const change of changes) {
|
|
3067
|
+
const target = newState.schema.marks[change.name];
|
|
3068
|
+
if (!target) continue;
|
|
3069
|
+
if (change.add) tr.removeMark(change.from, change.to, target);
|
|
3070
|
+
else tr.addMark(change.from, change.to, target.create());
|
|
3071
|
+
tr.addMark(
|
|
3072
|
+
change.from,
|
|
3073
|
+
change.to,
|
|
3074
|
+
formatMark.create({ ...markAttrs(newSuggestionId(), current.author), format: change.name, delta: change.add ? "add" : "remove" })
|
|
3075
|
+
);
|
|
3076
|
+
}
|
|
3077
|
+
tr.setMeta(SUGGEST_APPLIED_META, true);
|
|
3078
|
+
return tr;
|
|
3079
|
+
},
|
|
3080
|
+
props: {
|
|
3081
|
+
handleTextInput: (view, from, to, text) => {
|
|
3082
|
+
const current = suggestChangesKey.getState(view.state);
|
|
3083
|
+
if (current?.mode !== "suggesting" || !text) return false;
|
|
3084
|
+
const insert = view.state.schema.marks[SUGGESTION_INSERT];
|
|
3085
|
+
const del = view.state.schema.marks[SUGGESTION_DELETE];
|
|
3086
|
+
if (!insert || !del) return false;
|
|
3087
|
+
const id = adjacentRunId(view.state, from, SUGGESTION_INSERT) ?? newSuggestionId();
|
|
3088
|
+
const tr = view.state.tr;
|
|
3089
|
+
if (to > from) tr.addMark(from, to, del.create(markAttrs(id, current.author)));
|
|
3090
|
+
const insertAt = to;
|
|
3091
|
+
tr.insertText(text, insertAt, insertAt);
|
|
3092
|
+
tr.addMark(insertAt, insertAt + text.length, insert.create(markAttrs(id, current.author)));
|
|
3093
|
+
view.dispatch(tr);
|
|
3094
|
+
return true;
|
|
3095
|
+
},
|
|
3096
|
+
handleKeyDown: (view, event) => {
|
|
3097
|
+
const current = suggestChangesKey.getState(view.state);
|
|
3098
|
+
if (current?.mode !== "suggesting") return false;
|
|
3099
|
+
if (event.key !== "Backspace" && event.key !== "Delete") return false;
|
|
3100
|
+
const del = view.state.schema.marks[SUGGESTION_DELETE];
|
|
3101
|
+
if (!del) return false;
|
|
3102
|
+
const { selection, doc } = view.state;
|
|
3103
|
+
let from;
|
|
3104
|
+
let to;
|
|
3105
|
+
if (!selection.empty) {
|
|
3106
|
+
from = selection.from;
|
|
3107
|
+
to = selection.to;
|
|
3108
|
+
} else if (event.key === "Backspace") {
|
|
3109
|
+
if (selection.from <= 1) return false;
|
|
3110
|
+
from = selection.from - 1;
|
|
3111
|
+
to = selection.from;
|
|
3112
|
+
} else {
|
|
3113
|
+
if (selection.to >= doc.content.size - 1) return false;
|
|
3114
|
+
from = selection.to;
|
|
3115
|
+
to = selection.to + 1;
|
|
3116
|
+
}
|
|
3117
|
+
const id = adjacentRunId(view.state, from, SUGGESTION_DELETE) ?? newSuggestionId();
|
|
3118
|
+
const tr = view.state.tr.addMark(from, to, del.create(markAttrs(id, current.author)));
|
|
3119
|
+
if (event.key === "Backspace" && selection.empty) {
|
|
3120
|
+
tr.setSelection(import_state3.TextSelection.create(tr.doc, from));
|
|
3121
|
+
}
|
|
3122
|
+
view.dispatch(tr);
|
|
3123
|
+
return true;
|
|
3124
|
+
},
|
|
3125
|
+
handlePaste: (view, _event, slice) => {
|
|
3126
|
+
const current = suggestChangesKey.getState(view.state);
|
|
3127
|
+
if (current?.mode !== "suggesting") return false;
|
|
3128
|
+
const insert = view.state.schema.marks[SUGGESTION_INSERT];
|
|
3129
|
+
const del = view.state.schema.marks[SUGGESTION_DELETE];
|
|
3130
|
+
if (!insert || !del) return false;
|
|
3131
|
+
const { from, to } = view.state.selection;
|
|
3132
|
+
const id = adjacentRunId(view.state, from, SUGGESTION_INSERT) ?? newSuggestionId();
|
|
3133
|
+
const tr = view.state.tr;
|
|
3134
|
+
if (to > from) tr.addMark(from, to, del.create(markAttrs(id, current.author)));
|
|
3135
|
+
const insertAt = to;
|
|
3136
|
+
tr.insert(insertAt, slice.content);
|
|
3137
|
+
tr.addMark(insertAt, insertAt + slice.content.size, insert.create(markAttrs(id, current.author)));
|
|
3138
|
+
view.dispatch(tr);
|
|
3139
|
+
return true;
|
|
3140
|
+
}
|
|
3141
|
+
}
|
|
3142
|
+
})
|
|
3143
|
+
];
|
|
3144
|
+
},
|
|
3145
|
+
addCommands() {
|
|
3146
|
+
return {
|
|
3147
|
+
setDocumentMode: (mode) => ({ state, dispatch }) => {
|
|
3148
|
+
if (!dispatch) return false;
|
|
3149
|
+
dispatch(state.tr.setMeta(suggestChangesKey, { mode }));
|
|
3150
|
+
return true;
|
|
3151
|
+
},
|
|
3152
|
+
setSuggestionAuthor: (author) => ({ state, dispatch }) => {
|
|
3153
|
+
if (!dispatch) return false;
|
|
3154
|
+
dispatch(state.tr.setMeta(suggestChangesKey, { author }));
|
|
3155
|
+
return true;
|
|
3156
|
+
},
|
|
3157
|
+
acceptSuggestion: (id) => ({ state, dispatch }) => {
|
|
3158
|
+
const tr = buildResolveTr(state, true, id);
|
|
3159
|
+
if (!tr || !dispatch) return false;
|
|
3160
|
+
dispatch(tr);
|
|
3161
|
+
return true;
|
|
3162
|
+
},
|
|
3163
|
+
rejectSuggestion: (id) => ({ state, dispatch }) => {
|
|
3164
|
+
const tr = buildResolveTr(state, false, id);
|
|
3165
|
+
if (!tr || !dispatch) return false;
|
|
3166
|
+
dispatch(tr);
|
|
3167
|
+
return true;
|
|
3168
|
+
},
|
|
3169
|
+
acceptAllSuggestions: () => ({ state, dispatch }) => {
|
|
3170
|
+
const tr = buildResolveTr(state, true);
|
|
3171
|
+
if (!tr || !dispatch) return false;
|
|
3172
|
+
dispatch(tr);
|
|
3173
|
+
return true;
|
|
3174
|
+
},
|
|
3175
|
+
rejectAllSuggestions: () => ({ state, dispatch }) => {
|
|
3176
|
+
const tr = buildResolveTr(state, false);
|
|
3177
|
+
if (!tr || !dispatch) return false;
|
|
3178
|
+
dispatch(tr);
|
|
3179
|
+
return true;
|
|
3180
|
+
}
|
|
3181
|
+
};
|
|
3182
|
+
}
|
|
3183
|
+
});
|
|
3184
|
+
function editorDispatch(editor, meta) {
|
|
3185
|
+
editor.view.dispatch(editor.state.tr.setMeta(suggestChangesKey, meta));
|
|
3186
|
+
}
|
|
3187
|
+
function setDocumentMode(editor, mode) {
|
|
3188
|
+
editorDispatch(editor, { mode });
|
|
3189
|
+
return true;
|
|
3190
|
+
}
|
|
3191
|
+
function setSuggestionAuthor(editor, author) {
|
|
3192
|
+
editorDispatch(editor, { author });
|
|
3193
|
+
return true;
|
|
3194
|
+
}
|
|
3195
|
+
function getSuggestions(editor) {
|
|
3196
|
+
const byId = /* @__PURE__ */ new Map();
|
|
3197
|
+
const scan = (markName, type) => {
|
|
3198
|
+
editor.state.doc.descendants((node, pos) => {
|
|
3199
|
+
if (!node.isText) return;
|
|
3200
|
+
for (const mark of node.marks) {
|
|
3201
|
+
if (mark.type.name !== markName) continue;
|
|
3202
|
+
const id = mark.attrs.suggestionId;
|
|
3203
|
+
const existing = byId.get(id);
|
|
3204
|
+
if (existing) {
|
|
3205
|
+
existing.from = Math.min(existing.from, pos);
|
|
3206
|
+
existing.to = Math.max(existing.to, pos + node.nodeSize);
|
|
3207
|
+
} else {
|
|
3208
|
+
byId.set(id, {
|
|
3209
|
+
id,
|
|
3210
|
+
type,
|
|
3211
|
+
authorId: mark.attrs.authorId ?? null,
|
|
3212
|
+
authorName: mark.attrs.authorName ?? null,
|
|
3213
|
+
from: pos,
|
|
3214
|
+
to: pos + node.nodeSize,
|
|
3215
|
+
...type === "format" ? {
|
|
3216
|
+
format: mark.attrs.format ?? void 0,
|
|
3217
|
+
delta: mark.attrs.delta ?? void 0
|
|
3218
|
+
} : {}
|
|
3219
|
+
});
|
|
3220
|
+
}
|
|
3221
|
+
}
|
|
3222
|
+
});
|
|
3223
|
+
};
|
|
3224
|
+
scan(SUGGESTION_INSERT, "insert");
|
|
3225
|
+
scan(SUGGESTION_DELETE, "delete");
|
|
3226
|
+
scan(SUGGESTION_FORMAT, "format");
|
|
3227
|
+
return [...byId.values()].sort((a, b) => a.from - b.from);
|
|
3228
|
+
}
|
|
3229
|
+
function buildResolveTr(state, accept, id) {
|
|
3230
|
+
const { schema } = state;
|
|
3231
|
+
const insertMark = schema.marks[SUGGESTION_INSERT];
|
|
3232
|
+
const deleteMark = schema.marks[SUGGESTION_DELETE];
|
|
3233
|
+
const formatMark = schema.marks[SUGGESTION_FORMAT];
|
|
3234
|
+
if (!insertMark || !deleteMark) return null;
|
|
3235
|
+
const insertRanges = collectRanges(state.doc, SUGGESTION_INSERT, id);
|
|
3236
|
+
const deleteRanges = collectRanges(state.doc, SUGGESTION_DELETE, id);
|
|
3237
|
+
const formatRanges = formatMark ? collectRanges(state.doc, SUGGESTION_FORMAT, id) : [];
|
|
3238
|
+
if (insertRanges.length === 0 && deleteRanges.length === 0 && formatRanges.length === 0) return null;
|
|
3239
|
+
const tr = state.tr;
|
|
3240
|
+
for (const range of formatRanges) {
|
|
3241
|
+
if (accept) {
|
|
3242
|
+
const target = schema.marks[range.attrs.format];
|
|
3243
|
+
if (target) {
|
|
3244
|
+
if (range.attrs.delta === "remove") tr.removeMark(range.from, range.to, target);
|
|
3245
|
+
else tr.addMark(range.from, range.to, target.create());
|
|
3246
|
+
}
|
|
3247
|
+
}
|
|
3248
|
+
if (formatMark) tr.removeMark(range.from, range.to, formatMark);
|
|
3249
|
+
}
|
|
3250
|
+
const rangesToUnmark = accept ? insertRanges : deleteRanges;
|
|
3251
|
+
const markToRemove = accept ? insertMark : deleteMark;
|
|
3252
|
+
const rangesToDelete = accept ? deleteRanges : insertRanges;
|
|
3253
|
+
for (const range of rangesToUnmark) {
|
|
3254
|
+
tr.removeMark(range.from, range.to, markToRemove);
|
|
3255
|
+
}
|
|
3256
|
+
for (const range of [...rangesToDelete].sort((a, b) => b.from - a.from)) {
|
|
3257
|
+
tr.delete(range.from, range.to);
|
|
3258
|
+
}
|
|
3259
|
+
tr.setMeta(SUGGEST_APPLIED_META, true);
|
|
3260
|
+
return tr.docChanged ? tr : null;
|
|
3261
|
+
}
|
|
3262
|
+
function resolveSuggestions(editor, accept, id) {
|
|
3263
|
+
const tr = buildResolveTr(editor.state, accept, id);
|
|
3264
|
+
if (!tr) return false;
|
|
3265
|
+
editor.view.dispatch(tr);
|
|
3266
|
+
return true;
|
|
3267
|
+
}
|
|
3268
|
+
var acceptSuggestion = (editor, id) => resolveSuggestions(editor, true, id);
|
|
3269
|
+
var rejectSuggestion = (editor, id) => resolveSuggestions(editor, false, id);
|
|
3270
|
+
var acceptAllSuggestions = (editor) => resolveSuggestions(editor, true);
|
|
3271
|
+
var rejectAllSuggestions = (editor) => resolveSuggestions(editor, false);
|
|
3272
|
+
var suggestChangesPlugin = (0, import_docflow_core19.definePlugin)({
|
|
3273
|
+
id: "suggestChanges",
|
|
3274
|
+
tiptapExtensions: [SuggestionInsertMark, SuggestionDeleteMark, SuggestionFormatMark, SuggestChanges],
|
|
3275
|
+
commands: {
|
|
3276
|
+
setDocumentMode: (editor, ...args) => setDocumentMode(editor, args[0]),
|
|
3277
|
+
setSuggestionAuthor: (editor, ...args) => setSuggestionAuthor(editor, args[0] ?? {}),
|
|
3278
|
+
acceptSuggestion: (editor, ...args) => acceptSuggestion(editor, args[0]),
|
|
3279
|
+
rejectSuggestion: (editor, ...args) => rejectSuggestion(editor, args[0]),
|
|
3280
|
+
acceptAllSuggestions: (editor) => acceptAllSuggestions(editor),
|
|
3281
|
+
rejectAllSuggestions: (editor) => rejectAllSuggestions(editor)
|
|
3282
|
+
}
|
|
3283
|
+
});
|
|
3284
|
+
|
|
3285
|
+
// src/smartElements.ts
|
|
3286
|
+
var import_core12 = require("@tiptap/core");
|
|
3287
|
+
var import_docflow_core20 = require("@kedataindo/docflow-core");
|
|
2889
3288
|
function todayISO() {
|
|
2890
3289
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2891
3290
|
}
|
|
@@ -2902,7 +3301,7 @@ var DEFAULT_STATUSES = ["To Do", "In Progress", "Review", "Approved"];
|
|
|
2902
3301
|
function slugify(s) {
|
|
2903
3302
|
return s.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
|
|
2904
3303
|
}
|
|
2905
|
-
var DateChipNode =
|
|
3304
|
+
var DateChipNode = import_core12.Node.create({
|
|
2906
3305
|
name: "dateChip",
|
|
2907
3306
|
group: "inline",
|
|
2908
3307
|
inline: true,
|
|
@@ -2922,7 +3321,7 @@ var DateChipNode = import_core11.Node.create({
|
|
|
2922
3321
|
return [{ tag: 'span[data-node-type="date-chip"]' }];
|
|
2923
3322
|
},
|
|
2924
3323
|
renderHTML({ node, HTMLAttributes }) {
|
|
2925
|
-
return ["span", (0,
|
|
3324
|
+
return ["span", (0, import_core12.mergeAttributes)(HTMLAttributes, {
|
|
2926
3325
|
"data-node-type": "date-chip",
|
|
2927
3326
|
class: "docs-chip docs-chip--date"
|
|
2928
3327
|
}), formatDate(node.attrs.date)];
|
|
@@ -2975,7 +3374,7 @@ var DateChipNode = import_core11.Node.create({
|
|
|
2975
3374
|
};
|
|
2976
3375
|
}
|
|
2977
3376
|
});
|
|
2978
|
-
var PeopleChipNode =
|
|
3377
|
+
var PeopleChipNode = import_core12.Node.create({
|
|
2979
3378
|
name: "peopleChip",
|
|
2980
3379
|
group: "inline",
|
|
2981
3380
|
inline: true,
|
|
@@ -3000,7 +3399,7 @@ var PeopleChipNode = import_core11.Node.create({
|
|
|
3000
3399
|
return [{ tag: 'span[data-node-type="people-chip"]' }];
|
|
3001
3400
|
},
|
|
3002
3401
|
renderHTML({ node, HTMLAttributes }) {
|
|
3003
|
-
return ["span", (0,
|
|
3402
|
+
return ["span", (0, import_core12.mergeAttributes)(HTMLAttributes, {
|
|
3004
3403
|
"data-node-type": "people-chip",
|
|
3005
3404
|
class: "docs-chip docs-chip--people"
|
|
3006
3405
|
}), `@${node.attrs.name || "user"}`];
|
|
@@ -3037,7 +3436,7 @@ var PeopleChipNode = import_core11.Node.create({
|
|
|
3037
3436
|
};
|
|
3038
3437
|
}
|
|
3039
3438
|
});
|
|
3040
|
-
var FileChipNode =
|
|
3439
|
+
var FileChipNode = import_core12.Node.create({
|
|
3041
3440
|
name: "fileChip",
|
|
3042
3441
|
group: "inline",
|
|
3043
3442
|
inline: true,
|
|
@@ -3062,7 +3461,7 @@ var FileChipNode = import_core11.Node.create({
|
|
|
3062
3461
|
return [{ tag: 'span[data-node-type="file-chip"]' }];
|
|
3063
3462
|
},
|
|
3064
3463
|
renderHTML({ node, HTMLAttributes }) {
|
|
3065
|
-
return ["span", (0,
|
|
3464
|
+
return ["span", (0, import_core12.mergeAttributes)(HTMLAttributes, {
|
|
3066
3465
|
"data-node-type": "file-chip",
|
|
3067
3466
|
class: "docs-chip docs-chip--file"
|
|
3068
3467
|
}), node.attrs.name || "file"];
|
|
@@ -3099,7 +3498,7 @@ var FileChipNode = import_core11.Node.create({
|
|
|
3099
3498
|
};
|
|
3100
3499
|
}
|
|
3101
3500
|
});
|
|
3102
|
-
var DropdownChipNode =
|
|
3501
|
+
var DropdownChipNode = import_core12.Node.create({
|
|
3103
3502
|
name: "dropdownChip",
|
|
3104
3503
|
group: "inline",
|
|
3105
3504
|
inline: true,
|
|
@@ -3130,7 +3529,7 @@ var DropdownChipNode = import_core11.Node.create({
|
|
|
3130
3529
|
return [{ tag: 'span[data-node-type="dropdown-chip"]' }];
|
|
3131
3530
|
},
|
|
3132
3531
|
renderHTML({ node, HTMLAttributes }) {
|
|
3133
|
-
return ["span", (0,
|
|
3532
|
+
return ["span", (0, import_core12.mergeAttributes)(HTMLAttributes, {
|
|
3134
3533
|
"data-node-type": "dropdown-chip",
|
|
3135
3534
|
class: "docs-chip docs-chip--dropdown"
|
|
3136
3535
|
}), node.attrs.selected || ""];
|
|
@@ -3182,7 +3581,7 @@ var DropdownChipNode = import_core11.Node.create({
|
|
|
3182
3581
|
};
|
|
3183
3582
|
}
|
|
3184
3583
|
});
|
|
3185
|
-
var LocationChipNode =
|
|
3584
|
+
var LocationChipNode = import_core12.Node.create({
|
|
3186
3585
|
name: "locationChip",
|
|
3187
3586
|
group: "inline",
|
|
3188
3587
|
inline: true,
|
|
@@ -3218,7 +3617,7 @@ var LocationChipNode = import_core11.Node.create({
|
|
|
3218
3617
|
return [{ tag: 'span[data-node-type="location-chip"]' }];
|
|
3219
3618
|
},
|
|
3220
3619
|
renderHTML({ node, HTMLAttributes }) {
|
|
3221
|
-
return ["span", (0,
|
|
3620
|
+
return ["span", (0, import_core12.mergeAttributes)(HTMLAttributes, {
|
|
3222
3621
|
"data-node-type": "location-chip",
|
|
3223
3622
|
class: "docs-chip docs-chip--location"
|
|
3224
3623
|
}), node.attrs.label || ""];
|
|
@@ -3255,7 +3654,7 @@ var LocationChipNode = import_core11.Node.create({
|
|
|
3255
3654
|
};
|
|
3256
3655
|
}
|
|
3257
3656
|
});
|
|
3258
|
-
var smartElementsPlugin = (0,
|
|
3657
|
+
var smartElementsPlugin = (0, import_docflow_core20.definePlugin)({
|
|
3259
3658
|
id: "smart-elements",
|
|
3260
3659
|
tiptapExtensions: [
|
|
3261
3660
|
DateChipNode,
|
|
@@ -3314,10 +3713,10 @@ var smartElementsPlugin = (0, import_docflow_core19.definePlugin)({
|
|
|
3314
3713
|
});
|
|
3315
3714
|
|
|
3316
3715
|
// src/tablePageSplit.ts
|
|
3317
|
-
var
|
|
3318
|
-
var
|
|
3319
|
-
var
|
|
3320
|
-
var PLUGIN_KEY = new
|
|
3716
|
+
var import_docflow_core21 = require("@kedataindo/docflow-core");
|
|
3717
|
+
var import_core13 = require("@tiptap/core");
|
|
3718
|
+
var import_state4 = require("@tiptap/pm/state");
|
|
3719
|
+
var PLUGIN_KEY = new import_state4.PluginKey("docflow/table-page-split");
|
|
3321
3720
|
var SPLIT_MARK = "head";
|
|
3322
3721
|
var MAX_SPLIT_DEPTH = 16;
|
|
3323
3722
|
function readPageContentHeightPx(view, editor) {
|
|
@@ -3492,9 +3891,10 @@ function runSplitPass(view, editor) {
|
|
|
3492
3891
|
tr.replaceWith(pos, pos + node.nodeSize, chain);
|
|
3493
3892
|
}
|
|
3494
3893
|
tr.setMeta(PLUGIN_KEY, { splitAtRow: -1 });
|
|
3894
|
+
tr.setMeta("addToHistory", false);
|
|
3495
3895
|
v.dispatch(tr);
|
|
3496
3896
|
}
|
|
3497
|
-
var TablePageSplitExtension =
|
|
3897
|
+
var TablePageSplitExtension = import_core13.Extension.create({
|
|
3498
3898
|
name: "tablePageSplit",
|
|
3499
3899
|
addProseMirrorPlugins() {
|
|
3500
3900
|
let viewRef = null;
|
|
@@ -3502,7 +3902,7 @@ var TablePageSplitExtension = import_core12.Extension.create({
|
|
|
3502
3902
|
const ext = this;
|
|
3503
3903
|
const editorRef = ext.editor ?? null;
|
|
3504
3904
|
return [
|
|
3505
|
-
new
|
|
3905
|
+
new import_state4.Plugin({
|
|
3506
3906
|
key: PLUGIN_KEY,
|
|
3507
3907
|
view(_editorView) {
|
|
3508
3908
|
viewRef = _editorView;
|
|
@@ -3534,15 +3934,15 @@ var TablePageSplitExtension = import_core12.Extension.create({
|
|
|
3534
3934
|
];
|
|
3535
3935
|
}
|
|
3536
3936
|
});
|
|
3537
|
-
var tablePageSplitPlugin = (0,
|
|
3937
|
+
var tablePageSplitPlugin = (0, import_docflow_core21.definePlugin)({
|
|
3538
3938
|
id: "tablePageSplit",
|
|
3539
3939
|
tiptapExtensions: [TablePageSplitExtension]
|
|
3540
3940
|
});
|
|
3541
3941
|
|
|
3542
3942
|
// src/slashMenu.ts
|
|
3543
|
-
var
|
|
3544
|
-
var
|
|
3545
|
-
var
|
|
3943
|
+
var import_core14 = require("@tiptap/core");
|
|
3944
|
+
var import_state5 = require("@tiptap/pm/state");
|
|
3945
|
+
var import_docflow_core22 = require("@kedataindo/docflow-core");
|
|
3546
3946
|
var slashState = {
|
|
3547
3947
|
open: false,
|
|
3548
3948
|
query: "",
|
|
@@ -3596,12 +3996,12 @@ function getRegisteredCommands() {
|
|
|
3596
3996
|
return true;
|
|
3597
3997
|
});
|
|
3598
3998
|
}
|
|
3599
|
-
var SlashMenuExtension =
|
|
3999
|
+
var SlashMenuExtension = import_core14.Extension.create({
|
|
3600
4000
|
name: "slashMenu",
|
|
3601
4001
|
addProseMirrorPlugins() {
|
|
3602
4002
|
return [
|
|
3603
|
-
new
|
|
3604
|
-
key: new
|
|
4003
|
+
new import_state5.Plugin({
|
|
4004
|
+
key: new import_state5.PluginKey("slashMenu"),
|
|
3605
4005
|
props: {
|
|
3606
4006
|
handleTextInput(view, from, _to, text) {
|
|
3607
4007
|
if (text === "/") {
|
|
@@ -3687,7 +4087,7 @@ var SlashMenuExtension = import_core13.Extension.create({
|
|
|
3687
4087
|
];
|
|
3688
4088
|
}
|
|
3689
4089
|
});
|
|
3690
|
-
var slashMenuPlugin = (0,
|
|
4090
|
+
var slashMenuPlugin = (0, import_docflow_core22.definePlugin)({
|
|
3691
4091
|
id: "slash-menu",
|
|
3692
4092
|
tiptapExtensions: [SlashMenuExtension],
|
|
3693
4093
|
hooks: {
|
|
@@ -3720,6 +4120,7 @@ var defaultPlugins = [
|
|
|
3720
4120
|
citationPlugin,
|
|
3721
4121
|
aiPlugin,
|
|
3722
4122
|
commentPlugin,
|
|
4123
|
+
suggestChangesPlugin,
|
|
3723
4124
|
smartElementsPlugin
|
|
3724
4125
|
];
|
|
3725
4126
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -3741,10 +4142,18 @@ var defaultPlugins = [
|
|
|
3741
4142
|
LocationChipNode,
|
|
3742
4143
|
PageBreak,
|
|
3743
4144
|
PeopleChipNode,
|
|
4145
|
+
SUGGESTION_DELETE,
|
|
4146
|
+
SUGGESTION_FORMAT,
|
|
4147
|
+
SUGGESTION_INSERT,
|
|
3744
4148
|
SlashMenuExtension,
|
|
4149
|
+
SuggestionDeleteMark,
|
|
4150
|
+
SuggestionFormatMark,
|
|
4151
|
+
SuggestionInsertMark,
|
|
3745
4152
|
TocEntryNode,
|
|
3746
4153
|
TocNode,
|
|
3747
4154
|
TocPageNumNode,
|
|
4155
|
+
acceptAllSuggestions,
|
|
4156
|
+
acceptSuggestion,
|
|
3748
4157
|
aiPlugin,
|
|
3749
4158
|
aiPluginKey,
|
|
3750
4159
|
alignmentPlugin,
|
|
@@ -3761,6 +4170,7 @@ var defaultPlugins = [
|
|
|
3761
4170
|
formattingPlugin,
|
|
3762
4171
|
getAIPreview,
|
|
3763
4172
|
getCitationEngine,
|
|
4173
|
+
getSuggestions,
|
|
3764
4174
|
headingsPlugin,
|
|
3765
4175
|
highlightPlugin,
|
|
3766
4176
|
imagePlugin,
|
|
@@ -3774,10 +4184,15 @@ var defaultPlugins = [
|
|
|
3774
4184
|
placeholderPlugin,
|
|
3775
4185
|
regenerateToc,
|
|
3776
4186
|
registerSlashCommands,
|
|
4187
|
+
rejectAllSuggestions,
|
|
4188
|
+
rejectSuggestion,
|
|
3777
4189
|
sanitizeCiteprocHtml,
|
|
4190
|
+
setDocumentMode,
|
|
4191
|
+
setSuggestionAuthor,
|
|
3778
4192
|
slashMenuPlugin,
|
|
3779
4193
|
slashState,
|
|
3780
4194
|
smartElementsPlugin,
|
|
4195
|
+
suggestChangesPlugin,
|
|
3781
4196
|
tablePageSplitPlugin,
|
|
3782
4197
|
tablePlugin,
|
|
3783
4198
|
textColorPlugin,
|