@@ -22,6 +22,8 @@ class QuipProcessor {
22
22
this . threadsTotal = 0 ;
23
23
this . foldersTotal = 0 ;
24
24
25
+ this . referencesMap = new Map ( ) ;
26
+
25
27
this . phase = 'STOP' ; //START, STOP, ANALYSIS, EXPORT
26
28
27
29
this . quipService = new QuipService ( quipToken , options . quipApiURL ) ;
@@ -45,21 +47,21 @@ class QuipProcessor {
45
47
this . start = true ;
46
48
this . threadsProcessed = 0 ;
47
49
48
- const user = await this . quipService . getUser ( ) ;
49
- if ( ! user ) {
50
+ this . quipUser = await this . quipService . getUser ( ) ;
51
+ if ( ! this . quipUser ) {
50
52
this . logger . error ( "Can't load the User" ) ;
51
53
this . stopExport ( ) ;
52
54
return ;
53
55
}
54
56
55
57
let folderIdsToExport = [
56
- //user .desktop_folder_id,
57
- //user .archive_folder_id,
58
- //user .starred_folder_id,
59
- user . private_folder_id ,
60
- //user .trash_folder_id
61
- ...user . shared_folder_ids ,
62
- ...user . group_folder_ids
58
+ //this.quipUser .desktop_folder_id,
59
+ //this.quipUser .archive_folder_id,
60
+ //this.quipUser .starred_folder_id,
61
+ this . quipUser . private_folder_id ,
62
+ //this.quipUser .trash_folder_id
63
+ ...this . quipUser . shared_folder_ids ,
64
+ ...this . quipUser . group_folder_ids
63
65
] ;
64
66
65
67
if ( folderIds && folderIds . length > 0 ) {
@@ -81,34 +83,84 @@ class QuipProcessor {
81
83
this . phase = phase ;
82
84
}
83
85
84
- _getMatches ( text , regexp /*, threadId*/ ) {
86
+ _getMatches ( text , regexp ) {
85
87
const matches = [ ] ;
86
88
87
89
let regexpResult = regexp . exec ( text ) ;
88
90
89
91
while ( regexpResult != null ) {
90
- //if(regexpResult[2] === threadId) {
91
- matches . push ( {
92
- replacement : regexpResult [ 1 ] ,
93
- threadId : regexpResult [ 2 ] ,
94
- blobId : regexpResult [ 3 ] ,
95
- fileName : regexpResult [ 4 ]
96
- } ) ;
97
- //}
92
+ matches . push ( {
93
+ replacement : regexpResult [ 1 ] ,
94
+ threadId : regexpResult [ 2 ] ,
95
+ blobId : regexpResult [ 3 ] ,
96
+ fileName : regexpResult [ 4 ]
97
+ } ) ;
98
98
regexpResult = regexp . exec ( text ) ;
99
99
}
100
100
101
101
return matches ;
102
102
}
103
103
104
+ async _resolveReferences ( html , pathDeepness ) {
105
+ //look up for document or folder references
106
+ const regexp = new RegExp ( `href=\\"(${ this . quipUser . url } /([\\w-]+))\\"` , 'gim' ) ;
107
+ const matchesReference = this . _getMatches ( html , regexp ) ;
108
+
109
+ //replace references to documents
110
+ if ( this . options . resolveReferences ) {
111
+ for ( const reference of matchesReference ) {
112
+ html = await this . _processReference ( html , reference , pathDeepness ) ;
113
+ }
114
+ }
115
+
116
+ return html ;
117
+ }
118
+
119
+ async _processReference ( html , reference , pathDeepness ) {
120
+ let referencedObject = this . referencesMap . get ( reference . threadId ) ;
121
+
122
+ let path , folder , title ;
123
+ if ( referencedObject ) {
124
+ path = referencedObject . path ;
125
+ folder = referencedObject . folder ;
126
+ title = referencedObject . title ;
127
+ }
128
+
129
+ if ( ! path ) {
130
+ //correct path for threads
131
+ const referencedThread = await this . quipService . getThread ( reference . threadId ) ;
132
+ if ( ! referencedThread ) {
133
+ return html ;
134
+ }
135
+ referencedObject = this . referencesMap . get ( referencedThread . thread . id ) ;
136
+ if ( referencedObject ) {
137
+ path = referencedObject . path ;
138
+ folder = false ;
139
+ title = referencedThread . thread . title ;
140
+ }
141
+ }
142
+
143
+ if ( ! path || ! title ) {
144
+ return html ;
145
+ }
146
+
147
+ if ( folder ) {
148
+ path = '../' . repeat ( pathDeepness ) + path + title ;
149
+ } else {
150
+ path = '../' . repeat ( pathDeepness ) + path + sanitizeFilename ( title . trim ( ) ) + '.html' ;
151
+ }
152
+
153
+ return html . replace ( reference . replacement , path ) ;
154
+ }
155
+
104
156
async _processDocumentThread ( quipThread , path ) {
105
157
//look up for images in html
106
158
let regexp = new RegExp ( "src='(/blob/([\\w-]+)/([\\w-]+))'" , 'gim' ) ;
107
- const matchesImg = this . _getMatches ( quipThread . html , regexp , quipThread . thread . id ) ;
159
+ const matchesImg = this . _getMatches ( quipThread . html , regexp ) ;
108
160
109
161
//look up for links in html
110
162
regexp = new RegExp ( 'href=\\"(.*/blob/(.+)/(.+)\\?name=(.+))\\"' , 'gim' ) ;
111
- const matchesLink = this . _getMatches ( quipThread . html , regexp , quipThread . thread . id ) ;
163
+ const matchesLink = this . _getMatches ( quipThread . html , regexp ) ;
112
164
113
165
const pathDeepness = path . split ( "/" ) . length - 1 ;
114
166
let wrappedHtml = quipThread . html ;
@@ -126,7 +178,7 @@ class QuipProcessor {
126
178
127
179
if ( this . documentTemplate ) {
128
180
//wrap html code
129
- wrappedHtml = ejs . render ( this . documentTemplate , documentRenderOptions ) ;
181
+ wrappedHtml = ejs . render ( this . documentTemplate , documentRenderOptions ) ;
130
182
}
131
183
132
184
//replace blob references for links
@@ -139,6 +191,11 @@ class QuipProcessor {
139
191
wrappedHtml = await this . _processFile ( wrappedHtml , image , path , this . options . embeddedImages ) ;
140
192
}
141
193
194
+ //replace references to documents
195
+ if ( this . options . resolveReferences ) {
196
+ wrappedHtml = await this . _resolveReferences ( wrappedHtml , pathDeepness ) ;
197
+ }
198
+
142
199
this . saveCallback ( wrappedHtml , sanitizeFilename ( `${ quipThread . thread . title . trim ( ) } .html` ) , 'THREAD' , path ) ;
143
200
}
144
201
@@ -273,19 +330,33 @@ class QuipProcessor {
273
330
} ) ;
274
331
}
275
332
276
- async _countThreadsAndFolders ( quipFolder ) {
333
+ async _countThreadsAndFolders ( quipFolder , path ) {
277
334
const threadIds = [ ] ;
278
335
const folderIds = [ ] ;
279
336
337
+ if ( this . options . resolveReferences ) {
338
+ this . referencesMap . set ( quipFolder . folder . id , {
339
+ path,
340
+ folder : true ,
341
+ title : quipFolder . folder . title
342
+ } ) ;
343
+ }
344
+
280
345
if ( ! quipFolder . children || quipFolder . children . length === 0 ) {
281
346
return ;
282
347
}
283
348
349
+ const pathForChildren = `${ path } ${ quipFolder . folder . title } /` ;
350
+
284
351
for ( const index in quipFolder . children ) {
285
352
const quipChild = quipFolder . children [ index ] ;
286
-
287
353
if ( quipChild . thread_id ) { //thread
288
354
threadIds . push ( quipChild . thread_id ) ;
355
+ if ( this . options . resolveReferences ) {
356
+ this . referencesMap . set ( quipChild . thread_id , {
357
+ path : pathForChildren
358
+ } ) ;
359
+ }
289
360
} else if ( quipChild . folder_id ) { //folder
290
361
folderIds . push ( quipChild . folder_id ) ;
291
362
}
@@ -308,7 +379,7 @@ class QuipProcessor {
308
379
}
309
380
310
381
for ( const index in childFolders ) {
311
- await this . _countThreadsAndFolders ( childFolders [ index ] ) ;
382
+ await this . _countThreadsAndFolders ( childFolders [ index ] , pathForChildren ) ;
312
383
}
313
384
}
314
385
@@ -326,7 +397,7 @@ class QuipProcessor {
326
397
}
327
398
328
399
for ( const index in quipFolders ) {
329
- await this . _countThreadsAndFolders ( quipFolders [ index ] ) ;
400
+ await this . _countThreadsAndFolders ( quipFolders [ index ] , "" ) ;
330
401
}
331
402
332
403
this . _changePhase ( 'EXPORT' ) ;
0 commit comments