From 9eb2fb3f92085ca39f14c354a408350687762ad4 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Wed, 1 Oct 2025 15:15:40 -0700 Subject: [PATCH 1/5] Now all overtype instances get passed through `fixupOvertype`. --- src/lib/enhancers/github/GitHubEditEnhancer.tsx | 15 +++++++-------- .../github/GitHubIssueAppendEnhancer.tsx | 14 ++++++++------ .../github/GitHubIssueCreateEnhancer.tsx | 14 ++++++++------ .../enhancers/github/GitHubPrAppendEnhancer.tsx | 16 +++++++++------- .../enhancers/github/GitHubPrCreateEnhancer.tsx | 14 ++++++++------ src/lib/enhancers/modifyDOM.ts | 12 ++++++++++++ 6 files changed, 52 insertions(+), 33 deletions(-) diff --git a/src/lib/enhancers/github/GitHubEditEnhancer.tsx b/src/lib/enhancers/github/GitHubEditEnhancer.tsx index 931dccd..300b12e 100644 --- a/src/lib/enhancers/github/GitHubEditEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubEditEnhancer.tsx @@ -6,7 +6,7 @@ import type { StrippedLocation, } from "@/lib/enhancer" import { logger } from "@/lib/logger" -import { modifyDOM } from "../modifyDOM" +import { fixupOvertype, modifyDOM } from "../modifyDOM" import { commonGitHubOptions, prepareGitHubHighlighter } from "./github-common" const GH_EDIT = "GH_EDIT" as const @@ -71,13 +71,12 @@ export class GitHubEditEnhancer implements CommentEnhancer { ): OverTypeInstance { prepareGitHubHighlighter() const overtypeContainer = modifyDOM(textArea) - const overtype = new OverType(overtypeContainer, { - ...commonGitHubOptions, - padding: spot.isIssue ? "var(--base-size-16)" : "var(--base-size-8)", - })[0]! - if (!spot.isIssue) { - // TODO: autoheight not working - } + const overtype = fixupOvertype( + new OverType(overtypeContainer, { + ...commonGitHubOptions, + padding: spot.isIssue ? "var(--base-size-16)" : "var(--base-size-8)", + }) + ) return overtype } diff --git a/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx b/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx index a169067..5f3b556 100644 --- a/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx @@ -8,7 +8,7 @@ import type { StrippedLocation, } from "@/lib/enhancer" import { logger } from "@/lib/logger" -import { modifyDOM } from "../modifyDOM" +import { fixupOvertype, modifyDOM } from "../modifyDOM" import { commonGitHubOptions, prepareGitHubHighlighter } from "./github-common" const GH_ISSUE_APPEND = "GH_ISSUE_APPEND" as const @@ -78,11 +78,13 @@ export class GitHubIssueAppendEnhancer ): OverTypeInstance { prepareGitHubHighlighter() const overtypeContainer = modifyDOM(textArea) - return new OverType(overtypeContainer, { - ...commonGitHubOptions, - minHeight: "100px", - placeholder: "Use Markdown to format your comment", - })[0]! + return fixupOvertype( + new OverType(overtypeContainer, { + ...commonGitHubOptions, + minHeight: "100px", + placeholder: "Use Markdown to format your comment", + }) + ) } tableUpperDecoration(spot: GitHubIssueAppendSpot): React.ReactNode { diff --git a/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx b/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx index 684aad5..5a53281 100644 --- a/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx @@ -7,7 +7,7 @@ import type { StrippedLocation, } from "../../enhancer" import { logger } from "../../logger" -import { modifyDOM } from "../modifyDOM" +import { fixupOvertype, modifyDOM } from "../modifyDOM" import { commonGitHubOptions, prepareGitHubHighlighter } from "./github-common" const GH_ISSUE_CREATE = "GH_ISSUE_CREATE" as const @@ -68,11 +68,13 @@ export class GitHubIssueCreateEnhancer ): OverTypeInstance { prepareGitHubHighlighter() const overtypeContainer = modifyDOM(textArea) - return new OverType(overtypeContainer, { - ...commonGitHubOptions, - minHeight: "400px", - placeholder: "Type your description here...", - })[0]! + return fixupOvertype( + new OverType(overtypeContainer, { + ...commonGitHubOptions, + minHeight: "400px", + placeholder: "Type your description here...", + }) + ) } tableUpperDecoration(spot: GitHubIssueCreateSpot): React.ReactNode { diff --git a/src/lib/enhancers/github/GitHubPrAppendEnhancer.tsx b/src/lib/enhancers/github/GitHubPrAppendEnhancer.tsx index 4d4360d..accf056 100644 --- a/src/lib/enhancers/github/GitHubPrAppendEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubPrAppendEnhancer.tsx @@ -8,7 +8,7 @@ import type { StrippedLocation, } from "@/lib/enhancer" import { logger } from "@/lib/logger" -import { modifyDOM } from "../modifyDOM" +import { fixupOvertype, modifyDOM } from "../modifyDOM" import { commonGitHubOptions, prepareGitHubHighlighter } from "./github-common" const GH_PR_APPEND = "GH_PR_APPEND" as const @@ -69,12 +69,14 @@ export class GitHubPrAppendEnhancer ): OverTypeInstance { prepareGitHubHighlighter() const overtypeContainer = modifyDOM(textArea) - const overtype = new OverType(overtypeContainer, { - ...commonGitHubOptions, - minHeight: "102px", - padding: "var(--base-size-8)", - placeholder: "Add your comment here...", - })[0]! + const overtype = fixupOvertype( + new OverType(overtypeContainer, { + ...commonGitHubOptions, + minHeight: "102px", + padding: "var(--base-size-8)", + placeholder: "Add your comment here...", + }) + ) const listenForEmpty = new MutationObserver(() => { if (textArea.value === "") { overtype.updatePreview() diff --git a/src/lib/enhancers/github/GitHubPrCreateEnhancer.tsx b/src/lib/enhancers/github/GitHubPrCreateEnhancer.tsx index 7ffb02e..c28f570 100644 --- a/src/lib/enhancers/github/GitHubPrCreateEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubPrCreateEnhancer.tsx @@ -7,7 +7,7 @@ import type { StrippedLocation, } from "../../enhancer" import { logger } from "../../logger" -import { modifyDOM } from "../modifyDOM" +import { fixupOvertype, modifyDOM } from "../modifyDOM" import { commonGitHubOptions, prepareGitHubHighlighter } from "./github-common" const GH_PR_CREATE = "GH_PR_CREATE" as const @@ -83,11 +83,13 @@ export class GitHubPrCreateEnhancer ): OverTypeInstance { prepareGitHubHighlighter() const overtypeContainer = modifyDOM(textArea) - return new OverType(overtypeContainer, { - ...commonGitHubOptions, - minHeight: "250px", - placeholder: "Type your description here...", - })[0]! + return fixupOvertype( + new OverType(overtypeContainer, { + ...commonGitHubOptions, + minHeight: "250px", + placeholder: "Type your description here...", + }) + ) } tableUpperDecoration(spot: GitHubPrCreateSpot): React.ReactNode { diff --git a/src/lib/enhancers/modifyDOM.ts b/src/lib/enhancers/modifyDOM.ts index 0d16822..3797f69 100644 --- a/src/lib/enhancers/modifyDOM.ts +++ b/src/lib/enhancers/modifyDOM.ts @@ -1,3 +1,15 @@ +import type { OverTypeInstance } from "overtype" + +// Assert that OverType returned exactly one instance and return it +export function fixupOvertype(instances: OverTypeInstance[]): OverTypeInstance { + if (instances.length !== 1) { + throw new Error( + `Expected OverType to return exactly 1 instance, got ${instances.length}` + ) + } + return instances[0]! +} + // Modify the DOM to trick overtype into adopting it instead of recreating it export function modifyDOM(overtypeInput: HTMLTextAreaElement): HTMLElement { overtypeInput.classList.add("overtype-input") From 7d7067ec639bfee9f47a5923e8611091dbb25262 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Wed, 1 Oct 2025 15:23:34 -0700 Subject: [PATCH 2/5] Use `MutationObserver` to make sure we update when pictures get dragged-on. --- src/lib/enhancers/modifyDOM.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/lib/enhancers/modifyDOM.ts b/src/lib/enhancers/modifyDOM.ts index 3797f69..2a4e31e 100644 --- a/src/lib/enhancers/modifyDOM.ts +++ b/src/lib/enhancers/modifyDOM.ts @@ -7,7 +7,18 @@ export function fixupOvertype(instances: OverTypeInstance[]): OverTypeInstance { `Expected OverType to return exactly 1 instance, got ${instances.length}` ) } - return instances[0]! + const overtype = instances[0]! + // this works, but we're now updating twice as often as we need to, because + // overtype has a built-in update which usually works but not always (#101) + // and we're doing this which does always work + const updateOnChange = new MutationObserver(() => { + overtype.updatePreview() + }) + updateOnChange.observe(overtype.textarea, { + attributes: true, + characterData: true, + }) + return overtype } // Modify the DOM to trick overtype into adopting it instead of recreating it From 8c2c11a7c7069d4a1e5b83e0403485350d21f67b Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Wed, 1 Oct 2025 15:23:55 -0700 Subject: [PATCH 3/5] This means we don't need to listen for empty in particular. --- src/lib/enhancers/github/GitHubPrAppendEnhancer.tsx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/lib/enhancers/github/GitHubPrAppendEnhancer.tsx b/src/lib/enhancers/github/GitHubPrAppendEnhancer.tsx index accf056..2018431 100644 --- a/src/lib/enhancers/github/GitHubPrAppendEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubPrAppendEnhancer.tsx @@ -77,12 +77,6 @@ export class GitHubPrAppendEnhancer placeholder: "Add your comment here...", }) ) - const listenForEmpty = new MutationObserver(() => { - if (textArea.value === "") { - overtype.updatePreview() - } - }) - listenForEmpty.observe(textArea, { attributes: true, characterData: true }) return overtype } From 883e4250ecfeee706f9fa82273d70b5a783b8dd3 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Wed, 1 Oct 2025 15:54:25 -0700 Subject: [PATCH 4/5] Rename `modifyDOM` to `overtype-misc`. --- src/lib/enhancers/github/GitHubEditEnhancer.tsx | 2 +- src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx | 2 +- src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx | 2 +- src/lib/enhancers/github/GitHubPrAppendEnhancer.tsx | 2 +- src/lib/enhancers/github/GitHubPrCreateEnhancer.tsx | 2 +- src/lib/enhancers/{modifyDOM.ts => overtype-misc.ts} | 0 6 files changed, 5 insertions(+), 5 deletions(-) rename src/lib/enhancers/{modifyDOM.ts => overtype-misc.ts} (100%) diff --git a/src/lib/enhancers/github/GitHubEditEnhancer.tsx b/src/lib/enhancers/github/GitHubEditEnhancer.tsx index 300b12e..17bb08b 100644 --- a/src/lib/enhancers/github/GitHubEditEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubEditEnhancer.tsx @@ -6,7 +6,7 @@ import type { StrippedLocation, } from "@/lib/enhancer" import { logger } from "@/lib/logger" -import { fixupOvertype, modifyDOM } from "../modifyDOM" +import { fixupOvertype, modifyDOM } from "../overtype-misc" import { commonGitHubOptions, prepareGitHubHighlighter } from "./github-common" const GH_EDIT = "GH_EDIT" as const diff --git a/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx b/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx index 5f3b556..fe1c368 100644 --- a/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubIssueAppendEnhancer.tsx @@ -8,7 +8,7 @@ import type { StrippedLocation, } from "@/lib/enhancer" import { logger } from "@/lib/logger" -import { fixupOvertype, modifyDOM } from "../modifyDOM" +import { fixupOvertype, modifyDOM } from "../overtype-misc" import { commonGitHubOptions, prepareGitHubHighlighter } from "./github-common" const GH_ISSUE_APPEND = "GH_ISSUE_APPEND" as const diff --git a/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx b/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx index 5a53281..a9ee917 100644 --- a/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubIssueCreateEnhancer.tsx @@ -7,7 +7,7 @@ import type { StrippedLocation, } from "../../enhancer" import { logger } from "../../logger" -import { fixupOvertype, modifyDOM } from "../modifyDOM" +import { fixupOvertype, modifyDOM } from "../overtype-misc" import { commonGitHubOptions, prepareGitHubHighlighter } from "./github-common" const GH_ISSUE_CREATE = "GH_ISSUE_CREATE" as const diff --git a/src/lib/enhancers/github/GitHubPrAppendEnhancer.tsx b/src/lib/enhancers/github/GitHubPrAppendEnhancer.tsx index 2018431..434ee3d 100644 --- a/src/lib/enhancers/github/GitHubPrAppendEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubPrAppendEnhancer.tsx @@ -8,7 +8,7 @@ import type { StrippedLocation, } from "@/lib/enhancer" import { logger } from "@/lib/logger" -import { fixupOvertype, modifyDOM } from "../modifyDOM" +import { fixupOvertype, modifyDOM } from "../overtype-misc" import { commonGitHubOptions, prepareGitHubHighlighter } from "./github-common" const GH_PR_APPEND = "GH_PR_APPEND" as const diff --git a/src/lib/enhancers/github/GitHubPrCreateEnhancer.tsx b/src/lib/enhancers/github/GitHubPrCreateEnhancer.tsx index c28f570..9b2c48a 100644 --- a/src/lib/enhancers/github/GitHubPrCreateEnhancer.tsx +++ b/src/lib/enhancers/github/GitHubPrCreateEnhancer.tsx @@ -7,7 +7,7 @@ import type { StrippedLocation, } from "../../enhancer" import { logger } from "../../logger" -import { fixupOvertype, modifyDOM } from "../modifyDOM" +import { fixupOvertype, modifyDOM } from "../overtype-misc" import { commonGitHubOptions, prepareGitHubHighlighter } from "./github-common" const GH_PR_CREATE = "GH_PR_CREATE" as const diff --git a/src/lib/enhancers/modifyDOM.ts b/src/lib/enhancers/overtype-misc.ts similarity index 100% rename from src/lib/enhancers/modifyDOM.ts rename to src/lib/enhancers/overtype-misc.ts From aaca3ffd5a5ceaedfb660f6385f7b11a7415e43f Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Wed, 1 Oct 2025 15:57:31 -0700 Subject: [PATCH 5/5] Centralize our github-centered color scheme into github-common. --- src/lib/enhancers/github/github-common.ts | 21 +++++++++++++++++++++ src/lib/registries.ts | 21 --------------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/lib/enhancers/github/github-common.ts b/src/lib/enhancers/github/github-common.ts index 0573d6e..796f70c 100644 --- a/src/lib/enhancers/github/github-common.ts +++ b/src/lib/enhancers/github/github-common.ts @@ -11,6 +11,27 @@ export const commonGitHubOptions: Options = { export function prepareGitHubHighlighter() { oncePerRefresh("github-highlighter", () => { + const textColor = "rgb(31, 35, 40)" + const headingColor = "rgb(174, 52, 151)" + OverType.setTheme({ + colors: { + blockquote: "rgb(89, 99, 110)", + code: "#59636e", + codeBg: "#f6f8fa", + cursor: "#000000", + em: "rgb(126, 123, 255)", + h1: headingColor, + h2: headingColor, + h3: headingColor, + hr: "#5a7a9b", + link: "rgb(9, 105, 218)", + selection: "rgba(0, 123, 255, 0.3)", + strong: "rgb(45, 1, 142)", + syntaxMarker: textColor, + text: textColor, + }, + name: "custom-github", + }) OverType.setCodeHighlighter(githubHighlighter) }) } diff --git a/src/lib/registries.ts b/src/lib/registries.ts index 3757d06..9edfa00 100644 --- a/src/lib/registries.ts +++ b/src/lib/registries.ts @@ -32,27 +32,6 @@ export class EnhancerRegistry { this.register(new GitHubIssueCreateEnhancer()) this.register(new GitHubPrAppendEnhancer()) this.register(new GitHubPrCreateEnhancer()) - const textColor = "rgb(31, 35, 40)" - const headingColor = "rgb(174, 52, 151)" - OverType.setTheme({ - colors: { - blockquote: "rgb(89, 99, 110)", - code: "#59636e", - codeBg: "#f6f8fa", - cursor: "#000000", - em: "rgb(126, 123, 255)", - h1: headingColor, - h2: headingColor, - h3: headingColor, - hr: "#5a7a9b", - link: "rgb(9, 105, 218)", - selection: "rgba(0, 123, 255, 0.3)", - strong: "rgb(45, 1, 142)", - syntaxMarker: textColor, - text: textColor, - }, - name: "custom-github", - }) } private register(enhancer: CommentEnhancer): void {