From b124c2e0f134fe87c0d9d8a17bd85c5291f7e2c5 Mon Sep 17 00:00:00 2001 From: Todd Riley Date: Fri, 12 Sep 2025 12:19:40 -0400 Subject: [PATCH 1/5] GitHub color theme. --- browser-extension/src/lib/registries.ts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/browser-extension/src/lib/registries.ts b/browser-extension/src/lib/registries.ts index b6d8ad9..8a39045 100644 --- a/browser-extension/src/lib/registries.ts +++ b/browser-extension/src/lib/registries.ts @@ -1,4 +1,5 @@ import type { OverTypeInstance } from 'overtype' +import OverType from 'overtype' import type { CommentEnhancer, CommentSpot } from './enhancer' import { GitHubIssueAddCommentEnhancer } from './enhancers/github/githubIssueAddComment' import { GitHubPRAddCommentEnhancer } from './enhancers/github/githubPRAddComment' @@ -19,6 +20,26 @@ export class EnhancerRegistry { // Register all available handlers this.register(new GitHubIssueAddCommentEnhancer()) this.register(new GitHubPRAddCommentEnhancer()) + const textColor = 'rgb(31, 35, 40)' + OverType.setTheme({ + colors: { + blockquote: 'rgb(89, 99, 110)', + code: '#59636e', + codeBg: '#f6f8fa', + cursor: '#f95738', + em: 'rgb(126, 123, 255)', + h1: textColor, + h2: textColor, + h3: textColor, + hr: '#5a7a9b', + link: 'rgb(9, 105, 218)', + selection: 'rgba(244, 211, 94, 0.4)', + strong: 'rgb(45, 1, 142)', + syntaxMarker: textColor, + text: textColor, + }, + name: 'custom-github', + }) } private register(enhancer: CommentEnhancer): void { From b342218207003a3afe77c3de41c9f30ee32c4eec Mon Sep 17 00:00:00 2001 From: Todd Riley Date: Fri, 12 Sep 2025 16:35:12 -0400 Subject: [PATCH 2/5] Don't let GitHub clobber the class name. --- browser-extension/playwright.config.ts | 15 +++-- .../src/lib/enhancers/modifyDOM.ts | 17 ++++++ browser-extension/src/lib/registries.ts | 7 ++- .../src/playgrounds/github-playground.ts | 56 ++++++++++--------- browser-extension/vitest.config.ts | 10 ++-- browser-extension/wxt.config.ts | 24 ++++---- 6 files changed, 74 insertions(+), 55 deletions(-) diff --git a/browser-extension/playwright.config.ts b/browser-extension/playwright.config.ts index 173e3b5..a295f27 100644 --- a/browser-extension/playwright.config.ts +++ b/browser-extension/playwright.config.ts @@ -1,13 +1,12 @@ // playwright.config.ts -import { defineConfig } from '@playwright/test' +import { defineConfig } from "@playwright/test"; export default defineConfig({ - testDir: 'tests/e2e', + testDir: "tests/e2e", use: { - screenshot: 'only-on-failure', - video: 'retain-on-failure', - trace: 'retain-on-failure', + screenshot: "only-on-failure", + video: "retain-on-failure", + trace: "retain-on-failure", }, - reporter: [['html', { open: 'never' }]], -}) - + reporter: [["html", { open: "never" }]], +}); diff --git a/browser-extension/src/lib/enhancers/modifyDOM.ts b/browser-extension/src/lib/enhancers/modifyDOM.ts index 4e51a76..f7daa7d 100644 --- a/browser-extension/src/lib/enhancers/modifyDOM.ts +++ b/browser-extension/src/lib/enhancers/modifyDOM.ts @@ -9,5 +9,22 @@ export function modifyDOM(overtypeInput: HTMLTextAreaElement): HTMLElement { overtypeInput.placeholder = 'Add your comment here...' const overtypeContainer = overtypeWrapper.parentElement!.closest('div')! overtypeContainer.classList.add('overtype-container') + + // Watch for class changes and restore if removed + const observer = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + if (mutation.type === 'attributes' && mutation.attributeName === 'class') { + if (!overtypeContainer.classList.contains('overtype-container')) { + overtypeContainer.classList.add('overtype-container') + } + } + }) + }) + + observer.observe(overtypeContainer, { + attributeFilter: ['class'], + attributes: true, + }) + return overtypeContainer.parentElement!.closest('div')! } diff --git a/browser-extension/src/lib/registries.ts b/browser-extension/src/lib/registries.ts index 8a39045..373a7a4 100644 --- a/browser-extension/src/lib/registries.ts +++ b/browser-extension/src/lib/registries.ts @@ -21,6 +21,7 @@ export class EnhancerRegistry { this.register(new GitHubIssueAddCommentEnhancer()) this.register(new GitHubPRAddCommentEnhancer()) const textColor = 'rgb(31, 35, 40)' + const headingColor = 'rgb(174, 52, 151)' OverType.setTheme({ colors: { blockquote: 'rgb(89, 99, 110)', @@ -28,9 +29,9 @@ export class EnhancerRegistry { codeBg: '#f6f8fa', cursor: '#f95738', em: 'rgb(126, 123, 255)', - h1: textColor, - h2: textColor, - h3: textColor, + h1: headingColor, + h2: headingColor, + h3: headingColor, hr: '#5a7a9b', link: 'rgb(9, 105, 218)', selection: 'rgba(244, 211, 94, 0.4)', diff --git a/browser-extension/src/playgrounds/github-playground.ts b/browser-extension/src/playgrounds/github-playground.ts index 860a0e9..4b4d046 100644 --- a/browser-extension/src/playgrounds/github-playground.ts +++ b/browser-extension/src/playgrounds/github-playground.ts @@ -1,47 +1,49 @@ -import hljs from 'highlight.js' -import OverType from 'overtype' +import hljs from "highlight.js"; +import OverType from "overtype"; export function githubPrNewCommentContentScript() { - if (window.location.hostname !== 'github.com') { - return + if (window.location.hostname !== "github.com") { + return; } - OverType.setCodeHighlighter(hljsHighlighter) - const ghCommentBox = document.getElementById('new_comment_field') as HTMLTextAreaElement | null + OverType.setCodeHighlighter(hljsHighlighter); + const ghCommentBox = document.getElementById( + "new_comment_field", + ) as HTMLTextAreaElement | null; if (ghCommentBox) { - const overtypeContainer = modifyDOM(ghCommentBox) + const overtypeContainer = modifyDOM(ghCommentBox); new OverType(overtypeContainer, { autoResize: true, - minHeight: '102px', - padding: 'var(--base-size-8)', - placeholder: 'Add your comment here...', - }) + minHeight: "102px", + padding: "var(--base-size-8)", + placeholder: "Add your comment here...", + }); } } 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')! + 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")!; } function hljsHighlighter(code: string, language?: string) { try { if (language && hljs.getLanguage(language)) { - const result = hljs.highlight(code, { language }) - return result.value + const result = hljs.highlight(code, { language }); + return result.value; } else { - const result = hljs.highlightAuto(code) - return result.value + const result = hljs.highlightAuto(code); + return result.value; } } catch (error) { - console.warn('highlight.js highlighting failed:', error) - return code + console.warn("highlight.js highlighting failed:", error); + return code; } } diff --git a/browser-extension/vitest.config.ts b/browser-extension/vitest.config.ts index 98e411b..58e6c54 100644 --- a/browser-extension/vitest.config.ts +++ b/browser-extension/vitest.config.ts @@ -1,11 +1,11 @@ -import { defineConfig } from 'vitest/config' -import { WxtVitest } from 'wxt/testing' +import { defineConfig } from "vitest/config"; +import { WxtVitest } from "wxt/testing"; export default defineConfig({ plugins: [WxtVitest()], test: { - environment: 'node', - pool: 'threads', + environment: "node", + pool: "threads", globals: true, }, -}) +}); diff --git a/browser-extension/wxt.config.ts b/browser-extension/wxt.config.ts index 7a4699a..b040e4d 100644 --- a/browser-extension/wxt.config.ts +++ b/browser-extension/wxt.config.ts @@ -1,22 +1,22 @@ -import { defineConfig } from 'wxt' +import { defineConfig } from "wxt"; export default defineConfig({ manifest: { description: - 'Syntax highlighting and autosave for comments on GitHub (and other other markdown-friendly websites).', - host_permissions: ['https://*/*', 'http://*/*'], + "Syntax highlighting and autosave for comments on GitHub (and other other markdown-friendly websites).", + host_permissions: ["https://*/*", "http://*/*"], icons: { - 16: '/icons/icon-16.png', - 48: '/icons/icon-48.png', - 128: '/icons/icon-128.png', + 16: "/icons/icon-16.png", + 48: "/icons/icon-48.png", + 128: "/icons/icon-128.png", }, - name: 'Gitcasso', - permissions: ['activeTab', 'tabs'], - version: '1.0.0', + name: "Gitcasso", + permissions: ["activeTab", "tabs"], + version: "1.0.0", }, - modules: ['@wxt-dev/webextension-polyfill'], - srcDir: 'src', + modules: ["@wxt-dev/webextension-polyfill"], + srcDir: "src", webExt: { disabled: true, }, -}) +}); From 36df3448017e2ec2d0c027962d0d636c0bcb7848 Mon Sep 17 00:00:00 2001 From: Todd Riley Date: Fri, 12 Sep 2025 18:04:18 -0400 Subject: [PATCH 3/5] Add mocks. --- browser-extension/tests/har-fixture.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/browser-extension/tests/har-fixture.ts b/browser-extension/tests/har-fixture.ts index 6464657..b15cb39 100644 --- a/browser-extension/tests/har-fixture.ts +++ b/browser-extension/tests/har-fixture.ts @@ -1,5 +1,12 @@ import { vi } from 'vitest' +// Mock MutationObserver for tests +global.MutationObserver = vi.fn().mockImplementation(() => ({ + disconnect: vi.fn(), + observe: vi.fn(), + takeRecords: vi.fn(() => []), +})) + // Mock the OverType editor component vi.mock('overtype', () => { const mockConstructor = vi.fn().mockImplementation(() => [ @@ -15,6 +22,7 @@ vi.mock('overtype', () => { }, ]) ;(mockConstructor as any).setCodeHighlighter = vi.fn() + ;(mockConstructor as any).setTheme = vi.fn() return { default: mockConstructor, } From d91add68b371f47887d865e08a64ada78e73345c Mon Sep 17 00:00:00 2001 From: Todd Riley Date: Fri, 12 Sep 2025 18:08:20 -0400 Subject: [PATCH 4/5] Biome format config files too. --- browser-extension/biome.json | 2 +- browser-extension/playwright.config.ts | 14 +++++++------- browser-extension/vitest.config.ts | 10 +++++----- browser-extension/wxt.config.ts | 24 ++++++++++++------------ 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/browser-extension/biome.json b/browser-extension/biome.json index d4b34d1..33cd57f 100644 --- a/browser-extension/biome.json +++ b/browser-extension/biome.json @@ -10,7 +10,7 @@ }, "files": { "ignoreUnknown": false, - "includes": [".*", "src/**", "tests/**", "!src/overtype", "!src/playgrounds"] + "includes": [".*", "*.config.ts", "src/**", "tests/**", "!src/overtype"] }, "formatter": { "enabled": true, diff --git a/browser-extension/playwright.config.ts b/browser-extension/playwright.config.ts index a295f27..ea2fa0f 100644 --- a/browser-extension/playwright.config.ts +++ b/browser-extension/playwright.config.ts @@ -1,12 +1,12 @@ // playwright.config.ts -import { defineConfig } from "@playwright/test"; +import { defineConfig } from '@playwright/test' export default defineConfig({ - testDir: "tests/e2e", + reporter: [['html', { open: 'never' }]], + testDir: 'tests/e2e', use: { - screenshot: "only-on-failure", - video: "retain-on-failure", - trace: "retain-on-failure", + screenshot: 'only-on-failure', + trace: 'retain-on-failure', + video: 'retain-on-failure', }, - reporter: [["html", { open: "never" }]], -}); +}) diff --git a/browser-extension/vitest.config.ts b/browser-extension/vitest.config.ts index 58e6c54..d545330 100644 --- a/browser-extension/vitest.config.ts +++ b/browser-extension/vitest.config.ts @@ -1,11 +1,11 @@ -import { defineConfig } from "vitest/config"; -import { WxtVitest } from "wxt/testing"; +import { defineConfig } from 'vitest/config' +import { WxtVitest } from 'wxt/testing' export default defineConfig({ plugins: [WxtVitest()], test: { - environment: "node", - pool: "threads", + environment: 'node', globals: true, + pool: 'threads', }, -}); +}) diff --git a/browser-extension/wxt.config.ts b/browser-extension/wxt.config.ts index b040e4d..7a4699a 100644 --- a/browser-extension/wxt.config.ts +++ b/browser-extension/wxt.config.ts @@ -1,22 +1,22 @@ -import { defineConfig } from "wxt"; +import { defineConfig } from 'wxt' export default defineConfig({ manifest: { description: - "Syntax highlighting and autosave for comments on GitHub (and other other markdown-friendly websites).", - host_permissions: ["https://*/*", "http://*/*"], + 'Syntax highlighting and autosave for comments on GitHub (and other other markdown-friendly websites).', + host_permissions: ['https://*/*', 'http://*/*'], icons: { - 16: "/icons/icon-16.png", - 48: "/icons/icon-48.png", - 128: "/icons/icon-128.png", + 16: '/icons/icon-16.png', + 48: '/icons/icon-48.png', + 128: '/icons/icon-128.png', }, - name: "Gitcasso", - permissions: ["activeTab", "tabs"], - version: "1.0.0", + name: 'Gitcasso', + permissions: ['activeTab', 'tabs'], + version: '1.0.0', }, - modules: ["@wxt-dev/webextension-polyfill"], - srcDir: "src", + modules: ['@wxt-dev/webextension-polyfill'], + srcDir: 'src', webExt: { disabled: true, }, -}); +}) From 031d2e3eaef962832cc911d9f37fc41959632800 Mon Sep 17 00:00:00 2001 From: Todd Riley Date: Fri, 12 Sep 2025 18:13:20 -0400 Subject: [PATCH 5/5] Delete playground. --- browser-extension/src/entrypoints/content.ts | 7 +-- .../src/playgrounds/github-playground.ts | 49 ------------------- 2 files changed, 1 insertion(+), 55 deletions(-) delete mode 100644 browser-extension/src/playgrounds/github-playground.ts diff --git a/browser-extension/src/entrypoints/content.ts b/browser-extension/src/entrypoints/content.ts index 83de338..2093239 100644 --- a/browser-extension/src/entrypoints/content.ts +++ b/browser-extension/src/entrypoints/content.ts @@ -1,8 +1,7 @@ -import { CONFIG, type ModeType } from '../lib/config' +import { CONFIG } from '../lib/config' import type { CommentEvent, CommentSpot } from '../lib/enhancer' import { logger } from '../lib/logger' import { EnhancerRegistry, TextareaRegistry } from '../lib/registries' -import { githubPrNewCommentContentScript } from '../playgrounds/github-playground' const enhancers = new EnhancerRegistry() const enhancedTextareas = new TextareaRegistry() @@ -24,10 +23,6 @@ enhancedTextareas.setEventHandlers( export default defineContentScript({ main() { - if ((CONFIG.MODE as ModeType) === 'PLAYGROUNDS_PR') { - githubPrNewCommentContentScript() - return - } const textAreasOnPageLoad = document.querySelectorAll(`textarea`) for (const textarea of textAreasOnPageLoad) { enhanceMaybe(textarea) diff --git a/browser-extension/src/playgrounds/github-playground.ts b/browser-extension/src/playgrounds/github-playground.ts deleted file mode 100644 index 4b4d046..0000000 --- a/browser-extension/src/playgrounds/github-playground.ts +++ /dev/null @@ -1,49 +0,0 @@ -import hljs from "highlight.js"; -import OverType from "overtype"; - -export function githubPrNewCommentContentScript() { - if (window.location.hostname !== "github.com") { - return; - } - OverType.setCodeHighlighter(hljsHighlighter); - const ghCommentBox = document.getElementById( - "new_comment_field", - ) as HTMLTextAreaElement | null; - if (ghCommentBox) { - const overtypeContainer = modifyDOM(ghCommentBox); - new OverType(overtypeContainer, { - autoResize: true, - minHeight: "102px", - padding: "var(--base-size-8)", - placeholder: "Add your comment here...", - }); - } -} - -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")!; -} - -function hljsHighlighter(code: string, language?: string) { - try { - if (language && hljs.getLanguage(language)) { - const result = hljs.highlight(code, { language }); - return result.value; - } else { - const result = hljs.highlightAuto(code); - return result.value; - } - } catch (error) { - console.warn("highlight.js highlighting failed:", error); - return code; - } -}