@@ -224,16 +224,51 @@ class larkDocScraper {
224224
225225 // fs.writeFileSync(`records.json`, JSON.stringify(this.records, null, 2))
226226
227- const slugs = { }
227+ const slugEntries = [ ]
228+ const recordsBySeqId = new Map ( records . map ( record => [ record . fields [ 'Seq. ID' ] , record ] ) )
229+ const recordsByRecordId = new Map ( records . map ( record => [ record . record_id , record ] ) )
228230 if ( records . length > 0 ) {
229231 for ( let record of records ) {
230232 if ( record . fields . Slug ) {
231- slugs [ record . fields . Docs . link . split ( '/' ) . pop ( ) ] = { slug : record . fields . Slug , title : record . fields . Docs . text }
233+ const parentSeqId = record . fields . Parent ?. [ 0 ] ?. text || null
234+ const parentRecordId = record . fields [ '父记录' ] ?. [ 0 ] ?. record_ids ?. [ 0 ] || record . fields . Parent ?. [ 0 ] ?. record_ids ?. [ 0 ] || null
235+ const parentRecord = parentRecordId
236+ ? recordsByRecordId . get ( parentRecordId )
237+ : parentSeqId
238+ ? recordsBySeqId . get ( parentSeqId )
239+ : null
240+ slugEntries . push ( {
241+ key : record . fields . Docs . link . split ( '/' ) . pop ( ) ,
242+ token : record . fields . Docs . link . split ( '/' ) . pop ( ) ,
243+ slug : record . fields . Slug ,
244+ title : record . fields . Docs . text ,
245+ parent_token : parentRecord ?. fields ?. Docs ?. link ?. split ( '/' ) . pop ( ) || null ,
246+ record_id : record . record_id ,
247+ seq_id : record . fields [ 'Seq. ID' ] ,
248+ } )
232249 } else {
233250 throw new Error ( `Slug field not found for record ${ record . fields [ 'Seq. ID' ] } ` )
234251 }
235252 }
236253 }
254+
255+ const tokenCounts = new Map ( )
256+ slugEntries . forEach ( entry => {
257+ tokenCounts . set ( entry . token , ( tokenCounts . get ( entry . token ) || 0 ) + 1 )
258+ } )
259+
260+ const slugs = { }
261+ slugEntries . forEach ( entry => {
262+ const key = tokenCounts . get ( entry . token ) > 1
263+ ? `${ entry . token } #${ entry . record_id || entry . seq_id || Object . keys ( slugs ) . length } `
264+ : entry . token
265+ slugs [ key ] = {
266+ token : entry . token ,
267+ slug : entry . slug ,
268+ title : entry . title ,
269+ parent_token : entry . parent_token ,
270+ }
271+ } )
237272
238273 const slugs_arr = this . __uniquify ( Object . values ( slugs ) . map ( s => s . slug instanceof Array ? s . slug [ 0 ] [ s . slug [ 0 ] . type ] : s . slug ) )
239274 const slug_keys = Object . keys ( slugs )
@@ -246,6 +281,10 @@ class larkDocScraper {
246281 }
247282 } )
248283
284+ slug_keys . forEach ( s => {
285+ slugs [ s ] . parent_slug = slugs [ s ] . parent_token ? this . __slug_value ( slugs [ slugs [ s ] . parent_token ] ?. slug ) : null
286+ } )
287+
249288 this . slugs = slugs
250289
251290 // fs.writeFileSync(`slugs.json`, JSON.stringify(this.slugs, null, 2))
@@ -274,6 +313,15 @@ class larkDocScraper {
274313 return slug
275314 }
276315
316+ __slug_contexts ( preferredSlugPrefix ) {
317+ const contexts = [ preferredSlugPrefix ] . filter ( Boolean )
318+ if ( preferredSlugPrefix && preferredSlugPrefix . includes ( '-' ) ) {
319+ contexts . push ( preferredSlugPrefix . split ( '-' ) . pop ( ) )
320+ }
321+
322+ return contexts
323+ }
324+
277325 async __slugify ( token , title = null , preferredSlugPrefix = null ) {
278326 if ( ! this . slugs ) {
279327 await this . __base ( this . base )
@@ -282,16 +330,40 @@ class larkDocScraper {
282330 var slug = this . slugs [ token ]
283331
284332 if ( ! slug && title != null ) {
285- const records = Object . keys ( this . slugs ) . filter ( key => this . slugs [ key ] . title == title )
333+ const tokenRecords = Object . keys ( this . slugs ) . filter ( key => key === token || this . slugs [ key ] . token === token )
334+ const records = ( tokenRecords . length > 0 ? tokenRecords : Object . keys ( this . slugs ) )
335+ . filter ( key => this . slugs [ key ] . title == title )
286336 if ( records . length === 1 ) {
287337 slug = this . slugs [ records [ 0 ] ]
288338 } else if ( records . length > 1 ) {
339+ const exactSlugRecords = records . filter ( key => this . __slug_value ( this . slugs [ key ] . slug ) === title )
340+ if ( exactSlugRecords . length === 1 ) {
341+ slug = this . slugs [ exactSlugRecords [ 0 ] ]
342+ }
343+ }
344+
345+ if ( ! slug && records . length > 1 ) {
289346 if ( preferredSlugPrefix ) {
290- const contextualRecords = records . filter ( key => {
291- const value = this . __slug_value ( this . slugs [ key ] . slug )
292- return value === preferredSlugPrefix || value . startsWith ( `${ preferredSlugPrefix } -` )
347+ const contexts = this . __slug_contexts ( preferredSlugPrefix )
348+ let contextualRecords = records . filter ( key => {
349+ const parentSlug = this . slugs [ key ] . parent_slug
350+ return parentSlug && contexts . some ( context => parentSlug === context )
293351 } )
294352
353+ if ( contextualRecords . length !== 1 ) {
354+ contextualRecords = records . filter ( key => {
355+ const parentSlug = this . slugs [ key ] . parent_slug
356+ return parentSlug && contexts . some ( context => parentSlug . endsWith ( `-${ context } ` ) )
357+ } )
358+ }
359+
360+ if ( contextualRecords . length !== 1 ) {
361+ contextualRecords = records . filter ( key => {
362+ const value = this . __slug_value ( this . slugs [ key ] . slug )
363+ return contexts . some ( context => value === context || value . startsWith ( `${ context } -` ) )
364+ } )
365+ }
366+
295367 if ( contextualRecords . length === 1 ) {
296368 slug = this . slugs [ contextualRecords [ 0 ] ]
297369 }
@@ -487,7 +559,8 @@ class larkDocScraper {
487559 return 0 ;
488560 } )
489561
490- this . docs . slug = await this . __slugify ( this . docs . token , this . docs . name , preferredSlugPrefix )
562+ const resolvedDocSlug = await this . __slugify ( this . docs . token , this . docs . name , preferredSlugPrefix )
563+ this . docs . slug = resolvedDocSlug || this . docs . slug
491564
492565 if ( jres . has_more ) {
493566 await this . __fetch_drive_children ( folder_token , jres . data . next_page_token , recursive , preferredSlugPrefix )
0 commit comments