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
8 changes: 4 additions & 4 deletions apps/desktop/src/renderer/styles/desktop.css
Original file line number Diff line number Diff line change
Expand Up @@ -1713,8 +1713,8 @@ ul.actor-stack {
}

.desktop-shell .title-bar-controls .offline-mark {
width: var(--control-height);
height: var(--control-height);
width: var(--luke-control-height);
height: var(--luke-control-height);
justify-content: center;
padding: 0;
}
Expand All @@ -1727,8 +1727,8 @@ ul.actor-stack {
--sidebar-toggle-clearance: calc(
var(--title-bar-left) +
3 *
var(--control-height) +
var(--control-gap)
var(--luke-control-height) +
var(--luke-control-gap)
);
}

Expand Down
30 changes: 15 additions & 15 deletions apps/desktop/src/renderer/styles/settings.css
Original file line number Diff line number Diff line change
Expand Up @@ -636,17 +636,17 @@
.picture-choice {
display: grid;
align-items: start;
gap: var(--space-16);
gap: var(--luke-space-16);
grid-template-columns: minmax(140px, 200px) minmax(0, 1fr);
}

.picture-choice-stage {
position: relative;
overflow: hidden;
aspect-ratio: 1;
border-radius: var(--control-radius);
background: var(--hairline);
box-shadow: inset 0 0 0 1px var(--hairline-strong);
border-radius: var(--luke-control-radius);
background: var(--luke-color-border);
box-shadow: inset 0 0 0 1px var(--luke-color-border-strong);
}

.picture-choice-stage img,
Expand All @@ -664,7 +664,7 @@
right: 0;
bottom: 0;
left: 0;
padding: var(--space-16) var(--space-8) var(--space-6);
padding: var(--luke-space-16) var(--luke-space-8) var(--luke-space-6);
background: linear-gradient(transparent, rgb(0 0 0 / 65%));
color: #fff;
font-size: 13px;
Expand All @@ -677,7 +677,7 @@
margin: 0;
padding: 0;
border: 0;
gap: var(--space-12) var(--space-8);
gap: var(--luke-space-12) var(--luke-space-8);
grid-template-columns: repeat(4, minmax(0, 1fr));
}

Expand All @@ -687,11 +687,11 @@
min-width: 0;
flex-direction: column;
align-items: center;
gap: var(--space-4);
gap: var(--luke-space-4);
padding: 0;
border: 0;
background: none;
color: var(--text-secondary);
color: var(--luke-color-text-muted);
cursor: pointer;
font: inherit;
}
Expand All @@ -709,22 +709,22 @@
max-width: 88px;
aspect-ratio: 1;
border-radius: 50%;
background: var(--hairline);
box-shadow: inset 0 0 0 1px var(--hairline-strong);
background: var(--luke-color-border);
box-shadow: inset 0 0 0 1px var(--luke-color-border-strong);
transition: box-shadow var(--duration-quick) var(--motion-exit);
}

.picture-choice-face:hover .picture-choice-photo {
box-shadow: 0 0 0 2px var(--hairline-strong);
box-shadow: 0 0 0 2px var(--luke-color-border-strong);
}

.picture-choice-face:has(> :checked) .picture-choice-photo {
box-shadow: 0 0 0 2px var(--switch-on);
box-shadow: 0 0 0 2px var(--luke-color-switch-on);
}

:root[data-keyboard="true"] .picture-choice-face:has(> :focus-visible) .picture-choice-photo {
outline: var(--focus-ring-width) solid var(--focus-ring);
outline-offset: calc(2px + var(--focus-ring-offset));
outline: var(--luke-focus-ring-width) solid var(--luke-color-focus-ring);
outline-offset: calc(2px + var(--luke-focus-ring-offset));
}

.picture-choice-name {
Expand All @@ -736,7 +736,7 @@
}

.picture-choice-face:has(> :checked) .picture-choice-name {
color: var(--text-primary);
color: var(--luke-color-text);
font-weight: 600;
}

Expand Down
50 changes: 25 additions & 25 deletions apps/desktop/src/renderer/styles/tasks.css
Original file line number Diff line number Diff line change
Expand Up @@ -1839,7 +1839,7 @@
display: flex;
min-width: 0;
align-items: center;
gap: var(--space-8);
gap: var(--luke-space-8);
}

.pull-request-branch-row > .pull-request-branches {
Expand All @@ -1851,20 +1851,20 @@
display: inline-flex;
flex: none;
align-items: center;
gap: var(--space-4);
gap: var(--luke-space-4);
height: 22px;
margin-top: var(--space-2);
padding: 0 var(--space-6);
border: 1px solid var(--hairline);
margin-top: var(--luke-space-2);
padding: 0 var(--luke-space-6);
border: 1px solid var(--luke-color-border);
border-radius: 6px;
background: transparent;
color: var(--text-secondary);
color: var(--luke-color-text-muted);
font-size: 11.5px;
}

.pull-request-stack:hover {
background: var(--raised);
color: var(--text-primary);
background: var(--luke-color-fill-hover);
color: var(--luke-color-text);
}

.pull-request-stack > svg {
Expand All @@ -1873,7 +1873,7 @@
}

.pull-request-stack-count {
color: var(--text-tertiary);
color: var(--luke-color-text-subtle);
font-variant-numeric: tabular-nums;
}

Expand All @@ -1884,20 +1884,20 @@
.pull-request-labels {
display: flex;
flex-wrap: wrap;
gap: var(--space-4);
margin: var(--space-6) 0 var(--space-2);
gap: var(--luke-space-4);
margin: var(--luke-space-6) 0 var(--luke-space-2);
padding: 0 var(--row-inset);
list-style: none;
}

.pull-request-label {
max-width: 100%;
overflow: hidden;
padding: 1px var(--space-8);
border: 1px solid var(--label-edge-dark, var(--hairline));
padding: 1px var(--luke-space-8);
border: 1px solid var(--label-edge-dark, var(--luke-color-border));
border-radius: 999px;
background: var(--label-fill-dark, transparent);
color: var(--label-words-dark, var(--text-secondary));
color: var(--label-words-dark, var(--luke-color-text-muted));
font-size: 11px;
font-weight: 500;
line-height: 1.45;
Expand All @@ -1907,17 +1907,17 @@

@media (prefers-color-scheme: light) {
.pull-request-label {
border-color: var(--label-edge-light, var(--hairline));
border-color: var(--label-edge-light, var(--luke-color-border));
background: var(--label-fill-light, transparent);
color: var(--label-words-light, var(--text-secondary));
color: var(--label-words-light, var(--luke-color-text-muted));
}
}

/* The reviewers' glyph, standing for the word in the header's one line. */
.pull-request-reviewers-glyph {
width: 14px;
height: 14px;
color: var(--text-tertiary);
color: var(--luke-color-text-subtle);
}

.pull-request-page {
Expand Down Expand Up @@ -2233,29 +2233,29 @@ button.pull-request-check:hover {
so the window's own type and card draw it, inset from the code's edges
as GitHub's are; an outdated one stands in a list above the diff. */
.diff-note {
padding: var(--space-6) var(--space-12);
padding: var(--luke-space-6) var(--luke-space-12);
font-family: var(--luke-font-sans);
white-space: normal;
}

.diff-inline-thread {
--focus-ring-offset: var(--focus-ring-inset);
--luke-focus-ring-offset: var(--luke-focus-ring-inset);
max-width: 720px;
overflow: clip;
border: 1px solid var(--hairline);
border-radius: var(--control-radius);
background: var(--section-fill);
border: 1px solid var(--luke-color-border);
border-radius: var(--luke-control-radius);
background: var(--luke-color-surface);
}

.diff-outdated-threads {
display: flex;
flex: none;
flex-direction: column;
gap: var(--space-6);
gap: var(--luke-space-6);
margin: 0;
padding: var(--space-8) var(--space-12);
padding: var(--luke-space-8) var(--luke-space-12);
list-style: none;
border-bottom: 1px solid var(--hairline);
border-bottom: 1px solid var(--luke-color-border);
}

.pull-request-thread-head {
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/breadcrumbs/breadcrumbs.css
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
flex: 0 1 auto;
overflow: clip;
overflow-clip-margin: padding-box
calc(var(--focus-ring-width, 2px) + var(--focus-ring-offset, 1px));
calc(var(--luke-focus-ring-width) + var(--luke-focus-ring-offset));
}

.luke-breadcrumbs ol {
Expand Down
87 changes: 87 additions & 0 deletions scripts/repository-checks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,93 @@ fi
# Oct 17 plan-to-task rename broke the 26 turns then running.
pnpm --silent --filter @luke/database check:renames

# A `var(--name)` with no fallback, where nothing declares `--name`, fails
# nothing: the declaration it stands in is invalid at computed-value time, so a
# border, a gap, or a colour silently drops. That is how CSS merged after
# #3524 and #3569 retired the desktop's token aliases (`--hairline`,
# `--space-*`, `--focus-ring-width`, …) went on reading names nobody set. So
# every such read in a tracked sheet, page, or script under apps/ and packages/
# must name a property one of them declares: a sheet's `--name:` or
# `@property --name`, or a script's write of it (CSS text in a string, a style
# object's `"--name":` key, a `["--name"] =`, or `setProperty`'s first
# argument, spelled or held in a constant), where a `--name-${…}` declaration
# declares the whole family. A script that only reads a name, through
# `getPropertyValue`, declares nothing. A name only a third-party stylesheet
# sets is listed here by hand.
# Note that the declarations are pooled across every app, so a name one profile
# sets and another reads unset still passes; the check catches a name gone
# everywhere, which is what a retired token is.
node --input-type=module -e '
import { execFileSync } from "node:child_process";
import { readFileSync } from "node:fs";
import path from "node:path";

const root = process.argv[1];
// Set by the stylesheet Excalidraw ships, which the board imports.
const THIRD_PARTY = ["--default-button-size"];
const SCRIPT = /\.tsx?$/;
const NAME = "(--[\\w-]+)";
const QUOTED = `["\x27\x60]${NAME}["\x27\x60]`;
// What a script writes a property with, the name always the first group.
const SCRIPT_WRITES = [
new RegExp(`(?<![\\w-])${NAME}\\s*:`, "g"),
new RegExp(`${QUOTED}\\s*:`, "g"),
new RegExp(`\\[\\s*${QUOTED}\\s*\\]\\s*=(?!=)`, "g"),
new RegExp(`setProperty\\(\\s*${QUOTED}`, "g"),
];
const SCRIPT_FAMILIES = [
/(?<![\w-])(--[\w-]+?)\$\{[^}]*\}\s*:/g,
/setProperty\(\s*\x60(--[\w-]+?)\$\{/g,
];
const files = execFileSync("git", ["-C", root, "ls-files", "-z", "--", "apps", "packages"], {
encoding: "utf8",
})
.split("\0")
.filter((file) => /\.(css|html|tsx?)$/.test(file) && !/\.test\.tsx?$/.test(file));
const declared = new Set(THIRD_PARTY);
const families = [];
const reads = [];
for (const file of files) {
const source = readFileSync(path.join(root, file), "utf8");
// Blank comments, keeping every newline, so a name a comment mentions
// declares nothing and a line number still points home.
const text = SCRIPT.test(file)
? source.replace(/^\s*(\/\/|\/\*|\*).*$/gm, "")
: source.replace(/\/\*[\s\S]*?\*\//g, (comment) => comment.replace(/[^\n]/g, " "));
if (SCRIPT.test(file)) {
for (const write of SCRIPT_WRITES) {
for (const [, name] of text.matchAll(write)) declared.add(name);
}
for (const family of SCRIPT_FAMILIES) {
for (const [, name] of text.matchAll(family)) families.push(name);
}
// A constant handed to setProperty declares the name it holds.
for (const [, constant] of text.matchAll(/setProperty\(\s*([A-Za-z_$][\w$]*)\s*,/g)) {
const held = text.match(new RegExp(`\\b${constant}\\s*=\\s*${QUOTED}`));
if (held) declared.add(held[1]);
}
} else {
for (const [, name, registered] of text.matchAll(/(--[\w-]+)\s*:|@property\s+(--[\w-]+)/g)) {
declared.add(name ?? registered);
}
}
for (const read of text.matchAll(/var\(\s*(--[\w-]+)\s*\)/g)) {
const line = text.slice(0, read.index).split("\n").length;
reads.push({ file, line, name: read[1] });
}
}
const unset = reads.filter(
({ name }) => !declared.has(name) && !families.some((family) => name.startsWith(family)),
);
if (unset.length > 0) {
const lines = unset.map(({ file, line, name }) => ` ${file}:${line}: ${name}`).join("\n");
process.stderr.write(
`error: var() reads a custom property nothing declares and gives no fallback, so the declaration silently drops (a retired token reads its --luke-* role):\n${lines}\n`,
);
process.exit(1);
}
' "$LUKE_REPO_ROOT"

# This is the one scan for secrets the repository runs (AGENTS.md's "Never"), and
# a test fixture shaped like a provider's live credential is what GitHub's
# secret scanning raises an alert on, which history keeps open once pushed. So
Expand Down
Loading