@@ -6,13 +6,30 @@ import { MarkSpec } from "prosemirror-model";
66
77// The ideal solution would be to not depend on tiptap nodes / marks, but be able to use prosemirror nodes / marks directly
88// this way we could directly use the exported marks from @handlewithcare /prosemirror-suggest-changes
9+
10+ const formatAttributionTitle = (
11+ action : string ,
12+ userIds : readonly string [ ] | null ,
13+ timestamp : number | null ,
14+ ) : string => {
15+ const who = userIds && userIds . length > 0 ? userIds . join ( ", " ) : "unknown" ;
16+ const when =
17+ timestamp != null
18+ ? new Date ( timestamp ) . toLocaleString ( [ ] , {
19+ dateStyle : "medium" ,
20+ timeStyle : "short" ,
21+ } )
22+ : "unknown time" ;
23+ return `${ action } by ${ who } on ${ when } ` ;
24+ } ;
925export const SuggestionAddMark = Mark . create ( {
1026 name : "y-attributed-insert" ,
1127 inclusive : false ,
12- excludes : "" ,
28+ // excludes: "", TODO: what's desired?
1329 addAttributes ( ) {
1430 return {
15- id : { default : null , validate : "number" } , // note: validate is supported in prosemirror but not in tiptap, so this doesn't actually work (considered not critical)
31+ userIds : { default : null } ,
32+ timestamp : { default : null } ,
1633 "user-color" : { default : null , validate : "string" } ,
1734 } ;
1835 } ,
@@ -28,7 +45,13 @@ export const SuggestionAddMark = Mark.create({
2845 return [
2946 "ins" ,
3047 {
31- "data-id" : String ( mark . attrs [ "id" ] ) ,
48+ "data-description" : formatAttributionTitle (
49+ "Inserted" ,
50+ mark . attrs [ "userIds" ] ,
51+ mark . attrs [ "timestamp" ] ,
52+ ) ,
53+ "data-user-ids" : JSON . stringify ( mark . attrs [ "userIds" ] ) ,
54+ "data-timestamp" : String ( mark . attrs [ "timestamp" ] ) ,
3255 "data-user-color" : String ( mark . attrs [ "user-color" ] ) ,
3356 "data-inline" : String ( inline ) ,
3457 style :
@@ -44,12 +67,15 @@ export const SuggestionAddMark = Mark.create({
4467 {
4568 tag : "ins" ,
4669 getAttrs ( node ) {
47- if ( ! node . dataset [ "id " ] ) {
70+ if ( ! node . dataset [ "userIds " ] ) {
4871 return false ;
4972 }
5073 return {
51- id : parseInt ( node . dataset [ "id" ] , 10 ) ,
52- userColor : node . dataset [ "userColor" ] ,
74+ userIds : JSON . parse ( node . dataset [ "userIds" ] ) ,
75+ timestamp : node . dataset [ "timestamp" ]
76+ ? parseInt ( node . dataset [ "timestamp" ] , 10 )
77+ : null ,
78+ "user-color" : node . dataset [ "userColor" ] ,
5379 } ;
5480 } ,
5581 } ,
@@ -61,10 +87,11 @@ export const SuggestionAddMark = Mark.create({
6187export const SuggestionDeleteMark = Mark . create ( {
6288 name : "y-attributed-delete" ,
6389 inclusive : false ,
64- excludes : "" ,
90+ // excludes: "", TODO: what's desired?
6591 addAttributes ( ) {
6692 return {
67- id : { default : null , validate : "number" } , // note: validate is supported in prosemirror but not in tiptap
93+ userIds : { default : null } ,
94+ timestamp : { default : null } ,
6895 "user-color" : { default : null , validate : "string" } ,
6996 } ;
7097 } ,
@@ -76,14 +103,17 @@ export const SuggestionDeleteMark = Mark.create({
76103 blocknoteIgnore : true ,
77104 inclusive : false ,
78105
79- // attrs: {
80- // id: { validate: "number" },
81- // },
82106 toDOM ( mark , inline ) {
83107 return [
84108 "del" ,
85109 {
86- "data-id" : String ( mark . attrs [ "id" ] ) ,
110+ "data-description" : formatAttributionTitle (
111+ "Deleted" ,
112+ mark . attrs [ "userIds" ] ,
113+ mark . attrs [ "timestamp" ] ,
114+ ) ,
115+ "data-user-ids" : JSON . stringify ( mark . attrs [ "userIds" ] ) ,
116+ "data-timestamp" : String ( mark . attrs [ "timestamp" ] ) ,
87117 "data-user-color" : String ( mark . attrs [ "user-color" ] ) ,
88118 "data-inline" : String ( inline ) ,
89119 style :
@@ -99,12 +129,15 @@ export const SuggestionDeleteMark = Mark.create({
99129 {
100130 tag : "del" ,
101131 getAttrs ( node ) {
102- if ( ! node . dataset [ "id " ] ) {
132+ if ( ! node . dataset [ "userIds " ] ) {
103133 return false ;
104134 }
105135 return {
106- id : parseInt ( node . dataset [ "id" ] , 10 ) ,
107- userColor : node . dataset [ "userColor" ] ,
136+ userIds : JSON . parse ( node . dataset [ "userIds" ] ) ,
137+ timestamp : node . dataset [ "timestamp" ]
138+ ? parseInt ( node . dataset [ "timestamp" ] , 10 )
139+ : null ,
140+ "user-color" : node . dataset [ "userColor" ] ,
108141 } ;
109142 } ,
110143 } ,
@@ -116,10 +149,12 @@ export const SuggestionDeleteMark = Mark.create({
116149export const SuggestionModificationMark = Mark . create ( {
117150 name : "y-attributed-format" ,
118151 inclusive : false ,
119- excludes : "" ,
152+ // excludes: "", TODO: what's desired?
120153 addAttributes ( ) {
121154 return {
122- id : { default : null , validate : "number" } , // note: validate is supported in prosemirror but not in tiptap
155+ userIds : { default : null } ,
156+ format : { default : null } ,
157+ timestamp : { default : null } ,
123158 "user-color" : { default : null , validate : "string" } ,
124159 } ;
125160 } ,
@@ -134,8 +169,15 @@ export const SuggestionModificationMark = Mark.create({
134169 return [
135170 inline ? "span" : "div" ,
136171 {
172+ "data-description" : formatAttributionTitle (
173+ "Modified" ,
174+ mark . attrs [ "userIds" ] ,
175+ mark . attrs [ "timestamp" ] ,
176+ ) ,
137177 "data-type" : "modification" ,
138- "data-id" : String ( mark . attrs [ "id" ] ) ,
178+ "data-user-ids" : JSON . stringify ( mark . attrs [ "userIds" ] ) ,
179+ "data-format" : JSON . stringify ( mark . attrs [ "format" ] ) ,
180+ "data-timestamp" : String ( mark . attrs [ "timestamp" ] ) ,
139181 "data-user-color" : String ( mark . attrs [ "user-color" ] ) ,
140182 style :
141183 ( inline ? "" : "display: contents" ) +
@@ -150,23 +192,35 @@ export const SuggestionModificationMark = Mark.create({
150192 {
151193 tag : "span[data-type='modification']" ,
152194 getAttrs ( node ) {
153- if ( ! node . dataset [ "id " ] ) {
195+ if ( ! node . dataset [ "userIds " ] ) {
154196 return false ;
155197 }
156198 return {
157- id : parseInt ( node . dataset [ "id" ] , 10 ) ,
199+ userIds : JSON . parse ( node . dataset [ "userIds" ] ) ,
200+ format : node . dataset [ "format" ]
201+ ? JSON . parse ( node . dataset [ "format" ] )
202+ : null ,
203+ timestamp : node . dataset [ "timestamp" ]
204+ ? parseInt ( node . dataset [ "timestamp" ] , 10 )
205+ : null ,
158206 "user-color" : node . dataset [ "userColor" ] ,
159207 } ;
160208 } ,
161209 } ,
162210 {
163211 tag : "div[data-type='modification']" ,
164212 getAttrs ( node ) {
165- if ( ! node . dataset [ "id " ] ) {
213+ if ( ! node . dataset [ "userIds " ] ) {
166214 return false ;
167215 }
168216 return {
169- id : parseInt ( node . dataset [ "id" ] , 10 ) ,
217+ userIds : JSON . parse ( node . dataset [ "userIds" ] ) ,
218+ format : node . dataset [ "format" ]
219+ ? JSON . parse ( node . dataset [ "format" ] )
220+ : null ,
221+ timestamp : node . dataset [ "timestamp" ]
222+ ? parseInt ( node . dataset [ "timestamp" ] , 10 )
223+ : null ,
170224 "user-color" : node . dataset [ "userColor" ] ,
171225 } ;
172226 } ,
0 commit comments