@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.js
CHANGED
|
@@ -818,8 +818,22 @@ var GoogleDocsHighlight = Highlight.extend({
|
|
|
818
818
|
return [
|
|
819
819
|
// Standard <mark> tag (default TipTap behavior)
|
|
820
820
|
{ tag: "mark" },
|
|
821
|
-
// Google Docs pastes background-color as inline span style
|
|
822
|
-
|
|
821
|
+
// Google Docs pastes background-color as an inline span style.
|
|
822
|
+
//
|
|
823
|
+
// This MUST be a *style* rule (no `tag`). A tag rule — `{ tag: 'span',
|
|
824
|
+
// style: 'background-color' }` — is treated as `{ tag: 'span' }` by
|
|
825
|
+
// ProseMirror (a rule with `tag` is a tag rule and `style` is ignored),
|
|
826
|
+
// and since mark rules run before node rules and only the first matching
|
|
827
|
+
// tag rule wins, it swallows EVERY <span>: custom nodes such as
|
|
828
|
+
// `span[data-toc-page]` degrade to highlight-marked text on load (issue
|
|
829
|
+
// #23), and it also loses to TextStyle's own bare span rule anyway.
|
|
830
|
+
//
|
|
831
|
+
// A style rule is applied in addition to the matched tag rule (see
|
|
832
|
+
// DOMParser.readStyles), and only fires for elements that actually carry
|
|
833
|
+
// the inline style — so bare spans and custom span-nodes are left alone.
|
|
834
|
+
// `getAttrs` receives the style VALUE here (not the element), so read the
|
|
835
|
+
// colour straight from it.
|
|
836
|
+
{ style: "background-color", getAttrs: (value) => ({ color: value }) }
|
|
823
837
|
];
|
|
824
838
|
},
|
|
825
839
|
renderHTML({ HTMLAttributes }) {
|
|
@@ -2776,9 +2790,394 @@ var commentPlugin = {
|
|
|
2776
2790
|
commands: {}
|
|
2777
2791
|
};
|
|
2778
2792
|
|
|
2779
|
-
// src/
|
|
2780
|
-
import {
|
|
2793
|
+
// src/suggestChanges.ts
|
|
2794
|
+
import { Extension as Extension4, Mark as Mark2, mergeAttributes as mergeAttributes8 } from "@tiptap/core";
|
|
2795
|
+
import { Plugin as Plugin2, PluginKey as PluginKey2, TextSelection } from "@tiptap/pm/state";
|
|
2796
|
+
import { AddMarkStep, RemoveMarkStep } from "@tiptap/pm/transform";
|
|
2781
2797
|
import { definePlugin as definePlugin19 } from "@kedataindo/docflow-core";
|
|
2798
|
+
var SUGGESTION_INSERT = "suggestionInsert";
|
|
2799
|
+
var SUGGESTION_DELETE = "suggestionDelete";
|
|
2800
|
+
var SUGGESTION_FORMAT = "suggestionFormat";
|
|
2801
|
+
var FORMAT_MARKS = /* @__PURE__ */ new Set(["bold", "italic", "underline", "strike", "highlight"]);
|
|
2802
|
+
var SUGGEST_APPLIED_META = "suggestChanges:applied";
|
|
2803
|
+
var suggestChangesKey = new PluginKey2("suggestChanges");
|
|
2804
|
+
var suggestionAttributes = () => ({
|
|
2805
|
+
suggestionId: {
|
|
2806
|
+
default: null,
|
|
2807
|
+
parseHTML: (el) => el.getAttribute("data-suggestion-id"),
|
|
2808
|
+
renderHTML: (attrs) => attrs.suggestionId ? { "data-suggestion-id": attrs.suggestionId } : {}
|
|
2809
|
+
},
|
|
2810
|
+
authorId: {
|
|
2811
|
+
default: null,
|
|
2812
|
+
parseHTML: (el) => el.getAttribute("data-suggestion-author"),
|
|
2813
|
+
renderHTML: (attrs) => attrs.authorId ? { "data-suggestion-author": attrs.authorId } : {}
|
|
2814
|
+
},
|
|
2815
|
+
authorName: { default: null },
|
|
2816
|
+
createdAt: { default: null }
|
|
2817
|
+
});
|
|
2818
|
+
var SuggestionInsertMark = Mark2.create({
|
|
2819
|
+
name: SUGGESTION_INSERT,
|
|
2820
|
+
addAttributes() {
|
|
2821
|
+
return suggestionAttributes();
|
|
2822
|
+
},
|
|
2823
|
+
parseHTML() {
|
|
2824
|
+
return [{ tag: 'span[data-suggestion="insert"]' }];
|
|
2825
|
+
},
|
|
2826
|
+
renderHTML({ HTMLAttributes }) {
|
|
2827
|
+
return [
|
|
2828
|
+
"span",
|
|
2829
|
+
mergeAttributes8(HTMLAttributes, {
|
|
2830
|
+
"data-suggestion": "insert",
|
|
2831
|
+
class: "docflow-suggestion docflow-suggestion--insert"
|
|
2832
|
+
}),
|
|
2833
|
+
0
|
|
2834
|
+
];
|
|
2835
|
+
}
|
|
2836
|
+
});
|
|
2837
|
+
var SuggestionDeleteMark = Mark2.create({
|
|
2838
|
+
name: SUGGESTION_DELETE,
|
|
2839
|
+
addAttributes() {
|
|
2840
|
+
return suggestionAttributes();
|
|
2841
|
+
},
|
|
2842
|
+
parseHTML() {
|
|
2843
|
+
return [{ tag: 'span[data-suggestion="delete"]' }];
|
|
2844
|
+
},
|
|
2845
|
+
renderHTML({ HTMLAttributes }) {
|
|
2846
|
+
return [
|
|
2847
|
+
"span",
|
|
2848
|
+
mergeAttributes8(HTMLAttributes, {
|
|
2849
|
+
"data-suggestion": "delete",
|
|
2850
|
+
class: "docflow-suggestion docflow-suggestion--delete"
|
|
2851
|
+
}),
|
|
2852
|
+
0
|
|
2853
|
+
];
|
|
2854
|
+
}
|
|
2855
|
+
});
|
|
2856
|
+
var SuggestionFormatMark = Mark2.create({
|
|
2857
|
+
name: SUGGESTION_FORMAT,
|
|
2858
|
+
addAttributes() {
|
|
2859
|
+
return {
|
|
2860
|
+
...suggestionAttributes(),
|
|
2861
|
+
format: {
|
|
2862
|
+
default: null,
|
|
2863
|
+
parseHTML: (el) => el.getAttribute("data-suggestion-format"),
|
|
2864
|
+
renderHTML: (attrs) => attrs.format ? { "data-suggestion-format": attrs.format } : {}
|
|
2865
|
+
},
|
|
2866
|
+
delta: { default: "add" }
|
|
2867
|
+
};
|
|
2868
|
+
},
|
|
2869
|
+
parseHTML() {
|
|
2870
|
+
return [{ tag: 'span[data-suggestion="format"]' }];
|
|
2871
|
+
},
|
|
2872
|
+
renderHTML({ HTMLAttributes }) {
|
|
2873
|
+
return [
|
|
2874
|
+
"span",
|
|
2875
|
+
mergeAttributes8(HTMLAttributes, {
|
|
2876
|
+
"data-suggestion": "format",
|
|
2877
|
+
class: "docflow-suggestion docflow-suggestion--format"
|
|
2878
|
+
}),
|
|
2879
|
+
0
|
|
2880
|
+
];
|
|
2881
|
+
}
|
|
2882
|
+
});
|
|
2883
|
+
var suggestionSeq = 0;
|
|
2884
|
+
var newSuggestionId = () => {
|
|
2885
|
+
suggestionSeq += 1;
|
|
2886
|
+
return `sug-${Date.now().toString(36)}-${suggestionSeq.toString(36)}`;
|
|
2887
|
+
};
|
|
2888
|
+
var adjacentRunId = (editorState, pos, markName) => {
|
|
2889
|
+
if (pos <= 0) return null;
|
|
2890
|
+
const before = editorState.doc.resolve(pos).nodeBefore;
|
|
2891
|
+
if (!before || !before.isText) return null;
|
|
2892
|
+
const mark = before.marks.find((m) => m.type.name === markName);
|
|
2893
|
+
return mark?.attrs.suggestionId ?? null;
|
|
2894
|
+
};
|
|
2895
|
+
var markAttrs = (id, author) => ({
|
|
2896
|
+
suggestionId: id,
|
|
2897
|
+
authorId: author.id ?? null,
|
|
2898
|
+
authorName: author.name ?? null,
|
|
2899
|
+
createdAt: Date.now()
|
|
2900
|
+
});
|
|
2901
|
+
var collectRanges = (doc, markName, id) => {
|
|
2902
|
+
const out = [];
|
|
2903
|
+
doc.descendants((node, pos) => {
|
|
2904
|
+
if (!node.isText || node.marks.length === 0) return;
|
|
2905
|
+
for (const mark of node.marks) {
|
|
2906
|
+
if (mark.type.name !== markName) continue;
|
|
2907
|
+
if (id && mark.attrs.suggestionId !== id) continue;
|
|
2908
|
+
out.push({ from: pos, to: pos + node.nodeSize, attrs: mark.attrs });
|
|
2909
|
+
}
|
|
2910
|
+
});
|
|
2911
|
+
return out;
|
|
2912
|
+
};
|
|
2913
|
+
var SuggestChanges = Extension4.create({
|
|
2914
|
+
name: "suggestChanges",
|
|
2915
|
+
addStorage() {
|
|
2916
|
+
return { suggestions: [] };
|
|
2917
|
+
},
|
|
2918
|
+
addProseMirrorPlugins() {
|
|
2919
|
+
const editor = this.editor;
|
|
2920
|
+
const syncStorage = () => {
|
|
2921
|
+
const storage = editor.storage.suggestChanges;
|
|
2922
|
+
if (storage) storage.suggestions = getSuggestions(editor);
|
|
2923
|
+
};
|
|
2924
|
+
return [
|
|
2925
|
+
new Plugin2({
|
|
2926
|
+
key: suggestChangesKey,
|
|
2927
|
+
state: {
|
|
2928
|
+
init: () => ({ mode: "editing", author: {} }),
|
|
2929
|
+
apply: (tr, value) => {
|
|
2930
|
+
const meta = tr.getMeta(suggestChangesKey);
|
|
2931
|
+
if (!meta) return value;
|
|
2932
|
+
return {
|
|
2933
|
+
mode: meta.mode ?? value.mode,
|
|
2934
|
+
author: meta.author ?? value.author
|
|
2935
|
+
};
|
|
2936
|
+
}
|
|
2937
|
+
},
|
|
2938
|
+
view: () => {
|
|
2939
|
+
syncStorage();
|
|
2940
|
+
return { update: syncStorage };
|
|
2941
|
+
},
|
|
2942
|
+
appendTransaction: (transactions, _oldState, newState) => {
|
|
2943
|
+
if (transactions.some((tr2) => tr2.getMeta(SUGGEST_APPLIED_META))) return null;
|
|
2944
|
+
const current = suggestChangesKey.getState(newState);
|
|
2945
|
+
if (current?.mode !== "suggesting") return null;
|
|
2946
|
+
const formatMark = newState.schema.marks[SUGGESTION_FORMAT];
|
|
2947
|
+
if (!formatMark) return null;
|
|
2948
|
+
const changes = [];
|
|
2949
|
+
for (const tr2 of transactions) {
|
|
2950
|
+
for (const step of tr2.steps) {
|
|
2951
|
+
if (step instanceof AddMarkStep || step instanceof RemoveMarkStep) {
|
|
2952
|
+
if (!FORMAT_MARKS.has(step.mark.type.name)) continue;
|
|
2953
|
+
changes.push({ from: step.from, to: step.to, name: step.mark.type.name, add: step instanceof AddMarkStep });
|
|
2954
|
+
}
|
|
2955
|
+
}
|
|
2956
|
+
}
|
|
2957
|
+
if (changes.length === 0) return null;
|
|
2958
|
+
const tr = newState.tr;
|
|
2959
|
+
for (const change of changes) {
|
|
2960
|
+
const target = newState.schema.marks[change.name];
|
|
2961
|
+
if (!target) continue;
|
|
2962
|
+
if (change.add) tr.removeMark(change.from, change.to, target);
|
|
2963
|
+
else tr.addMark(change.from, change.to, target.create());
|
|
2964
|
+
tr.addMark(
|
|
2965
|
+
change.from,
|
|
2966
|
+
change.to,
|
|
2967
|
+
formatMark.create({ ...markAttrs(newSuggestionId(), current.author), format: change.name, delta: change.add ? "add" : "remove" })
|
|
2968
|
+
);
|
|
2969
|
+
}
|
|
2970
|
+
tr.setMeta(SUGGEST_APPLIED_META, true);
|
|
2971
|
+
return tr;
|
|
2972
|
+
},
|
|
2973
|
+
props: {
|
|
2974
|
+
handleTextInput: (view, from, to, text) => {
|
|
2975
|
+
const current = suggestChangesKey.getState(view.state);
|
|
2976
|
+
if (current?.mode !== "suggesting" || !text) return false;
|
|
2977
|
+
const insert = view.state.schema.marks[SUGGESTION_INSERT];
|
|
2978
|
+
const del = view.state.schema.marks[SUGGESTION_DELETE];
|
|
2979
|
+
if (!insert || !del) return false;
|
|
2980
|
+
const id = adjacentRunId(view.state, from, SUGGESTION_INSERT) ?? newSuggestionId();
|
|
2981
|
+
const tr = view.state.tr;
|
|
2982
|
+
if (to > from) tr.addMark(from, to, del.create(markAttrs(id, current.author)));
|
|
2983
|
+
const insertAt = to;
|
|
2984
|
+
tr.insertText(text, insertAt, insertAt);
|
|
2985
|
+
tr.addMark(insertAt, insertAt + text.length, insert.create(markAttrs(id, current.author)));
|
|
2986
|
+
view.dispatch(tr);
|
|
2987
|
+
return true;
|
|
2988
|
+
},
|
|
2989
|
+
handleKeyDown: (view, event) => {
|
|
2990
|
+
const current = suggestChangesKey.getState(view.state);
|
|
2991
|
+
if (current?.mode !== "suggesting") return false;
|
|
2992
|
+
if (event.key !== "Backspace" && event.key !== "Delete") return false;
|
|
2993
|
+
const del = view.state.schema.marks[SUGGESTION_DELETE];
|
|
2994
|
+
if (!del) return false;
|
|
2995
|
+
const { selection, doc } = view.state;
|
|
2996
|
+
let from;
|
|
2997
|
+
let to;
|
|
2998
|
+
if (!selection.empty) {
|
|
2999
|
+
from = selection.from;
|
|
3000
|
+
to = selection.to;
|
|
3001
|
+
} else if (event.key === "Backspace") {
|
|
3002
|
+
if (selection.from <= 1) return false;
|
|
3003
|
+
from = selection.from - 1;
|
|
3004
|
+
to = selection.from;
|
|
3005
|
+
} else {
|
|
3006
|
+
if (selection.to >= doc.content.size - 1) return false;
|
|
3007
|
+
from = selection.to;
|
|
3008
|
+
to = selection.to + 1;
|
|
3009
|
+
}
|
|
3010
|
+
const id = adjacentRunId(view.state, from, SUGGESTION_DELETE) ?? newSuggestionId();
|
|
3011
|
+
const tr = view.state.tr.addMark(from, to, del.create(markAttrs(id, current.author)));
|
|
3012
|
+
if (event.key === "Backspace" && selection.empty) {
|
|
3013
|
+
tr.setSelection(TextSelection.create(tr.doc, from));
|
|
3014
|
+
}
|
|
3015
|
+
view.dispatch(tr);
|
|
3016
|
+
return true;
|
|
3017
|
+
},
|
|
3018
|
+
handlePaste: (view, _event, slice) => {
|
|
3019
|
+
const current = suggestChangesKey.getState(view.state);
|
|
3020
|
+
if (current?.mode !== "suggesting") return false;
|
|
3021
|
+
const insert = view.state.schema.marks[SUGGESTION_INSERT];
|
|
3022
|
+
const del = view.state.schema.marks[SUGGESTION_DELETE];
|
|
3023
|
+
if (!insert || !del) return false;
|
|
3024
|
+
const { from, to } = view.state.selection;
|
|
3025
|
+
const id = adjacentRunId(view.state, from, SUGGESTION_INSERT) ?? newSuggestionId();
|
|
3026
|
+
const tr = view.state.tr;
|
|
3027
|
+
if (to > from) tr.addMark(from, to, del.create(markAttrs(id, current.author)));
|
|
3028
|
+
const insertAt = to;
|
|
3029
|
+
tr.insert(insertAt, slice.content);
|
|
3030
|
+
tr.addMark(insertAt, insertAt + slice.content.size, insert.create(markAttrs(id, current.author)));
|
|
3031
|
+
view.dispatch(tr);
|
|
3032
|
+
return true;
|
|
3033
|
+
}
|
|
3034
|
+
}
|
|
3035
|
+
})
|
|
3036
|
+
];
|
|
3037
|
+
},
|
|
3038
|
+
addCommands() {
|
|
3039
|
+
return {
|
|
3040
|
+
setDocumentMode: (mode) => ({ state, dispatch }) => {
|
|
3041
|
+
if (!dispatch) return false;
|
|
3042
|
+
dispatch(state.tr.setMeta(suggestChangesKey, { mode }));
|
|
3043
|
+
return true;
|
|
3044
|
+
},
|
|
3045
|
+
setSuggestionAuthor: (author) => ({ state, dispatch }) => {
|
|
3046
|
+
if (!dispatch) return false;
|
|
3047
|
+
dispatch(state.tr.setMeta(suggestChangesKey, { author }));
|
|
3048
|
+
return true;
|
|
3049
|
+
},
|
|
3050
|
+
acceptSuggestion: (id) => ({ state, dispatch }) => {
|
|
3051
|
+
const tr = buildResolveTr(state, true, id);
|
|
3052
|
+
if (!tr || !dispatch) return false;
|
|
3053
|
+
dispatch(tr);
|
|
3054
|
+
return true;
|
|
3055
|
+
},
|
|
3056
|
+
rejectSuggestion: (id) => ({ state, dispatch }) => {
|
|
3057
|
+
const tr = buildResolveTr(state, false, id);
|
|
3058
|
+
if (!tr || !dispatch) return false;
|
|
3059
|
+
dispatch(tr);
|
|
3060
|
+
return true;
|
|
3061
|
+
},
|
|
3062
|
+
acceptAllSuggestions: () => ({ state, dispatch }) => {
|
|
3063
|
+
const tr = buildResolveTr(state, true);
|
|
3064
|
+
if (!tr || !dispatch) return false;
|
|
3065
|
+
dispatch(tr);
|
|
3066
|
+
return true;
|
|
3067
|
+
},
|
|
3068
|
+
rejectAllSuggestions: () => ({ state, dispatch }) => {
|
|
3069
|
+
const tr = buildResolveTr(state, false);
|
|
3070
|
+
if (!tr || !dispatch) return false;
|
|
3071
|
+
dispatch(tr);
|
|
3072
|
+
return true;
|
|
3073
|
+
}
|
|
3074
|
+
};
|
|
3075
|
+
}
|
|
3076
|
+
});
|
|
3077
|
+
function editorDispatch(editor, meta) {
|
|
3078
|
+
editor.view.dispatch(editor.state.tr.setMeta(suggestChangesKey, meta));
|
|
3079
|
+
}
|
|
3080
|
+
function setDocumentMode(editor, mode) {
|
|
3081
|
+
editorDispatch(editor, { mode });
|
|
3082
|
+
return true;
|
|
3083
|
+
}
|
|
3084
|
+
function setSuggestionAuthor(editor, author) {
|
|
3085
|
+
editorDispatch(editor, { author });
|
|
3086
|
+
return true;
|
|
3087
|
+
}
|
|
3088
|
+
function getSuggestions(editor) {
|
|
3089
|
+
const byId = /* @__PURE__ */ new Map();
|
|
3090
|
+
const scan = (markName, type) => {
|
|
3091
|
+
editor.state.doc.descendants((node, pos) => {
|
|
3092
|
+
if (!node.isText) return;
|
|
3093
|
+
for (const mark of node.marks) {
|
|
3094
|
+
if (mark.type.name !== markName) continue;
|
|
3095
|
+
const id = mark.attrs.suggestionId;
|
|
3096
|
+
const existing = byId.get(id);
|
|
3097
|
+
if (existing) {
|
|
3098
|
+
existing.from = Math.min(existing.from, pos);
|
|
3099
|
+
existing.to = Math.max(existing.to, pos + node.nodeSize);
|
|
3100
|
+
} else {
|
|
3101
|
+
byId.set(id, {
|
|
3102
|
+
id,
|
|
3103
|
+
type,
|
|
3104
|
+
authorId: mark.attrs.authorId ?? null,
|
|
3105
|
+
authorName: mark.attrs.authorName ?? null,
|
|
3106
|
+
from: pos,
|
|
3107
|
+
to: pos + node.nodeSize,
|
|
3108
|
+
...type === "format" ? {
|
|
3109
|
+
format: mark.attrs.format ?? void 0,
|
|
3110
|
+
delta: mark.attrs.delta ?? void 0
|
|
3111
|
+
} : {}
|
|
3112
|
+
});
|
|
3113
|
+
}
|
|
3114
|
+
}
|
|
3115
|
+
});
|
|
3116
|
+
};
|
|
3117
|
+
scan(SUGGESTION_INSERT, "insert");
|
|
3118
|
+
scan(SUGGESTION_DELETE, "delete");
|
|
3119
|
+
scan(SUGGESTION_FORMAT, "format");
|
|
3120
|
+
return [...byId.values()].sort((a, b) => a.from - b.from);
|
|
3121
|
+
}
|
|
3122
|
+
function buildResolveTr(state, accept, id) {
|
|
3123
|
+
const { schema } = state;
|
|
3124
|
+
const insertMark = schema.marks[SUGGESTION_INSERT];
|
|
3125
|
+
const deleteMark = schema.marks[SUGGESTION_DELETE];
|
|
3126
|
+
const formatMark = schema.marks[SUGGESTION_FORMAT];
|
|
3127
|
+
if (!insertMark || !deleteMark) return null;
|
|
3128
|
+
const insertRanges = collectRanges(state.doc, SUGGESTION_INSERT, id);
|
|
3129
|
+
const deleteRanges = collectRanges(state.doc, SUGGESTION_DELETE, id);
|
|
3130
|
+
const formatRanges = formatMark ? collectRanges(state.doc, SUGGESTION_FORMAT, id) : [];
|
|
3131
|
+
if (insertRanges.length === 0 && deleteRanges.length === 0 && formatRanges.length === 0) return null;
|
|
3132
|
+
const tr = state.tr;
|
|
3133
|
+
for (const range of formatRanges) {
|
|
3134
|
+
if (accept) {
|
|
3135
|
+
const target = schema.marks[range.attrs.format];
|
|
3136
|
+
if (target) {
|
|
3137
|
+
if (range.attrs.delta === "remove") tr.removeMark(range.from, range.to, target);
|
|
3138
|
+
else tr.addMark(range.from, range.to, target.create());
|
|
3139
|
+
}
|
|
3140
|
+
}
|
|
3141
|
+
if (formatMark) tr.removeMark(range.from, range.to, formatMark);
|
|
3142
|
+
}
|
|
3143
|
+
const rangesToUnmark = accept ? insertRanges : deleteRanges;
|
|
3144
|
+
const markToRemove = accept ? insertMark : deleteMark;
|
|
3145
|
+
const rangesToDelete = accept ? deleteRanges : insertRanges;
|
|
3146
|
+
for (const range of rangesToUnmark) {
|
|
3147
|
+
tr.removeMark(range.from, range.to, markToRemove);
|
|
3148
|
+
}
|
|
3149
|
+
for (const range of [...rangesToDelete].sort((a, b) => b.from - a.from)) {
|
|
3150
|
+
tr.delete(range.from, range.to);
|
|
3151
|
+
}
|
|
3152
|
+
tr.setMeta(SUGGEST_APPLIED_META, true);
|
|
3153
|
+
return tr.docChanged ? tr : null;
|
|
3154
|
+
}
|
|
3155
|
+
function resolveSuggestions(editor, accept, id) {
|
|
3156
|
+
const tr = buildResolveTr(editor.state, accept, id);
|
|
3157
|
+
if (!tr) return false;
|
|
3158
|
+
editor.view.dispatch(tr);
|
|
3159
|
+
return true;
|
|
3160
|
+
}
|
|
3161
|
+
var acceptSuggestion = (editor, id) => resolveSuggestions(editor, true, id);
|
|
3162
|
+
var rejectSuggestion = (editor, id) => resolveSuggestions(editor, false, id);
|
|
3163
|
+
var acceptAllSuggestions = (editor) => resolveSuggestions(editor, true);
|
|
3164
|
+
var rejectAllSuggestions = (editor) => resolveSuggestions(editor, false);
|
|
3165
|
+
var suggestChangesPlugin = definePlugin19({
|
|
3166
|
+
id: "suggestChanges",
|
|
3167
|
+
tiptapExtensions: [SuggestionInsertMark, SuggestionDeleteMark, SuggestionFormatMark, SuggestChanges],
|
|
3168
|
+
commands: {
|
|
3169
|
+
setDocumentMode: (editor, ...args) => setDocumentMode(editor, args[0]),
|
|
3170
|
+
setSuggestionAuthor: (editor, ...args) => setSuggestionAuthor(editor, args[0] ?? {}),
|
|
3171
|
+
acceptSuggestion: (editor, ...args) => acceptSuggestion(editor, args[0]),
|
|
3172
|
+
rejectSuggestion: (editor, ...args) => rejectSuggestion(editor, args[0]),
|
|
3173
|
+
acceptAllSuggestions: (editor) => acceptAllSuggestions(editor),
|
|
3174
|
+
rejectAllSuggestions: (editor) => rejectAllSuggestions(editor)
|
|
3175
|
+
}
|
|
3176
|
+
});
|
|
3177
|
+
|
|
3178
|
+
// src/smartElements.ts
|
|
3179
|
+
import { Node as Node7, mergeAttributes as mergeAttributes9 } from "@tiptap/core";
|
|
3180
|
+
import { definePlugin as definePlugin20 } from "@kedataindo/docflow-core";
|
|
2782
3181
|
function todayISO() {
|
|
2783
3182
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2784
3183
|
}
|
|
@@ -2815,7 +3214,7 @@ var DateChipNode = Node7.create({
|
|
|
2815
3214
|
return [{ tag: 'span[data-node-type="date-chip"]' }];
|
|
2816
3215
|
},
|
|
2817
3216
|
renderHTML({ node, HTMLAttributes }) {
|
|
2818
|
-
return ["span",
|
|
3217
|
+
return ["span", mergeAttributes9(HTMLAttributes, {
|
|
2819
3218
|
"data-node-type": "date-chip",
|
|
2820
3219
|
class: "docs-chip docs-chip--date"
|
|
2821
3220
|
}), formatDate(node.attrs.date)];
|
|
@@ -2893,7 +3292,7 @@ var PeopleChipNode = Node7.create({
|
|
|
2893
3292
|
return [{ tag: 'span[data-node-type="people-chip"]' }];
|
|
2894
3293
|
},
|
|
2895
3294
|
renderHTML({ node, HTMLAttributes }) {
|
|
2896
|
-
return ["span",
|
|
3295
|
+
return ["span", mergeAttributes9(HTMLAttributes, {
|
|
2897
3296
|
"data-node-type": "people-chip",
|
|
2898
3297
|
class: "docs-chip docs-chip--people"
|
|
2899
3298
|
}), `@${node.attrs.name || "user"}`];
|
|
@@ -2955,7 +3354,7 @@ var FileChipNode = Node7.create({
|
|
|
2955
3354
|
return [{ tag: 'span[data-node-type="file-chip"]' }];
|
|
2956
3355
|
},
|
|
2957
3356
|
renderHTML({ node, HTMLAttributes }) {
|
|
2958
|
-
return ["span",
|
|
3357
|
+
return ["span", mergeAttributes9(HTMLAttributes, {
|
|
2959
3358
|
"data-node-type": "file-chip",
|
|
2960
3359
|
class: "docs-chip docs-chip--file"
|
|
2961
3360
|
}), node.attrs.name || "file"];
|
|
@@ -3023,7 +3422,7 @@ var DropdownChipNode = Node7.create({
|
|
|
3023
3422
|
return [{ tag: 'span[data-node-type="dropdown-chip"]' }];
|
|
3024
3423
|
},
|
|
3025
3424
|
renderHTML({ node, HTMLAttributes }) {
|
|
3026
|
-
return ["span",
|
|
3425
|
+
return ["span", mergeAttributes9(HTMLAttributes, {
|
|
3027
3426
|
"data-node-type": "dropdown-chip",
|
|
3028
3427
|
class: "docs-chip docs-chip--dropdown"
|
|
3029
3428
|
}), node.attrs.selected || ""];
|
|
@@ -3111,7 +3510,7 @@ var LocationChipNode = Node7.create({
|
|
|
3111
3510
|
return [{ tag: 'span[data-node-type="location-chip"]' }];
|
|
3112
3511
|
},
|
|
3113
3512
|
renderHTML({ node, HTMLAttributes }) {
|
|
3114
|
-
return ["span",
|
|
3513
|
+
return ["span", mergeAttributes9(HTMLAttributes, {
|
|
3115
3514
|
"data-node-type": "location-chip",
|
|
3116
3515
|
class: "docs-chip docs-chip--location"
|
|
3117
3516
|
}), node.attrs.label || ""];
|
|
@@ -3148,7 +3547,7 @@ var LocationChipNode = Node7.create({
|
|
|
3148
3547
|
};
|
|
3149
3548
|
}
|
|
3150
3549
|
});
|
|
3151
|
-
var smartElementsPlugin =
|
|
3550
|
+
var smartElementsPlugin = definePlugin20({
|
|
3152
3551
|
id: "smart-elements",
|
|
3153
3552
|
tiptapExtensions: [
|
|
3154
3553
|
DateChipNode,
|
|
@@ -3207,10 +3606,10 @@ var smartElementsPlugin = definePlugin19({
|
|
|
3207
3606
|
});
|
|
3208
3607
|
|
|
3209
3608
|
// src/tablePageSplit.ts
|
|
3210
|
-
import { definePlugin as
|
|
3211
|
-
import { Extension as
|
|
3212
|
-
import { Plugin as
|
|
3213
|
-
var PLUGIN_KEY = new
|
|
3609
|
+
import { definePlugin as definePlugin21 } from "@kedataindo/docflow-core";
|
|
3610
|
+
import { Extension as Extension5 } from "@tiptap/core";
|
|
3611
|
+
import { Plugin as Plugin3, PluginKey as PluginKey3 } from "@tiptap/pm/state";
|
|
3612
|
+
var PLUGIN_KEY = new PluginKey3("docflow/table-page-split");
|
|
3214
3613
|
var SPLIT_MARK = "head";
|
|
3215
3614
|
var MAX_SPLIT_DEPTH = 16;
|
|
3216
3615
|
function readPageContentHeightPx(view, editor) {
|
|
@@ -3387,7 +3786,7 @@ function runSplitPass(view, editor) {
|
|
|
3387
3786
|
tr.setMeta(PLUGIN_KEY, { splitAtRow: -1 });
|
|
3388
3787
|
v.dispatch(tr);
|
|
3389
3788
|
}
|
|
3390
|
-
var TablePageSplitExtension =
|
|
3789
|
+
var TablePageSplitExtension = Extension5.create({
|
|
3391
3790
|
name: "tablePageSplit",
|
|
3392
3791
|
addProseMirrorPlugins() {
|
|
3393
3792
|
let viewRef = null;
|
|
@@ -3395,7 +3794,7 @@ var TablePageSplitExtension = Extension4.create({
|
|
|
3395
3794
|
const ext = this;
|
|
3396
3795
|
const editorRef = ext.editor ?? null;
|
|
3397
3796
|
return [
|
|
3398
|
-
new
|
|
3797
|
+
new Plugin3({
|
|
3399
3798
|
key: PLUGIN_KEY,
|
|
3400
3799
|
view(_editorView) {
|
|
3401
3800
|
viewRef = _editorView;
|
|
@@ -3427,15 +3826,15 @@ var TablePageSplitExtension = Extension4.create({
|
|
|
3427
3826
|
];
|
|
3428
3827
|
}
|
|
3429
3828
|
});
|
|
3430
|
-
var tablePageSplitPlugin =
|
|
3829
|
+
var tablePageSplitPlugin = definePlugin21({
|
|
3431
3830
|
id: "tablePageSplit",
|
|
3432
3831
|
tiptapExtensions: [TablePageSplitExtension]
|
|
3433
3832
|
});
|
|
3434
3833
|
|
|
3435
3834
|
// src/slashMenu.ts
|
|
3436
|
-
import { Extension as
|
|
3437
|
-
import { Plugin as
|
|
3438
|
-
import { definePlugin as
|
|
3835
|
+
import { Extension as Extension6 } from "@tiptap/core";
|
|
3836
|
+
import { Plugin as Plugin4, PluginKey as PluginKey4 } from "@tiptap/pm/state";
|
|
3837
|
+
import { definePlugin as definePlugin22 } from "@kedataindo/docflow-core";
|
|
3439
3838
|
var slashState = {
|
|
3440
3839
|
open: false,
|
|
3441
3840
|
query: "",
|
|
@@ -3489,12 +3888,12 @@ function getRegisteredCommands() {
|
|
|
3489
3888
|
return true;
|
|
3490
3889
|
});
|
|
3491
3890
|
}
|
|
3492
|
-
var SlashMenuExtension =
|
|
3891
|
+
var SlashMenuExtension = Extension6.create({
|
|
3493
3892
|
name: "slashMenu",
|
|
3494
3893
|
addProseMirrorPlugins() {
|
|
3495
3894
|
return [
|
|
3496
|
-
new
|
|
3497
|
-
key: new
|
|
3895
|
+
new Plugin4({
|
|
3896
|
+
key: new PluginKey4("slashMenu"),
|
|
3498
3897
|
props: {
|
|
3499
3898
|
handleTextInput(view, from, _to, text) {
|
|
3500
3899
|
if (text === "/") {
|
|
@@ -3580,7 +3979,7 @@ var SlashMenuExtension = Extension5.create({
|
|
|
3580
3979
|
];
|
|
3581
3980
|
}
|
|
3582
3981
|
});
|
|
3583
|
-
var slashMenuPlugin =
|
|
3982
|
+
var slashMenuPlugin = definePlugin22({
|
|
3584
3983
|
id: "slash-menu",
|
|
3585
3984
|
tiptapExtensions: [SlashMenuExtension],
|
|
3586
3985
|
hooks: {
|
|
@@ -3613,6 +4012,7 @@ var defaultPlugins = [
|
|
|
3613
4012
|
citationPlugin,
|
|
3614
4013
|
aiPlugin,
|
|
3615
4014
|
commentPlugin,
|
|
4015
|
+
suggestChangesPlugin,
|
|
3616
4016
|
smartElementsPlugin
|
|
3617
4017
|
];
|
|
3618
4018
|
export {
|
|
@@ -3633,10 +4033,18 @@ export {
|
|
|
3633
4033
|
LocationChipNode,
|
|
3634
4034
|
PageBreak,
|
|
3635
4035
|
PeopleChipNode,
|
|
4036
|
+
SUGGESTION_DELETE,
|
|
4037
|
+
SUGGESTION_FORMAT,
|
|
4038
|
+
SUGGESTION_INSERT,
|
|
3636
4039
|
SlashMenuExtension,
|
|
4040
|
+
SuggestionDeleteMark,
|
|
4041
|
+
SuggestionFormatMark,
|
|
4042
|
+
SuggestionInsertMark,
|
|
3637
4043
|
TocEntryNode,
|
|
3638
4044
|
TocNode,
|
|
3639
4045
|
TocPageNumNode,
|
|
4046
|
+
acceptAllSuggestions,
|
|
4047
|
+
acceptSuggestion,
|
|
3640
4048
|
aiPlugin,
|
|
3641
4049
|
aiPluginKey,
|
|
3642
4050
|
alignmentPlugin,
|
|
@@ -3653,6 +4061,7 @@ export {
|
|
|
3653
4061
|
formattingPlugin,
|
|
3654
4062
|
getAIPreview,
|
|
3655
4063
|
getCitationEngine,
|
|
4064
|
+
getSuggestions,
|
|
3656
4065
|
headingsPlugin,
|
|
3657
4066
|
highlightPlugin,
|
|
3658
4067
|
imagePlugin,
|
|
@@ -3666,10 +4075,15 @@ export {
|
|
|
3666
4075
|
placeholderPlugin,
|
|
3667
4076
|
regenerateToc,
|
|
3668
4077
|
registerSlashCommands,
|
|
4078
|
+
rejectAllSuggestions,
|
|
4079
|
+
rejectSuggestion,
|
|
3669
4080
|
sanitizeCiteprocHtml,
|
|
4081
|
+
setDocumentMode,
|
|
4082
|
+
setSuggestionAuthor,
|
|
3670
4083
|
slashMenuPlugin,
|
|
3671
4084
|
slashState,
|
|
3672
4085
|
smartElementsPlugin,
|
|
4086
|
+
suggestChangesPlugin,
|
|
3673
4087
|
tablePageSplitPlugin,
|
|
3674
4088
|
tablePlugin,
|
|
3675
4089
|
textColorPlugin,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kedataindo/docflow-plugins",
|
|
3
3
|
"license": "Apache-2.0",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.89",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"module": "./dist/index.js",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@tiptap/pm": "^2.11.0",
|
|
32
32
|
"citeproc": "^2.4.63",
|
|
33
33
|
"tiptap-markdown": "0.8.10",
|
|
34
|
-
"@kedataindo/docflow-core": "0.0.
|
|
34
|
+
"@kedataindo/docflow-core": "0.0.86"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"@tiptap/core": "^2.11.0",
|