@kedataindo/docflow-plugins 0.0.87 → 0.0.89
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 +456 -28
- package/dist/index.d.cts +54 -2
- package/dist/index.d.ts +54 -2
- package/dist/index.js +438 -24
- 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,
|
|
@@ -911,8 +925,22 @@ var GoogleDocsHighlight = import_extension_highlight.default.extend({
|
|
|
911
925
|
return [
|
|
912
926
|
// Standard <mark> tag (default TipTap behavior)
|
|
913
927
|
{ tag: "mark" },
|
|
914
|
-
// Google Docs pastes background-color as inline span style
|
|
915
|
-
|
|
928
|
+
// Google Docs pastes background-color as an inline span style.
|
|
929
|
+
//
|
|
930
|
+
// This MUST be a *style* rule (no `tag`). A tag rule — `{ tag: 'span',
|
|
931
|
+
// style: 'background-color' }` — is treated as `{ tag: 'span' }` by
|
|
932
|
+
// ProseMirror (a rule with `tag` is a tag rule and `style` is ignored),
|
|
933
|
+
// and since mark rules run before node rules and only the first matching
|
|
934
|
+
// tag rule wins, it swallows EVERY <span>: custom nodes such as
|
|
935
|
+
// `span[data-toc-page]` degrade to highlight-marked text on load (issue
|
|
936
|
+
// #23), and it also loses to TextStyle's own bare span rule anyway.
|
|
937
|
+
//
|
|
938
|
+
// A style rule is applied in addition to the matched tag rule (see
|
|
939
|
+
// DOMParser.readStyles), and only fires for elements that actually carry
|
|
940
|
+
// the inline style — so bare spans and custom span-nodes are left alone.
|
|
941
|
+
// `getAttrs` receives the style VALUE here (not the element), so read the
|
|
942
|
+
// colour straight from it.
|
|
943
|
+
{ style: "background-color", getAttrs: (value) => ({ color: value }) }
|
|
916
944
|
];
|
|
917
945
|
},
|
|
918
946
|
renderHTML({ HTMLAttributes }) {
|
|
@@ -2869,9 +2897,394 @@ var commentPlugin = {
|
|
|
2869
2897
|
commands: {}
|
|
2870
2898
|
};
|
|
2871
2899
|
|
|
2872
|
-
// src/
|
|
2900
|
+
// src/suggestChanges.ts
|
|
2873
2901
|
var import_core11 = require("@tiptap/core");
|
|
2902
|
+
var import_state3 = require("@tiptap/pm/state");
|
|
2903
|
+
var import_transform2 = require("@tiptap/pm/transform");
|
|
2874
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");
|
|
2875
3288
|
function todayISO() {
|
|
2876
3289
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2877
3290
|
}
|
|
@@ -2888,7 +3301,7 @@ var DEFAULT_STATUSES = ["To Do", "In Progress", "Review", "Approved"];
|
|
|
2888
3301
|
function slugify(s) {
|
|
2889
3302
|
return s.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
|
|
2890
3303
|
}
|
|
2891
|
-
var DateChipNode =
|
|
3304
|
+
var DateChipNode = import_core12.Node.create({
|
|
2892
3305
|
name: "dateChip",
|
|
2893
3306
|
group: "inline",
|
|
2894
3307
|
inline: true,
|
|
@@ -2908,7 +3321,7 @@ var DateChipNode = import_core11.Node.create({
|
|
|
2908
3321
|
return [{ tag: 'span[data-node-type="date-chip"]' }];
|
|
2909
3322
|
},
|
|
2910
3323
|
renderHTML({ node, HTMLAttributes }) {
|
|
2911
|
-
return ["span", (0,
|
|
3324
|
+
return ["span", (0, import_core12.mergeAttributes)(HTMLAttributes, {
|
|
2912
3325
|
"data-node-type": "date-chip",
|
|
2913
3326
|
class: "docs-chip docs-chip--date"
|
|
2914
3327
|
}), formatDate(node.attrs.date)];
|
|
@@ -2961,7 +3374,7 @@ var DateChipNode = import_core11.Node.create({
|
|
|
2961
3374
|
};
|
|
2962
3375
|
}
|
|
2963
3376
|
});
|
|
2964
|
-
var PeopleChipNode =
|
|
3377
|
+
var PeopleChipNode = import_core12.Node.create({
|
|
2965
3378
|
name: "peopleChip",
|
|
2966
3379
|
group: "inline",
|
|
2967
3380
|
inline: true,
|
|
@@ -2986,7 +3399,7 @@ var PeopleChipNode = import_core11.Node.create({
|
|
|
2986
3399
|
return [{ tag: 'span[data-node-type="people-chip"]' }];
|
|
2987
3400
|
},
|
|
2988
3401
|
renderHTML({ node, HTMLAttributes }) {
|
|
2989
|
-
return ["span", (0,
|
|
3402
|
+
return ["span", (0, import_core12.mergeAttributes)(HTMLAttributes, {
|
|
2990
3403
|
"data-node-type": "people-chip",
|
|
2991
3404
|
class: "docs-chip docs-chip--people"
|
|
2992
3405
|
}), `@${node.attrs.name || "user"}`];
|
|
@@ -3023,7 +3436,7 @@ var PeopleChipNode = import_core11.Node.create({
|
|
|
3023
3436
|
};
|
|
3024
3437
|
}
|
|
3025
3438
|
});
|
|
3026
|
-
var FileChipNode =
|
|
3439
|
+
var FileChipNode = import_core12.Node.create({
|
|
3027
3440
|
name: "fileChip",
|
|
3028
3441
|
group: "inline",
|
|
3029
3442
|
inline: true,
|
|
@@ -3048,7 +3461,7 @@ var FileChipNode = import_core11.Node.create({
|
|
|
3048
3461
|
return [{ tag: 'span[data-node-type="file-chip"]' }];
|
|
3049
3462
|
},
|
|
3050
3463
|
renderHTML({ node, HTMLAttributes }) {
|
|
3051
|
-
return ["span", (0,
|
|
3464
|
+
return ["span", (0, import_core12.mergeAttributes)(HTMLAttributes, {
|
|
3052
3465
|
"data-node-type": "file-chip",
|
|
3053
3466
|
class: "docs-chip docs-chip--file"
|
|
3054
3467
|
}), node.attrs.name || "file"];
|
|
@@ -3085,7 +3498,7 @@ var FileChipNode = import_core11.Node.create({
|
|
|
3085
3498
|
};
|
|
3086
3499
|
}
|
|
3087
3500
|
});
|
|
3088
|
-
var DropdownChipNode =
|
|
3501
|
+
var DropdownChipNode = import_core12.Node.create({
|
|
3089
3502
|
name: "dropdownChip",
|
|
3090
3503
|
group: "inline",
|
|
3091
3504
|
inline: true,
|
|
@@ -3116,7 +3529,7 @@ var DropdownChipNode = import_core11.Node.create({
|
|
|
3116
3529
|
return [{ tag: 'span[data-node-type="dropdown-chip"]' }];
|
|
3117
3530
|
},
|
|
3118
3531
|
renderHTML({ node, HTMLAttributes }) {
|
|
3119
|
-
return ["span", (0,
|
|
3532
|
+
return ["span", (0, import_core12.mergeAttributes)(HTMLAttributes, {
|
|
3120
3533
|
"data-node-type": "dropdown-chip",
|
|
3121
3534
|
class: "docs-chip docs-chip--dropdown"
|
|
3122
3535
|
}), node.attrs.selected || ""];
|
|
@@ -3168,7 +3581,7 @@ var DropdownChipNode = import_core11.Node.create({
|
|
|
3168
3581
|
};
|
|
3169
3582
|
}
|
|
3170
3583
|
});
|
|
3171
|
-
var LocationChipNode =
|
|
3584
|
+
var LocationChipNode = import_core12.Node.create({
|
|
3172
3585
|
name: "locationChip",
|
|
3173
3586
|
group: "inline",
|
|
3174
3587
|
inline: true,
|
|
@@ -3204,7 +3617,7 @@ var LocationChipNode = import_core11.Node.create({
|
|
|
3204
3617
|
return [{ tag: 'span[data-node-type="location-chip"]' }];
|
|
3205
3618
|
},
|
|
3206
3619
|
renderHTML({ node, HTMLAttributes }) {
|
|
3207
|
-
return ["span", (0,
|
|
3620
|
+
return ["span", (0, import_core12.mergeAttributes)(HTMLAttributes, {
|
|
3208
3621
|
"data-node-type": "location-chip",
|
|
3209
3622
|
class: "docs-chip docs-chip--location"
|
|
3210
3623
|
}), node.attrs.label || ""];
|
|
@@ -3241,7 +3654,7 @@ var LocationChipNode = import_core11.Node.create({
|
|
|
3241
3654
|
};
|
|
3242
3655
|
}
|
|
3243
3656
|
});
|
|
3244
|
-
var smartElementsPlugin = (0,
|
|
3657
|
+
var smartElementsPlugin = (0, import_docflow_core20.definePlugin)({
|
|
3245
3658
|
id: "smart-elements",
|
|
3246
3659
|
tiptapExtensions: [
|
|
3247
3660
|
DateChipNode,
|
|
@@ -3300,10 +3713,10 @@ var smartElementsPlugin = (0, import_docflow_core19.definePlugin)({
|
|
|
3300
3713
|
});
|
|
3301
3714
|
|
|
3302
3715
|
// src/tablePageSplit.ts
|
|
3303
|
-
var
|
|
3304
|
-
var
|
|
3305
|
-
var
|
|
3306
|
-
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");
|
|
3307
3720
|
var SPLIT_MARK = "head";
|
|
3308
3721
|
var MAX_SPLIT_DEPTH = 16;
|
|
3309
3722
|
function readPageContentHeightPx(view, editor) {
|
|
@@ -3480,7 +3893,7 @@ function runSplitPass(view, editor) {
|
|
|
3480
3893
|
tr.setMeta(PLUGIN_KEY, { splitAtRow: -1 });
|
|
3481
3894
|
v.dispatch(tr);
|
|
3482
3895
|
}
|
|
3483
|
-
var TablePageSplitExtension =
|
|
3896
|
+
var TablePageSplitExtension = import_core13.Extension.create({
|
|
3484
3897
|
name: "tablePageSplit",
|
|
3485
3898
|
addProseMirrorPlugins() {
|
|
3486
3899
|
let viewRef = null;
|
|
@@ -3488,7 +3901,7 @@ var TablePageSplitExtension = import_core12.Extension.create({
|
|
|
3488
3901
|
const ext = this;
|
|
3489
3902
|
const editorRef = ext.editor ?? null;
|
|
3490
3903
|
return [
|
|
3491
|
-
new
|
|
3904
|
+
new import_state4.Plugin({
|
|
3492
3905
|
key: PLUGIN_KEY,
|
|
3493
3906
|
view(_editorView) {
|
|
3494
3907
|
viewRef = _editorView;
|
|
@@ -3520,15 +3933,15 @@ var TablePageSplitExtension = import_core12.Extension.create({
|
|
|
3520
3933
|
];
|
|
3521
3934
|
}
|
|
3522
3935
|
});
|
|
3523
|
-
var tablePageSplitPlugin = (0,
|
|
3936
|
+
var tablePageSplitPlugin = (0, import_docflow_core21.definePlugin)({
|
|
3524
3937
|
id: "tablePageSplit",
|
|
3525
3938
|
tiptapExtensions: [TablePageSplitExtension]
|
|
3526
3939
|
});
|
|
3527
3940
|
|
|
3528
3941
|
// src/slashMenu.ts
|
|
3529
|
-
var
|
|
3530
|
-
var
|
|
3531
|
-
var
|
|
3942
|
+
var import_core14 = require("@tiptap/core");
|
|
3943
|
+
var import_state5 = require("@tiptap/pm/state");
|
|
3944
|
+
var import_docflow_core22 = require("@kedataindo/docflow-core");
|
|
3532
3945
|
var slashState = {
|
|
3533
3946
|
open: false,
|
|
3534
3947
|
query: "",
|
|
@@ -3582,12 +3995,12 @@ function getRegisteredCommands() {
|
|
|
3582
3995
|
return true;
|
|
3583
3996
|
});
|
|
3584
3997
|
}
|
|
3585
|
-
var SlashMenuExtension =
|
|
3998
|
+
var SlashMenuExtension = import_core14.Extension.create({
|
|
3586
3999
|
name: "slashMenu",
|
|
3587
4000
|
addProseMirrorPlugins() {
|
|
3588
4001
|
return [
|
|
3589
|
-
new
|
|
3590
|
-
key: new
|
|
4002
|
+
new import_state5.Plugin({
|
|
4003
|
+
key: new import_state5.PluginKey("slashMenu"),
|
|
3591
4004
|
props: {
|
|
3592
4005
|
handleTextInput(view, from, _to, text) {
|
|
3593
4006
|
if (text === "/") {
|
|
@@ -3673,7 +4086,7 @@ var SlashMenuExtension = import_core13.Extension.create({
|
|
|
3673
4086
|
];
|
|
3674
4087
|
}
|
|
3675
4088
|
});
|
|
3676
|
-
var slashMenuPlugin = (0,
|
|
4089
|
+
var slashMenuPlugin = (0, import_docflow_core22.definePlugin)({
|
|
3677
4090
|
id: "slash-menu",
|
|
3678
4091
|
tiptapExtensions: [SlashMenuExtension],
|
|
3679
4092
|
hooks: {
|
|
@@ -3706,6 +4119,7 @@ var defaultPlugins = [
|
|
|
3706
4119
|
citationPlugin,
|
|
3707
4120
|
aiPlugin,
|
|
3708
4121
|
commentPlugin,
|
|
4122
|
+
suggestChangesPlugin,
|
|
3709
4123
|
smartElementsPlugin
|
|
3710
4124
|
];
|
|
3711
4125
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -3727,10 +4141,18 @@ var defaultPlugins = [
|
|
|
3727
4141
|
LocationChipNode,
|
|
3728
4142
|
PageBreak,
|
|
3729
4143
|
PeopleChipNode,
|
|
4144
|
+
SUGGESTION_DELETE,
|
|
4145
|
+
SUGGESTION_FORMAT,
|
|
4146
|
+
SUGGESTION_INSERT,
|
|
3730
4147
|
SlashMenuExtension,
|
|
4148
|
+
SuggestionDeleteMark,
|
|
4149
|
+
SuggestionFormatMark,
|
|
4150
|
+
SuggestionInsertMark,
|
|
3731
4151
|
TocEntryNode,
|
|
3732
4152
|
TocNode,
|
|
3733
4153
|
TocPageNumNode,
|
|
4154
|
+
acceptAllSuggestions,
|
|
4155
|
+
acceptSuggestion,
|
|
3734
4156
|
aiPlugin,
|
|
3735
4157
|
aiPluginKey,
|
|
3736
4158
|
alignmentPlugin,
|
|
@@ -3747,6 +4169,7 @@ var defaultPlugins = [
|
|
|
3747
4169
|
formattingPlugin,
|
|
3748
4170
|
getAIPreview,
|
|
3749
4171
|
getCitationEngine,
|
|
4172
|
+
getSuggestions,
|
|
3750
4173
|
headingsPlugin,
|
|
3751
4174
|
highlightPlugin,
|
|
3752
4175
|
imagePlugin,
|
|
@@ -3760,10 +4183,15 @@ var defaultPlugins = [
|
|
|
3760
4183
|
placeholderPlugin,
|
|
3761
4184
|
regenerateToc,
|
|
3762
4185
|
registerSlashCommands,
|
|
4186
|
+
rejectAllSuggestions,
|
|
4187
|
+
rejectSuggestion,
|
|
3763
4188
|
sanitizeCiteprocHtml,
|
|
4189
|
+
setDocumentMode,
|
|
4190
|
+
setSuggestionAuthor,
|
|
3764
4191
|
slashMenuPlugin,
|
|
3765
4192
|
slashState,
|
|
3766
4193
|
smartElementsPlugin,
|
|
4194
|
+
suggestChangesPlugin,
|
|
3767
4195
|
tablePageSplitPlugin,
|
|
3768
4196
|
tablePlugin,
|
|
3769
4197
|
textColorPlugin,
|