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
4 changes: 3 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ jobs:
echo "f929eb8e5b72a85543eeeefb2c38f34a68e0c530e70758a2905b78840c76602c $RUNNER_TEMP/syncthing.tar.gz" | sha256sum --check
tar -xzf "$RUNNER_TEMP/syncthing.tar.gz" -C "$RUNNER_TEMP"
echo "$RUNNER_TEMP/syncthing-linux-amd64-v2.1.3" >> "$GITHUB_PATH"
- run: npx playwright install --with-deps chromium
# The runner image already has Chrome's libraries; apt mirrors have taken
# over twelve minutes to deliver them again.
- run: npx playwright install chromium
- name: Test installed release
run: bash scripts/test-release.sh "$PWD"/release/*.tar.gz
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
Expand Down
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,20 @@ discovery and relays disabled, and stop them on exit. Set

`app/` and `client/` own the application; `static/` owns its external assets;
`themes/` owns base palettes; `integration/` owns the optional Omarchy CSS
template and browser refresh helper. Tests assert the current API, rendering and
formatting contracts directly.
template, its browser refresh helper and `host-palette.json`, which maps a
shell's semantic colors onto that template. Tests assert the current API,
rendering and formatting contracts directly.

## Plugin integration

The plugin imports the same compiled archive, pins its checksum, and supplies
Omarchy palette values to the included template. Its Go bridge provides optional
local file actions. Without a plugin grant, ordinary Syncthing operations remain
available and local file actions report unavailable access.
Omarchy palette values to the included template. Material You shells such as Dux
Shell export semantic roles instead (background, surfaces, foreground, muted,
border, accent, success, warning, danger, info); `host-palette.json` defines how
those fill the template, and the contrast suite covers Dux Shell's default
theme. The plugin's Go bridge provides optional local file actions. Without a
plugin grant, ordinary Syncthing operations remain available and local file
actions report unavailable access.

This is a third-party Syncthing interface. Original authors and dependency
licenses remain credited in About and in the release.
41 changes: 41 additions & 0 deletions integration/host-palette.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"format": 1,
"template": "omarchy-theme.css.in",
"roles": [
"mode",
"background",
"surface",
"surfaceVariant",
"foreground",
"muted",
"accent",
"success",
"warning",
"danger",
"border",
"info"
],
"constants": {
"palette": "portable"
},
"tokens": {
"mode": "mode",
"background": "background",
"surface": "surface",
"surface_dark": "surfaceVariant",
"selection": "surfaceVariant",
"foreground": "foreground",
"foreground_light": "foreground",
"foreground_dark": "muted",
"muted": "border",
"accent": "accent",
"blue": "accent",
"magenta": "accent",
"green": "success",
"yellow": "warning",
"bright_yellow": "warning",
"orange": "warning",
"red": "danger",
"cyan": "info"
}
}
34 changes: 34 additions & 0 deletions tests/host-palette.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import assert from 'node:assert/strict';
import { readFile } from 'node:fs/promises';
import test from 'node:test';

const contract = JSON.parse(
await readFile(
new URL('../integration/host-palette.json', import.meta.url),
'utf8',
),
);
const template = await readFile(
new URL(`../integration/${contract.template}`, import.meta.url),
'utf8',
);

test('the host palette contract resolves every template token', () => {
const placeholders = new Set(
[...template.matchAll(/{{(\w+)}}/g)].map((match) => match[1]),
);
const resolved = new Set([
...Object.keys(contract.tokens),
...Object.keys(contract.constants),
]);
assert.deepEqual([...placeholders].sort(), [...resolved].sort());
for (const key of Object.keys(contract.constants))
assert.ok(!(key in contract.tokens), `${key} is both constant and role`);
});

test('every host role is used and every token names a role', () => {
assert.equal(contract.format, 1);
assert.equal(new Set(contract.roles).size, contract.roles.length);
const used = new Set(Object.values(contract.tokens));
assert.deepEqual([...used].sort(), [...contract.roles].sort());
});
51 changes: 51 additions & 0 deletions tests/omarchy-contrast.spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -431,11 +431,62 @@ const palettes = {
orange: '#4a4a4a',
},
};

const hostPalette = JSON.parse(
await readFile(
new URL('../integration/host-palette.json', import.meta.url),
'utf8',
),
);
// Material You shells export semantic roles, not terminal colors; these are
// Dux Shell's default purple theme with its fixed success, warning and info.
const hostPalettes = {
'dux-purple-dark': {
mode: 'dark',
background: '#141218',
surface: '#211f24',
surfaceVariant: '#2b292f',
foreground: '#e6e0e9',
muted: '#cac4cf',
accent: '#d0bcff',
success: '#4caf50',
warning: '#ff9800',
danger: '#f2b8b5',
border: '#948f99',
info: '#2196f3',
},
'dux-purple-light': {
mode: 'light',
background: '#fef7ff',
surface: '#f2ecf4',
surfaceVariant: '#ece6ee',
foreground: '#1d1b20',
muted: '#49454e',
accent: '#6750a4',
success: '#4caf50',
warning: '#ff9800',
danger: '#f2b8b5',
border: '#7a757f',
info: '#2196f3',
},
};
for (const [name, roles] of Object.entries(hostPalettes))
palettes[name] = Object.fromEntries(
Object.entries(hostPalette.tokens).map(([token, role]) => [
token,
roles[role],
]),
);
const derivedText = {
'rose-pine': 'color(srgb 0.102353 0.0964706 0.142353)',
'catppuccin-latte': 'color(srgb 0.0596078 0.0619608 0.0823529)',
};
const semanticText = {
'dux-purple-light': {
success: '#1d1b20',
warning: '#1d1b20',
danger: '#1d1b20',
},
ethereal: { danger: '#ffcead' },
gruvbox: { danger: '#d4be98' },
kanagawa: { success: '#dcd7ba', danger: '#dcd7ba' },
Expand Down
Loading