@@ -5,16 +5,43 @@ type SuperDocConfig = ConstructorParameters<typeof SuperDoc>[0];
55type SuperDocInstance = InstanceType < typeof SuperDoc > ;
66type SuperDocReadyPayload = Parameters < NonNullable < SuperDocConfig [ 'onReady' ] > > [ 0 ] ;
77type OverrideType = 'markdown' | 'html' | 'text' ;
8+ type StoryLocator =
9+ | { kind : 'story' ; storyType : 'body' }
10+ | { kind : 'story' ; storyType : 'headerFooterPart' ; refId : string }
11+ | { kind : 'story' ; storyType : 'footnote' | 'endnote' ; noteId : string } ;
812type ContentOverrideInput = {
913 contentOverride ?: string ;
1014 overrideType ?: OverrideType ;
1115} ;
16+ type BehaviorHarnessCommentSnapshot = {
17+ commentId ?: string ;
18+ importedId ?: string ;
19+ trackedChange ?: boolean ;
20+ trackedChangeText ?: string | null ;
21+ trackedChangeType ?: string | null ;
22+ trackedChangeDisplayType ?: string | null ;
23+ trackedChangeStory ?: StoryLocator | null ;
24+ trackedChangeStoryKind ?: string | null ;
25+ trackedChangeStoryLabel ?: string ;
26+ trackedChangeAnchorKey ?: string | null ;
27+ deletedText ?: string | null ;
28+ resolvedTime ?: number | null ;
29+ } ;
30+ type BehaviorHarnessApi = {
31+ getActiveStorySession : ( ) => StoryLocator | null ;
32+ getActiveStoryText : ( ) => string | null ;
33+ getBodyStoryText : ( ) => string | null ;
34+ getCommentsSnapshot : ( ) => BehaviorHarnessCommentSnapshot [ ] ;
35+ getEditorCommentPositions : ( ) => Record < string , unknown > ;
36+ getActiveCommentId : ( ) => string | null ;
37+ } ;
1238
1339type HarnessWindow = Window &
1440 typeof globalThis & {
1541 superdocReady ?: boolean ;
1642 superdoc ?: SuperDocInstance ;
1743 editor ?: unknown ;
44+ behaviorHarness ?: BehaviorHarnessApi ;
1845 behaviorHarnessInit ?: ( input ?: ContentOverrideInput ) => void ;
1946 } ;
2047
@@ -42,6 +69,63 @@ if (!showCaret) {
4269}
4370
4471let instance : SuperDocInstance | null = null ;
72+ const commentsPanel = document . querySelector < HTMLElement > ( '#comments-panel' ) ;
73+
74+ function getEditorText ( editor : any ) : string | null {
75+ const state = editor ?. state ;
76+ const doc = state ?. doc ;
77+ if ( ! doc || typeof doc . textBetween !== 'function' || typeof doc . content ?. size !== 'number' ) return null ;
78+ return doc . textBetween ( 0 , doc . content . size , '\n' , '\n' ) ;
79+ }
80+
81+ function cloneJson < T > ( value : T ) : T {
82+ return JSON . parse ( JSON . stringify ( value ) ) as T ;
83+ }
84+
85+ function buildBehaviorHarnessApi ( ) : BehaviorHarnessApi {
86+ return {
87+ getActiveStorySession : ( ) => {
88+ const session = ( harnessWindow . editor as any ) ?. presentationEditor
89+ ?. getStorySessionManager ?.( )
90+ ?. getActiveSession ?.( ) ;
91+ return session ?. locator ?? null ;
92+ } ,
93+ getActiveStoryText : ( ) => {
94+ const activeEditor = ( harnessWindow . editor as any ) ?. presentationEditor ?. getActiveEditor ?.( ) ;
95+ if ( ! activeEditor || activeEditor === harnessWindow . editor ) return null ;
96+ return getEditorText ( activeEditor ) ;
97+ } ,
98+ getBodyStoryText : ( ) => getEditorText ( harnessWindow . editor ) ,
99+ getCommentsSnapshot : ( ) => {
100+ const comments = ( harnessWindow . superdoc as any ) ?. commentsStore ?. commentsList ?? [ ] ;
101+ return comments . map ( ( comment : any ) => {
102+ const raw = typeof comment ?. getValues === 'function' ? comment . getValues ( ) : comment ;
103+ return cloneJson ( {
104+ commentId : raw ?. commentId ,
105+ importedId : raw ?. importedId ,
106+ trackedChange : raw ?. trackedChange === true ,
107+ trackedChangeText : raw ?. trackedChangeText ?? null ,
108+ trackedChangeType : raw ?. trackedChangeType ?? null ,
109+ trackedChangeDisplayType : raw ?. trackedChangeDisplayType ?? null ,
110+ trackedChangeStory : raw ?. trackedChangeStory ?? null ,
111+ trackedChangeStoryKind : raw ?. trackedChangeStoryKind ?? null ,
112+ trackedChangeStoryLabel : raw ?. trackedChangeStoryLabel ?? '' ,
113+ trackedChangeAnchorKey : raw ?. trackedChangeAnchorKey ?? null ,
114+ deletedText : raw ?. deletedText ?? null ,
115+ resolvedTime : raw ?. resolvedTime ?? null ,
116+ } ) ;
117+ } ) ;
118+ } ,
119+ getEditorCommentPositions : ( ) => {
120+ const positions = ( harnessWindow . superdoc as any ) ?. commentsStore ?. editorCommentPositions ?? { } ;
121+ return cloneJson ( positions ) ;
122+ } ,
123+ getActiveCommentId : ( ) => {
124+ const activeComment = ( harnessWindow . superdoc as any ) ?. commentsStore ?. activeComment ;
125+ return activeComment == null ? null : String ( activeComment ) ;
126+ } ,
127+ } ;
128+ }
45129
46130function applyContentOverride ( config : SuperDocConfig , input ?: ContentOverrideInput ) {
47131 if ( ! input ?. contentOverride || ! input ?. overrideType ) return ;
@@ -77,10 +161,15 @@ function init(file?: File, content?: ContentOverrideInput) {
77161 telemetry : { enabled : false } ,
78162 onReady : ( { superdoc } : SuperDocReadyPayload ) => {
79163 harnessWindow . superdoc = superdoc ;
164+ if ( comments === 'panel' && commentsPanel ) {
165+ commentsPanel . replaceChildren ( ) ;
166+ superdoc . addCommentsList ( commentsPanel ) ;
167+ }
80168 superdoc . activeEditor . on ( 'create' , ( payload : unknown ) => {
81169 if ( ! payload || typeof payload !== 'object' || ! ( 'editor' in payload ) ) return ;
82170 harnessWindow . editor = ( payload as { editor : unknown } ) . editor ;
83171 } ) ;
172+ harnessWindow . behaviorHarness = buildBehaviorHarnessApi ( ) ;
84173 harnessWindow . superdocReady = true ;
85174 } ,
86175 } ;
@@ -104,6 +193,14 @@ function init(file?: File, content?: ContentOverrideInput) {
104193 // Comments
105194 if ( comments === 'on' || comments === 'panel' ) {
106195 config . comments = { visible : true } ;
196+ if ( comments === 'panel' ) {
197+ config . modules = {
198+ ...( config . modules ?? { } ) ,
199+ comments : {
200+ ...( ( config . modules as Record < string , unknown > | undefined ) ?. comments as Record < string , unknown > | undefined ) ,
201+ } ,
202+ } ;
203+ }
107204 } else if ( comments === 'readonly' ) {
108205 config . comments = { visible : true , readOnly : true } ;
109206 } else if ( comments === 'disabled' ) {
@@ -135,6 +232,10 @@ function init(file?: File, content?: ContentOverrideInput) {
135232 }
136233
137234 instance = new SuperDoc ( config ) ;
235+ if ( commentsPanel ) {
236+ commentsPanel . classList . toggle ( 'is-visible' , comments === 'panel' ) ;
237+ if ( comments !== 'panel' ) commentsPanel . replaceChildren ( ) ;
238+ }
138239
139240 if ( ! showSelection ) {
140241 const style = document . createElement ( 'style' ) ;
0 commit comments