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
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import OverType, { type OverTypeInstance } from '../../../overtype/overtype'
import type { CommentEnhancer, CommentSpot } from '../../enhancer'
import { logger } from '../../logger'
import { modifyDOM } from '../modifyDOM'
import { githubHighlighter } from './githubHighlighter'

interface GitHubIssueAddCommentSpot extends CommentSpot {
type: 'GH_ISSUE_ADD_COMMENT'
domain: string
slug: string // owner/repo
number: number // issue number, undefined for new issues
}

export class GitHubIssueAddCommentEnhancer implements CommentEnhancer<GitHubIssueAddCommentSpot> {
forSpotTypes(): string[] {
return ['GH_ISSUE_ADD_COMMENT']
}

tryToEnhance(_textarea: HTMLTextAreaElement): GitHubIssueAddCommentSpot | null {
if (window.location.hostname !== 'github.com' || _textarea.id !== ':r2v:') {
return null
}

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

const match = window.location.pathname.match(/^\/([^/]+)\/([^/]+)(?:\/issues\/(\d+))/)
logger.debug(`${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}`
return {
domain: 'github.com',
number,
slug,
type: 'GH_ISSUE_ADD_COMMENT',
unique_key,
}
}

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

enhance(textArea: HTMLTextAreaElement, _spot: GitHubIssueAddCommentSpot): OverTypeInstance {
const overtypeContainer = modifyDOM(textArea)
return new OverType(overtypeContainer, {
autoResize: true,
minHeight: '100px',
padding: 'var(--base-size-16)',
placeholder: 'Use Markdown to format your comment',
})[0]!
}

tableTitle(spot: GitHubIssueAddCommentSpot): string {
const { slug, number } = spot
return `${slug} Issue #${number}`
}

tableIcon(_: GitHubIssueAddCommentSpot): string {
return '🔄' // PR icon TODO: icon urls in /public
}

buildUrl(spot: GitHubIssueAddCommentSpot): string {
return `https://${spot.domain}/${spot.slug}/issue/${spot.number}`
}
}
23 changes: 5 additions & 18 deletions browser-extension/src/lib/enhancers/github/githubPRAddComment.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import OverType, { type OverTypeInstance } from '../../../overtype/overtype'
import type { CommentEnhancer, CommentSpot } from '../../enhancer'
import { logger } from '../../logger'
import { modifyDOM } from '../modifyDOM'
import { githubHighlighter } from './githubHighlighter'
import { GITHUB_SPOT_TYPES, type GitHubSpotType } from './githubSpotTypes'

interface GitHubPRAddCommentSpot extends CommentSpot {
type: GitHubSpotType // Override to narrow from string to specific union
type: 'GH_PR_ADD_COMMENT' // Override to narrow from string to specific union
domain: string
slug: string // owner/repo
number: number // issue/PR number, undefined for new issues and PRs
}

export class GitHubPRAddCommentEnhancer implements CommentEnhancer<GitHubPRAddCommentSpot> {
forSpotTypes(): string[] {
return [...GITHUB_SPOT_TYPES]
return ['GH_PR_ADD_COMMENT']
}

tryToEnhance(_textarea: HTMLTextAreaElement): GitHubPRAddCommentSpot | null {
// Only handle github.com domains TODO: identify GitHub Enterprise somehow
if (window.location.hostname !== 'github.com') {
if (window.location.hostname !== 'github.com' || _textarea.id !== 'new_comment_field') {
return null
}

Expand Down Expand Up @@ -46,7 +46,7 @@ export class GitHubPRAddCommentEnhancer implements CommentEnhancer<GitHubPRAddCo
}

enhance(textArea: HTMLTextAreaElement, _spot: GitHubPRAddCommentSpot): OverTypeInstance {
const overtypeContainer = this.modifyDOM(textArea)
const overtypeContainer = modifyDOM(textArea)
return new OverType(overtypeContainer, {
autoResize: true,
minHeight: '102px',
Expand All @@ -55,19 +55,6 @@ export class GitHubPRAddCommentEnhancer implements CommentEnhancer<GitHubPRAddCo
})[0]!
}

private modifyDOM(overtypeInput: HTMLTextAreaElement): HTMLElement {
overtypeInput.classList.add('overtype-input')
const overtypePreview = document.createElement('div')
overtypePreview.classList.add('overtype-preview')
overtypeInput.insertAdjacentElement('afterend', overtypePreview)
const overtypeWrapper = overtypeInput.parentElement!.closest('div')!
overtypeWrapper.classList.add('overtype-wrapper')
overtypeInput.placeholder = 'Add your comment here...'
const overtypeContainer = overtypeWrapper.parentElement!.closest('div')!
overtypeContainer.classList.add('overtype-container')
return overtypeContainer.parentElement!.closest('div')!
}

tableTitle(spot: GitHubPRAddCommentSpot): string {
const { slug, number } = spot
return `${slug} PR #${number}`
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export const GITHUB_SPOT_TYPES = [
'GH_PR_ADD_COMMENT',
'GH_ISSUE_ADD_COMMENT',
/* TODO
'GH_ISSUE_NEW',
'GH_PR_NEW',
'GH_ISSUE_ADD_COMMENT',
'GH_ISSUE_EDIT_COMMENT',
'GH_PR_EDIT_COMMENT',
'GH_PR_CODE_COMMENT',
Expand Down
13 changes: 13 additions & 0 deletions browser-extension/src/lib/enhancers/modifyDOM.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Modify the DOM to trick overtype into adopting it instead of recreating it
export function modifyDOM(overtypeInput: HTMLTextAreaElement): HTMLElement {
overtypeInput.classList.add('overtype-input')
const overtypePreview = document.createElement('div')
overtypePreview.classList.add('overtype-preview')
overtypeInput.insertAdjacentElement('afterend', overtypePreview)
const overtypeWrapper = overtypeInput.parentElement!.closest('div')!
overtypeWrapper.classList.add('overtype-wrapper')
overtypeInput.placeholder = 'Add your comment here...'
const overtypeContainer = overtypeWrapper.parentElement!.closest('div')!
overtypeContainer.classList.add('overtype-container')
return overtypeContainer.parentElement!.closest('div')!
}
2 changes: 2 additions & 0 deletions browser-extension/src/lib/registries.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { OverTypeInstance } from '../overtype/overtype'
import type { CommentEnhancer, CommentSpot } from './enhancer'
import { GitHubIssueAddCommentEnhancer } from './enhancers/github/githubIssueAddComment'
import { GitHubPRAddCommentEnhancer } from './enhancers/github/githubPRAddComment'

export interface EnhancedTextarea<T extends CommentSpot = CommentSpot> {
Expand All @@ -15,6 +16,7 @@ export class EnhancerRegistry {

constructor() {
// Register all available handlers
this.register(new GitHubIssueAddCommentEnhancer())
this.register(new GitHubPRAddCommentEnhancer())
}

Expand Down
4 changes: 3 additions & 1 deletion browser-extension/src/overtype/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ export function generateStyles(options = {}) {
}

/* Middle-ground CSS Reset - Prevent parent styles from leaking in */
.overtype-container * {
.overtype-container .overtype-wrapper,
.overtype-container .overtype-input,
.overtype-container .overtype-preview {
/* Box model - these commonly leak */
/* margin: 0 !important; */
padding: 0 !important;
Expand Down