Draft
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
110 changes: 110 additions & 0 deletions packages/app/src/context/zoom-keybind.test.ts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
import { describe, expect, test } from "bun:test"
import { readFileSync } from "node:fs"
import { join } from "node:path"
import { matchKeybind, parseKeybind } from "./command"

// harmoniqs/amicode#266 — Cmd/Ctrl +/- zoom did nothing in the webview.
//
// The zoom commands, their CSS-zoom implementation, and the platform signal all
// existed and were correct. Only the keybind strings were wrong: dispatch is an
// exact (normalized-key, modifier-mask) lookup with no fallback, and only
// "mod+=" / "mod+-" were registered.
//
// What a user actually presses:
// Ctrl+Plus on a US layout IS Ctrl+Shift+"=", which arrives as key "+"
// (normalized "plus") WITH the shift bit — wrong key AND wrong mask.
// The numpad's "+" arrives unshifted. On DE/FR/Nordic layouts "=" is itself
// a shifted key, so even the canonical chord carries shift.
//
// So the bare chord worked only on a US layout with the main-row "=", which is
// why this survived: it works for whoever tries it that one way. There was no
// test of any kind over zoom before this file.
//
// These assert the CHORD SET, deliberately decoupled from where it is
// registered — layout.tsx gates the commands on platform.platform === "web"
// and cannot be imported here without dragging the whole page graph in.
const ZOOM_IN = "mod+=,mod+shift+=,mod+plus,mod+shift+plus"
const ZOOM_OUT = "mod+-,mod+shift+_"
const ZOOM_RESET = "mod+0"

/** `mod` resolves to meta on mac and ctrl elsewhere; drive whichever the parse
* produced so these pass on both. */
function chord(config: string, key: string, opts: { shift?: boolean } = {}) {
const first = parseKeybind(config)[0]!
return new KeyboardEvent("keydown", {
key,
ctrlKey: first.ctrl,
metaKey: first.meta,
shiftKey: opts.shift ?? false,
})
}

describe("zoom keybinds cover every chord that means zoom (amicode#266)", () => {
test("zoom in: main-row =, US Ctrl+Plus, numpad +, and shifted-= layouts", () => {
const kb = parseKeybind(ZOOM_IN)

// Ctrl/Cmd + "=" — the canonical chord, US main row.
expect(matchKeybind(kb, chord(ZOOM_IN, "="))).toBe(true)
// Ctrl/Cmd + Plus on US: shift+"=" surfaces as "+" with the shift bit.
expect(matchKeybind(kb, chord(ZOOM_IN, "+", { shift: true }))).toBe(true)
// Numpad plus: "+" with no shift.
expect(matchKeybind(kb, chord(ZOOM_IN, "+"))).toBe(true)
// Layouts where "=" itself requires shift (DE/FR/Nordic).
expect(matchKeybind(kb, chord(ZOOM_IN, "=", { shift: true }))).toBe(true)
})

test("zoom out: main-row - and the shifted underscore", () => {
const kb = parseKeybind(ZOOM_OUT)

expect(matchKeybind(kb, chord(ZOOM_OUT, "-"))).toBe(true)
expect(matchKeybind(kb, chord(ZOOM_OUT, "_", { shift: true }))).toBe(true)
})

test("zoom reset stays a single unambiguous chord", () => {
// "0" is unshifted on every layout we ship to — no widening needed, and
// widening it would start swallowing chords that mean something else.
const kb = parseKeybind(ZOOM_RESET)
expect(matchKeybind(kb, chord(ZOOM_RESET, "0"))).toBe(true)
expect(kb).toHaveLength(1)
})

test("the bare chord alone misses Ctrl+Plus — the regression this locks", () => {
// Guards the fix itself: if someone narrows the config back to "mod+=",
// this is the assertion that explains why they should not.
const narrow = parseKeybind("mod+=")
expect(matchKeybind(narrow, chord("mod+=", "+", { shift: true }))).toBe(false)
expect(matchKeybind(narrow, chord("mod+=", "+"))).toBe(false)
expect(matchKeybind(narrow, chord("mod+=", "=", { shift: true }))).toBe(false)
})

// The seam. Everything above proves the chord SETS behave; this proves the
// app actually registers them. #266 shipped because the mechanism was right
// and its one integration was not — asserting the set without asserting the
// registration would reproduce that exact failure mode in the fix's own test.
test("layout.tsx registers these exact chord sets", () => {
const layout = readFileSync(join(import.meta.dir, "..", "pages", "layout.tsx"), "utf8")
expect(layout).toContain(`keybind: "${ZOOM_IN}"`)
expect(layout).toContain(`keybind: "${ZOOM_OUT}"`)
expect(layout).toContain(`keybind: "${ZOOM_RESET}"`)
})

test("zoom chords do not collide with each other", () => {
const zin = parseKeybind(ZOOM_IN)
const zout = parseKeybind(ZOOM_OUT)

for (const [key, shift] of [
["=", false],
["+", true],
["+", false],
["=", true],
] as const) {
expect(matchKeybind(zout, chord(ZOOM_OUT, key, { shift }))).toBe(false)
}
for (const [key, shift] of [
["-", false],
["_", true],
] as const) {
expect(matchKeybind(zin, chord(ZOOM_IN, key, { shift }))).toBe(false)
}
})
})
15 changes: 13 additions & 2 deletions packages/app/src/pages/layout.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -922,14 +922,25 @@ export default function LegacyLayout(props: ParentProps) {
id: "view.zoomIn",
title: language.t("amicode.zoomIn"),
category: language.t("command.category.view"),
keybind: "mod+=",
// Keybind matching is an exact (key, modifier-mask) lookup, so
// every chord that physically means "zoom in" must be registered
// (harmoniqs/amicode#266). On a US layout Ctrl/Cmd + Plus IS
// shift+"=", which arrives as key "+" (normalized "plus") WITH
// the shift bit — matching neither the key nor the mask of a bare
// "mod+=". The numpad's "+" arrives unshifted, and on layouts
// where "=" itself is shifted (DE/FR/Nordic) even the canonical
// chord carries shift. Only the first is shown in tooltips
// (displayKeybind takes parseKeybind(config)[0]).
keybind: "mod+=,mod+shift+=,mod+plus,mod+shift+plus",
onSelect: () => webZoomIn(),
},
{
id: "view.zoomOut",
title: language.t("amicode.zoomOut"),
category: language.t("command.category.view"),
keybind: "mod+-",
// Same reasoning: shift+"-" arrives as "_", and the numpad's
// minus arrives as a bare "-" (already covered).
keybind: "mod+-,mod+shift+_",
onSelect: () => webZoomOut(),
},
{
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Draft
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
110 changes: 110 additions & 0 deletions packages/app/src/context/zoom-keybind.test.ts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
import { describe, expect, test } from "bun:test"
import { readFileSync } from "node:fs"
import { join } from "node:path"
import { matchKeybind, parseKeybind } from "./command"

// harmoniqs/amicode#266 — Cmd/Ctrl +/- zoom did nothing in the webview.
//
// The zoom commands, their CSS-zoom implementation, and the platform signal all
// existed and were correct. Only the keybind strings were wrong: dispatch is an
// exact (normalized-key, modifier-mask) lookup with no fallback, and only
// "mod+=" / "mod+-" were registered.
//
// What a user actually presses:
// Ctrl+Plus on a US layout IS Ctrl+Shift+"=", which arrives as key "+"
// (normalized "plus") WITH the shift bit — wrong key AND wrong mask.
// The numpad's "+" arrives unshifted. On DE/FR/Nordic layouts "=" is itself
// a shifted key, so even the canonical chord carries shift.
//
// So the bare chord worked only on a US layout with the main-row "=", which is
// why this survived: it works for whoever tries it that one way. There was no
// test of any kind over zoom before this file.
//
// These assert the CHORD SET, deliberately decoupled from where it is
// registered — layout.tsx gates the commands on platform.platform === "web"
// and cannot be imported here without dragging the whole page graph in.
const ZOOM_IN = "mod+=,mod+shift+=,mod+plus,mod+shift+plus"
const ZOOM_OUT = "mod+-,mod+shift+_"
const ZOOM_RESET = "mod+0"

/** `mod` resolves to meta on mac and ctrl elsewhere; drive whichever the parse
* produced so these pass on both. */
function chord(config: string, key: string, opts: { shift?: boolean } = {}) {
const first = parseKeybind(config)[0]!
return new KeyboardEvent("keydown", {
key,
ctrlKey: first.ctrl,
metaKey: first.meta,
shiftKey: opts.shift ?? false,
})
}

describe("zoom keybinds cover every chord that means zoom (amicode#266)", () => {
test("zoom in: main-row =, US Ctrl+Plus, numpad +, and shifted-= layouts", () => {
const kb = parseKeybind(ZOOM_IN)

// Ctrl/Cmd + "=" — the canonical chord, US main row.
expect(matchKeybind(kb, chord(ZOOM_IN, "="))).toBe(true)
// Ctrl/Cmd + Plus on US: shift+"=" surfaces as "+" with the shift bit.
expect(matchKeybind(kb, chord(ZOOM_IN, "+", { shift: true }))).toBe(true)
// Numpad plus: "+" with no shift.
expect(matchKeybind(kb, chord(ZOOM_IN, "+"))).toBe(true)
// Layouts where "=" itself requires shift (DE/FR/Nordic).
expect(matchKeybind(kb, chord(ZOOM_IN, "=", { shift: true }))).toBe(true)
})

test("zoom out: main-row - and the shifted underscore", () => {
const kb = parseKeybind(ZOOM_OUT)

expect(matchKeybind(kb, chord(ZOOM_OUT, "-"))).toBe(true)
expect(matchKeybind(kb, chord(ZOOM_OUT, "_", { shift: true }))).toBe(true)
})

test("zoom reset stays a single unambiguous chord", () => {
// "0" is unshifted on every layout we ship to — no widening needed, and
// widening it would start swallowing chords that mean something else.
const kb = parseKeybind(ZOOM_RESET)
expect(matchKeybind(kb, chord(ZOOM_RESET, "0"))).toBe(true)
expect(kb).toHaveLength(1)
})

test("the bare chord alone misses Ctrl+Plus — the regression this locks", () => {
// Guards the fix itself: if someone narrows the config back to "mod+=",
// this is the assertion that explains why they should not.
const narrow = parseKeybind("mod+=")
expect(matchKeybind(narrow, chord("mod+=", "+", { shift: true }))).toBe(false)
expect(matchKeybind(narrow, chord("mod+=", "+"))).toBe(false)
expect(matchKeybind(narrow, chord("mod+=", "=", { shift: true }))).toBe(false)
})

// The seam. Everything above proves the chord SETS behave; this proves the
// app actually registers them. #266 shipped because the mechanism was right
// and its one integration was not — asserting the set without asserting the
// registration would reproduce that exact failure mode in the fix's own test.
test("layout.tsx registers these exact chord sets", () => {
const layout = readFileSync(join(import.meta.dir, "..", "pages", "layout.tsx"), "utf8")
expect(layout).toContain(`keybind: "${ZOOM_IN}"`)
expect(layout).toContain(`keybind: "${ZOOM_OUT}"`)
expect(layout).toContain(`keybind: "${ZOOM_RESET}"`)
})

test("zoom chords do not collide with each other", () => {
const zin = parseKeybind(ZOOM_IN)
const zout = parseKeybind(ZOOM_OUT)

for (const [key, shift] of [
["=", false],
["+", true],
["+", false],
["=", true],
] as const) {
expect(matchKeybind(zout, chord(ZOOM_OUT, key, { shift }))).toBe(false)
}
for (const [key, shift] of [
["-", false],
["_", true],
] as const) {
expect(matchKeybind(zin, chord(ZOOM_IN, key, { shift }))).toBe(false)
}
})
})
15 changes: 13 additions & 2 deletions packages/app/src/pages/layout.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -922,14 +922,25 @@ export default function LegacyLayout(props: ParentProps) {
id: "view.zoomIn",
title: language.t("amicode.zoomIn"),
category: language.t("command.category.view"),
keybind: "mod+=",
// Keybind matching is an exact (key, modifier-mask) lookup, so
// every chord that physically means "zoom in" must be registered
// (harmoniqs/amicode#266). On a US layout Ctrl/Cmd + Plus IS
// shift+"=", which arrives as key "+" (normalized "plus") WITH
// the shift bit — matching neither the key nor the mask of a bare
// "mod+=". The numpad's "+" arrives unshifted, and on layouts
// where "=" itself is shifted (DE/FR/Nordic) even the canonical
// chord carries shift. Only the first is shown in tooltips
// (displayKeybind takes parseKeybind(config)[0]).
keybind: "mod+=,mod+shift+=,mod+plus,mod+shift+plus",
onSelect: () => webZoomIn(),
},
{
id: "view.zoomOut",
title: language.t("amicode.zoomOut"),
category: language.t("command.category.view"),
keybind: "mod+-",
// Same reasoning: shift+"-" arrives as "_", and the numpad's
// minus arrives as a bare "-" (already covered).
keybind: "mod+-,mod+shift+_",
onSelect: () => webZoomOut(),
},
{
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Draft
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
110 changes: 110 additions & 0 deletions packages/app/src/context/zoom-keybind.test.ts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
import { describe, expect, test } from "bun:test"
import { readFileSync } from "node:fs"
import { join } from "node:path"
import { matchKeybind, parseKeybind } from "./command"

// harmoniqs/amicode#266 — Cmd/Ctrl +/- zoom did nothing in the webview.
//
// The zoom commands, their CSS-zoom implementation, and the platform signal all
// existed and were correct. Only the keybind strings were wrong: dispatch is an
// exact (normalized-key, modifier-mask) lookup with no fallback, and only
// "mod+=" / "mod+-" were registered.
//
// What a user actually presses:
// Ctrl+Plus on a US layout IS Ctrl+Shift+"=", which arrives as key "+"
// (normalized "plus") WITH the shift bit — wrong key AND wrong mask.
// The numpad's "+" arrives unshifted. On DE/FR/Nordic layouts "=" is itself
// a shifted key, so even the canonical chord carries shift.
//
// So the bare chord worked only on a US layout with the main-row "=", which is
// why this survived: it works for whoever tries it that one way. There was no
// test of any kind over zoom before this file.
//
// These assert the CHORD SET, deliberately decoupled from where it is
// registered — layout.tsx gates the commands on platform.platform === "web"
// and cannot be imported here without dragging the whole page graph in.
const ZOOM_IN = "mod+=,mod+shift+=,mod+plus,mod+shift+plus"
const ZOOM_OUT = "mod+-,mod+shift+_"
const ZOOM_RESET = "mod+0"

/** `mod` resolves to meta on mac and ctrl elsewhere; drive whichever the parse
* produced so these pass on both. */
function chord(config: string, key: string, opts: { shift?: boolean } = {}) {
const first = parseKeybind(config)[0]!
return new KeyboardEvent("keydown", {
key,
ctrlKey: first.ctrl,
metaKey: first.meta,
shiftKey: opts.shift ?? false,
})
}

describe("zoom keybinds cover every chord that means zoom (amicode#266)", () => {
test("zoom in: main-row =, US Ctrl+Plus, numpad +, and shifted-= layouts", () => {
const kb = parseKeybind(ZOOM_IN)

// Ctrl/Cmd + "=" — the canonical chord, US main row.
expect(matchKeybind(kb, chord(ZOOM_IN, "="))).toBe(true)
// Ctrl/Cmd + Plus on US: shift+"=" surfaces as "+" with the shift bit.
expect(matchKeybind(kb, chord(ZOOM_IN, "+", { shift: true }))).toBe(true)
// Numpad plus: "+" with no shift.
expect(matchKeybind(kb, chord(ZOOM_IN, "+"))).toBe(true)
// Layouts where "=" itself requires shift (DE/FR/Nordic).
expect(matchKeybind(kb, chord(ZOOM_IN, "=", { shift: true }))).toBe(true)
})

test("zoom out: main-row - and the shifted underscore", () => {
const kb = parseKeybind(ZOOM_OUT)

expect(matchKeybind(kb, chord(ZOOM_OUT, "-"))).toBe(true)
expect(matchKeybind(kb, chord(ZOOM_OUT, "_", { shift: true }))).toBe(true)
})

test("zoom reset stays a single unambiguous chord", () => {
// "0" is unshifted on every layout we ship to — no widening needed, and
// widening it would start swallowing chords that mean something else.
const kb = parseKeybind(ZOOM_RESET)
expect(matchKeybind(kb, chord(ZOOM_RESET, "0"))).toBe(true)
expect(kb).toHaveLength(1)
})

test("the bare chord alone misses Ctrl+Plus — the regression this locks", () => {
// Guards the fix itself: if someone narrows the config back to "mod+=",
// this is the assertion that explains why they should not.
const narrow = parseKeybind("mod+=")
expect(matchKeybind(narrow, chord("mod+=", "+", { shift: true }))).toBe(false)
expect(matchKeybind(narrow, chord("mod+=", "+"))).toBe(false)
expect(matchKeybind(narrow, chord("mod+=", "=", { shift: true }))).toBe(false)
})

// The seam. Everything above proves the chord SETS behave; this proves the
// app actually registers them. #266 shipped because the mechanism was right
// and its one integration was not — asserting the set without asserting the
// registration would reproduce that exact failure mode in the fix's own test.
test("layout.tsx registers these exact chord sets", () => {
const layout = readFileSync(join(import.meta.dir, "..", "pages", "layout.tsx"), "utf8")
expect(layout).toContain(`keybind: "${ZOOM_IN}"`)
expect(layout).toContain(`keybind: "${ZOOM_OUT}"`)
expect(layout).toContain(`keybind: "${ZOOM_RESET}"`)
})

test("zoom chords do not collide with each other", () => {
const zin = parseKeybind(ZOOM_IN)
const zout = parseKeybind(ZOOM_OUT)

for (const [key, shift] of [
["=", false],
["+", true],
["+", false],
["=", true],
] as const) {
expect(matchKeybind(zout, chord(ZOOM_OUT, key, { shift }))).toBe(false)
}
for (const [key, shift] of [
["-", false],
["_", true],
] as const) {
expect(matchKeybind(zin, chord(ZOOM_IN, key, { shift }))).toBe(false)
}
})
})
15 changes: 13 additions & 2 deletions packages/app/src/pages/layout.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -922,14 +922,25 @@ export default function LegacyLayout(props: ParentProps) {
id: "view.zoomIn",
title: language.t("amicode.zoomIn"),
category: language.t("command.category.view"),
keybind: "mod+=",
// Keybind matching is an exact (key, modifier-mask) lookup, so
// every chord that physically means "zoom in" must be registered
// (harmoniqs/amicode#266). On a US layout Ctrl/Cmd + Plus IS
// shift+"=", which arrives as key "+" (normalized "plus") WITH
// the shift bit — matching neither the key nor the mask of a bare
// "mod+=". The numpad's "+" arrives unshifted, and on layouts
// where "=" itself is shifted (DE/FR/Nordic) even the canonical
// chord carries shift. Only the first is shown in tooltips
// (displayKeybind takes parseKeybind(config)[0]).
keybind: "mod+=,mod+shift+=,mod+plus,mod+shift+plus",
onSelect: () => webZoomIn(),
},
{
id: "view.zoomOut",
title: language.t("amicode.zoomOut"),
category: language.t("command.category.view"),
keybind: "mod+-",
// Same reasoning: shift+"-" arrives as "_", and the numpad's
// minus arrives as a bare "-" (already covered).
keybind: "mod+-,mod+shift+_",
onSelect: () => webZoomOut(),
},
{
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Draft
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
110 changes: 110 additions & 0 deletions packages/app/src/context/zoom-keybind.test.ts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
import { describe, expect, test } from "bun:test"
import { readFileSync } from "node:fs"
import { join } from "node:path"
import { matchKeybind, parseKeybind } from "./command"

// harmoniqs/amicode#266 — Cmd/Ctrl +/- zoom did nothing in the webview.
//
// The zoom commands, their CSS-zoom implementation, and the platform signal all
// existed and were correct. Only the keybind strings were wrong: dispatch is an
// exact (normalized-key, modifier-mask) lookup with no fallback, and only
// "mod+=" / "mod+-" were registered.
//
// What a user actually presses:
// Ctrl+Plus on a US layout IS Ctrl+Shift+"=", which arrives as key "+"
// (normalized "plus") WITH the shift bit — wrong key AND wrong mask.
// The numpad's "+" arrives unshifted. On DE/FR/Nordic layouts "=" is itself
// a shifted key, so even the canonical chord carries shift.
//
// So the bare chord worked only on a US layout with the main-row "=", which is
// why this survived: it works for whoever tries it that one way. There was no
// test of any kind over zoom before this file.
//
// These assert the CHORD SET, deliberately decoupled from where it is
// registered — layout.tsx gates the commands on platform.platform === "web"
// and cannot be imported here without dragging the whole page graph in.
const ZOOM_IN = "mod+=,mod+shift+=,mod+plus,mod+shift+plus"
const ZOOM_OUT = "mod+-,mod+shift+_"
const ZOOM_RESET = "mod+0"

/** `mod` resolves to meta on mac and ctrl elsewhere; drive whichever the parse
* produced so these pass on both. */
function chord(config: string, key: string, opts: { shift?: boolean } = {}) {
const first = parseKeybind(config)[0]!
return new KeyboardEvent("keydown", {
key,
ctrlKey: first.ctrl,
metaKey: first.meta,
shiftKey: opts.shift ?? false,
})
}

describe("zoom keybinds cover every chord that means zoom (amicode#266)", () => {
test("zoom in: main-row =, US Ctrl+Plus, numpad +, and shifted-= layouts", () => {
const kb = parseKeybind(ZOOM_IN)

// Ctrl/Cmd + "=" — the canonical chord, US main row.
expect(matchKeybind(kb, chord(ZOOM_IN, "="))).toBe(true)
// Ctrl/Cmd + Plus on US: shift+"=" surfaces as "+" with the shift bit.
expect(matchKeybind(kb, chord(ZOOM_IN, "+", { shift: true }))).toBe(true)
// Numpad plus: "+" with no shift.
expect(matchKeybind(kb, chord(ZOOM_IN, "+"))).toBe(true)
// Layouts where "=" itself requires shift (DE/FR/Nordic).
expect(matchKeybind(kb, chord(ZOOM_IN, "=", { shift: true }))).toBe(true)
})

test("zoom out: main-row - and the shifted underscore", () => {
const kb = parseKeybind(ZOOM_OUT)

expect(matchKeybind(kb, chord(ZOOM_OUT, "-"))).toBe(true)
expect(matchKeybind(kb, chord(ZOOM_OUT, "_", { shift: true }))).toBe(true)
})

test("zoom reset stays a single unambiguous chord", () => {
// "0" is unshifted on every layout we ship to — no widening needed, and
// widening it would start swallowing chords that mean something else.
const kb = parseKeybind(ZOOM_RESET)
expect(matchKeybind(kb, chord(ZOOM_RESET, "0"))).toBe(true)
expect(kb).toHaveLength(1)
})

test("the bare chord alone misses Ctrl+Plus — the regression this locks", () => {
// Guards the fix itself: if someone narrows the config back to "mod+=",
// this is the assertion that explains why they should not.
const narrow = parseKeybind("mod+=")
expect(matchKeybind(narrow, chord("mod+=", "+", { shift: true }))).toBe(false)
expect(matchKeybind(narrow, chord("mod+=", "+"))).toBe(false)
expect(matchKeybind(narrow, chord("mod+=", "=", { shift: true }))).toBe(false)
})

// The seam. Everything above proves the chord SETS behave; this proves the
// app actually registers them. #266 shipped because the mechanism was right
// and its one integration was not — asserting the set without asserting the
// registration would reproduce that exact failure mode in the fix's own test.
test("layout.tsx registers these exact chord sets", () => {
const layout = readFileSync(join(import.meta.dir, "..", "pages", "layout.tsx"), "utf8")
expect(layout).toContain(`keybind: "${ZOOM_IN}"`)
expect(layout).toContain(`keybind: "${ZOOM_OUT}"`)
expect(layout).toContain(`keybind: "${ZOOM_RESET}"`)
})

test("zoom chords do not collide with each other", () => {
const zin = parseKeybind(ZOOM_IN)
const zout = parseKeybind(ZOOM_OUT)

for (const [key, shift] of [
["=", false],
["+", true],
["+", false],
["=", true],
] as const) {
expect(matchKeybind(zout, chord(ZOOM_OUT, key, { shift }))).toBe(false)
}
for (const [key, shift] of [
["-", false],
["_", true],
] as const) {
expect(matchKeybind(zin, chord(ZOOM_IN, key, { shift }))).toBe(false)
}
})
})
15 changes: 13 additions & 2 deletions packages/app/src/pages/layout.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -922,14 +922,25 @@ export default function LegacyLayout(props: ParentProps) {
id: "view.zoomIn",
title: language.t("amicode.zoomIn"),
category: language.t("command.category.view"),
keybind: "mod+=",
// Keybind matching is an exact (key, modifier-mask) lookup, so
// every chord that physically means "zoom in" must be registered
// (harmoniqs/amicode#266). On a US layout Ctrl/Cmd + Plus IS
// shift+"=", which arrives as key "+" (normalized "plus") WITH
// the shift bit — matching neither the key nor the mask of a bare
// "mod+=". The numpad's "+" arrives unshifted, and on layouts
// where "=" itself is shifted (DE/FR/Nordic) even the canonical
// chord carries shift. Only the first is shown in tooltips
// (displayKeybind takes parseKeybind(config)[0]).
keybind: "mod+=,mod+shift+=,mod+plus,mod+shift+plus",
onSelect: () => webZoomIn(),
},
{
id: "view.zoomOut",
title: language.t("amicode.zoomOut"),
category: language.t("command.category.view"),
keybind: "mod+-",
// Same reasoning: shift+"-" arrives as "_", and the numpad's
// minus arrives as a bare "-" (already covered).
keybind: "mod+-,mod+shift+_",
onSelect: () => webZoomOut(),
},
{
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Draft
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
110 changes: 110 additions & 0 deletions packages/app/src/context/zoom-keybind.test.ts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
import { describe, expect, test } from "bun:test"
import { readFileSync } from "node:fs"
import { join } from "node:path"
import { matchKeybind, parseKeybind } from "./command"

// harmoniqs/amicode#266 — Cmd/Ctrl +/- zoom did nothing in the webview.
//
// The zoom commands, their CSS-zoom implementation, and the platform signal all
// existed and were correct. Only the keybind strings were wrong: dispatch is an
// exact (normalized-key, modifier-mask) lookup with no fallback, and only
// "mod+=" / "mod+-" were registered.
//
// What a user actually presses:
// Ctrl+Plus on a US layout IS Ctrl+Shift+"=", which arrives as key "+"
// (normalized "plus") WITH the shift bit — wrong key AND wrong mask.
// The numpad's "+" arrives unshifted. On DE/FR/Nordic layouts "=" is itself
// a shifted key, so even the canonical chord carries shift.
//
// So the bare chord worked only on a US layout with the main-row "=", which is
// why this survived: it works for whoever tries it that one way. There was no
// test of any kind over zoom before this file.
//
// These assert the CHORD SET, deliberately decoupled from where it is
// registered — layout.tsx gates the commands on platform.platform === "web"
// and cannot be imported here without dragging the whole page graph in.
const ZOOM_IN = "mod+=,mod+shift+=,mod+plus,mod+shift+plus"
const ZOOM_OUT = "mod+-,mod+shift+_"
const ZOOM_RESET = "mod+0"

/** `mod` resolves to meta on mac and ctrl elsewhere; drive whichever the parse
* produced so these pass on both. */
function chord(config: string, key: string, opts: { shift?: boolean } = {}) {
const first = parseKeybind(config)[0]!
return new KeyboardEvent("keydown", {
key,
ctrlKey: first.ctrl,
metaKey: first.meta,
shiftKey: opts.shift ?? false,
})
}

describe("zoom keybinds cover every chord that means zoom (amicode#266)", () => {
test("zoom in: main-row =, US Ctrl+Plus, numpad +, and shifted-= layouts", () => {
const kb = parseKeybind(ZOOM_IN)

// Ctrl/Cmd + "=" — the canonical chord, US main row.
expect(matchKeybind(kb, chord(ZOOM_IN, "="))).toBe(true)
// Ctrl/Cmd + Plus on US: shift+"=" surfaces as "+" with the shift bit.
expect(matchKeybind(kb, chord(ZOOM_IN, "+", { shift: true }))).toBe(true)
// Numpad plus: "+" with no shift.
expect(matchKeybind(kb, chord(ZOOM_IN, "+"))).toBe(true)
// Layouts where "=" itself requires shift (DE/FR/Nordic).
expect(matchKeybind(kb, chord(ZOOM_IN, "=", { shift: true }))).toBe(true)
})

test("zoom out: main-row - and the shifted underscore", () => {
const kb = parseKeybind(ZOOM_OUT)

expect(matchKeybind(kb, chord(ZOOM_OUT, "-"))).toBe(true)
expect(matchKeybind(kb, chord(ZOOM_OUT, "_", { shift: true }))).toBe(true)
})

test("zoom reset stays a single unambiguous chord", () => {
// "0" is unshifted on every layout we ship to — no widening needed, and
// widening it would start swallowing chords that mean something else.
const kb = parseKeybind(ZOOM_RESET)
expect(matchKeybind(kb, chord(ZOOM_RESET, "0"))).toBe(true)
expect(kb).toHaveLength(1)
})

test("the bare chord alone misses Ctrl+Plus — the regression this locks", () => {
// Guards the fix itself: if someone narrows the config back to "mod+=",
// this is the assertion that explains why they should not.
const narrow = parseKeybind("mod+=")
expect(matchKeybind(narrow, chord("mod+=", "+", { shift: true }))).toBe(false)
expect(matchKeybind(narrow, chord("mod+=", "+"))).toBe(false)
expect(matchKeybind(narrow, chord("mod+=", "=", { shift: true }))).toBe(false)
})

// The seam. Everything above proves the chord SETS behave; this proves the
// app actually registers them. #266 shipped because the mechanism was right
// and its one integration was not — asserting the set without asserting the
// registration would reproduce that exact failure mode in the fix's own test.
test("layout.tsx registers these exact chord sets", () => {
const layout = readFileSync(join(import.meta.dir, "..", "pages", "layout.tsx"), "utf8")
expect(layout).toContain(`keybind: "${ZOOM_IN}"`)
expect(layout).toContain(`keybind: "${ZOOM_OUT}"`)
expect(layout).toContain(`keybind: "${ZOOM_RESET}"`)
})

test("zoom chords do not collide with each other", () => {
const zin = parseKeybind(ZOOM_IN)
const zout = parseKeybind(ZOOM_OUT)

for (const [key, shift] of [
["=", false],
["+", true],
["+", false],
["=", true],
] as const) {
expect(matchKeybind(zout, chord(ZOOM_OUT, key, { shift }))).toBe(false)
}
for (const [key, shift] of [
["-", false],
["_", true],
] as const) {
expect(matchKeybind(zin, chord(ZOOM_IN, key, { shift }))).toBe(false)
}
})
})
15 changes: 13 additions & 2 deletions packages/app/src/pages/layout.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -922,14 +922,25 @@ export default function LegacyLayout(props: ParentProps) {
id: "view.zoomIn",
title: language.t("amicode.zoomIn"),
category: language.t("command.category.view"),
keybind: "mod+=",
// Keybind matching is an exact (key, modifier-mask) lookup, so
// every chord that physically means "zoom in" must be registered
// (harmoniqs/amicode#266). On a US layout Ctrl/Cmd + Plus IS
// shift+"=", which arrives as key "+" (normalized "plus") WITH
// the shift bit — matching neither the key nor the mask of a bare
// "mod+=". The numpad's "+" arrives unshifted, and on layouts
// where "=" itself is shifted (DE/FR/Nordic) even the canonical
// chord carries shift. Only the first is shown in tooltips
// (displayKeybind takes parseKeybind(config)[0]).
keybind: "mod+=,mod+shift+=,mod+plus,mod+shift+plus",
onSelect: () => webZoomIn(),
},
{
id: "view.zoomOut",
title: language.t("amicode.zoomOut"),
category: language.t("command.category.view"),
keybind: "mod+-",
// Same reasoning: shift+"-" arrives as "_", and the numpad's
// minus arrives as a bare "-" (already covered).
keybind: "mod+-,mod+shift+_",
onSelect: () => webZoomOut(),
},
{
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Draft
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
110 changes: 110 additions & 0 deletions packages/app/src/context/zoom-keybind.test.ts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
import { describe, expect, test } from "bun:test"
import { readFileSync } from "node:fs"
import { join } from "node:path"
import { matchKeybind, parseKeybind } from "./command"

// harmoniqs/amicode#266 — Cmd/Ctrl +/- zoom did nothing in the webview.
//
// The zoom commands, their CSS-zoom implementation, and the platform signal all
// existed and were correct. Only the keybind strings were wrong: dispatch is an
// exact (normalized-key, modifier-mask) lookup with no fallback, and only
// "mod+=" / "mod+-" were registered.
//
// What a user actually presses:
// Ctrl+Plus on a US layout IS Ctrl+Shift+"=", which arrives as key "+"
// (normalized "plus") WITH the shift bit — wrong key AND wrong mask.
// The numpad's "+" arrives unshifted. On DE/FR/Nordic layouts "=" is itself
// a shifted key, so even the canonical chord carries shift.
//
// So the bare chord worked only on a US layout with the main-row "=", which is
// why this survived: it works for whoever tries it that one way. There was no
// test of any kind over zoom before this file.
//
// These assert the CHORD SET, deliberately decoupled from where it is
// registered — layout.tsx gates the commands on platform.platform === "web"
// and cannot be imported here without dragging the whole page graph in.
const ZOOM_IN = "mod+=,mod+shift+=,mod+plus,mod+shift+plus"
const ZOOM_OUT = "mod+-,mod+shift+_"
const ZOOM_RESET = "mod+0"

/** `mod` resolves to meta on mac and ctrl elsewhere; drive whichever the parse
* produced so these pass on both. */
function chord(config: string, key: string, opts: { shift?: boolean } = {}) {
const first = parseKeybind(config)[0]!
return new KeyboardEvent("keydown", {
key,
ctrlKey: first.ctrl,
metaKey: first.meta,
shiftKey: opts.shift ?? false,
})
}

describe("zoom keybinds cover every chord that means zoom (amicode#266)", () => {
test("zoom in: main-row =, US Ctrl+Plus, numpad +, and shifted-= layouts", () => {
const kb = parseKeybind(ZOOM_IN)

// Ctrl/Cmd + "=" — the canonical chord, US main row.
expect(matchKeybind(kb, chord(ZOOM_IN, "="))).toBe(true)
// Ctrl/Cmd + Plus on US: shift+"=" surfaces as "+" with the shift bit.
expect(matchKeybind(kb, chord(ZOOM_IN, "+", { shift: true }))).toBe(true)
// Numpad plus: "+" with no shift.
expect(matchKeybind(kb, chord(ZOOM_IN, "+"))).toBe(true)
// Layouts where "=" itself requires shift (DE/FR/Nordic).
expect(matchKeybind(kb, chord(ZOOM_IN, "=", { shift: true }))).toBe(true)
})

test("zoom out: main-row - and the shifted underscore", () => {
const kb = parseKeybind(ZOOM_OUT)

expect(matchKeybind(kb, chord(ZOOM_OUT, "-"))).toBe(true)
expect(matchKeybind(kb, chord(ZOOM_OUT, "_", { shift: true }))).toBe(true)
})

test("zoom reset stays a single unambiguous chord", () => {
// "0" is unshifted on every layout we ship to — no widening needed, and
// widening it would start swallowing chords that mean something else.
const kb = parseKeybind(ZOOM_RESET)
expect(matchKeybind(kb, chord(ZOOM_RESET, "0"))).toBe(true)
expect(kb).toHaveLength(1)
})

test("the bare chord alone misses Ctrl+Plus — the regression this locks", () => {
// Guards the fix itself: if someone narrows the config back to "mod+=",
// this is the assertion that explains why they should not.
const narrow = parseKeybind("mod+=")
expect(matchKeybind(narrow, chord("mod+=", "+", { shift: true }))).toBe(false)
expect(matchKeybind(narrow, chord("mod+=", "+"))).toBe(false)
expect(matchKeybind(narrow, chord("mod+=", "=", { shift: true }))).toBe(false)
})

// The seam. Everything above proves the chord SETS behave; this proves the
// app actually registers them. #266 shipped because the mechanism was right
// and its one integration was not — asserting the set without asserting the
// registration would reproduce that exact failure mode in the fix's own test.
test("layout.tsx registers these exact chord sets", () => {
const layout = readFileSync(join(import.meta.dir, "..", "pages", "layout.tsx"), "utf8")
expect(layout).toContain(`keybind: "${ZOOM_IN}"`)
expect(layout).toContain(`keybind: "${ZOOM_OUT}"`)
expect(layout).toContain(`keybind: "${ZOOM_RESET}"`)
})

test("zoom chords do not collide with each other", () => {
const zin = parseKeybind(ZOOM_IN)
const zout = parseKeybind(ZOOM_OUT)

for (const [key, shift] of [
["=", false],
["+", true],
["+", false],
["=", true],
] as const) {
expect(matchKeybind(zout, chord(ZOOM_OUT, key, { shift }))).toBe(false)
}
for (const [key, shift] of [
["-", false],
["_", true],
] as const) {
expect(matchKeybind(zin, chord(ZOOM_IN, key, { shift }))).toBe(false)
}
})
})
15 changes: 13 additions & 2 deletions packages/app/src/pages/layout.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -922,14 +922,25 @@ export default function LegacyLayout(props: ParentProps) {
id: "view.zoomIn",
title: language.t("amicode.zoomIn"),
category: language.t("command.category.view"),
keybind: "mod+=",
// Keybind matching is an exact (key, modifier-mask) lookup, so
// every chord that physically means "zoom in" must be registered
// (harmoniqs/amicode#266). On a US layout Ctrl/Cmd + Plus IS
// shift+"=", which arrives as key "+" (normalized "plus") WITH
// the shift bit — matching neither the key nor the mask of a bare
// "mod+=". The numpad's "+" arrives unshifted, and on layouts
// where "=" itself is shifted (DE/FR/Nordic) even the canonical
// chord carries shift. Only the first is shown in tooltips
// (displayKeybind takes parseKeybind(config)[0]).
keybind: "mod+=,mod+shift+=,mod+plus,mod+shift+plus",
onSelect: () => webZoomIn(),
},
{
id: "view.zoomOut",
title: language.t("amicode.zoomOut"),
category: language.t("command.category.view"),
keybind: "mod+-",
// Same reasoning: shift+"-" arrives as "_", and the numpad's
// minus arrives as a bare "-" (already covered).
keybind: "mod+-,mod+shift+_",
onSelect: () => webZoomOut(),
},
{
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Draft
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
110 changes: 110 additions & 0 deletions packages/app/src/context/zoom-keybind.test.ts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
import { describe, expect, test } from "bun:test"
import { readFileSync } from "node:fs"
import { join } from "node:path"
import { matchKeybind, parseKeybind } from "./command"

// harmoniqs/amicode#266 — Cmd/Ctrl +/- zoom did nothing in the webview.
//
// The zoom commands, their CSS-zoom implementation, and the platform signal all
// existed and were correct. Only the keybind strings were wrong: dispatch is an
// exact (normalized-key, modifier-mask) lookup with no fallback, and only
// "mod+=" / "mod+-" were registered.
//
// What a user actually presses:
// Ctrl+Plus on a US layout IS Ctrl+Shift+"=", which arrives as key "+"
// (normalized "plus") WITH the shift bit — wrong key AND wrong mask.
// The numpad's "+" arrives unshifted. On DE/FR/Nordic layouts "=" is itself
// a shifted key, so even the canonical chord carries shift.
//
// So the bare chord worked only on a US layout with the main-row "=", which is
// why this survived: it works for whoever tries it that one way. There was no
// test of any kind over zoom before this file.
//
// These assert the CHORD SET, deliberately decoupled from where it is
// registered — layout.tsx gates the commands on platform.platform === "web"
// and cannot be imported here without dragging the whole page graph in.
const ZOOM_IN = "mod+=,mod+shift+=,mod+plus,mod+shift+plus"
const ZOOM_OUT = "mod+-,mod+shift+_"
const ZOOM_RESET = "mod+0"

/** `mod` resolves to meta on mac and ctrl elsewhere; drive whichever the parse
* produced so these pass on both. */
function chord(config: string, key: string, opts: { shift?: boolean } = {}) {
const first = parseKeybind(config)[0]!
return new KeyboardEvent("keydown", {
key,
ctrlKey: first.ctrl,
metaKey: first.meta,
shiftKey: opts.shift ?? false,
})
}

describe("zoom keybinds cover every chord that means zoom (amicode#266)", () => {
test("zoom in: main-row =, US Ctrl+Plus, numpad +, and shifted-= layouts", () => {
const kb = parseKeybind(ZOOM_IN)

// Ctrl/Cmd + "=" — the canonical chord, US main row.
expect(matchKeybind(kb, chord(ZOOM_IN, "="))).toBe(true)
// Ctrl/Cmd + Plus on US: shift+"=" surfaces as "+" with the shift bit.
expect(matchKeybind(kb, chord(ZOOM_IN, "+", { shift: true }))).toBe(true)
// Numpad plus: "+" with no shift.
expect(matchKeybind(kb, chord(ZOOM_IN, "+"))).toBe(true)
// Layouts where "=" itself requires shift (DE/FR/Nordic).
expect(matchKeybind(kb, chord(ZOOM_IN, "=", { shift: true }))).toBe(true)
})

test("zoom out: main-row - and the shifted underscore", () => {
const kb = parseKeybind(ZOOM_OUT)

expect(matchKeybind(kb, chord(ZOOM_OUT, "-"))).toBe(true)
expect(matchKeybind(kb, chord(ZOOM_OUT, "_", { shift: true }))).toBe(true)
})

test("zoom reset stays a single unambiguous chord", () => {
// "0" is unshifted on every layout we ship to — no widening needed, and
// widening it would start swallowing chords that mean something else.
const kb = parseKeybind(ZOOM_RESET)
expect(matchKeybind(kb, chord(ZOOM_RESET, "0"))).toBe(true)
expect(kb).toHaveLength(1)
})

test("the bare chord alone misses Ctrl+Plus — the regression this locks", () => {
// Guards the fix itself: if someone narrows the config back to "mod+=",
// this is the assertion that explains why they should not.
const narrow = parseKeybind("mod+=")
expect(matchKeybind(narrow, chord("mod+=", "+", { shift: true }))).toBe(false)
expect(matchKeybind(narrow, chord("mod+=", "+"))).toBe(false)
expect(matchKeybind(narrow, chord("mod+=", "=", { shift: true }))).toBe(false)
})

// The seam. Everything above proves the chord SETS behave; this proves the
// app actually registers them. #266 shipped because the mechanism was right
// and its one integration was not — asserting the set without asserting the
// registration would reproduce that exact failure mode in the fix's own test.
test("layout.tsx registers these exact chord sets", () => {
const layout = readFileSync(join(import.meta.dir, "..", "pages", "layout.tsx"), "utf8")
expect(layout).toContain(`keybind: "${ZOOM_IN}"`)
expect(layout).toContain(`keybind: "${ZOOM_OUT}"`)
expect(layout).toContain(`keybind: "${ZOOM_RESET}"`)
})

test("zoom chords do not collide with each other", () => {
const zin = parseKeybind(ZOOM_IN)
const zout = parseKeybind(ZOOM_OUT)

for (const [key, shift] of [
["=", false],
["+", true],
["+", false],
["=", true],
] as const) {
expect(matchKeybind(zout, chord(ZOOM_OUT, key, { shift }))).toBe(false)
}
for (const [key, shift] of [
["-", false],
["_", true],
] as const) {
expect(matchKeybind(zin, chord(ZOOM_IN, key, { shift }))).toBe(false)
}
})
})
15 changes: 13 additions & 2 deletions packages/app/src/pages/layout.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -922,14 +922,25 @@ export default function LegacyLayout(props: ParentProps) {
id: "view.zoomIn",
title: language.t("amicode.zoomIn"),
category: language.t("command.category.view"),
keybind: "mod+=",
// Keybind matching is an exact (key, modifier-mask) lookup, so
// every chord that physically means "zoom in" must be registered
// (harmoniqs/amicode#266). On a US layout Ctrl/Cmd + Plus IS
// shift+"=", which arrives as key "+" (normalized "plus") WITH
// the shift bit — matching neither the key nor the mask of a bare
// "mod+=". The numpad's "+" arrives unshifted, and on layouts
// where "=" itself is shifted (DE/FR/Nordic) even the canonical
// chord carries shift. Only the first is shown in tooltips
// (displayKeybind takes parseKeybind(config)[0]).
keybind: "mod+=,mod+shift+=,mod+plus,mod+shift+plus",
onSelect: () => webZoomIn(),
},
{
id: "view.zoomOut",
title: language.t("amicode.zoomOut"),
category: language.t("command.category.view"),
keybind: "mod+-",
// Same reasoning: shift+"-" arrives as "_", and the numpad's
// minus arrives as a bare "-" (already covered).
keybind: "mod+-,mod+shift+_",
onSelect: () => webZoomOut(),
},
{
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Draft
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
110 changes: 110 additions & 0 deletions packages/app/src/context/zoom-keybind.test.ts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
import { describe, expect, test } from "bun:test"
import { readFileSync } from "node:fs"
import { join } from "node:path"
import { matchKeybind, parseKeybind } from "./command"

// harmoniqs/amicode#266 — Cmd/Ctrl +/- zoom did nothing in the webview.
//
// The zoom commands, their CSS-zoom implementation, and the platform signal all
// existed and were correct. Only the keybind strings were wrong: dispatch is an
// exact (normalized-key, modifier-mask) lookup with no fallback, and only
// "mod+=" / "mod+-" were registered.
//
// What a user actually presses:
// Ctrl+Plus on a US layout IS Ctrl+Shift+"=", which arrives as key "+"
// (normalized "plus") WITH the shift bit — wrong key AND wrong mask.
// The numpad's "+" arrives unshifted. On DE/FR/Nordic layouts "=" is itself
// a shifted key, so even the canonical chord carries shift.
//
// So the bare chord worked only on a US layout with the main-row "=", which is
// why this survived: it works for whoever tries it that one way. There was no
// test of any kind over zoom before this file.
//
// These assert the CHORD SET, deliberately decoupled from where it is
// registered — layout.tsx gates the commands on platform.platform === "web"
// and cannot be imported here without dragging the whole page graph in.
const ZOOM_IN = "mod+=,mod+shift+=,mod+plus,mod+shift+plus"
const ZOOM_OUT = "mod+-,mod+shift+_"
const ZOOM_RESET = "mod+0"

/** `mod` resolves to meta on mac and ctrl elsewhere; drive whichever the parse
* produced so these pass on both. */
function chord(config: string, key: string, opts: { shift?: boolean } = {}) {
const first = parseKeybind(config)[0]!
return new KeyboardEvent("keydown", {
key,
ctrlKey: first.ctrl,
metaKey: first.meta,
shiftKey: opts.shift ?? false,
})
}

describe("zoom keybinds cover every chord that means zoom (amicode#266)", () => {
test("zoom in: main-row =, US Ctrl+Plus, numpad +, and shifted-= layouts", () => {
const kb = parseKeybind(ZOOM_IN)

// Ctrl/Cmd + "=" — the canonical chord, US main row.
expect(matchKeybind(kb, chord(ZOOM_IN, "="))).toBe(true)
// Ctrl/Cmd + Plus on US: shift+"=" surfaces as "+" with the shift bit.
expect(matchKeybind(kb, chord(ZOOM_IN, "+", { shift: true }))).toBe(true)
// Numpad plus: "+" with no shift.
expect(matchKeybind(kb, chord(ZOOM_IN, "+"))).toBe(true)
// Layouts where "=" itself requires shift (DE/FR/Nordic).
expect(matchKeybind(kb, chord(ZOOM_IN, "=", { shift: true }))).toBe(true)
})

test("zoom out: main-row - and the shifted underscore", () => {
const kb = parseKeybind(ZOOM_OUT)

expect(matchKeybind(kb, chord(ZOOM_OUT, "-"))).toBe(true)
expect(matchKeybind(kb, chord(ZOOM_OUT, "_", { shift: true }))).toBe(true)
})

test("zoom reset stays a single unambiguous chord", () => {
// "0" is unshifted on every layout we ship to — no widening needed, and
// widening it would start swallowing chords that mean something else.
const kb = parseKeybind(ZOOM_RESET)
expect(matchKeybind(kb, chord(ZOOM_RESET, "0"))).toBe(true)
expect(kb).toHaveLength(1)
})

test("the bare chord alone misses Ctrl+Plus — the regression this locks", () => {
// Guards the fix itself: if someone narrows the config back to "mod+=",
// this is the assertion that explains why they should not.
const narrow = parseKeybind("mod+=")
expect(matchKeybind(narrow, chord("mod+=", "+", { shift: true }))).toBe(false)
expect(matchKeybind(narrow, chord("mod+=", "+"))).toBe(false)
expect(matchKeybind(narrow, chord("mod+=", "=", { shift: true }))).toBe(false)
})

// The seam. Everything above proves the chord SETS behave; this proves the
// app actually registers them. #266 shipped because the mechanism was right
// and its one integration was not — asserting the set without asserting the
// registration would reproduce that exact failure mode in the fix's own test.
test("layout.tsx registers these exact chord sets", () => {
const layout = readFileSync(join(import.meta.dir, "..", "pages", "layout.tsx"), "utf8")
expect(layout).toContain(`keybind: "${ZOOM_IN}"`)
expect(layout).toContain(`keybind: "${ZOOM_OUT}"`)
expect(layout).toContain(`keybind: "${ZOOM_RESET}"`)
})

test("zoom chords do not collide with each other", () => {
const zin = parseKeybind(ZOOM_IN)
const zout = parseKeybind(ZOOM_OUT)

for (const [key, shift] of [
["=", false],
["+", true],
["+", false],
["=", true],
] as const) {
expect(matchKeybind(zout, chord(ZOOM_OUT, key, { shift }))).toBe(false)
}
for (const [key, shift] of [
["-", false],
["_", true],
] as const) {
expect(matchKeybind(zin, chord(ZOOM_IN, key, { shift }))).toBe(false)
}
})
})
15 changes: 13 additions & 2 deletions packages/app/src/pages/layout.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -922,14 +922,25 @@ export default function LegacyLayout(props: ParentProps) {
id: "view.zoomIn",
title: language.t("amicode.zoomIn"),
category: language.t("command.category.view"),
keybind: "mod+=",
// Keybind matching is an exact (key, modifier-mask) lookup, so
// every chord that physically means "zoom in" must be registered
// (harmoniqs/amicode#266). On a US layout Ctrl/Cmd + Plus IS
// shift+"=", which arrives as key "+" (normalized "plus") WITH
// the shift bit — matching neither the key nor the mask of a bare
// "mod+=". The numpad's "+" arrives unshifted, and on layouts
// where "=" itself is shifted (DE/FR/Nordic) even the canonical
// chord carries shift. Only the first is shown in tooltips
// (displayKeybind takes parseKeybind(config)[0]).
keybind: "mod+=,mod+shift+=,mod+plus,mod+shift+plus",
onSelect: () => webZoomIn(),
},
{
id: "view.zoomOut",
title: language.t("amicode.zoomOut"),
category: language.t("command.category.view"),
keybind: "mod+-",
// Same reasoning: shift+"-" arrives as "_", and the numpad's
// minus arrives as a bare "-" (already covered).
keybind: "mod+-,mod+shift+_",
onSelect: () => webZoomOut(),
},
{
Expand Down
Loading