@@ -175,8 +175,8 @@ export class FileManager {
175175
176176 const repoCleaned = repoName . replace ( / \/ / g, "-" ) ;
177177 const ownerCleaned = owner . replace ( / \/ / g, "-" ) ;
178- const issueFolder = ` ${ repo . issueFolder } / ${ ownerCleaned } / ${ repoCleaned } ` ;
179- const pullRequestFolder = ` ${ repo . pullRequestFolder } / ${ ownerCleaned } / ${ repoCleaned } ` ;
178+ const issueFolder = this . getIssueFolderPath ( repo , ownerCleaned , repoCleaned ) ;
179+ const pullRequestFolder = this . getPullRequestFolderPath ( repo , ownerCleaned , repoCleaned ) ;
180180
181181 await this . cleanupEmptyIssueFolder (
182182 repo ,
@@ -196,24 +196,41 @@ export class FileManager {
196196
197197 // ----- Private helper methods -----
198198
199+ /**
200+ * Get the issue folder path for a repository
201+ */
202+ private getIssueFolderPath ( repo : RepositoryTracking , ownerCleaned : string , repoCleaned : string ) : string {
203+ if ( repo . useCustomIssueFolder && repo . customIssueFolder && repo . customIssueFolder . trim ( ) ) {
204+ return repo . customIssueFolder . trim ( ) ;
205+ }
206+ return `${ repo . issueFolder } /${ ownerCleaned } /${ repoCleaned } ` ;
207+ }
208+
209+ /**
210+ * Get the pull request folder path for a repository
211+ */
212+ private getPullRequestFolderPath ( repo : RepositoryTracking , ownerCleaned : string , repoCleaned : string ) : string {
213+ if ( repo . useCustomPullRequestFolder && repo . customPullRequestFolder && repo . customPullRequestFolder . trim ( ) ) {
214+ return repo . customPullRequestFolder . trim ( ) ;
215+ }
216+ return `${ repo . pullRequestFolder } /${ ownerCleaned } /${ repoCleaned } ` ;
217+ }
218+
199219 private async cleanupDeletedIssues (
200220 repo : RepositoryTracking ,
201221 ownerCleaned : string ,
202222 repoCleaned : string ,
203223 allIssuesIncludingRecentlyClosed : any [ ] ,
204224 ) : Promise < void > {
205- const repoFolder = this . app . vault . getAbstractFileByPath (
206- `${ repo . issueFolder } /${ ownerCleaned } /${ repoCleaned } ` ,
207- ) ;
225+ const issueFolderPath = this . getIssueFolderPath ( repo , ownerCleaned , repoCleaned ) ;
226+ const repoFolder = this . app . vault . getAbstractFileByPath ( issueFolderPath ) ;
208227
209228 if ( repoFolder ) {
210229 const files = this . app . vault
211230 . getFiles ( )
212231 . filter (
213232 ( file ) =>
214- file . path . startsWith (
215- `${ repo . issueFolder } /${ ownerCleaned } /${ repoCleaned } /` ,
216- ) && file . extension === "md" ,
233+ file . path . startsWith ( `${ issueFolderPath } /` ) && file . extension === "md" ,
217234 ) ;
218235
219236 for ( const file of files ) {
@@ -263,18 +280,15 @@ export class FileManager {
263280 repoCleaned : string ,
264281 allPullRequestsIncludingRecentlyClosed : any [ ] ,
265282 ) : Promise < void > {
266- const repoFolder = this . app . vault . getAbstractFileByPath (
267- `${ repo . pullRequestFolder } /${ ownerCleaned } /${ repoCleaned } ` ,
268- ) ;
283+ const pullRequestFolderPath = this . getPullRequestFolderPath ( repo , ownerCleaned , repoCleaned ) ;
284+ const repoFolder = this . app . vault . getAbstractFileByPath ( pullRequestFolderPath ) ;
269285
270286 if ( repoFolder ) {
271287 const files = this . app . vault
272288 . getFiles ( )
273289 . filter (
274290 ( file ) =>
275- file . path . startsWith (
276- `${ repo . pullRequestFolder } /${ ownerCleaned } /${ repoCleaned } /` ,
277- ) && file . extension === "md" ,
291+ file . path . startsWith ( `${ pullRequestFolderPath } /` ) && file . extension === "md" ,
278292 ) ;
279293
280294 for ( const file of files ) {
@@ -323,15 +337,20 @@ export class FileManager {
323337 issue : any ,
324338 ) : Promise < void > {
325339 const fileName = `Issue - ${ issue . number } .md` ;
326- await this . ensureFolderExists ( repo . issueFolder ) ;
327- await this . ensureFolderExists ( `${ repo . issueFolder } /${ ownerCleaned } ` ) ;
328- await this . ensureFolderExists (
329- `${ repo . issueFolder } /${ ownerCleaned } /${ repoCleaned } ` ,
330- ) ;
340+ const issueFolderPath = this . getIssueFolderPath ( repo , ownerCleaned , repoCleaned ) ;
331341
332- const file = this . app . vault . getAbstractFileByPath (
333- `${ repo . issueFolder } /${ ownerCleaned } /${ repoCleaned } /${ fileName } ` ,
334- ) ;
342+ // Ensure folder structure exists
343+ if ( repo . useCustomIssueFolder && repo . customIssueFolder && repo . customIssueFolder . trim ( ) ) {
344+ // For custom folders, just ensure the custom path exists
345+ await this . ensureFolderExists ( repo . customIssueFolder . trim ( ) ) ;
346+ } else {
347+ // For default structure, ensure nested path exists
348+ await this . ensureFolderExists ( repo . issueFolder ) ;
349+ await this . ensureFolderExists ( `${ repo . issueFolder } /${ ownerCleaned } ` ) ;
350+ await this . ensureFolderExists ( `${ repo . issueFolder } /${ ownerCleaned } /${ repoCleaned } ` ) ;
351+ }
352+
353+ const file = this . app . vault . getAbstractFileByPath ( `${ issueFolderPath } /${ fileName } ` ) ;
335354
336355 const [ owner , repoName ] = repo . repository . split ( "/" ) ;
337356
@@ -407,10 +426,7 @@ export class FileManager {
407426 }
408427 }
409428 } else {
410- await this . app . vault . create (
411- `${ repo . issueFolder } /${ ownerCleaned } /${ repoCleaned } /${ fileName } ` ,
412- content ,
413- ) ;
429+ await this . app . vault . create ( `${ issueFolderPath } /${ fileName } ` , content ) ;
414430 this . noticeManager . debug ( `Created issue file for ${ issue . number } ` ) ;
415431 }
416432 }
@@ -422,18 +438,20 @@ export class FileManager {
422438 pr : any ,
423439 ) : Promise < void > {
424440 const fileName = `Pull Request - ${ pr . number } .md` ;
441+ const pullRequestFolderPath = this . getPullRequestFolderPath ( repo , ownerCleaned , repoCleaned ) ;
425442
426- await this . ensureFolderExists ( repo . pullRequestFolder ) ;
427- await this . ensureFolderExists (
428- `${ repo . pullRequestFolder } /${ ownerCleaned } ` ,
429- ) ;
430- await this . ensureFolderExists (
431- `${ repo . pullRequestFolder } /${ ownerCleaned } /${ repoCleaned } ` ,
432- ) ;
443+ // Ensure folder structure exists
444+ if ( repo . useCustomPullRequestFolder && repo . customPullRequestFolder && repo . customPullRequestFolder . trim ( ) ) {
445+ // For custom folders, just ensure the custom path exists
446+ await this . ensureFolderExists ( repo . customPullRequestFolder . trim ( ) ) ;
447+ } else {
448+ // For default structure, ensure nested path exists
449+ await this . ensureFolderExists ( repo . pullRequestFolder ) ;
450+ await this . ensureFolderExists ( `${ repo . pullRequestFolder } /${ ownerCleaned } ` ) ;
451+ await this . ensureFolderExists ( `${ repo . pullRequestFolder } /${ ownerCleaned } /${ repoCleaned } ` ) ;
452+ }
433453
434- const file = this . app . vault . getAbstractFileByPath (
435- `${ repo . pullRequestFolder } /${ ownerCleaned } /${ repoCleaned } /${ fileName } ` ,
436- ) ;
454+ const file = this . app . vault . getAbstractFileByPath ( `${ pullRequestFolderPath } /${ fileName } ` ) ;
437455
438456 const [ owner , repoName ] = repo . repository . split ( "/" ) ;
439457
@@ -509,10 +527,7 @@ export class FileManager {
509527 }
510528 }
511529 } else {
512- await this . app . vault . create (
513- `${ repo . pullRequestFolder } /${ ownerCleaned } /${ repoCleaned } /${ fileName } ` ,
514- content ,
515- ) ;
530+ await this . app . vault . create ( `${ pullRequestFolderPath } /${ fileName } ` , content ) ;
516531 this . noticeManager . debug ( `Created PR file for ${ pr . number } ` ) ;
517532 }
518533 }
@@ -643,28 +658,31 @@ ${this.formatComments(comments, this.settings.escapeMode)}
643658 }
644659 }
645660
646- if ( files . length === 0 ) {
647- this . noticeManager . info (
648- `Deleting empty folder: ${ issueFolder } ` ,
649- ) ;
650- const folder =
651- this . app . vault . getAbstractFileByPath ( issueFolder ) ;
652- if ( folder instanceof TFolder && folder . children . length === 0 ) {
653- await this . app . fileManager . trashFile ( folder ) ;
654- }
655- }
656-
657- const issueOwnerFolder = this . app . vault . getAbstractFileByPath (
658- `${ repo . issueFolder } /${ ownerCleaned } ` ,
659- ) ;
660-
661- if ( issueOwnerFolder instanceof TFolder ) {
662- const files = issueOwnerFolder . children ;
661+ // Only cleanup nested folder structure if not using custom folder
662+ if ( ! repo . useCustomIssueFolder || ! repo . customIssueFolder || ! repo . customIssueFolder . trim ( ) ) {
663663 if ( files . length === 0 ) {
664664 this . noticeManager . info (
665- `Deleting empty folder: ${ issueOwnerFolder . path } ` ,
665+ `Deleting empty folder: ${ issueFolder } ` ,
666666 ) ;
667- await this . app . fileManager . trashFile ( issueOwnerFolder ) ;
667+ const folder =
668+ this . app . vault . getAbstractFileByPath ( issueFolder ) ;
669+ if ( folder instanceof TFolder && folder . children . length === 0 ) {
670+ await this . app . fileManager . trashFile ( folder ) ;
671+ }
672+ }
673+
674+ const issueOwnerFolder = this . app . vault . getAbstractFileByPath (
675+ `${ repo . issueFolder } /${ ownerCleaned } ` ,
676+ ) ;
677+
678+ if ( issueOwnerFolder instanceof TFolder ) {
679+ const files = issueOwnerFolder . children ;
680+ if ( files . length === 0 ) {
681+ this . noticeManager . info (
682+ `Deleting empty folder: ${ issueOwnerFolder . path } ` ,
683+ ) ;
684+ await this . app . fileManager . trashFile ( issueOwnerFolder ) ;
685+ }
668686 }
669687 }
670688 }
@@ -703,38 +721,40 @@ ${this.formatComments(comments, this.settings.escapeMode)}
703721 }
704722 }
705723
706- if ( files . length === 0 ) {
707- this . noticeManager . info (
708- `Deleting empty folder: ${ pullRequestFolder } ` ,
709- ) ;
710- const folder =
711- this . app . vault . getAbstractFileByPath ( pullRequestFolder ) ;
712- if ( folder instanceof TFolder && folder . children . length === 0 ) {
713- await this . app . fileManager . trashFile ( folder ) ;
714- }
715- }
716-
717- const pullRequestOwnerFolder = this . app . vault . getAbstractFileByPath (
718- `${ repo . pullRequestFolder } /${ ownerCleaned } ` ,
719- ) ;
720-
721- if ( pullRequestOwnerFolder instanceof TFolder ) {
722- const files = pullRequestOwnerFolder . children ;
724+ // Only cleanup nested folder structure if not using custom folder
725+ if ( ! repo . useCustomPullRequestFolder || ! repo . customPullRequestFolder || ! repo . customPullRequestFolder . trim ( ) ) {
723726 if ( files . length === 0 ) {
724727 this . noticeManager . info (
725- `Deleting empty folder: ${ pullRequestOwnerFolder . path } ` ,
726- ) ;
727- await this . app . fileManager . trashFile (
728- pullRequestOwnerFolder ,
728+ `Deleting empty folder: ${ pullRequestFolder } ` ,
729729 ) ;
730+ const folder =
731+ this . app . vault . getAbstractFileByPath ( pullRequestFolder ) ;
732+ if ( folder instanceof TFolder && folder . children . length === 0 ) {
733+ await this . app . fileManager . trashFile ( folder ) ;
734+ }
735+ }
736+
737+ const pullRequestOwnerFolder = this . app . vault . getAbstractFileByPath (
738+ `${ repo . pullRequestFolder } /${ ownerCleaned } ` ,
739+ ) ;
740+
741+ if ( pullRequestOwnerFolder instanceof TFolder ) {
742+ const files = pullRequestOwnerFolder . children ;
743+ if ( files . length === 0 ) {
744+ this . noticeManager . info (
745+ `Deleting empty folder: ${ pullRequestOwnerFolder . path } ` ,
746+ ) ;
747+ await this . app . fileManager . trashFile (
748+ pullRequestOwnerFolder ,
749+ ) ;
750+ }
730751 }
731752 }
732753 }
733754 }
734755
735- /**
736- * Format comments section for issues and pull requests
737- */
756+ // Format comments section for issues and pull requests
757+
738758 private formatComments (
739759 comments : any [ ] ,
740760 escapeMode : "disabled" | "normal" | "strict" | "veryStrict" ,
@@ -744,9 +764,7 @@ ${this.formatComments(comments, this.settings.escapeMode)}
744764 }
745765
746766 comments . sort (
747- ( a , b ) =>
748- new Date ( a . created_at ) . getTime ( ) -
749- new Date ( b . created_at ) . getTime ( ) ,
767+ ( a , b ) => new Date ( a . created_at ) . getTime ( ) - new Date ( b . created_at ) . getTime ( ) ,
750768 ) ;
751769
752770 let commentSection = "\n## Comments\n\n" ;
0 commit comments