Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
/**
* Static-analysis contract for the native cursor convention.
*
* Native macOS / Windows reserve the pointing-hand cursor (`cursor: pointer`)
* for hyperlinks; every other control uses the default arrow. Only the
* link-styled in-app nav button (`.maka-markdown-link-internal`) may carry it.
* The runtime look-and-feel (which element shows which cursor) is still
* verified in a real window — this is the source bound.
*/

import { strict as assert } from 'node:assert';
import { readFile } from 'node:fs/promises';
import { describe, it } from 'node:test';
import { join } from 'node:path';

const STYLES_PATH = join(process.cwd(), 'src', 'renderer', 'styles.css');
const TOKENS_PATH = join(process.cwd(), 'src', 'renderer', 'maka-tokens.css');

/** Only the link-styled in-app nav button may carry the hand cursor. */
const CURSOR_POINTER_ALLOWLIST = ['.maka-markdown-link-internal'];

/**
* Selectors of every rule that declares `cursor: pointer`, sorted. Comments are
* stripped first; each hit walks back to the `{` that opens its rule and takes
* the selector after the previous block boundary. Depth is ignored, so a
* `cursor: pointer` hidden inside an at-rule (e.g. `@media`) is still caught.
*/
function selectorsWithHandCursor(css: string): string[] {
const stripped = css.replace(/\/\*[\s\S]*?\*\//g, '');
const selectors: string[] = [];
const re = /cursor:\s*pointer/g;
for (let m = re.exec(stripped); m; m = re.exec(stripped)) {
const open = stripped.lastIndexOf('{', m.index);
selectors.push(stripped.slice(0, open).split(/[{}]/).pop()?.trim() ?? '');
}
return selectors.sort();
}

describe('native cursor convention contract', () => {
it('styles.css: cursor:pointer lives only on the link-styled nav button', async () => {
const css = await readFile(STYLES_PATH, 'utf8');
assert.deepEqual(
selectorsWithHandCursor(css),
[...CURSOR_POINTER_ALLOWLIST].sort(),
'Only `.maka-markdown-link-internal` may carry `cursor: pointer` — it presents as a link, and native macOS reserves the hand for links while every other control uses the default arrow. Drop the declaration, or reuse the link class if the element genuinely is the in-app link button.',
);
});

it('maka-tokens.css: defines no cursor:pointer', async () => {
const css = await readFile(TOKENS_PATH, 'utf8');
assert.deepEqual(
selectorsWithHandCursor(css),
[],
'Design tokens must not set `cursor: pointer`; the hand cursor belongs only on the link-styled nav button in styles.css.',
);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -478,7 +478,13 @@ describe('localized main shell contract', () => {
assert.ok(workspaceTopActions, '.maka-workspace-top-actions rule must exist');
assert.ok(workspaceFeedbackAction, '.maka-workspace-feedback-action rule must exist');
assert.match(workspaceTopActions, /position:\s*absolute/);
assert.match(workspaceTopActions, /top:\s*11px/);
// PR-TITLEBAR-ROW-BASELINE: the right-side workspace top-actions
// share the single titlebar baseline with the two left strips —
// anchored on var(--maka-titlebar-control-safe-top), never a
// hardcoded vertical offset. We assert the baseline reference, not
// the per-container correction constant (geometry, free to tune):
// the invariant is that all three clusters key off the one baseline.
assert.match(workspaceTopActions, /top:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\)/);
assert.match(workspaceTopActions, /right:\s*24px/);
assert.match(workspaceTopActions, /gap:\s*6px/);
assert.match(workspaceFeedbackAction, /font-size:\s*11px/);
Expand DownExpand Up@@ -528,7 +534,15 @@ describe('localized main shell contract', () => {
assert.ok(collapsedTopbar, '.maka-collapsed-drag-strip rule must exist');
assert.match(collapsedTopbar, /min-height:\s*38px/);
assert.match(styles, /--maka-titlebar-control-safe-left:\s*94px/);
assert.match(collapsedTopbar, /padding:\s*8px 12px 0 var\(--maka-titlebar-control-safe-left\)/);
// PR-TITLEBAR-ROW-BASELINE: the macOS window has ONE physical
// titlebar row (traffic-light center). All three top icon clusters
// — sidebar header strip, collapsed strip, workspace top-actions —
// center their 24px icons on the single --maka-titlebar-control-safe-top
// baseline so the row can't jump when the sidebar collapses/expands.
// Each cluster applies its own small per-container correction; no
// cluster may reintroduce an independent vertical baseline.
assert.match(styles, /--maka-titlebar-control-safe-top:\s*20px/);
assert.match(collapsedTopbar, /padding:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\) 12px 0 var\(--maka-titlebar-control-safe-left\)/);
assert.match(collapsedTopbar, /-webkit-app-region:\s*drag/);
const collapsedTopbarButton = extractCssRule(styles, '.maka-collapsed-topbar-button');
assert.ok(collapsedTopbarButton, '.maka-collapsed-topbar-button rule must exist');
Expand All@@ -538,6 +552,10 @@ describe('localized main shell contract', () => {
assert.match(sidebarTopBar, /justify-content:\s*space-between/);
assert.match(sidebarTopBar, /box-sizing:\s*border-box/);
assert.match(sidebarTopBar, /padding-left:\s*calc\(var\(--maka-titlebar-control-safe-left\) - 10px\)/);
// same shared vertical baseline as the collapsed strip + workspace
// top-actions — references the one var(--maka-titlebar-control-safe-top),
// with its own per-container correction constant (not asserted).
assert.match(sidebarTopBar, /padding-top:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\)/);
assert.match(styles, /(?:^|\n)\.maka-nav-icon\s*\{[\s\S]*?width:\s*18px[\s\S]*?height:\s*18px/);
assert.match(styles, /\.maka-sidebar-modules\b/);
assert.doesNotMatch(styles, /\.maka-sidebar-module-hint\b/);
Expand All@@ -561,10 +579,10 @@ describe('localized main shell contract', () => {
const icon = await stat(iconPath);
const iconBuffer = await readFile(iconPath);

assert.ok(icon.size > 1_400_000, 'the edge-filled user-provided PNG icon must be present as the desktop app icon asset');
assert.ok(icon.size > 700_000, 'the padded macOS-safe-area PNG icon (PR #75) must be present as the desktop app icon asset');
assert.equal(iconBuffer.toString('ascii', 1, 4), 'PNG', 'desktop app icon must remain a PNG asset');
assert.equal(iconBuffer.readUInt32BE(16), 1254, 'desktop app icon width must match the supplied edge-filled icon');
assert.equal(iconBuffer.readUInt32BE(20), 1254, 'desktop app icon height must match the supplied edge-filled icon');
assert.equal(iconBuffer.readUInt32BE(16), 1024, 'desktop app icon width must match the supplied 1024² padded icon (PR #75)');
assert.equal(iconBuffer.readUInt32BE(20), 1024, 'desktop app icon height must match the supplied 1024² padded icon (PR #75)');
assert.equal(iconBuffer[25], 6, 'desktop app icon must be RGBA so the rounded icon corners stay transparent');
assert.match(tokens, /--background:\s*oklch\(1\.000 0 0\);/);
assert.match(tokens, /--surface-canvas:\s*oklch\(0\.935 0 0\);/);
Expand Down
7 changes: 0 additions & 7 deletions apps/desktop/src/renderer/maka-tokens.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -763,7 +763,6 @@
padding: 6px 10px;
border-radius: var(--radius-button);
color: var(--foreground-80);
cursor: pointer;
font-size: 14px;
line-height: 1.4;
user-select: none;
Expand All@@ -790,7 +789,6 @@
padding: 4px 8px;
border-radius: var(--radius-button);
color: var(--foreground-60);
cursor: pointer;
font-size: 13px;
}
.maka-sidebar-button:hover { background: var(--hover); color: var(--foreground); }
Expand DownExpand Up@@ -948,7 +946,6 @@
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
font-weight: 600;
color: var(--accent);
letter-spacing: 0.02em;
Expand DownExpand Up@@ -1158,7 +1155,6 @@
border-radius: 7px;
background: transparent;
color: var(--foreground-50);
cursor: pointer;
transition: background 120ms ease, color 120ms ease, box-shadow 120ms ease;
}
.maka-code-block-copy:hover {
Expand DownExpand Up@@ -1315,7 +1311,6 @@
border-radius: 7px;
background: var(--background);
color: var(--foreground-60);
cursor: pointer;
opacity: 0;
/* PR-CHAT-COPY-BUTTON-POLISH-0 (WAWQAQ 10min loop): the copy
button used to fade in on hover but never moved — felt like
Expand DownExpand Up@@ -1424,7 +1419,6 @@
.maka-tool { padding: 0; }
.maka-tool > summary {
list-style: none;
cursor: pointer;
padding: 8px 12px;
}
.maka-tool > summary::-webkit-details-marker { display: none; }
Expand DownExpand Up@@ -1670,7 +1664,6 @@
font-size: 13px;
font-weight: 500;
line-height: 1.2;
cursor: pointer;
transition: background 120ms ease, border-color 120ms ease, color 120ms ease, transform 120ms ease, box-shadow 120ms ease;
}
.maka-button:hover { background: var(--hover); }
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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
/**
* Static-analysis contract for the native cursor convention.
*
* Native macOS / Windows reserve the pointing-hand cursor (`cursor: pointer`)
* for hyperlinks; every other control uses the default arrow. Only the
* link-styled in-app nav button (`.maka-markdown-link-internal`) may carry it.
* The runtime look-and-feel (which element shows which cursor) is still
* verified in a real window — this is the source bound.
*/

import { strict as assert } from 'node:assert';
import { readFile } from 'node:fs/promises';
import { describe, it } from 'node:test';
import { join } from 'node:path';

const STYLES_PATH = join(process.cwd(), 'src', 'renderer', 'styles.css');
const TOKENS_PATH = join(process.cwd(), 'src', 'renderer', 'maka-tokens.css');

/** Only the link-styled in-app nav button may carry the hand cursor. */
const CURSOR_POINTER_ALLOWLIST = ['.maka-markdown-link-internal'];

/**
* Selectors of every rule that declares `cursor: pointer`, sorted. Comments are
* stripped first; each hit walks back to the `{` that opens its rule and takes
* the selector after the previous block boundary. Depth is ignored, so a
* `cursor: pointer` hidden inside an at-rule (e.g. `@media`) is still caught.
*/
function selectorsWithHandCursor(css: string): string[] {
const stripped = css.replace(/\/\*[\s\S]*?\*\//g, '');
const selectors: string[] = [];
const re = /cursor:\s*pointer/g;
for (let m = re.exec(stripped); m; m = re.exec(stripped)) {
const open = stripped.lastIndexOf('{', m.index);
selectors.push(stripped.slice(0, open).split(/[{}]/).pop()?.trim() ?? '');
}
return selectors.sort();
}

describe('native cursor convention contract', () => {
it('styles.css: cursor:pointer lives only on the link-styled nav button', async () => {
const css = await readFile(STYLES_PATH, 'utf8');
assert.deepEqual(
selectorsWithHandCursor(css),
[...CURSOR_POINTER_ALLOWLIST].sort(),
'Only `.maka-markdown-link-internal` may carry `cursor: pointer` — it presents as a link, and native macOS reserves the hand for links while every other control uses the default arrow. Drop the declaration, or reuse the link class if the element genuinely is the in-app link button.',
);
});

it('maka-tokens.css: defines no cursor:pointer', async () => {
const css = await readFile(TOKENS_PATH, 'utf8');
assert.deepEqual(
selectorsWithHandCursor(css),
[],
'Design tokens must not set `cursor: pointer`; the hand cursor belongs only on the link-styled nav button in styles.css.',
);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -478,7 +478,13 @@ describe('localized main shell contract', () => {
assert.ok(workspaceTopActions, '.maka-workspace-top-actions rule must exist');
assert.ok(workspaceFeedbackAction, '.maka-workspace-feedback-action rule must exist');
assert.match(workspaceTopActions, /position:\s*absolute/);
assert.match(workspaceTopActions, /top:\s*11px/);
// PR-TITLEBAR-ROW-BASELINE: the right-side workspace top-actions
// share the single titlebar baseline with the two left strips —
// anchored on var(--maka-titlebar-control-safe-top), never a
// hardcoded vertical offset. We assert the baseline reference, not
// the per-container correction constant (geometry, free to tune):
// the invariant is that all three clusters key off the one baseline.
assert.match(workspaceTopActions, /top:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\)/);
assert.match(workspaceTopActions, /right:\s*24px/);
assert.match(workspaceTopActions, /gap:\s*6px/);
assert.match(workspaceFeedbackAction, /font-size:\s*11px/);
Expand DownExpand Up@@ -528,7 +534,15 @@ describe('localized main shell contract', () => {
assert.ok(collapsedTopbar, '.maka-collapsed-drag-strip rule must exist');
assert.match(collapsedTopbar, /min-height:\s*38px/);
assert.match(styles, /--maka-titlebar-control-safe-left:\s*94px/);
assert.match(collapsedTopbar, /padding:\s*8px 12px 0 var\(--maka-titlebar-control-safe-left\)/);
// PR-TITLEBAR-ROW-BASELINE: the macOS window has ONE physical
// titlebar row (traffic-light center). All three top icon clusters
// — sidebar header strip, collapsed strip, workspace top-actions —
// center their 24px icons on the single --maka-titlebar-control-safe-top
// baseline so the row can't jump when the sidebar collapses/expands.
// Each cluster applies its own small per-container correction; no
// cluster may reintroduce an independent vertical baseline.
assert.match(styles, /--maka-titlebar-control-safe-top:\s*20px/);
assert.match(collapsedTopbar, /padding:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\) 12px 0 var\(--maka-titlebar-control-safe-left\)/);
assert.match(collapsedTopbar, /-webkit-app-region:\s*drag/);
const collapsedTopbarButton = extractCssRule(styles, '.maka-collapsed-topbar-button');
assert.ok(collapsedTopbarButton, '.maka-collapsed-topbar-button rule must exist');
Expand All@@ -538,6 +552,10 @@ describe('localized main shell contract', () => {
assert.match(sidebarTopBar, /justify-content:\s*space-between/);
assert.match(sidebarTopBar, /box-sizing:\s*border-box/);
assert.match(sidebarTopBar, /padding-left:\s*calc\(var\(--maka-titlebar-control-safe-left\) - 10px\)/);
// same shared vertical baseline as the collapsed strip + workspace
// top-actions — references the one var(--maka-titlebar-control-safe-top),
// with its own per-container correction constant (not asserted).
assert.match(sidebarTopBar, /padding-top:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\)/);
assert.match(styles, /(?:^|\n)\.maka-nav-icon\s*\{[\s\S]*?width:\s*18px[\s\S]*?height:\s*18px/);
assert.match(styles, /\.maka-sidebar-modules\b/);
assert.doesNotMatch(styles, /\.maka-sidebar-module-hint\b/);
Expand All@@ -561,10 +579,10 @@ describe('localized main shell contract', () => {
const icon = await stat(iconPath);
const iconBuffer = await readFile(iconPath);

assert.ok(icon.size > 1_400_000, 'the edge-filled user-provided PNG icon must be present as the desktop app icon asset');
assert.ok(icon.size > 700_000, 'the padded macOS-safe-area PNG icon (PR #75) must be present as the desktop app icon asset');
assert.equal(iconBuffer.toString('ascii', 1, 4), 'PNG', 'desktop app icon must remain a PNG asset');
assert.equal(iconBuffer.readUInt32BE(16), 1254, 'desktop app icon width must match the supplied edge-filled icon');
assert.equal(iconBuffer.readUInt32BE(20), 1254, 'desktop app icon height must match the supplied edge-filled icon');
assert.equal(iconBuffer.readUInt32BE(16), 1024, 'desktop app icon width must match the supplied 1024² padded icon (PR #75)');
assert.equal(iconBuffer.readUInt32BE(20), 1024, 'desktop app icon height must match the supplied 1024² padded icon (PR #75)');
assert.equal(iconBuffer[25], 6, 'desktop app icon must be RGBA so the rounded icon corners stay transparent');
assert.match(tokens, /--background:\s*oklch\(1\.000 0 0\);/);
assert.match(tokens, /--surface-canvas:\s*oklch\(0\.935 0 0\);/);
Expand Down
7 changes: 0 additions & 7 deletions apps/desktop/src/renderer/maka-tokens.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -763,7 +763,6 @@
padding: 6px 10px;
border-radius: var(--radius-button);
color: var(--foreground-80);
cursor: pointer;
font-size: 14px;
line-height: 1.4;
user-select: none;
Expand All@@ -790,7 +789,6 @@
padding: 4px 8px;
border-radius: var(--radius-button);
color: var(--foreground-60);
cursor: pointer;
font-size: 13px;
}
.maka-sidebar-button:hover { background: var(--hover); color: var(--foreground); }
Expand DownExpand Up@@ -948,7 +946,6 @@
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
font-weight: 600;
color: var(--accent);
letter-spacing: 0.02em;
Expand DownExpand Up@@ -1158,7 +1155,6 @@
border-radius: 7px;
background: transparent;
color: var(--foreground-50);
cursor: pointer;
transition: background 120ms ease, color 120ms ease, box-shadow 120ms ease;
}
.maka-code-block-copy:hover {
Expand DownExpand Up@@ -1315,7 +1311,6 @@
border-radius: 7px;
background: var(--background);
color: var(--foreground-60);
cursor: pointer;
opacity: 0;
/* PR-CHAT-COPY-BUTTON-POLISH-0 (WAWQAQ 10min loop): the copy
button used to fade in on hover but never moved — felt like
Expand DownExpand Up@@ -1424,7 +1419,6 @@
.maka-tool { padding: 0; }
.maka-tool > summary {
list-style: none;
cursor: pointer;
padding: 8px 12px;
}
.maka-tool > summary::-webkit-details-marker { display: none; }
Expand DownExpand Up@@ -1670,7 +1664,6 @@
font-size: 13px;
font-weight: 500;
line-height: 1.2;
cursor: pointer;
transition: background 120ms ease, border-color 120ms ease, color 120ms ease, transform 120ms ease, box-shadow 120ms ease;
}
.maka-button:hover { background: var(--hover); }
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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
/**
* Static-analysis contract for the native cursor convention.
*
* Native macOS / Windows reserve the pointing-hand cursor (`cursor: pointer`)
* for hyperlinks; every other control uses the default arrow. Only the
* link-styled in-app nav button (`.maka-markdown-link-internal`) may carry it.
* The runtime look-and-feel (which element shows which cursor) is still
* verified in a real window — this is the source bound.
*/

import { strict as assert } from 'node:assert';
import { readFile } from 'node:fs/promises';
import { describe, it } from 'node:test';
import { join } from 'node:path';

const STYLES_PATH = join(process.cwd(), 'src', 'renderer', 'styles.css');
const TOKENS_PATH = join(process.cwd(), 'src', 'renderer', 'maka-tokens.css');

/** Only the link-styled in-app nav button may carry the hand cursor. */
const CURSOR_POINTER_ALLOWLIST = ['.maka-markdown-link-internal'];

/**
* Selectors of every rule that declares `cursor: pointer`, sorted. Comments are
* stripped first; each hit walks back to the `{` that opens its rule and takes
* the selector after the previous block boundary. Depth is ignored, so a
* `cursor: pointer` hidden inside an at-rule (e.g. `@media`) is still caught.
*/
function selectorsWithHandCursor(css: string): string[] {
const stripped = css.replace(/\/\*[\s\S]*?\*\//g, '');
const selectors: string[] = [];
const re = /cursor:\s*pointer/g;
for (let m = re.exec(stripped); m; m = re.exec(stripped)) {
const open = stripped.lastIndexOf('{', m.index);
selectors.push(stripped.slice(0, open).split(/[{}]/).pop()?.trim() ?? '');
}
return selectors.sort();
}

describe('native cursor convention contract', () => {
it('styles.css: cursor:pointer lives only on the link-styled nav button', async () => {
const css = await readFile(STYLES_PATH, 'utf8');
assert.deepEqual(
selectorsWithHandCursor(css),
[...CURSOR_POINTER_ALLOWLIST].sort(),
'Only `.maka-markdown-link-internal` may carry `cursor: pointer` — it presents as a link, and native macOS reserves the hand for links while every other control uses the default arrow. Drop the declaration, or reuse the link class if the element genuinely is the in-app link button.',
);
});

it('maka-tokens.css: defines no cursor:pointer', async () => {
const css = await readFile(TOKENS_PATH, 'utf8');
assert.deepEqual(
selectorsWithHandCursor(css),
[],
'Design tokens must not set `cursor: pointer`; the hand cursor belongs only on the link-styled nav button in styles.css.',
);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -478,7 +478,13 @@ describe('localized main shell contract', () => {
assert.ok(workspaceTopActions, '.maka-workspace-top-actions rule must exist');
assert.ok(workspaceFeedbackAction, '.maka-workspace-feedback-action rule must exist');
assert.match(workspaceTopActions, /position:\s*absolute/);
assert.match(workspaceTopActions, /top:\s*11px/);
// PR-TITLEBAR-ROW-BASELINE: the right-side workspace top-actions
// share the single titlebar baseline with the two left strips —
// anchored on var(--maka-titlebar-control-safe-top), never a
// hardcoded vertical offset. We assert the baseline reference, not
// the per-container correction constant (geometry, free to tune):
// the invariant is that all three clusters key off the one baseline.
assert.match(workspaceTopActions, /top:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\)/);
assert.match(workspaceTopActions, /right:\s*24px/);
assert.match(workspaceTopActions, /gap:\s*6px/);
assert.match(workspaceFeedbackAction, /font-size:\s*11px/);
Expand DownExpand Up@@ -528,7 +534,15 @@ describe('localized main shell contract', () => {
assert.ok(collapsedTopbar, '.maka-collapsed-drag-strip rule must exist');
assert.match(collapsedTopbar, /min-height:\s*38px/);
assert.match(styles, /--maka-titlebar-control-safe-left:\s*94px/);
assert.match(collapsedTopbar, /padding:\s*8px 12px 0 var\(--maka-titlebar-control-safe-left\)/);
// PR-TITLEBAR-ROW-BASELINE: the macOS window has ONE physical
// titlebar row (traffic-light center). All three top icon clusters
// — sidebar header strip, collapsed strip, workspace top-actions —
// center their 24px icons on the single --maka-titlebar-control-safe-top
// baseline so the row can't jump when the sidebar collapses/expands.
// Each cluster applies its own small per-container correction; no
// cluster may reintroduce an independent vertical baseline.
assert.match(styles, /--maka-titlebar-control-safe-top:\s*20px/);
assert.match(collapsedTopbar, /padding:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\) 12px 0 var\(--maka-titlebar-control-safe-left\)/);
assert.match(collapsedTopbar, /-webkit-app-region:\s*drag/);
const collapsedTopbarButton = extractCssRule(styles, '.maka-collapsed-topbar-button');
assert.ok(collapsedTopbarButton, '.maka-collapsed-topbar-button rule must exist');
Expand All@@ -538,6 +552,10 @@ describe('localized main shell contract', () => {
assert.match(sidebarTopBar, /justify-content:\s*space-between/);
assert.match(sidebarTopBar, /box-sizing:\s*border-box/);
assert.match(sidebarTopBar, /padding-left:\s*calc\(var\(--maka-titlebar-control-safe-left\) - 10px\)/);
// same shared vertical baseline as the collapsed strip + workspace
// top-actions — references the one var(--maka-titlebar-control-safe-top),
// with its own per-container correction constant (not asserted).
assert.match(sidebarTopBar, /padding-top:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\)/);
assert.match(styles, /(?:^|\n)\.maka-nav-icon\s*\{[\s\S]*?width:\s*18px[\s\S]*?height:\s*18px/);
assert.match(styles, /\.maka-sidebar-modules\b/);
assert.doesNotMatch(styles, /\.maka-sidebar-module-hint\b/);
Expand All@@ -561,10 +579,10 @@ describe('localized main shell contract', () => {
const icon = await stat(iconPath);
const iconBuffer = await readFile(iconPath);

assert.ok(icon.size > 1_400_000, 'the edge-filled user-provided PNG icon must be present as the desktop app icon asset');
assert.ok(icon.size > 700_000, 'the padded macOS-safe-area PNG icon (PR #75) must be present as the desktop app icon asset');
assert.equal(iconBuffer.toString('ascii', 1, 4), 'PNG', 'desktop app icon must remain a PNG asset');
assert.equal(iconBuffer.readUInt32BE(16), 1254, 'desktop app icon width must match the supplied edge-filled icon');
assert.equal(iconBuffer.readUInt32BE(20), 1254, 'desktop app icon height must match the supplied edge-filled icon');
assert.equal(iconBuffer.readUInt32BE(16), 1024, 'desktop app icon width must match the supplied 1024² padded icon (PR #75)');
assert.equal(iconBuffer.readUInt32BE(20), 1024, 'desktop app icon height must match the supplied 1024² padded icon (PR #75)');
assert.equal(iconBuffer[25], 6, 'desktop app icon must be RGBA so the rounded icon corners stay transparent');
assert.match(tokens, /--background:\s*oklch\(1\.000 0 0\);/);
assert.match(tokens, /--surface-canvas:\s*oklch\(0\.935 0 0\);/);
Expand Down
7 changes: 0 additions & 7 deletions apps/desktop/src/renderer/maka-tokens.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -763,7 +763,6 @@
padding: 6px 10px;
border-radius: var(--radius-button);
color: var(--foreground-80);
cursor: pointer;
font-size: 14px;
line-height: 1.4;
user-select: none;
Expand All@@ -790,7 +789,6 @@
padding: 4px 8px;
border-radius: var(--radius-button);
color: var(--foreground-60);
cursor: pointer;
font-size: 13px;
}
.maka-sidebar-button:hover { background: var(--hover); color: var(--foreground); }
Expand DownExpand Up@@ -948,7 +946,6 @@
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
font-weight: 600;
color: var(--accent);
letter-spacing: 0.02em;
Expand DownExpand Up@@ -1158,7 +1155,6 @@
border-radius: 7px;
background: transparent;
color: var(--foreground-50);
cursor: pointer;
transition: background 120ms ease, color 120ms ease, box-shadow 120ms ease;
}
.maka-code-block-copy:hover {
Expand DownExpand Up@@ -1315,7 +1311,6 @@
border-radius: 7px;
background: var(--background);
color: var(--foreground-60);
cursor: pointer;
opacity: 0;
/* PR-CHAT-COPY-BUTTON-POLISH-0 (WAWQAQ 10min loop): the copy
button used to fade in on hover but never moved — felt like
Expand DownExpand Up@@ -1424,7 +1419,6 @@
.maka-tool { padding: 0; }
.maka-tool > summary {
list-style: none;
cursor: pointer;
padding: 8px 12px;
}
.maka-tool > summary::-webkit-details-marker { display: none; }
Expand DownExpand Up@@ -1670,7 +1664,6 @@
font-size: 13px;
font-weight: 500;
line-height: 1.2;
cursor: pointer;
transition: background 120ms ease, border-color 120ms ease, color 120ms ease, transform 120ms ease, box-shadow 120ms ease;
}
.maka-button:hover { background: var(--hover); }
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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
/**
* Static-analysis contract for the native cursor convention.
*
* Native macOS / Windows reserve the pointing-hand cursor (`cursor: pointer`)
* for hyperlinks; every other control uses the default arrow. Only the
* link-styled in-app nav button (`.maka-markdown-link-internal`) may carry it.
* The runtime look-and-feel (which element shows which cursor) is still
* verified in a real window — this is the source bound.
*/

import { strict as assert } from 'node:assert';
import { readFile } from 'node:fs/promises';
import { describe, it } from 'node:test';
import { join } from 'node:path';

const STYLES_PATH = join(process.cwd(), 'src', 'renderer', 'styles.css');
const TOKENS_PATH = join(process.cwd(), 'src', 'renderer', 'maka-tokens.css');

/** Only the link-styled in-app nav button may carry the hand cursor. */
const CURSOR_POINTER_ALLOWLIST = ['.maka-markdown-link-internal'];

/**
* Selectors of every rule that declares `cursor: pointer`, sorted. Comments are
* stripped first; each hit walks back to the `{` that opens its rule and takes
* the selector after the previous block boundary. Depth is ignored, so a
* `cursor: pointer` hidden inside an at-rule (e.g. `@media`) is still caught.
*/
function selectorsWithHandCursor(css: string): string[] {
const stripped = css.replace(/\/\*[\s\S]*?\*\//g, '');
const selectors: string[] = [];
const re = /cursor:\s*pointer/g;
for (let m = re.exec(stripped); m; m = re.exec(stripped)) {
const open = stripped.lastIndexOf('{', m.index);
selectors.push(stripped.slice(0, open).split(/[{}]/).pop()?.trim() ?? '');
}
return selectors.sort();
}

describe('native cursor convention contract', () => {
it('styles.css: cursor:pointer lives only on the link-styled nav button', async () => {
const css = await readFile(STYLES_PATH, 'utf8');
assert.deepEqual(
selectorsWithHandCursor(css),
[...CURSOR_POINTER_ALLOWLIST].sort(),
'Only `.maka-markdown-link-internal` may carry `cursor: pointer` — it presents as a link, and native macOS reserves the hand for links while every other control uses the default arrow. Drop the declaration, or reuse the link class if the element genuinely is the in-app link button.',
);
});

it('maka-tokens.css: defines no cursor:pointer', async () => {
const css = await readFile(TOKENS_PATH, 'utf8');
assert.deepEqual(
selectorsWithHandCursor(css),
[],
'Design tokens must not set `cursor: pointer`; the hand cursor belongs only on the link-styled nav button in styles.css.',
);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -478,7 +478,13 @@ describe('localized main shell contract', () => {
assert.ok(workspaceTopActions, '.maka-workspace-top-actions rule must exist');
assert.ok(workspaceFeedbackAction, '.maka-workspace-feedback-action rule must exist');
assert.match(workspaceTopActions, /position:\s*absolute/);
assert.match(workspaceTopActions, /top:\s*11px/);
// PR-TITLEBAR-ROW-BASELINE: the right-side workspace top-actions
// share the single titlebar baseline with the two left strips —
// anchored on var(--maka-titlebar-control-safe-top), never a
// hardcoded vertical offset. We assert the baseline reference, not
// the per-container correction constant (geometry, free to tune):
// the invariant is that all three clusters key off the one baseline.
assert.match(workspaceTopActions, /top:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\)/);
assert.match(workspaceTopActions, /right:\s*24px/);
assert.match(workspaceTopActions, /gap:\s*6px/);
assert.match(workspaceFeedbackAction, /font-size:\s*11px/);
Expand DownExpand Up@@ -528,7 +534,15 @@ describe('localized main shell contract', () => {
assert.ok(collapsedTopbar, '.maka-collapsed-drag-strip rule must exist');
assert.match(collapsedTopbar, /min-height:\s*38px/);
assert.match(styles, /--maka-titlebar-control-safe-left:\s*94px/);
assert.match(collapsedTopbar, /padding:\s*8px 12px 0 var\(--maka-titlebar-control-safe-left\)/);
// PR-TITLEBAR-ROW-BASELINE: the macOS window has ONE physical
// titlebar row (traffic-light center). All three top icon clusters
// — sidebar header strip, collapsed strip, workspace top-actions —
// center their 24px icons on the single --maka-titlebar-control-safe-top
// baseline so the row can't jump when the sidebar collapses/expands.
// Each cluster applies its own small per-container correction; no
// cluster may reintroduce an independent vertical baseline.
assert.match(styles, /--maka-titlebar-control-safe-top:\s*20px/);
assert.match(collapsedTopbar, /padding:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\) 12px 0 var\(--maka-titlebar-control-safe-left\)/);
assert.match(collapsedTopbar, /-webkit-app-region:\s*drag/);
const collapsedTopbarButton = extractCssRule(styles, '.maka-collapsed-topbar-button');
assert.ok(collapsedTopbarButton, '.maka-collapsed-topbar-button rule must exist');
Expand All@@ -538,6 +552,10 @@ describe('localized main shell contract', () => {
assert.match(sidebarTopBar, /justify-content:\s*space-between/);
assert.match(sidebarTopBar, /box-sizing:\s*border-box/);
assert.match(sidebarTopBar, /padding-left:\s*calc\(var\(--maka-titlebar-control-safe-left\) - 10px\)/);
// same shared vertical baseline as the collapsed strip + workspace
// top-actions — references the one var(--maka-titlebar-control-safe-top),
// with its own per-container correction constant (not asserted).
assert.match(sidebarTopBar, /padding-top:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\)/);
assert.match(styles, /(?:^|\n)\.maka-nav-icon\s*\{[\s\S]*?width:\s*18px[\s\S]*?height:\s*18px/);
assert.match(styles, /\.maka-sidebar-modules\b/);
assert.doesNotMatch(styles, /\.maka-sidebar-module-hint\b/);
Expand All@@ -561,10 +579,10 @@ describe('localized main shell contract', () => {
const icon = await stat(iconPath);
const iconBuffer = await readFile(iconPath);

assert.ok(icon.size > 1_400_000, 'the edge-filled user-provided PNG icon must be present as the desktop app icon asset');
assert.ok(icon.size > 700_000, 'the padded macOS-safe-area PNG icon (PR #75) must be present as the desktop app icon asset');
assert.equal(iconBuffer.toString('ascii', 1, 4), 'PNG', 'desktop app icon must remain a PNG asset');
assert.equal(iconBuffer.readUInt32BE(16), 1254, 'desktop app icon width must match the supplied edge-filled icon');
assert.equal(iconBuffer.readUInt32BE(20), 1254, 'desktop app icon height must match the supplied edge-filled icon');
assert.equal(iconBuffer.readUInt32BE(16), 1024, 'desktop app icon width must match the supplied 1024² padded icon (PR #75)');
assert.equal(iconBuffer.readUInt32BE(20), 1024, 'desktop app icon height must match the supplied 1024² padded icon (PR #75)');
assert.equal(iconBuffer[25], 6, 'desktop app icon must be RGBA so the rounded icon corners stay transparent');
assert.match(tokens, /--background:\s*oklch\(1\.000 0 0\);/);
assert.match(tokens, /--surface-canvas:\s*oklch\(0\.935 0 0\);/);
Expand Down
7 changes: 0 additions & 7 deletions apps/desktop/src/renderer/maka-tokens.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -763,7 +763,6 @@
padding: 6px 10px;
border-radius: var(--radius-button);
color: var(--foreground-80);
cursor: pointer;
font-size: 14px;
line-height: 1.4;
user-select: none;
Expand All@@ -790,7 +789,6 @@
padding: 4px 8px;
border-radius: var(--radius-button);
color: var(--foreground-60);
cursor: pointer;
font-size: 13px;
}
.maka-sidebar-button:hover { background: var(--hover); color: var(--foreground); }
Expand DownExpand Up@@ -948,7 +946,6 @@
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
font-weight: 600;
color: var(--accent);
letter-spacing: 0.02em;
Expand DownExpand Up@@ -1158,7 +1155,6 @@
border-radius: 7px;
background: transparent;
color: var(--foreground-50);
cursor: pointer;
transition: background 120ms ease, color 120ms ease, box-shadow 120ms ease;
}
.maka-code-block-copy:hover {
Expand DownExpand Up@@ -1315,7 +1311,6 @@
border-radius: 7px;
background: var(--background);
color: var(--foreground-60);
cursor: pointer;
opacity: 0;
/* PR-CHAT-COPY-BUTTON-POLISH-0 (WAWQAQ 10min loop): the copy
button used to fade in on hover but never moved — felt like
Expand DownExpand Up@@ -1424,7 +1419,6 @@
.maka-tool { padding: 0; }
.maka-tool > summary {
list-style: none;
cursor: pointer;
padding: 8px 12px;
}
.maka-tool > summary::-webkit-details-marker { display: none; }
Expand DownExpand Up@@ -1670,7 +1664,6 @@
font-size: 13px;
font-weight: 500;
line-height: 1.2;
cursor: pointer;
transition: background 120ms ease, border-color 120ms ease, color 120ms ease, transform 120ms ease, box-shadow 120ms ease;
}
.maka-button:hover { background: var(--hover); }
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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
/**
* Static-analysis contract for the native cursor convention.
*
* Native macOS / Windows reserve the pointing-hand cursor (`cursor: pointer`)
* for hyperlinks; every other control uses the default arrow. Only the
* link-styled in-app nav button (`.maka-markdown-link-internal`) may carry it.
* The runtime look-and-feel (which element shows which cursor) is still
* verified in a real window — this is the source bound.
*/

import { strict as assert } from 'node:assert';
import { readFile } from 'node:fs/promises';
import { describe, it } from 'node:test';
import { join } from 'node:path';

const STYLES_PATH = join(process.cwd(), 'src', 'renderer', 'styles.css');
const TOKENS_PATH = join(process.cwd(), 'src', 'renderer', 'maka-tokens.css');

/** Only the link-styled in-app nav button may carry the hand cursor. */
const CURSOR_POINTER_ALLOWLIST = ['.maka-markdown-link-internal'];

/**
* Selectors of every rule that declares `cursor: pointer`, sorted. Comments are
* stripped first; each hit walks back to the `{` that opens its rule and takes
* the selector after the previous block boundary. Depth is ignored, so a
* `cursor: pointer` hidden inside an at-rule (e.g. `@media`) is still caught.
*/
function selectorsWithHandCursor(css: string): string[] {
const stripped = css.replace(/\/\*[\s\S]*?\*\//g, '');
const selectors: string[] = [];
const re = /cursor:\s*pointer/g;
for (let m = re.exec(stripped); m; m = re.exec(stripped)) {
const open = stripped.lastIndexOf('{', m.index);
selectors.push(stripped.slice(0, open).split(/[{}]/).pop()?.trim() ?? '');
}
return selectors.sort();
}

describe('native cursor convention contract', () => {
it('styles.css: cursor:pointer lives only on the link-styled nav button', async () => {
const css = await readFile(STYLES_PATH, 'utf8');
assert.deepEqual(
selectorsWithHandCursor(css),
[...CURSOR_POINTER_ALLOWLIST].sort(),
'Only `.maka-markdown-link-internal` may carry `cursor: pointer` — it presents as a link, and native macOS reserves the hand for links while every other control uses the default arrow. Drop the declaration, or reuse the link class if the element genuinely is the in-app link button.',
);
});

it('maka-tokens.css: defines no cursor:pointer', async () => {
const css = await readFile(TOKENS_PATH, 'utf8');
assert.deepEqual(
selectorsWithHandCursor(css),
[],
'Design tokens must not set `cursor: pointer`; the hand cursor belongs only on the link-styled nav button in styles.css.',
);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -478,7 +478,13 @@ describe('localized main shell contract', () => {
assert.ok(workspaceTopActions, '.maka-workspace-top-actions rule must exist');
assert.ok(workspaceFeedbackAction, '.maka-workspace-feedback-action rule must exist');
assert.match(workspaceTopActions, /position:\s*absolute/);
assert.match(workspaceTopActions, /top:\s*11px/);
// PR-TITLEBAR-ROW-BASELINE: the right-side workspace top-actions
// share the single titlebar baseline with the two left strips —
// anchored on var(--maka-titlebar-control-safe-top), never a
// hardcoded vertical offset. We assert the baseline reference, not
// the per-container correction constant (geometry, free to tune):
// the invariant is that all three clusters key off the one baseline.
assert.match(workspaceTopActions, /top:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\)/);
assert.match(workspaceTopActions, /right:\s*24px/);
assert.match(workspaceTopActions, /gap:\s*6px/);
assert.match(workspaceFeedbackAction, /font-size:\s*11px/);
Expand DownExpand Up@@ -528,7 +534,15 @@ describe('localized main shell contract', () => {
assert.ok(collapsedTopbar, '.maka-collapsed-drag-strip rule must exist');
assert.match(collapsedTopbar, /min-height:\s*38px/);
assert.match(styles, /--maka-titlebar-control-safe-left:\s*94px/);
assert.match(collapsedTopbar, /padding:\s*8px 12px 0 var\(--maka-titlebar-control-safe-left\)/);
// PR-TITLEBAR-ROW-BASELINE: the macOS window has ONE physical
// titlebar row (traffic-light center). All three top icon clusters
// — sidebar header strip, collapsed strip, workspace top-actions —
// center their 24px icons on the single --maka-titlebar-control-safe-top
// baseline so the row can't jump when the sidebar collapses/expands.
// Each cluster applies its own small per-container correction; no
// cluster may reintroduce an independent vertical baseline.
assert.match(styles, /--maka-titlebar-control-safe-top:\s*20px/);
assert.match(collapsedTopbar, /padding:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\) 12px 0 var\(--maka-titlebar-control-safe-left\)/);
assert.match(collapsedTopbar, /-webkit-app-region:\s*drag/);
const collapsedTopbarButton = extractCssRule(styles, '.maka-collapsed-topbar-button');
assert.ok(collapsedTopbarButton, '.maka-collapsed-topbar-button rule must exist');
Expand All@@ -538,6 +552,10 @@ describe('localized main shell contract', () => {
assert.match(sidebarTopBar, /justify-content:\s*space-between/);
assert.match(sidebarTopBar, /box-sizing:\s*border-box/);
assert.match(sidebarTopBar, /padding-left:\s*calc\(var\(--maka-titlebar-control-safe-left\) - 10px\)/);
// same shared vertical baseline as the collapsed strip + workspace
// top-actions — references the one var(--maka-titlebar-control-safe-top),
// with its own per-container correction constant (not asserted).
assert.match(sidebarTopBar, /padding-top:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\)/);
assert.match(styles, /(?:^|\n)\.maka-nav-icon\s*\{[\s\S]*?width:\s*18px[\s\S]*?height:\s*18px/);
assert.match(styles, /\.maka-sidebar-modules\b/);
assert.doesNotMatch(styles, /\.maka-sidebar-module-hint\b/);
Expand All@@ -561,10 +579,10 @@ describe('localized main shell contract', () => {
const icon = await stat(iconPath);
const iconBuffer = await readFile(iconPath);

assert.ok(icon.size > 1_400_000, 'the edge-filled user-provided PNG icon must be present as the desktop app icon asset');
assert.ok(icon.size > 700_000, 'the padded macOS-safe-area PNG icon (PR #75) must be present as the desktop app icon asset');
assert.equal(iconBuffer.toString('ascii', 1, 4), 'PNG', 'desktop app icon must remain a PNG asset');
assert.equal(iconBuffer.readUInt32BE(16), 1254, 'desktop app icon width must match the supplied edge-filled icon');
assert.equal(iconBuffer.readUInt32BE(20), 1254, 'desktop app icon height must match the supplied edge-filled icon');
assert.equal(iconBuffer.readUInt32BE(16), 1024, 'desktop app icon width must match the supplied 1024² padded icon (PR #75)');
assert.equal(iconBuffer.readUInt32BE(20), 1024, 'desktop app icon height must match the supplied 1024² padded icon (PR #75)');
assert.equal(iconBuffer[25], 6, 'desktop app icon must be RGBA so the rounded icon corners stay transparent');
assert.match(tokens, /--background:\s*oklch\(1\.000 0 0\);/);
assert.match(tokens, /--surface-canvas:\s*oklch\(0\.935 0 0\);/);
Expand Down
7 changes: 0 additions & 7 deletions apps/desktop/src/renderer/maka-tokens.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -763,7 +763,6 @@
padding: 6px 10px;
border-radius: var(--radius-button);
color: var(--foreground-80);
cursor: pointer;
font-size: 14px;
line-height: 1.4;
user-select: none;
Expand All@@ -790,7 +789,6 @@
padding: 4px 8px;
border-radius: var(--radius-button);
color: var(--foreground-60);
cursor: pointer;
font-size: 13px;
}
.maka-sidebar-button:hover { background: var(--hover); color: var(--foreground); }
Expand DownExpand Up@@ -948,7 +946,6 @@
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
font-weight: 600;
color: var(--accent);
letter-spacing: 0.02em;
Expand DownExpand Up@@ -1158,7 +1155,6 @@
border-radius: 7px;
background: transparent;
color: var(--foreground-50);
cursor: pointer;
transition: background 120ms ease, color 120ms ease, box-shadow 120ms ease;
}
.maka-code-block-copy:hover {
Expand DownExpand Up@@ -1315,7 +1311,6 @@
border-radius: 7px;
background: var(--background);
color: var(--foreground-60);
cursor: pointer;
opacity: 0;
/* PR-CHAT-COPY-BUTTON-POLISH-0 (WAWQAQ 10min loop): the copy
button used to fade in on hover but never moved — felt like
Expand DownExpand Up@@ -1424,7 +1419,6 @@
.maka-tool { padding: 0; }
.maka-tool > summary {
list-style: none;
cursor: pointer;
padding: 8px 12px;
}
.maka-tool > summary::-webkit-details-marker { display: none; }
Expand DownExpand Up@@ -1670,7 +1664,6 @@
font-size: 13px;
font-weight: 500;
line-height: 1.2;
cursor: pointer;
transition: background 120ms ease, border-color 120ms ease, color 120ms ease, transform 120ms ease, box-shadow 120ms ease;
}
.maka-button:hover { background: var(--hover); }
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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
/**
* Static-analysis contract for the native cursor convention.
*
* Native macOS / Windows reserve the pointing-hand cursor (`cursor: pointer`)
* for hyperlinks; every other control uses the default arrow. Only the
* link-styled in-app nav button (`.maka-markdown-link-internal`) may carry it.
* The runtime look-and-feel (which element shows which cursor) is still
* verified in a real window — this is the source bound.
*/

import { strict as assert } from 'node:assert';
import { readFile } from 'node:fs/promises';
import { describe, it } from 'node:test';
import { join } from 'node:path';

const STYLES_PATH = join(process.cwd(), 'src', 'renderer', 'styles.css');
const TOKENS_PATH = join(process.cwd(), 'src', 'renderer', 'maka-tokens.css');

/** Only the link-styled in-app nav button may carry the hand cursor. */
const CURSOR_POINTER_ALLOWLIST = ['.maka-markdown-link-internal'];

/**
* Selectors of every rule that declares `cursor: pointer`, sorted. Comments are
* stripped first; each hit walks back to the `{` that opens its rule and takes
* the selector after the previous block boundary. Depth is ignored, so a
* `cursor: pointer` hidden inside an at-rule (e.g. `@media`) is still caught.
*/
function selectorsWithHandCursor(css: string): string[] {
const stripped = css.replace(/\/\*[\s\S]*?\*\//g, '');
const selectors: string[] = [];
const re = /cursor:\s*pointer/g;
for (let m = re.exec(stripped); m; m = re.exec(stripped)) {
const open = stripped.lastIndexOf('{', m.index);
selectors.push(stripped.slice(0, open).split(/[{}]/).pop()?.trim() ?? '');
}
return selectors.sort();
}

describe('native cursor convention contract', () => {
it('styles.css: cursor:pointer lives only on the link-styled nav button', async () => {
const css = await readFile(STYLES_PATH, 'utf8');
assert.deepEqual(
selectorsWithHandCursor(css),
[...CURSOR_POINTER_ALLOWLIST].sort(),
'Only `.maka-markdown-link-internal` may carry `cursor: pointer` — it presents as a link, and native macOS reserves the hand for links while every other control uses the default arrow. Drop the declaration, or reuse the link class if the element genuinely is the in-app link button.',
);
});

it('maka-tokens.css: defines no cursor:pointer', async () => {
const css = await readFile(TOKENS_PATH, 'utf8');
assert.deepEqual(
selectorsWithHandCursor(css),
[],
'Design tokens must not set `cursor: pointer`; the hand cursor belongs only on the link-styled nav button in styles.css.',
);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -478,7 +478,13 @@ describe('localized main shell contract', () => {
assert.ok(workspaceTopActions, '.maka-workspace-top-actions rule must exist');
assert.ok(workspaceFeedbackAction, '.maka-workspace-feedback-action rule must exist');
assert.match(workspaceTopActions, /position:\s*absolute/);
assert.match(workspaceTopActions, /top:\s*11px/);
// PR-TITLEBAR-ROW-BASELINE: the right-side workspace top-actions
// share the single titlebar baseline with the two left strips —
// anchored on var(--maka-titlebar-control-safe-top), never a
// hardcoded vertical offset. We assert the baseline reference, not
// the per-container correction constant (geometry, free to tune):
// the invariant is that all three clusters key off the one baseline.
assert.match(workspaceTopActions, /top:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\)/);
assert.match(workspaceTopActions, /right:\s*24px/);
assert.match(workspaceTopActions, /gap:\s*6px/);
assert.match(workspaceFeedbackAction, /font-size:\s*11px/);
Expand DownExpand Up@@ -528,7 +534,15 @@ describe('localized main shell contract', () => {
assert.ok(collapsedTopbar, '.maka-collapsed-drag-strip rule must exist');
assert.match(collapsedTopbar, /min-height:\s*38px/);
assert.match(styles, /--maka-titlebar-control-safe-left:\s*94px/);
assert.match(collapsedTopbar, /padding:\s*8px 12px 0 var\(--maka-titlebar-control-safe-left\)/);
// PR-TITLEBAR-ROW-BASELINE: the macOS window has ONE physical
// titlebar row (traffic-light center). All three top icon clusters
// — sidebar header strip, collapsed strip, workspace top-actions —
// center their 24px icons on the single --maka-titlebar-control-safe-top
// baseline so the row can't jump when the sidebar collapses/expands.
// Each cluster applies its own small per-container correction; no
// cluster may reintroduce an independent vertical baseline.
assert.match(styles, /--maka-titlebar-control-safe-top:\s*20px/);
assert.match(collapsedTopbar, /padding:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\) 12px 0 var\(--maka-titlebar-control-safe-left\)/);
assert.match(collapsedTopbar, /-webkit-app-region:\s*drag/);
const collapsedTopbarButton = extractCssRule(styles, '.maka-collapsed-topbar-button');
assert.ok(collapsedTopbarButton, '.maka-collapsed-topbar-button rule must exist');
Expand All@@ -538,6 +552,10 @@ describe('localized main shell contract', () => {
assert.match(sidebarTopBar, /justify-content:\s*space-between/);
assert.match(sidebarTopBar, /box-sizing:\s*border-box/);
assert.match(sidebarTopBar, /padding-left:\s*calc\(var\(--maka-titlebar-control-safe-left\) - 10px\)/);
// same shared vertical baseline as the collapsed strip + workspace
// top-actions — references the one var(--maka-titlebar-control-safe-top),
// with its own per-container correction constant (not asserted).
assert.match(sidebarTopBar, /padding-top:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\)/);
assert.match(styles, /(?:^|\n)\.maka-nav-icon\s*\{[\s\S]*?width:\s*18px[\s\S]*?height:\s*18px/);
assert.match(styles, /\.maka-sidebar-modules\b/);
assert.doesNotMatch(styles, /\.maka-sidebar-module-hint\b/);
Expand All@@ -561,10 +579,10 @@ describe('localized main shell contract', () => {
const icon = await stat(iconPath);
const iconBuffer = await readFile(iconPath);

assert.ok(icon.size > 1_400_000, 'the edge-filled user-provided PNG icon must be present as the desktop app icon asset');
assert.ok(icon.size > 700_000, 'the padded macOS-safe-area PNG icon (PR #75) must be present as the desktop app icon asset');
assert.equal(iconBuffer.toString('ascii', 1, 4), 'PNG', 'desktop app icon must remain a PNG asset');
assert.equal(iconBuffer.readUInt32BE(16), 1254, 'desktop app icon width must match the supplied edge-filled icon');
assert.equal(iconBuffer.readUInt32BE(20), 1254, 'desktop app icon height must match the supplied edge-filled icon');
assert.equal(iconBuffer.readUInt32BE(16), 1024, 'desktop app icon width must match the supplied 1024² padded icon (PR #75)');
assert.equal(iconBuffer.readUInt32BE(20), 1024, 'desktop app icon height must match the supplied 1024² padded icon (PR #75)');
assert.equal(iconBuffer[25], 6, 'desktop app icon must be RGBA so the rounded icon corners stay transparent');
assert.match(tokens, /--background:\s*oklch\(1\.000 0 0\);/);
assert.match(tokens, /--surface-canvas:\s*oklch\(0\.935 0 0\);/);
Expand Down
7 changes: 0 additions & 7 deletions apps/desktop/src/renderer/maka-tokens.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -763,7 +763,6 @@
padding: 6px 10px;
border-radius: var(--radius-button);
color: var(--foreground-80);
cursor: pointer;
font-size: 14px;
line-height: 1.4;
user-select: none;
Expand All@@ -790,7 +789,6 @@
padding: 4px 8px;
border-radius: var(--radius-button);
color: var(--foreground-60);
cursor: pointer;
font-size: 13px;
}
.maka-sidebar-button:hover { background: var(--hover); color: var(--foreground); }
Expand DownExpand Up@@ -948,7 +946,6 @@
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
font-weight: 600;
color: var(--accent);
letter-spacing: 0.02em;
Expand DownExpand Up@@ -1158,7 +1155,6 @@
border-radius: 7px;
background: transparent;
color: var(--foreground-50);
cursor: pointer;
transition: background 120ms ease, color 120ms ease, box-shadow 120ms ease;
}
.maka-code-block-copy:hover {
Expand DownExpand Up@@ -1315,7 +1311,6 @@
border-radius: 7px;
background: var(--background);
color: var(--foreground-60);
cursor: pointer;
opacity: 0;
/* PR-CHAT-COPY-BUTTON-POLISH-0 (WAWQAQ 10min loop): the copy
button used to fade in on hover but never moved — felt like
Expand DownExpand Up@@ -1424,7 +1419,6 @@
.maka-tool { padding: 0; }
.maka-tool > summary {
list-style: none;
cursor: pointer;
padding: 8px 12px;
}
.maka-tool > summary::-webkit-details-marker { display: none; }
Expand DownExpand Up@@ -1670,7 +1664,6 @@
font-size: 13px;
font-weight: 500;
line-height: 1.2;
cursor: pointer;
transition: background 120ms ease, border-color 120ms ease, color 120ms ease, transform 120ms ease, box-shadow 120ms ease;
}
.maka-button:hover { background: var(--hover); }
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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
/**
* Static-analysis contract for the native cursor convention.
*
* Native macOS / Windows reserve the pointing-hand cursor (`cursor: pointer`)
* for hyperlinks; every other control uses the default arrow. Only the
* link-styled in-app nav button (`.maka-markdown-link-internal`) may carry it.
* The runtime look-and-feel (which element shows which cursor) is still
* verified in a real window — this is the source bound.
*/

import { strict as assert } from 'node:assert';
import { readFile } from 'node:fs/promises';
import { describe, it } from 'node:test';
import { join } from 'node:path';

const STYLES_PATH = join(process.cwd(), 'src', 'renderer', 'styles.css');
const TOKENS_PATH = join(process.cwd(), 'src', 'renderer', 'maka-tokens.css');

/** Only the link-styled in-app nav button may carry the hand cursor. */
const CURSOR_POINTER_ALLOWLIST = ['.maka-markdown-link-internal'];

/**
* Selectors of every rule that declares `cursor: pointer`, sorted. Comments are
* stripped first; each hit walks back to the `{` that opens its rule and takes
* the selector after the previous block boundary. Depth is ignored, so a
* `cursor: pointer` hidden inside an at-rule (e.g. `@media`) is still caught.
*/
function selectorsWithHandCursor(css: string): string[] {
const stripped = css.replace(/\/\*[\s\S]*?\*\//g, '');
const selectors: string[] = [];
const re = /cursor:\s*pointer/g;
for (let m = re.exec(stripped); m; m = re.exec(stripped)) {
const open = stripped.lastIndexOf('{', m.index);
selectors.push(stripped.slice(0, open).split(/[{}]/).pop()?.trim() ?? '');
}
return selectors.sort();
}

describe('native cursor convention contract', () => {
it('styles.css: cursor:pointer lives only on the link-styled nav button', async () => {
const css = await readFile(STYLES_PATH, 'utf8');
assert.deepEqual(
selectorsWithHandCursor(css),
[...CURSOR_POINTER_ALLOWLIST].sort(),
'Only `.maka-markdown-link-internal` may carry `cursor: pointer` — it presents as a link, and native macOS reserves the hand for links while every other control uses the default arrow. Drop the declaration, or reuse the link class if the element genuinely is the in-app link button.',
);
});

it('maka-tokens.css: defines no cursor:pointer', async () => {
const css = await readFile(TOKENS_PATH, 'utf8');
assert.deepEqual(
selectorsWithHandCursor(css),
[],
'Design tokens must not set `cursor: pointer`; the hand cursor belongs only on the link-styled nav button in styles.css.',
);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -478,7 +478,13 @@ describe('localized main shell contract', () => {
assert.ok(workspaceTopActions, '.maka-workspace-top-actions rule must exist');
assert.ok(workspaceFeedbackAction, '.maka-workspace-feedback-action rule must exist');
assert.match(workspaceTopActions, /position:\s*absolute/);
assert.match(workspaceTopActions, /top:\s*11px/);
// PR-TITLEBAR-ROW-BASELINE: the right-side workspace top-actions
// share the single titlebar baseline with the two left strips —
// anchored on var(--maka-titlebar-control-safe-top), never a
// hardcoded vertical offset. We assert the baseline reference, not
// the per-container correction constant (geometry, free to tune):
// the invariant is that all three clusters key off the one baseline.
assert.match(workspaceTopActions, /top:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\)/);
assert.match(workspaceTopActions, /right:\s*24px/);
assert.match(workspaceTopActions, /gap:\s*6px/);
assert.match(workspaceFeedbackAction, /font-size:\s*11px/);
Expand DownExpand Up@@ -528,7 +534,15 @@ describe('localized main shell contract', () => {
assert.ok(collapsedTopbar, '.maka-collapsed-drag-strip rule must exist');
assert.match(collapsedTopbar, /min-height:\s*38px/);
assert.match(styles, /--maka-titlebar-control-safe-left:\s*94px/);
assert.match(collapsedTopbar, /padding:\s*8px 12px 0 var\(--maka-titlebar-control-safe-left\)/);
// PR-TITLEBAR-ROW-BASELINE: the macOS window has ONE physical
// titlebar row (traffic-light center). All three top icon clusters
// — sidebar header strip, collapsed strip, workspace top-actions —
// center their 24px icons on the single --maka-titlebar-control-safe-top
// baseline so the row can't jump when the sidebar collapses/expands.
// Each cluster applies its own small per-container correction; no
// cluster may reintroduce an independent vertical baseline.
assert.match(styles, /--maka-titlebar-control-safe-top:\s*20px/);
assert.match(collapsedTopbar, /padding:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\) 12px 0 var\(--maka-titlebar-control-safe-left\)/);
assert.match(collapsedTopbar, /-webkit-app-region:\s*drag/);
const collapsedTopbarButton = extractCssRule(styles, '.maka-collapsed-topbar-button');
assert.ok(collapsedTopbarButton, '.maka-collapsed-topbar-button rule must exist');
Expand All@@ -538,6 +552,10 @@ describe('localized main shell contract', () => {
assert.match(sidebarTopBar, /justify-content:\s*space-between/);
assert.match(sidebarTopBar, /box-sizing:\s*border-box/);
assert.match(sidebarTopBar, /padding-left:\s*calc\(var\(--maka-titlebar-control-safe-left\) - 10px\)/);
// same shared vertical baseline as the collapsed strip + workspace
// top-actions — references the one var(--maka-titlebar-control-safe-top),
// with its own per-container correction constant (not asserted).
assert.match(sidebarTopBar, /padding-top:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\)/);
assert.match(styles, /(?:^|\n)\.maka-nav-icon\s*\{[\s\S]*?width:\s*18px[\s\S]*?height:\s*18px/);
assert.match(styles, /\.maka-sidebar-modules\b/);
assert.doesNotMatch(styles, /\.maka-sidebar-module-hint\b/);
Expand All@@ -561,10 +579,10 @@ describe('localized main shell contract', () => {
const icon = await stat(iconPath);
const iconBuffer = await readFile(iconPath);

assert.ok(icon.size > 1_400_000, 'the edge-filled user-provided PNG icon must be present as the desktop app icon asset');
assert.ok(icon.size > 700_000, 'the padded macOS-safe-area PNG icon (PR #75) must be present as the desktop app icon asset');
assert.equal(iconBuffer.toString('ascii', 1, 4), 'PNG', 'desktop app icon must remain a PNG asset');
assert.equal(iconBuffer.readUInt32BE(16), 1254, 'desktop app icon width must match the supplied edge-filled icon');
assert.equal(iconBuffer.readUInt32BE(20), 1254, 'desktop app icon height must match the supplied edge-filled icon');
assert.equal(iconBuffer.readUInt32BE(16), 1024, 'desktop app icon width must match the supplied 1024² padded icon (PR #75)');
assert.equal(iconBuffer.readUInt32BE(20), 1024, 'desktop app icon height must match the supplied 1024² padded icon (PR #75)');
assert.equal(iconBuffer[25], 6, 'desktop app icon must be RGBA so the rounded icon corners stay transparent');
assert.match(tokens, /--background:\s*oklch\(1\.000 0 0\);/);
assert.match(tokens, /--surface-canvas:\s*oklch\(0\.935 0 0\);/);
Expand Down
7 changes: 0 additions & 7 deletions apps/desktop/src/renderer/maka-tokens.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -763,7 +763,6 @@
padding: 6px 10px;
border-radius: var(--radius-button);
color: var(--foreground-80);
cursor: pointer;
font-size: 14px;
line-height: 1.4;
user-select: none;
Expand All@@ -790,7 +789,6 @@
padding: 4px 8px;
border-radius: var(--radius-button);
color: var(--foreground-60);
cursor: pointer;
font-size: 13px;
}
.maka-sidebar-button:hover { background: var(--hover); color: var(--foreground); }
Expand DownExpand Up@@ -948,7 +946,6 @@
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
font-weight: 600;
color: var(--accent);
letter-spacing: 0.02em;
Expand DownExpand Up@@ -1158,7 +1155,6 @@
border-radius: 7px;
background: transparent;
color: var(--foreground-50);
cursor: pointer;
transition: background 120ms ease, color 120ms ease, box-shadow 120ms ease;
}
.maka-code-block-copy:hover {
Expand DownExpand Up@@ -1315,7 +1311,6 @@
border-radius: 7px;
background: var(--background);
color: var(--foreground-60);
cursor: pointer;
opacity: 0;
/* PR-CHAT-COPY-BUTTON-POLISH-0 (WAWQAQ 10min loop): the copy
button used to fade in on hover but never moved — felt like
Expand DownExpand Up@@ -1424,7 +1419,6 @@
.maka-tool { padding: 0; }
.maka-tool > summary {
list-style: none;
cursor: pointer;
padding: 8px 12px;
}
.maka-tool > summary::-webkit-details-marker { display: none; }
Expand DownExpand Up@@ -1670,7 +1664,6 @@
font-size: 13px;
font-weight: 500;
line-height: 1.2;
cursor: pointer;
transition: background 120ms ease, border-color 120ms ease, color 120ms ease, transform 120ms ease, box-shadow 120ms ease;
}
.maka-button:hover { background: var(--hover); }
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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
/**
* Static-analysis contract for the native cursor convention.
*
* Native macOS / Windows reserve the pointing-hand cursor (`cursor: pointer`)
* for hyperlinks; every other control uses the default arrow. Only the
* link-styled in-app nav button (`.maka-markdown-link-internal`) may carry it.
* The runtime look-and-feel (which element shows which cursor) is still
* verified in a real window — this is the source bound.
*/

import { strict as assert } from 'node:assert';
import { readFile } from 'node:fs/promises';
import { describe, it } from 'node:test';
import { join } from 'node:path';

const STYLES_PATH = join(process.cwd(), 'src', 'renderer', 'styles.css');
const TOKENS_PATH = join(process.cwd(), 'src', 'renderer', 'maka-tokens.css');

/** Only the link-styled in-app nav button may carry the hand cursor. */
const CURSOR_POINTER_ALLOWLIST = ['.maka-markdown-link-internal'];

/**
* Selectors of every rule that declares `cursor: pointer`, sorted. Comments are
* stripped first; each hit walks back to the `{` that opens its rule and takes
* the selector after the previous block boundary. Depth is ignored, so a
* `cursor: pointer` hidden inside an at-rule (e.g. `@media`) is still caught.
*/
function selectorsWithHandCursor(css: string): string[] {
const stripped = css.replace(/\/\*[\s\S]*?\*\//g, '');
const selectors: string[] = [];
const re = /cursor:\s*pointer/g;
for (let m = re.exec(stripped); m; m = re.exec(stripped)) {
const open = stripped.lastIndexOf('{', m.index);
selectors.push(stripped.slice(0, open).split(/[{}]/).pop()?.trim() ?? '');
}
return selectors.sort();
}

describe('native cursor convention contract', () => {
it('styles.css: cursor:pointer lives only on the link-styled nav button', async () => {
const css = await readFile(STYLES_PATH, 'utf8');
assert.deepEqual(
selectorsWithHandCursor(css),
[...CURSOR_POINTER_ALLOWLIST].sort(),
'Only `.maka-markdown-link-internal` may carry `cursor: pointer` — it presents as a link, and native macOS reserves the hand for links while every other control uses the default arrow. Drop the declaration, or reuse the link class if the element genuinely is the in-app link button.',
);
});

it('maka-tokens.css: defines no cursor:pointer', async () => {
const css = await readFile(TOKENS_PATH, 'utf8');
assert.deepEqual(
selectorsWithHandCursor(css),
[],
'Design tokens must not set `cursor: pointer`; the hand cursor belongs only on the link-styled nav button in styles.css.',
);
});
});
Original file line numberDiff line numberDiff line change
Expand Up@@ -478,7 +478,13 @@ describe('localized main shell contract', () => {
assert.ok(workspaceTopActions, '.maka-workspace-top-actions rule must exist');
assert.ok(workspaceFeedbackAction, '.maka-workspace-feedback-action rule must exist');
assert.match(workspaceTopActions, /position:\s*absolute/);
assert.match(workspaceTopActions, /top:\s*11px/);
// PR-TITLEBAR-ROW-BASELINE: the right-side workspace top-actions
// share the single titlebar baseline with the two left strips —
// anchored on var(--maka-titlebar-control-safe-top), never a
// hardcoded vertical offset. We assert the baseline reference, not
// the per-container correction constant (geometry, free to tune):
// the invariant is that all three clusters key off the one baseline.
assert.match(workspaceTopActions, /top:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\)/);
assert.match(workspaceTopActions, /right:\s*24px/);
assert.match(workspaceTopActions, /gap:\s*6px/);
assert.match(workspaceFeedbackAction, /font-size:\s*11px/);
Expand DownExpand Up@@ -528,7 +534,15 @@ describe('localized main shell contract', () => {
assert.ok(collapsedTopbar, '.maka-collapsed-drag-strip rule must exist');
assert.match(collapsedTopbar, /min-height:\s*38px/);
assert.match(styles, /--maka-titlebar-control-safe-left:\s*94px/);
assert.match(collapsedTopbar, /padding:\s*8px 12px 0 var\(--maka-titlebar-control-safe-left\)/);
// PR-TITLEBAR-ROW-BASELINE: the macOS window has ONE physical
// titlebar row (traffic-light center). All three top icon clusters
// — sidebar header strip, collapsed strip, workspace top-actions —
// center their 24px icons on the single --maka-titlebar-control-safe-top
// baseline so the row can't jump when the sidebar collapses/expands.
// Each cluster applies its own small per-container correction; no
// cluster may reintroduce an independent vertical baseline.
assert.match(styles, /--maka-titlebar-control-safe-top:\s*20px/);
assert.match(collapsedTopbar, /padding:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\) 12px 0 var\(--maka-titlebar-control-safe-left\)/);
assert.match(collapsedTopbar, /-webkit-app-region:\s*drag/);
const collapsedTopbarButton = extractCssRule(styles, '.maka-collapsed-topbar-button');
assert.ok(collapsedTopbarButton, '.maka-collapsed-topbar-button rule must exist');
Expand All@@ -538,6 +552,10 @@ describe('localized main shell contract', () => {
assert.match(sidebarTopBar, /justify-content:\s*space-between/);
assert.match(sidebarTopBar, /box-sizing:\s*border-box/);
assert.match(sidebarTopBar, /padding-left:\s*calc\(var\(--maka-titlebar-control-safe-left\) - 10px\)/);
// same shared vertical baseline as the collapsed strip + workspace
// top-actions — references the one var(--maka-titlebar-control-safe-top),
// with its own per-container correction constant (not asserted).
assert.match(sidebarTopBar, /padding-top:\s*calc\(var\(--maka-titlebar-control-safe-top\) - \d+px\)/);
assert.match(styles, /(?:^|\n)\.maka-nav-icon\s*\{[\s\S]*?width:\s*18px[\s\S]*?height:\s*18px/);
assert.match(styles, /\.maka-sidebar-modules\b/);
assert.doesNotMatch(styles, /\.maka-sidebar-module-hint\b/);
Expand All@@ -561,10 +579,10 @@ describe('localized main shell contract', () => {
const icon = await stat(iconPath);
const iconBuffer = await readFile(iconPath);

assert.ok(icon.size > 1_400_000, 'the edge-filled user-provided PNG icon must be present as the desktop app icon asset');
assert.ok(icon.size > 700_000, 'the padded macOS-safe-area PNG icon (PR #75) must be present as the desktop app icon asset');
assert.equal(iconBuffer.toString('ascii', 1, 4), 'PNG', 'desktop app icon must remain a PNG asset');
assert.equal(iconBuffer.readUInt32BE(16), 1254, 'desktop app icon width must match the supplied edge-filled icon');
assert.equal(iconBuffer.readUInt32BE(20), 1254, 'desktop app icon height must match the supplied edge-filled icon');
assert.equal(iconBuffer.readUInt32BE(16), 1024, 'desktop app icon width must match the supplied 1024² padded icon (PR #75)');
assert.equal(iconBuffer.readUInt32BE(20), 1024, 'desktop app icon height must match the supplied 1024² padded icon (PR #75)');
assert.equal(iconBuffer[25], 6, 'desktop app icon must be RGBA so the rounded icon corners stay transparent');
assert.match(tokens, /--background:\s*oklch\(1\.000 0 0\);/);
assert.match(tokens, /--surface-canvas:\s*oklch\(0\.935 0 0\);/);
Expand Down
7 changes: 0 additions & 7 deletions apps/desktop/src/renderer/maka-tokens.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -763,7 +763,6 @@
padding: 6px 10px;
border-radius: var(--radius-button);
color: var(--foreground-80);
cursor: pointer;
font-size: 14px;
line-height: 1.4;
user-select: none;
Expand All@@ -790,7 +789,6 @@
padding: 4px 8px;
border-radius: var(--radius-button);
color: var(--foreground-60);
cursor: pointer;
font-size: 13px;
}
.maka-sidebar-button:hover { background: var(--hover); color: var(--foreground); }
Expand DownExpand Up@@ -948,7 +946,6 @@
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
font-weight: 600;
color: var(--accent);
letter-spacing: 0.02em;
Expand DownExpand Up@@ -1158,7 +1155,6 @@
border-radius: 7px;
background: transparent;
color: var(--foreground-50);
cursor: pointer;
transition: background 120ms ease, color 120ms ease, box-shadow 120ms ease;
}
.maka-code-block-copy:hover {
Expand DownExpand Up@@ -1315,7 +1311,6 @@
border-radius: 7px;
background: var(--background);
color: var(--foreground-60);
cursor: pointer;
opacity: 0;
/* PR-CHAT-COPY-BUTTON-POLISH-0 (WAWQAQ 10min loop): the copy
button used to fade in on hover but never moved — felt like
Expand DownExpand Up@@ -1424,7 +1419,6 @@
.maka-tool { padding: 0; }
.maka-tool > summary {
list-style: none;
cursor: pointer;
padding: 8px 12px;
}
.maka-tool > summary::-webkit-details-marker { display: none; }
Expand DownExpand Up@@ -1670,7 +1664,6 @@
font-size: 13px;
font-weight: 500;
line-height: 1.2;
cursor: pointer;
transition: background 120ms ease, border-color 120ms ease, color 120ms ease, transform 120ms ease, box-shadow 120ms ease;
}
.maka-button:hover { background: var(--hover); }
Expand Down
Loading