From a417a68d6cee19f0bde6331d42e180ef2ed1ae4d Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Tue, 7 Oct 2025 13:42:41 -0700 Subject: [PATCH 01/14] Fixup comment that got moved to a stale location. --- src/lib/enhancers/github/GitHubEditEnhancer.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/lib/enhancers/github/GitHubEditEnhancer.tsx b/src/lib/enhancers/github/GitHubEditEnhancer.tsx index 17bb08b..fd5b82c 100644 --- a/src/lib/enhancers/github/GitHubEditEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubEditEnhancer.tsx @@ -46,9 +46,8 @@ export class GitHubEditEnhancer implements CommentEnhancer { "[data-wrapper-timeline-id]" ) const isPRBodyEdit = - textarea.name === "pull_request[body]" || - textarea.name === "issue_comment[body]" - // ^this is the root pr comment ^this is the other pr comments (surprising!) + textarea.name === "pull_request[body]" || // this is the root pr comment + textarea.name === "issue_comment[body]" // this is the other pr comments (surprising!) if (!isIssueBodyRootEdit && !isIssueBodyCommentEdit && !isPRBodyEdit) { return null From 36d77ccb2209283abdffd5c783487b5db1407a26 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Tue, 7 Oct 2025 13:42:54 -0700 Subject: [PATCH 02/14] formatting bug --- tests/corpus-view.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/corpus-view.ts b/tests/corpus-view.ts index 4280918..ecc7948 100644 --- a/tests/corpus-view.ts +++ b/tests/corpus-view.ts @@ -562,7 +562,7 @@ function createGitcassoScript( ): string { const contentScriptSetup = contentScriptCode ? // Direct embedding (for HTML corpus) - ` + ` // Set up mocked location window.gitcassoMockLocation = { host: '${urlParts.host}', @@ -589,7 +589,7 @@ function createGitcassoScript( } ` : // Fetch-based loading (for HAR corpus) - ` + ` // Fetch and patch the content script to remove webextension-polyfill issues fetch('/chrome-mv3-dev/content-scripts/content.js') .then(response => response.text()) From 9a206e6ce16a647b35a5eee77825ef4cc105c84b Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Tue, 7 Oct 2025 14:06:59 -0700 Subject: [PATCH 03/14] Fixup a stale example in corpus-loop --- .claude/commands/corpus-loop.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.claude/commands/corpus-loop.md b/.claude/commands/corpus-loop.md index b669dcd..32adc72 100644 --- a/.claude/commands/corpus-loop.md +++ b/.claude/commands/corpus-loop.md @@ -33,7 +33,7 @@ description: uses Playwright MCP and the `corpus` to parse page elements - this output means that this page is simulating the url `https://github.com/diffplug/selfie/issues/523` - every textarea on the page is represented - `NO_SPOT` means that the spot was not enhanced -- `type: GH_ISSUE_ADD_COMMENT` means that it was enhanced by whichever implementation of `CommentEnhancer` returns the spot type `GH_ISSUE_ADD_COMMENT` +- `type: GH_ISSUE_APPEND` means that it was enhanced by whichever implementation of `CommentEnhancer` returns the spot type `GH_ISSUE_APPEND` - if you search for that string in `src/lib/enhancers` you will find the correct one - the `tryToEnhance` method returned a `CommentSpot`, and that whole data is splatted out above From fd5c38dbca7e706627d9522e1548e2d85787ee9d Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Tue, 7 Oct 2025 14:07:40 -0700 Subject: [PATCH 04/14] Make `search` part of `StrippedLocation` --- src/entrypoints/content.ts | 1 + src/lib/enhancer.ts | 1 + tests/corpus-fixture.ts | 2 ++ tests/corpus-view.ts | 7 +++++-- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/entrypoints/content.ts b/src/entrypoints/content.ts index 4e1e04d..3f8ef02 100644 --- a/src/entrypoints/content.ts +++ b/src/entrypoints/content.ts @@ -15,6 +15,7 @@ function detectLocation(): StrippedLocation { const result = { host: window.location.host, pathname: window.location.pathname, + search: window.location.search, } logger.debug("[gitcasso] detectLocation called, returning:", result) return result diff --git a/src/lib/enhancer.ts b/src/lib/enhancer.ts index 5f596da..c50dc01 100644 --- a/src/lib/enhancer.ts +++ b/src/lib/enhancer.ts @@ -26,6 +26,7 @@ export interface CommentEvent { export interface StrippedLocation { host: string pathname: string + search: string } /** Wraps the textareas of a given platform with Gitcasso's enhancements. */ diff --git a/tests/corpus-fixture.ts b/tests/corpus-fixture.ts index 649ae4b..e8a3181 100644 --- a/tests/corpus-fixture.ts +++ b/tests/corpus-fixture.ts @@ -66,6 +66,7 @@ export function detectedSpots() { const location: StrippedLocation = { host: window.location.host, pathname: window.location.pathname, + search: window.location.search, } const detectionResults = [] for (const textarea of textareas) { @@ -86,6 +87,7 @@ export function tableUI() { const location: StrippedLocation = { host: window.location.host, pathname: window.location.pathname, + search: window.location.search, } const uiResults = [] for (const textarea of textareas) { diff --git a/tests/corpus-view.ts b/tests/corpus-view.ts index ecc7948..60688e8 100644 --- a/tests/corpus-view.ts +++ b/tests/corpus-view.ts @@ -97,6 +97,7 @@ function getUrlParts(key: string) { hostname: url.hostname, href: originalUrl, pathname: url.pathname, + search: url.search, } } @@ -566,7 +567,8 @@ function createGitcassoScript( // Set up mocked location window.gitcassoMockLocation = { host: '${urlParts.host}', - pathname: '${urlParts.pathname}' + pathname: '${urlParts.pathname}', + search: '${urlParts.search}' }; // Set up browser API mocks @@ -603,7 +605,8 @@ function createGitcassoScript( ); window.gitcassoMockLocation = { host: '${urlParts.host}', - pathname: '${urlParts.pathname}' + pathname: '${urlParts.pathname}', + search: '${urlParts.search}' }; // Execute the patched script with browser API mocks prepended From 15c9171424f7fa32584d7c0083e98d64c6895674 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Tue, 7 Oct 2025 14:08:42 -0700 Subject: [PATCH 05/14] Make a change to GitHubEditEnhancer so that it detects edited comments on project pages. TODO: figure out appending comments to issues on project pages --- .../enhancers/github/GitHubEditEnhancer.tsx | 22 ++++++++++ .../__snapshots__/gh-detection.test.ts.snap | 32 ++++++++++---- .../__snapshots__/gh-ui.test.ts.snap | 43 +++++++++++++++++-- 3 files changed, 86 insertions(+), 11 deletions(-) diff --git a/src/lib/enhancers/github/GitHubEditEnhancer.tsx b/src/lib/enhancers/github/GitHubEditEnhancer.tsx index fd5b82c..65280aa 100644 --- a/src/lib/enhancers/github/GitHubEditEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubEditEnhancer.tsx @@ -29,6 +29,28 @@ export class GitHubEditEnhancer implements CommentEnhancer { return null } + // Check for project draft edit first + const isProjectDraftEdit = location.pathname.match( + /^\/(?:orgs|users)\/[^/]+\/projects\/\d+\/views\/\d+/ + ) + if (isProjectDraftEdit) { + const params = new URLSearchParams(location.search) + const itemId = params.get("itemId") + if (itemId && textarea.closest("[role='dialog']")) { + const unique_key = `github.com:project-draft:${itemId}:edit-body` + logger.debug( + `${this.constructor.name} enhanced project draft body textarea`, + unique_key + ) + return { + isIssue: true, + type: GH_EDIT, + unique_key, + } + } + return null + } + // Parse GitHub URL structure: /owner/repo/issues/123 or /owner/repo/pull/456 const match = location.pathname.match( /^\/([^/]+)\/([^/]+)\/(?:issues|pull)\/(\d+)/ diff --git a/tests/lib/enhancers/__snapshots__/gh-detection.test.ts.snap b/tests/lib/enhancers/__snapshots__/gh-detection.test.ts.snap index 67f29e6..46280dc 100644 --- a/tests/lib/enhancers/__snapshots__/gh-detection.test.ts.snap +++ b/tests/lib/enhancers/__snapshots__/gh-detection.test.ts.snap @@ -224,8 +224,12 @@ exports[`github detection > gh_project_draft:should detect correct spots 1`] = ` exports[`github detection > gh_project_draft_edit:should detect correct spots 1`] = ` [ { - "for": "id=:r5a: name=null className=prc-Textarea-TextArea-13q4j", - "spot": "NO_SPOT", + "for": "id=:r5a: name=null className=prc-Textarea-TextArea-13q4j overtype-input", + "spot": { + "isIssue": true, + "type": "GH_EDIT", + "unique_key": "github.com:project-draft:129503329:edit-body", + }, }, ] `; @@ -233,8 +237,12 @@ exports[`github detection > gh_project_draft_edit:should detect correct spots 1` exports[`github detection > gh_project_issue:should detect correct spots 1`] = ` [ { - "for": "id=:rbs: name=null className=prc-Textarea-TextArea-13q4j", - "spot": "NO_SPOT", + "for": "id=:rbs: name=null className=prc-Textarea-TextArea-13q4j overtype-input", + "spot": { + "isIssue": true, + "type": "GH_EDIT", + "unique_key": "github.com:project-draft:129503239:edit-body", + }, }, ] `; @@ -242,12 +250,20 @@ exports[`github detection > gh_project_issue:should detect correct spots 1`] = ` exports[`github detection > gh_project_issue_edit:should detect correct spots 1`] = ` [ { - "for": "id=:rdh: name=null className=prc-Textarea-TextArea-13q4j", - "spot": "NO_SPOT", + "for": "id=:rdh: name=null className=prc-Textarea-TextArea-13q4j overtype-input", + "spot": { + "isIssue": true, + "type": "GH_EDIT", + "unique_key": "github.com:project-draft:129503239:edit-body", + }, }, { - "for": "id=:rbs: name=null className=prc-Textarea-TextArea-13q4j", - "spot": "NO_SPOT", + "for": "id=:rbs: name=null className=prc-Textarea-TextArea-13q4j overtype-input", + "spot": { + "isIssue": true, + "type": "GH_EDIT", + "unique_key": "github.com:project-draft:129503239:edit-body", + }, }, ] `; diff --git a/tests/lib/enhancers/__snapshots__/gh-ui.test.ts.snap b/tests/lib/enhancers/__snapshots__/gh-ui.test.ts.snap index 33bcd78..7aace9e 100644 --- a/tests/lib/enhancers/__snapshots__/gh-ui.test.ts.snap +++ b/tests/lib/enhancers/__snapshots__/gh-ui.test.ts.snap @@ -274,8 +274,45 @@ exports[`github ui > gh_project:should render correct UI elements 1`] = `[]`; exports[`github ui > gh_project_draft:should render correct UI elements 1`] = `[]`; -exports[`github ui > gh_project_draft_edit:should render correct UI elements 1`] = `[]`; +exports[`github ui > gh_project_draft_edit:should render correct UI elements 1`] = ` +[ + { + "for": "id=:r5a: name=null className=prc-Textarea-TextArea-13q4j overtype-input", + "title": "N/A", + "upperDecoration": + N/A + , + }, +] +`; -exports[`github ui > gh_project_issue:should render correct UI elements 1`] = `[]`; +exports[`github ui > gh_project_issue:should render correct UI elements 1`] = ` +[ + { + "for": "id=:rbs: name=null className=prc-Textarea-TextArea-13q4j overtype-input", + "title": "N/A", + "upperDecoration": + N/A + , + }, +] +`; -exports[`github ui > gh_project_issue_edit:should render correct UI elements 1`] = `[]`; +exports[`github ui > gh_project_issue_edit:should render correct UI elements 1`] = ` +[ + { + "for": "id=:rdh: name=null className=prc-Textarea-TextArea-13q4j overtype-input", + "title": "N/A", + "upperDecoration": + N/A + , + }, + { + "for": "id=:rbs: name=null className=prc-Textarea-TextArea-13q4j overtype-input", + "title": "N/A", + "upperDecoration": + N/A + , + }, +] +`; From 7c9636e226954ab725f175253e2273644069d666 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Tue, 7 Oct 2025 14:21:08 -0700 Subject: [PATCH 06/14] Appending comments to issues within a project are now handled correctly. --- .../enhancers/github/GitHubEditEnhancer.tsx | 6 ++- .../github/GitHubIssueAppendEnhancer.tsx | 37 ++++++++++++++ .../__snapshots__/gh-detection.test.ts.snap | 18 ++++--- .../__snapshots__/gh-ui.test.ts.snap | 48 +++++++++++++++---- 4 files changed, 94 insertions(+), 15 deletions(-) diff --git a/src/lib/enhancers/github/GitHubEditEnhancer.tsx b/src/lib/enhancers/github/GitHubEditEnhancer.tsx index 65280aa..684be5a 100644 --- a/src/lib/enhancers/github/GitHubEditEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubEditEnhancer.tsx @@ -36,7 +36,11 @@ export class GitHubEditEnhancer implements CommentEnhancer { if (isProjectDraftEdit) { const params = new URLSearchParams(location.search) const itemId = params.get("itemId") - if (itemId && textarea.closest("[role='dialog']")) { + // Exclude textareas within Shared-module__CommentBox (those are for adding new comments, not editing) + const isInCommentBox = textarea.closest( + '[class*="Shared-module__CommentBox"]' + ) + if (itemId && textarea.closest("[role='dialog']") && !isInCommentBox) { const unique_key = `github.com:project-draft:${itemId}:edit-body` logger.debug( `${this.constructor.name} enhanced project draft body textarea`, diff --git a/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx b/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx index 5c05d45..a1428db 100644 --- a/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx @@ -45,6 +45,43 @@ export class GitHubIssueAppendEnhancer return null } + // Check for project URLs with issue parameter first + const isProjectView = location.pathname.match( + /^\/(?:orgs|users)\/[^/]+\/projects\/\d+\/views\/\d+/ + ) + if (isProjectView) { + const params = new URLSearchParams(location.search) + const issueParam = params.get("issue") + // Only match textareas within Shared-module__CommentBox (those are for adding new comments) + const isInCommentBox = textarea.closest( + '[class*="Shared-module__CommentBox"]' + ) + if (issueParam && isInCommentBox) { + // Parse issue parameter: "owner|repo|number" (URL encoded as owner%7Crepo%7Cnumber) + const parts = issueParam.split("|") + if (parts.length === 3) { + const [owner, repo, numberStr] = parts + const slug = `${owner}/${repo}` + const number = parseInt(numberStr!, 10) + const unique_key = `github.com:${slug}:${number}` + // For project views, the title is in the side panel dialog + const title = + document + .querySelector('[data-testid="issue-title"]') + ?.textContent?.trim() || "" + return { + domain: location.host, + number, + slug, + title, + type: GH_ISSUE_APPEND, + unique_key, + } + } + } + return null + } + // Parse GitHub URL structure: /owner/repo/issues/123 or /owner/repo/pull/456 logger.debug(`${this.constructor.name} examing url`, location.pathname) diff --git a/tests/lib/enhancers/__snapshots__/gh-detection.test.ts.snap b/tests/lib/enhancers/__snapshots__/gh-detection.test.ts.snap index 46280dc..94d92b9 100644 --- a/tests/lib/enhancers/__snapshots__/gh-detection.test.ts.snap +++ b/tests/lib/enhancers/__snapshots__/gh-detection.test.ts.snap @@ -239,9 +239,12 @@ exports[`github detection > gh_project_issue:should detect correct spots 1`] = ` { "for": "id=:rbs: name=null className=prc-Textarea-TextArea-13q4j overtype-input", "spot": { - "isIssue": true, - "type": "GH_EDIT", - "unique_key": "github.com:project-draft:129503239:edit-body", + "domain": "github.com", + "number": 57, + "slug": "diffplug/gitcasso", + "title": "what about drafts?", + "type": "GH_ISSUE_APPEND", + "unique_key": "github.com:diffplug/gitcasso:57", }, }, ] @@ -260,9 +263,12 @@ exports[`github detection > gh_project_issue_edit:should detect correct spots 1` { "for": "id=:rbs: name=null className=prc-Textarea-TextArea-13q4j overtype-input", "spot": { - "isIssue": true, - "type": "GH_EDIT", - "unique_key": "github.com:project-draft:129503239:edit-body", + "domain": "github.com", + "number": 57, + "slug": "diffplug/gitcasso", + "title": "what about drafts?", + "type": "GH_ISSUE_APPEND", + "unique_key": "github.com:diffplug/gitcasso:57", }, }, ] diff --git a/tests/lib/enhancers/__snapshots__/gh-ui.test.ts.snap b/tests/lib/enhancers/__snapshots__/gh-ui.test.ts.snap index 7aace9e..4ec9567 100644 --- a/tests/lib/enhancers/__snapshots__/gh-ui.test.ts.snap +++ b/tests/lib/enhancers/__snapshots__/gh-ui.test.ts.snap @@ -290,10 +290,26 @@ exports[`github ui > gh_project_issue:should render correct UI elements 1`] = ` [ { "for": "id=:rbs: name=null className=prc-Textarea-TextArea-13q4j overtype-input", - "title": "N/A", - "upperDecoration": - N/A - , + "title": "what about drafts?", + "upperDecoration": + + + + + # + 57 + + + diffplug/gitcasso + + + , }, ] `; @@ -309,10 +325,26 @@ exports[`github ui > gh_project_issue_edit:should render correct UI elements 1`] }, { "for": "id=:rbs: name=null className=prc-Textarea-TextArea-13q4j overtype-input", - "title": "N/A", - "upperDecoration": - N/A - , + "title": "what about drafts?", + "upperDecoration": + + + + + # + 57 + + + diffplug/gitcasso + + + , }, ] `; From d66cfa8c939540799b268198665a5d866f94b8bb Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Tue, 7 Oct 2025 14:42:50 -0700 Subject: [PATCH 07/14] Make project logic more permissive. --- .../enhancers/github/GitHubEditEnhancer.tsx | 60 ++++++++++++++----- .../github/GitHubIssueAppendEnhancer.tsx | 2 +- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/src/lib/enhancers/github/GitHubEditEnhancer.tsx b/src/lib/enhancers/github/GitHubEditEnhancer.tsx index 684be5a..e1f6e49 100644 --- a/src/lib/enhancers/github/GitHubEditEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubEditEnhancer.tsx @@ -31,27 +31,59 @@ export class GitHubEditEnhancer implements CommentEnhancer { // Check for project draft edit first const isProjectDraftEdit = location.pathname.match( - /^\/(?:orgs|users)\/[^/]+\/projects\/\d+\/views\/\d+/ + /^\/(?:orgs|users)\/[^/]+\/projects\/\d+(?:\/views\/\d+)?/ ) if (isProjectDraftEdit) { const params = new URLSearchParams(location.search) const itemId = params.get("itemId") - // Exclude textareas within Shared-module__CommentBox (those are for adding new comments, not editing) - const isInCommentBox = textarea.closest( - '[class*="Shared-module__CommentBox"]' - ) - if (itemId && textarea.closest("[role='dialog']") && !isInCommentBox) { - const unique_key = `github.com:project-draft:${itemId}:edit-body` - logger.debug( - `${this.constructor.name} enhanced project draft body textarea`, - unique_key + const issueParam = params.get("issue") + + // Handle draft editing (itemId parameter) + if (itemId) { + // Exclude textareas within Shared-module__CommentBox (those are for adding new comments, not editing) + const isInCommentBox = textarea.closest( + '[class*="Shared-module__CommentBox"]' ) - return { - isIssue: true, - type: GH_EDIT, - unique_key, + if (textarea.closest("[role='dialog']") && !isInCommentBox) { + const unique_key = `github.com:project-draft:${itemId}:edit-body` + logger.debug( + `${this.constructor.name} enhanced project draft body textarea`, + unique_key + ) + return { + isIssue: true, + type: GH_EDIT, + unique_key, + } + } + } + + // Handle existing issue comment editing (issue parameter) + if (issueParam) { + // Parse issue parameter: "owner|repo|number" + const parts = issueParam.split("|") + if (parts.length === 3) { + const [owner, repo, numberStr] = parts + const slug = `${owner}/${repo}` + const number = parseInt(numberStr!, 10) + + // Edit mode: empty placeholder + // Add new comment mode: has placeholder "Add your comment here..." or similar + if (!textarea.placeholder || textarea.placeholder.trim() === "") { + const unique_key = `github.com:${slug}:${number}:edit-comment` + logger.debug( + `${this.constructor.name} enhanced project issue comment edit textarea`, + unique_key + ) + return { + isIssue: true, + type: GH_EDIT, + unique_key, + } + } } } + return null } diff --git a/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx b/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx index a1428db..b556c7c 100644 --- a/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx @@ -47,7 +47,7 @@ export class GitHubIssueAppendEnhancer // Check for project URLs with issue parameter first const isProjectView = location.pathname.match( - /^\/(?:orgs|users)\/[^/]+\/projects\/\d+\/views\/\d+/ + /^\/(?:orgs|users)\/[^/]+\/projects\/\d+(?:\/views\/\d+)?/ ) if (isProjectView) { const params = new URLSearchParams(location.search) From 413f5ed33957888bbb30fb48dd39003729eec38c Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Tue, 7 Oct 2025 14:51:19 -0700 Subject: [PATCH 08/14] Make project draft logic less specific to the one snapshot. --- src/lib/enhancers/github/GitHubEditEnhancer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/enhancers/github/GitHubEditEnhancer.tsx b/src/lib/enhancers/github/GitHubEditEnhancer.tsx index e1f6e49..0113cb9 100644 --- a/src/lib/enhancers/github/GitHubEditEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubEditEnhancer.tsx @@ -44,7 +44,7 @@ export class GitHubEditEnhancer implements CommentEnhancer { const isInCommentBox = textarea.closest( '[class*="Shared-module__CommentBox"]' ) - if (textarea.closest("[role='dialog']") && !isInCommentBox) { + if (!isInCommentBox) { const unique_key = `github.com:project-draft:${itemId}:edit-body` logger.debug( `${this.constructor.name} enhanced project draft body textarea`, From f20d5b5f3a3ae4af91f0a7df4dcec747174c3f6e Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Tue, 7 Oct 2025 14:55:21 -0700 Subject: [PATCH 09/14] Update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1776c9e..77eb705 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 Version must be kept in-sync between [`package.json`](package.json) and [`wxt.config.js`](wxt.config.ts). ## [Unreleased] +### Added +- Support for GitHub projects (draft and "real" issues). ([#108](https://github.com/diffplug/gitcasso/pull/108)) ### Fixed - Appending to GitHub issues was not being enhanced, now fixed. ([#105](https://github.com/diffplug/gitcasso/issues/105)) - Reduced unnecessary permissions (no need for `host_permissions`) From 0056c735265b116b65767b0fdb421ca32a74319c Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Tue, 7 Oct 2025 15:04:21 -0700 Subject: [PATCH 10/14] Add `gh_project_issue_new` to the corpus. --- tests/corpus/_corpus-index.ts | 5 + tests/corpus/gh_project_issue_new.html | 1503 ++++++++++++++++++++++++ 2 files changed, 1508 insertions(+) create mode 100644 tests/corpus/gh_project_issue_new.html diff --git a/tests/corpus/_corpus-index.ts b/tests/corpus/_corpus-index.ts index aba7860..25bee0c 100644 --- a/tests/corpus/_corpus-index.ts +++ b/tests/corpus/_corpus-index.ts @@ -76,4 +76,9 @@ export const CORPUS: Record = { type: "html", url: "https://github.com/orgs/diffplug/projects/12/views/1?pane=issue&itemId=129503239&issue=diffplug%7Cgitcasso%7C57", }, + gh_project_issue_new: { + description: "creating a new issue within a project", + type: "html", + url: "https://github.com/orgs/diffplug/projects/12", + }, } as const diff --git a/tests/corpus/gh_project_issue_new.html b/tests/corpus/gh_project_issue_new.html new file mode 100644 index 0000000..3b45d04 --- /dev/null +++ b/tests/corpus/gh_project_issue_new.html @@ -0,0 +1,1503 @@ + + + + + + + + + + + + +New issue · Backlog · Gitcasso + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + + + +
+ +
+ +
+
+ + Select an owner + + + + + + Loading + + + +
+
+
+ +
+
+ +
+
+
+ +
+ Skip to content + + + + + + + + +
+
+ + + + + + +
+
+
+ +
+ + + +
+
+ +
+ +
+

    Unrefined

     (8 / 999)
    Estimate: 0
      Click a value to filter the view
        Click a value to filter the view
          Click a value to filter the view
          gitcasso #30

          Snapshots for Reddit, GitLab, etc.

            Click a value to filter the view
              Click a value to filter the view
                Click a value to filter the view
                  Click a value to filter the view

                  1.0 Backlog

                   (1)
                  Estimate: 0

                  In Progress

                   (2 / 5)
                  Estimate: 0
                  This is actively being worked on
                  Draft

                  figure out publishing

                    Click a value to filter the view
                      Click a value to filter the view

                      In PR

                       (0)
                      Estimate: 0

                      Done

                       (45)
                      Estimate: 0
                      This has been completed
                      + + + + +
                        +
                        + + + + + + + +
                        +
                        New issue · Backlog · Gitcasso
                        +
                        + + \ No newline at end of file From f5415cecb943c18dba104ae9927a7e0184b8387e Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Tue, 7 Oct 2025 15:05:37 -0700 Subject: [PATCH 11/14] Update `GitHubIssueCreateEnhancer` to handle the project case. --- .../github/GitHubIssueCreateEnhancer.tsx | 29 +++++++++++++++++++ .../__snapshots__/gh-detection.test.ts.snap | 15 ++++++++++ .../__snapshots__/gh-ui.test.ts.snap | 27 +++++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx b/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx index a9ee917..4a659d4 100644 --- a/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx @@ -37,6 +37,35 @@ export class GitHubIssueCreateEnhancer return null } + // Check for project board URLs first + const isProjectView = location.pathname.match( + /^\/(?:orgs|users)\/[^/]+\/projects\/\d+(?:\/views\/\d+)?/ + ) + if (isProjectView) { + // Check if we're in a "Create new issue" dialog + const dialog = textarea.closest('[role="dialog"]') + if (dialog) { + const dialogHeading = dialog.querySelector("h1")?.textContent + const slugMatch = dialogHeading?.match(/Create new issue in (.+)/) + if (slugMatch) { + const slug = slugMatch[1]! + const unique_key = `github.com:${slug}:new` + const titleInput = document.querySelector( + 'input[placeholder="Title"]' + ) as HTMLInputElement + const title = titleInput?.value || "" + return { + domain: location.host, + slug, + title, + type: GH_ISSUE_CREATE, + unique_key, + } + } + } + return null + } + // Parse GitHub URL structure: /owner/repo/issues/123 or /owner/repo/pull/456 logger.debug(`${this.constructor.name} examing url`, location.pathname) diff --git a/tests/lib/enhancers/__snapshots__/gh-detection.test.ts.snap b/tests/lib/enhancers/__snapshots__/gh-detection.test.ts.snap index 94d92b9..401542e 100644 --- a/tests/lib/enhancers/__snapshots__/gh-detection.test.ts.snap +++ b/tests/lib/enhancers/__snapshots__/gh-detection.test.ts.snap @@ -273,3 +273,18 @@ exports[`github detection > gh_project_issue_edit:should detect correct spots 1` }, ] `; + +exports[`github detection > gh_project_issue_new:should detect correct spots 1`] = ` +[ + { + "for": "id=:r4t: name=null className=prc-Textarea-TextArea-13q4j overtype-input", + "spot": { + "domain": "github.com", + "slug": "diffplug/gitcasso", + "title": "Draft project title", + "type": "GH_ISSUE_CREATE", + "unique_key": "github.com:diffplug/gitcasso:new", + }, + }, +] +`; diff --git a/tests/lib/enhancers/__snapshots__/gh-ui.test.ts.snap b/tests/lib/enhancers/__snapshots__/gh-ui.test.ts.snap index 4ec9567..15c6ae1 100644 --- a/tests/lib/enhancers/__snapshots__/gh-ui.test.ts.snap +++ b/tests/lib/enhancers/__snapshots__/gh-ui.test.ts.snap @@ -348,3 +348,30 @@ exports[`github ui > gh_project_issue_edit:should render correct UI elements 1`] }, ] `; + +exports[`github ui > gh_project_issue_new:should render correct UI elements 1`] = ` +[ + { + "for": "id=:r4t: name=null className=prc-Textarea-TextArea-13q4j overtype-input", + "title": "Draft project title", + "upperDecoration": + + + + + <draft> + + + diffplug/gitcasso + + + , + }, +] +`; From d8aa8b9169fdaf3a997a1b170a70e0f4d3954c13 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Tue, 7 Oct 2025 15:13:54 -0700 Subject: [PATCH 12/14] Refactor by claude. --- .../enhancers/github/GitHubEditEnhancer.tsx | 54 +++++++-------- .../github/GitHubIssueAppendEnhancer.tsx | 39 +++++------ .../github/GitHubIssueCreateEnhancer.tsx | 18 ++--- src/lib/enhancers/github/github-common.ts | 69 +++++++++++++++++++ 4 files changed, 117 insertions(+), 63 deletions(-) diff --git a/src/lib/enhancers/github/GitHubEditEnhancer.tsx b/src/lib/enhancers/github/GitHubEditEnhancer.tsx index 0113cb9..317bf45 100644 --- a/src/lib/enhancers/github/GitHubEditEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubEditEnhancer.tsx @@ -7,7 +7,13 @@ import type { } from "@/lib/enhancer" import { logger } from "@/lib/logger" import { fixupOvertype, modifyDOM } from "../overtype-misc" -import { commonGitHubOptions, prepareGitHubHighlighter } from "./github-common" +import { + commonGitHubOptions, + isGitHubProjectUrl, + isInProjectCommentBox, + parseProjectIssueParam, + prepareGitHubHighlighter, +} from "./github-common" const GH_EDIT = "GH_EDIT" as const @@ -30,21 +36,14 @@ export class GitHubEditEnhancer implements CommentEnhancer { } // Check for project draft edit first - const isProjectDraftEdit = location.pathname.match( - /^\/(?:orgs|users)\/[^/]+\/projects\/\d+(?:\/views\/\d+)?/ - ) - if (isProjectDraftEdit) { + if (isGitHubProjectUrl(location.pathname)) { const params = new URLSearchParams(location.search) const itemId = params.get("itemId") - const issueParam = params.get("issue") // Handle draft editing (itemId parameter) if (itemId) { // Exclude textareas within Shared-module__CommentBox (those are for adding new comments, not editing) - const isInCommentBox = textarea.closest( - '[class*="Shared-module__CommentBox"]' - ) - if (!isInCommentBox) { + if (!isInProjectCommentBox(textarea)) { const unique_key = `github.com:project-draft:${itemId}:edit-body` logger.debug( `${this.constructor.name} enhanced project draft body textarea`, @@ -59,27 +58,20 @@ export class GitHubEditEnhancer implements CommentEnhancer { } // Handle existing issue comment editing (issue parameter) - if (issueParam) { - // Parse issue parameter: "owner|repo|number" - const parts = issueParam.split("|") - if (parts.length === 3) { - const [owner, repo, numberStr] = parts - const slug = `${owner}/${repo}` - const number = parseInt(numberStr!, 10) - - // Edit mode: empty placeholder - // Add new comment mode: has placeholder "Add your comment here..." or similar - if (!textarea.placeholder || textarea.placeholder.trim() === "") { - const unique_key = `github.com:${slug}:${number}:edit-comment` - logger.debug( - `${this.constructor.name} enhanced project issue comment edit textarea`, - unique_key - ) - return { - isIssue: true, - type: GH_EDIT, - unique_key, - } + const issueInfo = parseProjectIssueParam(params) + if (issueInfo) { + // Edit mode: empty placeholder + // Add new comment mode: has placeholder "Add your comment here..." or similar + if (!textarea.placeholder || textarea.placeholder.trim() === "") { + const unique_key = `github.com:${issueInfo.slug}:${issueInfo.number}:edit-comment` + logger.debug( + `${this.constructor.name} enhanced project issue comment edit textarea`, + unique_key + ) + return { + isIssue: true, + type: GH_EDIT, + unique_key, } } } diff --git a/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx b/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx index b556c7c..292b399 100644 --- a/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx @@ -9,7 +9,14 @@ import type { } from "@/lib/enhancer" import { logger } from "@/lib/logger" import { fixupOvertype, modifyDOM } from "../overtype-misc" -import { commonGitHubOptions, prepareGitHubHighlighter } from "./github-common" +import { + commonGitHubOptions, + extractProjectIssueTitle, + isGitHubProjectUrl, + isInProjectCommentBox, + parseProjectIssueParam, + prepareGitHubHighlighter, +} from "./github-common" const GH_ISSUE_APPEND = "GH_ISSUE_APPEND" as const @@ -46,33 +53,19 @@ export class GitHubIssueAppendEnhancer } // Check for project URLs with issue parameter first - const isProjectView = location.pathname.match( - /^\/(?:orgs|users)\/[^/]+\/projects\/\d+(?:\/views\/\d+)?/ - ) - if (isProjectView) { + if (isGitHubProjectUrl(location.pathname)) { const params = new URLSearchParams(location.search) - const issueParam = params.get("issue") // Only match textareas within Shared-module__CommentBox (those are for adding new comments) - const isInCommentBox = textarea.closest( - '[class*="Shared-module__CommentBox"]' - ) - if (issueParam && isInCommentBox) { - // Parse issue parameter: "owner|repo|number" (URL encoded as owner%7Crepo%7Cnumber) - const parts = issueParam.split("|") - if (parts.length === 3) { - const [owner, repo, numberStr] = parts - const slug = `${owner}/${repo}` - const number = parseInt(numberStr!, 10) - const unique_key = `github.com:${slug}:${number}` + if (isInProjectCommentBox(textarea)) { + const issueInfo = parseProjectIssueParam(params) + if (issueInfo) { + const unique_key = `github.com:${issueInfo.slug}:${issueInfo.number}` // For project views, the title is in the side panel dialog - const title = - document - .querySelector('[data-testid="issue-title"]') - ?.textContent?.trim() || "" + const title = extractProjectIssueTitle() return { domain: location.host, - number, - slug, + number: issueInfo.number, + slug: issueInfo.slug, title, type: GH_ISSUE_APPEND, unique_key, diff --git a/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx b/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx index 4a659d4..0f1c6d1 100644 --- a/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx @@ -8,7 +8,12 @@ import type { } from "../../enhancer" import { logger } from "../../logger" import { fixupOvertype, modifyDOM } from "../overtype-misc" -import { commonGitHubOptions, prepareGitHubHighlighter } from "./github-common" +import { + commonGitHubOptions, + extractDialogSlug, + isGitHubProjectUrl, + prepareGitHubHighlighter, +} from "./github-common" const GH_ISSUE_CREATE = "GH_ISSUE_CREATE" as const @@ -38,17 +43,12 @@ export class GitHubIssueCreateEnhancer } // Check for project board URLs first - const isProjectView = location.pathname.match( - /^\/(?:orgs|users)\/[^/]+\/projects\/\d+(?:\/views\/\d+)?/ - ) - if (isProjectView) { + if (isGitHubProjectUrl(location.pathname)) { // Check if we're in a "Create new issue" dialog const dialog = textarea.closest('[role="dialog"]') if (dialog) { - const dialogHeading = dialog.querySelector("h1")?.textContent - const slugMatch = dialogHeading?.match(/Create new issue in (.+)/) - if (slugMatch) { - const slug = slugMatch[1]! + const slug = extractDialogSlug(dialog) + if (slug) { const unique_key = `github.com:${slug}:new` const titleInput = document.querySelector( 'input[placeholder="Title"]' diff --git a/src/lib/enhancers/github/github-common.ts b/src/lib/enhancers/github/github-common.ts index 09f57ff..438efaf 100644 --- a/src/lib/enhancers/github/github-common.ts +++ b/src/lib/enhancers/github/github-common.ts @@ -61,3 +61,72 @@ function githubHighlighter(code: string, language?: string) { return escapeHtml(code) } } + +// Project-related helper functions + +/** + * Check if the pathname matches a GitHub project URL pattern. + * Matches: /orgs/{org}/projects/{id} or /users/{user}/projects/{id} + * Optional: /views/{viewId} suffix + */ +export function isGitHubProjectUrl(pathname: string): boolean { + return /^\/(?:orgs|users)\/[^/]+\/projects\/\d+(?:\/views\/\d+)?/.test( + pathname + ) +} + +/** + * Parse the issue parameter from project URLs. + * Format: ?issue=owner|repo|number + * Returns: { slug: "owner/repo", number: 123 } or null if invalid + */ +export function parseProjectIssueParam( + searchParams: URLSearchParams +): { slug: string; number: number } | null { + const issueParam = searchParams.get("issue") + if (!issueParam) return null + + const parts = issueParam.split("|") + if (parts.length !== 3) return null + + const [owner, repo, numberStr] = parts + const number = parseInt(numberStr!, 10) + + if (Number.isNaN(number)) return null + + return { + slug: `${owner}/${repo}`, + number, + } +} + +/** + * Check if an element is within a project CommentBox container. + * CommentBox containers are used for adding new comments (not editing). + */ +export function isInProjectCommentBox(element: HTMLElement): boolean { + return !!element.closest('[class*="Shared-module__CommentBox"]') +} + +/** + * Extract the issue title from a project view. + * Used when viewing issues within a project board. + */ +export function extractProjectIssueTitle(): string { + return ( + document + .querySelector('[data-testid="issue-title"]') + ?.textContent?.trim() || "" + ) +} + +/** + * Extract the repository slug from a "Create new issue" dialog heading. + * Heading format: "Create new issue in owner/repo" + * Returns: "owner/repo" or null if not found + */ +export function extractDialogSlug(dialog: Element): string | null { + const dialogHeading = dialog.querySelector("h1")?.textContent + const slugMatch = dialogHeading?.match(/Create new issue in (.+)/) + return slugMatch ? slugMatch[1]! : null +} From 254bbd9843dfdc2e1692981b2f6f2be22392d632 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Tue, 7 Oct 2025 15:15:33 -0700 Subject: [PATCH 13/14] tweaked by me --- src/lib/enhancers/github/GitHubEditEnhancer.tsx | 4 ++-- src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx | 7 +++---- src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx | 7 +++---- src/lib/enhancers/github/github-common.ts | 2 +- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/lib/enhancers/github/GitHubEditEnhancer.tsx b/src/lib/enhancers/github/GitHubEditEnhancer.tsx index 317bf45..a9d23e5 100644 --- a/src/lib/enhancers/github/GitHubEditEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubEditEnhancer.tsx @@ -9,7 +9,7 @@ import { logger } from "@/lib/logger" import { fixupOvertype, modifyDOM } from "../overtype-misc" import { commonGitHubOptions, - isGitHubProjectUrl, + isProjectUrl, isInProjectCommentBox, parseProjectIssueParam, prepareGitHubHighlighter, @@ -36,7 +36,7 @@ export class GitHubEditEnhancer implements CommentEnhancer { } // Check for project draft edit first - if (isGitHubProjectUrl(location.pathname)) { + if (isProjectUrl(location.pathname)) { const params = new URLSearchParams(location.search) const itemId = params.get("itemId") diff --git a/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx b/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx index 292b399..2a8c6d6 100644 --- a/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx @@ -12,7 +12,7 @@ import { fixupOvertype, modifyDOM } from "../overtype-misc" import { commonGitHubOptions, extractProjectIssueTitle, - isGitHubProjectUrl, + isProjectUrl, isInProjectCommentBox, parseProjectIssueParam, prepareGitHubHighlighter, @@ -29,8 +29,7 @@ export interface GitHubIssueAppendSpot extends CommentSpot { } export class GitHubIssueAppendEnhancer - implements CommentEnhancer -{ + implements CommentEnhancer { forSpotTypes(): string[] { return [GH_ISSUE_APPEND] } @@ -53,7 +52,7 @@ export class GitHubIssueAppendEnhancer } // Check for project URLs with issue parameter first - if (isGitHubProjectUrl(location.pathname)) { + if (isProjectUrl(location.pathname)) { const params = new URLSearchParams(location.search) // Only match textareas within Shared-module__CommentBox (those are for adding new comments) if (isInProjectCommentBox(textarea)) { diff --git a/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx b/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx index 0f1c6d1..83d2e33 100644 --- a/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx @@ -11,7 +11,7 @@ import { fixupOvertype, modifyDOM } from "../overtype-misc" import { commonGitHubOptions, extractDialogSlug, - isGitHubProjectUrl, + isProjectUrl, prepareGitHubHighlighter, } from "./github-common" @@ -25,8 +25,7 @@ export interface GitHubIssueCreateSpot extends CommentSpot { } export class GitHubIssueCreateEnhancer - implements CommentEnhancer -{ + implements CommentEnhancer { forSpotTypes(): string[] { return [GH_ISSUE_CREATE] } @@ -43,7 +42,7 @@ export class GitHubIssueCreateEnhancer } // Check for project board URLs first - if (isGitHubProjectUrl(location.pathname)) { + if (isProjectUrl(location.pathname)) { // Check if we're in a "Create new issue" dialog const dialog = textarea.closest('[role="dialog"]') if (dialog) { diff --git a/src/lib/enhancers/github/github-common.ts b/src/lib/enhancers/github/github-common.ts index 438efaf..ef30bc9 100644 --- a/src/lib/enhancers/github/github-common.ts +++ b/src/lib/enhancers/github/github-common.ts @@ -69,7 +69,7 @@ function githubHighlighter(code: string, language?: string) { * Matches: /orgs/{org}/projects/{id} or /users/{user}/projects/{id} * Optional: /views/{viewId} suffix */ -export function isGitHubProjectUrl(pathname: string): boolean { +export function isProjectUrl(pathname: string): boolean { return /^\/(?:orgs|users)\/[^/]+\/projects\/\d+(?:\/views\/\d+)?/.test( pathname ) From 4bdb01dc75360b50c7eb08d5bd718de729708f07 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Tue, 7 Oct 2025 15:17:07 -0700 Subject: [PATCH 14/14] Undo refactoring for single-use-site functions. --- .../enhancers/github/GitHubEditEnhancer.tsx | 2 +- .../github/GitHubIssueAppendEnhancer.tsx | 11 +++++---- .../github/GitHubIssueCreateEnhancer.tsx | 10 ++++---- src/lib/enhancers/github/github-common.ts | 23 ------------------- 4 files changed, 14 insertions(+), 32 deletions(-) diff --git a/src/lib/enhancers/github/GitHubEditEnhancer.tsx b/src/lib/enhancers/github/GitHubEditEnhancer.tsx index a9d23e5..2bc8b61 100644 --- a/src/lib/enhancers/github/GitHubEditEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubEditEnhancer.tsx @@ -9,8 +9,8 @@ import { logger } from "@/lib/logger" import { fixupOvertype, modifyDOM } from "../overtype-misc" import { commonGitHubOptions, - isProjectUrl, isInProjectCommentBox, + isProjectUrl, parseProjectIssueParam, prepareGitHubHighlighter, } from "./github-common" diff --git a/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx b/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx index 2a8c6d6..24eadf8 100644 --- a/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx @@ -11,9 +11,8 @@ import { logger } from "@/lib/logger" import { fixupOvertype, modifyDOM } from "../overtype-misc" import { commonGitHubOptions, - extractProjectIssueTitle, - isProjectUrl, isInProjectCommentBox, + isProjectUrl, parseProjectIssueParam, prepareGitHubHighlighter, } from "./github-common" @@ -29,7 +28,8 @@ export interface GitHubIssueAppendSpot extends CommentSpot { } export class GitHubIssueAppendEnhancer - implements CommentEnhancer { + implements CommentEnhancer +{ forSpotTypes(): string[] { return [GH_ISSUE_APPEND] } @@ -60,7 +60,10 @@ export class GitHubIssueAppendEnhancer if (issueInfo) { const unique_key = `github.com:${issueInfo.slug}:${issueInfo.number}` // For project views, the title is in the side panel dialog - const title = extractProjectIssueTitle() + const title = + document + .querySelector('[data-testid="issue-title"]') + ?.textContent?.trim() || "" return { domain: location.host, number: issueInfo.number, diff --git a/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx b/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx index 83d2e33..fbcb019 100644 --- a/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx @@ -10,7 +10,6 @@ import { logger } from "../../logger" import { fixupOvertype, modifyDOM } from "../overtype-misc" import { commonGitHubOptions, - extractDialogSlug, isProjectUrl, prepareGitHubHighlighter, } from "./github-common" @@ -25,7 +24,8 @@ export interface GitHubIssueCreateSpot extends CommentSpot { } export class GitHubIssueCreateEnhancer - implements CommentEnhancer { + implements CommentEnhancer +{ forSpotTypes(): string[] { return [GH_ISSUE_CREATE] } @@ -46,8 +46,10 @@ export class GitHubIssueCreateEnhancer // Check if we're in a "Create new issue" dialog const dialog = textarea.closest('[role="dialog"]') if (dialog) { - const slug = extractDialogSlug(dialog) - if (slug) { + const dialogHeading = dialog.querySelector("h1")?.textContent + const slugMatch = dialogHeading?.match(/Create new issue in (.+)/) + if (slugMatch) { + const slug = slugMatch[1]! const unique_key = `github.com:${slug}:new` const titleInput = document.querySelector( 'input[placeholder="Title"]' diff --git a/src/lib/enhancers/github/github-common.ts b/src/lib/enhancers/github/github-common.ts index ef30bc9..26808fd 100644 --- a/src/lib/enhancers/github/github-common.ts +++ b/src/lib/enhancers/github/github-common.ts @@ -107,26 +107,3 @@ export function parseProjectIssueParam( export function isInProjectCommentBox(element: HTMLElement): boolean { return !!element.closest('[class*="Shared-module__CommentBox"]') } - -/** - * Extract the issue title from a project view. - * Used when viewing issues within a project board. - */ -export function extractProjectIssueTitle(): string { - return ( - document - .querySelector('[data-testid="issue-title"]') - ?.textContent?.trim() || "" - ) -} - -/** - * Extract the repository slug from a "Create new issue" dialog heading. - * Heading format: "Create new issue in owner/repo" - * Returns: "owner/repo" or null if not found - */ -export function extractDialogSlug(dialog: Element): string | null { - const dialogHeading = dialog.querySelector("h1")?.textContent - const slugMatch = dialogHeading?.match(/Create new issue in (.+)/) - return slugMatch ? slugMatch[1]! : null -}