Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions browser-extension/src/lib/enhancers/github/githubEditComment.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import OverType, { type OverTypeInstance } from 'overtype'
import type React from 'react'
import type { CommentEnhancer, CommentSpot } from '@/lib/enhancer'
import { logger } from '@/lib/logger'
import { modifyDOM } from '../modifyDOM'
import { commonGithubOptions } from './ghOptions'
import { githubHighlighter } from './githubHighlighter'

export interface GitHubEditCommentSpot extends CommentSpot {
type: 'GH_EDIT_COMMENT'
title: string
domain: string
slug: string
number: number
}

export class GitHubEditCommentEnhancer implements CommentEnhancer<GitHubEditCommentSpot> {
forSpotTypes(): string[] {
return ['GH_EDIT_COMMENT']
}

tryToEnhance(_textarea: HTMLTextAreaElement): GitHubEditCommentSpot | null {
if (
document.querySelector('meta[name="hostname"]')?.getAttribute('content') !== 'github.com' ||
!_textarea.matches('.TimelineItem textarea')
) {
return null
}

// Parse GitHub URL structure: /owner/repo/issues/123 or /owner/repo/pull/456
logger.info(`${this.constructor.name} examing url`, window.location.pathname)

const match = window.location.pathname.match(/^\/([^/]+)\/([^/]+)(?:\/(pull|issues)\/(\d+))/)
logger.info(`${this.constructor.name} found match`, window.location.pathname)
if (!match) return null
const [, owner, repo, numberStr] = match
const slug = `${owner}/${repo}`
const number = parseInt(numberStr!, 10)
const unique_key = `github.com:${slug}:${number}`
const title = 'TODO_TITLE'
return {
domain: 'github.com',
number,
slug,
title,
type: 'GH_EDIT_COMMENT',
unique_key,
}
}

prepareForFirstEnhancement(): void {
OverType.setCodeHighlighter(githubHighlighter)
}

enhance(textArea: HTMLTextAreaElement, _spot: GitHubEditCommentSpot): OverTypeInstance {
const overtypeContainer = modifyDOM(textArea)
return new OverType(overtypeContainer, {
...commonGithubOptions,
minHeight: '102px',
padding: 'var(--base-size-8)',
placeholder: 'Add your comment here...',
})[0]!
}

tableUpperDecoration(spot: GitHubEditCommentSpot): React.ReactNode {
const { slug, number } = spot
return (
<>
<span className='font-mono text-muted-foreground text-sm'>{slug}</span>
<span className='ml-2 font-medium'>PR #{number}</span>
</>
)
}

tableTitle(_spot: GitHubEditCommentSpot): string {
return 'TITLE_TODO'
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ export class GitHubPRNewCommentEnhancer implements CommentEnhancer<GitHubPRNewCo

// /owner/repo/compare/feature/more-enhancers?expand=1
// or /owner/repo/compare/feat/issue-static-and-dynamic...feature/more-enhancers?expand=1
logger.info(`${this.constructor.name} examing url`, location.pathname)
logger.debug(`${this.constructor.name} examing url`, window.location.pathname)

const match = location.pathname.match(
/^\/([^/]+)\/([^/]+)\/compare\/(?:([^.?]+)\.\.\.)?([^?]+)/,
)
logger.info(`${this.constructor.name} found match`, location.pathname, match)
logger.debug(`${this.constructor.name} found match`, window.location.pathname, match)

if (!match) return null
const [, owner, repo, baseBranch, compareBranch] = match
Expand Down
2 changes: 2 additions & 0 deletions browser-extension/src/lib/registries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { OverTypeInstance } from 'overtype'
import OverType from 'overtype'
import type { CommentEnhancer, CommentSpot, StrippedLocation } from './enhancer'
import { CommentEnhancerMissing } from './enhancers/CommentEnhancerMissing'
import { GitHubEditCommentEnhancer } from './enhancers/github/githubEditComment'
import { GitHubIssueAddCommentEnhancer } from './enhancers/github/githubIssueAddComment'
import { GitHubIssueNewCommentEnhancer } from './enhancers/github/githubIssueNewComment'
import { GitHubPRAddCommentEnhancer } from './enhancers/github/githubPRAddComment'
Expand All @@ -21,6 +22,7 @@ export class EnhancerRegistry {

constructor() {
// Register all available handlers
this.register(new GitHubEditCommentEnhancer())
this.register(new GitHubIssueAddCommentEnhancer())
this.register(new GitHubIssueNewCommentEnhancer())
this.register(new GitHubPRAddCommentEnhancer())
Expand Down
120 changes: 120 additions & 0 deletions browser-extension/tests/lib/enhancers/github.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,124 @@ describe('github', () => {
]
`)
})
withCorpus('gh_issue_edit').it('should create the correct spot object', async () => {
expect(enhancements(document, window)).toMatchInlineSnapshot(`
[
{
"for": "id=:rc3: name=null className=prc-Textarea-TextArea-13q4j focus-visible overtype-input",
"spot": {
"domain": "github.com",
"number": 56,
"slug": "diffplug/gitcasso",
"title": "TODO_TITLE",
"type": "GH_ISSUE_ADD_COMMENT",
"unique_key": "github.com:diffplug/gitcasso:56",
},
"title": "TITLE_TODO",
"upperDecoration": <React.Fragment>
<span
className="flex h-4 w-4 flex-shrink-0 items-center justify-center"
>
<IssueOpenedIcon
size={16}
/>
</span>
#
56
<a
className="truncate hover:underline"
href="https://github.com/diffplug/gitcasso"
>
diffplug/gitcasso
</a>
</React.Fragment>,
},
{
"for": "id=:ra7: name=null className=prc-Textarea-TextArea-13q4j overtype-input",
"spot": {
"domain": "github.com",
"number": 56,
"slug": "diffplug/gitcasso",
"title": "TODO_TITLE",
"type": "GH_ISSUE_ADD_COMMENT",
Comment on lines +188 to +217
Copy link
Member

@nedtwigg nedtwigg Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for issues, both the top and the bottom are identified as GH_ISSUE_ADD_COMMENT. That has to get fixed.

"unique_key": "github.com:diffplug/gitcasso:56",
},
"title": "TITLE_TODO",
"upperDecoration": <React.Fragment>
<span
className="flex h-4 w-4 flex-shrink-0 items-center justify-center"
>
<IssueOpenedIcon
size={16}
/>
</span>
#
56
<a
className="truncate hover:underline"
href="https://github.com/diffplug/gitcasso"
>
diffplug/gitcasso
</a>
</React.Fragment>,
},
]
`)
})
withCorpus('gh_pr_edit').it('should create the correct spot object', async () => {
expect(enhancements(document, window)).toMatchInlineSnapshot(`
[
{
"for": "id=issue-3429313834-body name=pull_request[body] className=js-comment-field js-paste-markdown js-task-list-field js-quick-submit js-size-to-fit size-to-fit js-session-resumable CommentBox-input FormControl-textarea js-saved-reply-shortcut-comment-field focus-visible overtype-input",
"spot": {
"domain": "github.com",
"number": NaN,
"slug": "diffplug/gitcasso",
"title": "TODO_TITLE",
"type": "GH_EDIT_COMMENT",
"unique_key": "github.com:diffplug/gitcasso:NaN",
},
"title": "TITLE_TODO",
"upperDecoration": <React.Fragment>
<span
className="font-mono text-muted-foreground text-sm"
>
diffplug/gitcasso
</span>
<span
className="ml-2 font-medium"
>
PR #
NaN
</span>
</React.Fragment>,
},
{
"for": "id=new_comment_field name=comment[body] className=js-comment-field js-paste-markdown js-task-list-field js-quick-submit FormControl-textarea CommentBox-input js-size-to-fit size-to-fit js-session-resumable js-saved-reply-shortcut-comment-field overtype-input",
"spot": {
"domain": "github.com",
"number": 58,
"slug": "diffplug/gitcasso",
"title": "TODO_TITLE",
"type": "GH_PR_ADD_COMMENT",
Comment on lines +252 to +277
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for PRs, the first textarea is GH_EDIT_COMMENT and the second one is GH_PR_ADD_COMMENT. That is great!

"unique_key": "github.com:diffplug/gitcasso:58",
},
"title": "TITLE_TODO",
"upperDecoration": <React.Fragment>
<span
className="font-mono text-muted-foreground text-sm"
>
diffplug/gitcasso
</span>
<span
className="ml-2 font-medium"
>
PR #
58
</span>
</React.Fragment>,
},
]
`)
})
})