mirror of
https://github.com/harivansh-afk/deskctl.git
synced 2026-04-15 07:04:46 +00:00
site init (barrett)
This commit is contained in:
parent
f05f441dee
commit
50c9594780
15 changed files with 5862 additions and 0 deletions
4
site/.gitignore
vendored
Normal file
4
site/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
|
.astro/
|
||||||
|
.vercel/
|
||||||
11
site/.prettierrc
Normal file
11
site/.prettierrc
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"plugins": ["prettier-plugin-astro"],
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": "*.astro",
|
||||||
|
"options": {
|
||||||
|
"parser": "astro"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
22
site/astro.config.mjs
Normal file
22
site/astro.config.mjs
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { defineConfig } from "astro/config";
|
||||||
|
import mdx from "@astrojs/mdx";
|
||||||
|
import vercel from "@astrojs/vercel";
|
||||||
|
import { midnight, daylight } from "./src/themes.mjs";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
output: "static",
|
||||||
|
adapter: vercel(),
|
||||||
|
build: {
|
||||||
|
format: "file",
|
||||||
|
},
|
||||||
|
integrations: [mdx()],
|
||||||
|
markdown: {
|
||||||
|
shikiConfig: {
|
||||||
|
themes: {
|
||||||
|
light: daylight,
|
||||||
|
dark: midnight,
|
||||||
|
},
|
||||||
|
wrap: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
24
site/package.json
Normal file
24
site/package.json
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"name": "deskctl-site",
|
||||||
|
"type": "module",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "astro dev",
|
||||||
|
"build": "astro build",
|
||||||
|
"preview": "astro preview",
|
||||||
|
"check": "astro check",
|
||||||
|
"format:check": "prettier --check 'src/**/*.{astro,mdx,css}' astro.config.mjs"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@astrojs/mdx": "^4.3.14",
|
||||||
|
"@astrojs/vercel": "^9.0.5",
|
||||||
|
"astro": "^5.18.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@astrojs/check": "^0.9.8",
|
||||||
|
"prettier": "^3.8.1",
|
||||||
|
"prettier-plugin-astro": "^0.14.1",
|
||||||
|
"typescript": "^5.9.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
5105
site/pnpm-lock.yaml
generated
Normal file
5105
site/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load diff
BIN
site/public/favicon.png
Normal file
BIN
site/public/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.8 KiB |
14
site/public/favicon.svg
Normal file
14
site/public/favicon.svg
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||||
|
<style>
|
||||||
|
text {
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: bold;
|
||||||
|
fill: #1a1a1a;
|
||||||
|
}
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
text { fill: #e0e0e0; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<text x="16" y="24" text-anchor="middle">:h</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 336 B |
115
site/src/layouts/DocLayout.astro
Normal file
115
site/src/layouts/DocLayout.astro
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
---
|
||||||
|
import "../styles/base.css";
|
||||||
|
import type { MarkdownHeading } from "astro";
|
||||||
|
const fm = Astro.props.frontmatter || Astro.props;
|
||||||
|
const title = fm.title;
|
||||||
|
const description = fm.description || "desktop control for AI agents";
|
||||||
|
const toc = fm.toc ?? false;
|
||||||
|
const headings: MarkdownHeading[] = Astro.props.headings ?? [];
|
||||||
|
const isIndex =
|
||||||
|
Astro.url.pathname === "/" || Astro.url.pathname === "/index.html";
|
||||||
|
const h2s = headings.filter((h) => h.depth === 2);
|
||||||
|
|
||||||
|
function formatTocText(text: string): string {
|
||||||
|
if (!text.includes(" ") && /[-.]/.test(text)) {
|
||||||
|
return `<code>${text}</code>`;
|
||||||
|
}
|
||||||
|
return text.replace(/\(([^)]+)\)/g, "(<code>$1</code>)");
|
||||||
|
}
|
||||||
|
---
|
||||||
|
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta name="description" content={description} />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
|
<title>{title ? `${title} — deskctl` : "deskctl"}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{
|
||||||
|
!isIndex && (
|
||||||
|
<nav>
|
||||||
|
<a class="title" href="/">
|
||||||
|
deskctl
|
||||||
|
</a>
|
||||||
|
<span class="sep">/</span>
|
||||||
|
<a href={Astro.url.pathname}>{title}</a>
|
||||||
|
</nav>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
toc && (
|
||||||
|
<aside class="toc-nav">
|
||||||
|
<ul>
|
||||||
|
{h2s.map((h) => (
|
||||||
|
<li>
|
||||||
|
<a href={`#${h.slug}`} set:html={formatTocText(h.text)} />
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</aside>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<slot />
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const links = document.querySelectorAll(".toc-nav a");
|
||||||
|
if (links.length) {
|
||||||
|
const ids = Array.from(links).map((a) =>
|
||||||
|
a.getAttribute("href")!.slice(1),
|
||||||
|
);
|
||||||
|
const sections = ids
|
||||||
|
.map((id) => document.getElementById(id))
|
||||||
|
.filter(Boolean) as HTMLElement[];
|
||||||
|
|
||||||
|
let clickLock = false;
|
||||||
|
let scrollTimer: number;
|
||||||
|
|
||||||
|
function activate(id: string) {
|
||||||
|
links.forEach((a) => {
|
||||||
|
a.classList.toggle("active", a.getAttribute("href") === `#${id}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
links.forEach((a) => {
|
||||||
|
a.addEventListener("click", () => {
|
||||||
|
activate(a.getAttribute("href")!.slice(1));
|
||||||
|
clickLock = true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const observer = new IntersectionObserver(
|
||||||
|
(entries) => {
|
||||||
|
if (clickLock) return;
|
||||||
|
for (const entry of entries) {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
activate(entry.target.id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ rootMargin: "0px 0px -60% 0px" },
|
||||||
|
);
|
||||||
|
|
||||||
|
sections.forEach((s) => observer.observe(s));
|
||||||
|
|
||||||
|
window.addEventListener(
|
||||||
|
"scroll",
|
||||||
|
() => {
|
||||||
|
clearTimeout(scrollTimer);
|
||||||
|
scrollTimer = window.setTimeout(() => {
|
||||||
|
clickLock = false;
|
||||||
|
}, 150);
|
||||||
|
},
|
||||||
|
{ passive: true },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
19
site/src/pages/architecture.mdx
Normal file
19
site/src/pages/architecture.mdx
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
---
|
||||||
|
layout: ../layouts/DocLayout.astro
|
||||||
|
title: Architecture
|
||||||
|
toc: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Architecture
|
||||||
|
|
||||||
|
## Client-daemon model
|
||||||
|
|
||||||
|
deskctl uses a client-daemon architecture over Unix sockets with an NDJSON wire protocol. The daemon starts automatically on the first command and keeps the X11 connection alive for fast repeated calls.
|
||||||
|
|
||||||
|
## Backend design
|
||||||
|
|
||||||
|
The backend is trait-based, making it straightforward to add support for different display servers. The current implementation targets X11 via `x11rb`.
|
||||||
|
|
||||||
|
## Wayland support
|
||||||
|
|
||||||
|
Coming soon. The trait-based backend design means adding Hyprland/Wayland support is a single trait implementation with zero refactoring of the core.
|
||||||
35
site/src/pages/index.astro
Normal file
35
site/src/pages/index.astro
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
import DocLayout from "../layouts/DocLayout.astro";
|
||||||
|
---
|
||||||
|
|
||||||
|
<DocLayout title="" description="desktop control for AI agents">
|
||||||
|
<header>
|
||||||
|
<h1>deskctl</h1>
|
||||||
|
<code>desktop control CLI for AI agents</code>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
X11 desktop control CLI for AI agents on Linux. Snapshot, click, type, and
|
||||||
|
focus windows through a simple command-line interface with a client-daemon
|
||||||
|
architecture over Unix sockets.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Documentation</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="/installation">Installation</a></li>
|
||||||
|
<li><a href="/usage">Usage</a></li>
|
||||||
|
<li><a href="/architecture">Architecture</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>Links</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href="https://github.com/harivansh-afk/deskctl">GitHub</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://crates.io/crates/deskctl">crates.io</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</DocLayout>
|
||||||
45
site/src/pages/installation.mdx
Normal file
45
site/src/pages/installation.mdx
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
---
|
||||||
|
layout: ../layouts/DocLayout.astro
|
||||||
|
title: Installation
|
||||||
|
---
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
|
||||||
|
## Cargo
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo install deskctl
|
||||||
|
```
|
||||||
|
|
||||||
|
## Docker build
|
||||||
|
|
||||||
|
Build a Linux binary with Docker:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker compose -f docker/docker-compose.yml run --rm build
|
||||||
|
```
|
||||||
|
|
||||||
|
This writes `dist/deskctl-linux-x86_64`.
|
||||||
|
|
||||||
|
## From source
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git clone https://github.com/harivansh-afk/deskctl
|
||||||
|
cd deskctl
|
||||||
|
cargo build
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deploy to a remote machine
|
||||||
|
|
||||||
|
Copy the binary to an SSH machine:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ssh -p 443 deskctl@ssh.agentcomputer.ai 'cat > ~/deskctl && chmod +x ~/deskctl' < dist/deskctl-linux-x86_64
|
||||||
|
```
|
||||||
|
|
||||||
|
## Runtime requirements
|
||||||
|
|
||||||
|
- Linux with X11 session
|
||||||
|
- `DISPLAY` environment variable set
|
||||||
|
- `XDG_SESSION_TYPE=x11`
|
||||||
|
- A window manager exposing standard EWMH properties
|
||||||
53
site/src/pages/usage.mdx
Normal file
53
site/src/pages/usage.mdx
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
---
|
||||||
|
layout: ../layouts/DocLayout.astro
|
||||||
|
title: Usage
|
||||||
|
toc: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
## Snapshot
|
||||||
|
|
||||||
|
Capture the current desktop state:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
deskctl snapshot
|
||||||
|
```
|
||||||
|
|
||||||
|
With annotations overlaid on windows:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
deskctl --json snapshot --annotate
|
||||||
|
```
|
||||||
|
|
||||||
|
## Click
|
||||||
|
|
||||||
|
Click a window by its annotation handle:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
deskctl click @w1
|
||||||
|
```
|
||||||
|
|
||||||
|
## Type
|
||||||
|
|
||||||
|
Type text into the focused window:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
deskctl type "hello world"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Focus
|
||||||
|
|
||||||
|
Focus a window by name:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
deskctl focus "firefox"
|
||||||
|
```
|
||||||
|
|
||||||
|
## JSON output
|
||||||
|
|
||||||
|
Pass `--json` for machine-readable output, useful for agent integrations:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
deskctl --json snapshot
|
||||||
|
```
|
||||||
346
site/src/styles/base.css
Normal file
346
site/src/styles/base.css
Normal file
|
|
@ -0,0 +1,346 @@
|
||||||
|
@font-face {
|
||||||
|
font-family: "Signifier";
|
||||||
|
src: url("https://www.barrettruth.com/fonts/signifier/Signifier-Regular.ttf")
|
||||||
|
format("truetype");
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Signifier";
|
||||||
|
src: url("https://www.barrettruth.com/fonts/signifier/Signifier-RegularItalic.ttf")
|
||||||
|
format("truetype");
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: italic;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Signifier";
|
||||||
|
src: url("https://www.barrettruth.com/fonts/signifier/Signifier-Light.ttf")
|
||||||
|
format("truetype");
|
||||||
|
font-weight: 300;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Signifier";
|
||||||
|
src: url("https://www.barrettruth.com/fonts/signifier/Signifier-LightItalic.ttf")
|
||||||
|
format("truetype");
|
||||||
|
font-weight: 300;
|
||||||
|
font-style: italic;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Signifier";
|
||||||
|
src: url("https://www.barrettruth.com/fonts/signifier/Signifier-Medium.ttf")
|
||||||
|
format("truetype");
|
||||||
|
font-weight: 500;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Signifier";
|
||||||
|
src: url("https://www.barrettruth.com/fonts/signifier/Signifier-Bold.ttf")
|
||||||
|
format("truetype");
|
||||||
|
font-weight: 700;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Berkeley Mono";
|
||||||
|
src: url("https://www.barrettruth.com/fonts/berkeley-mono/BerkeleyMono-Regular.ttf")
|
||||||
|
format("truetype");
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Berkeley Mono";
|
||||||
|
src: url("https://www.barrettruth.com/fonts/berkeley-mono/BerkeleyMono-Bold.ttf")
|
||||||
|
format("truetype");
|
||||||
|
font-weight: 700;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Berkeley Mono";
|
||||||
|
src: url("https://www.barrettruth.com/fonts/berkeley-mono/BerkeleyMono-Italic.ttf")
|
||||||
|
format("truetype");
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: italic;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
font-family: "Signifier", serif;
|
||||||
|
line-height: 1.65;
|
||||||
|
color: #1a1a1a;
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
background: #121212;
|
||||||
|
color: #e0e0e0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
max-width: 50rem;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 3rem clamp(1.25rem, 5vw, 3rem) 6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tagline {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
opacity: 0.5;
|
||||||
|
margin-top: -0.75rem;
|
||||||
|
margin-bottom: 1.75rem;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
gap: 20px;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
header h1 {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
header code {
|
||||||
|
font-size: clamp(1.75rem, 5vw, 2.5rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: clamp(1.75rem, 5vw, 2.5rem);
|
||||||
|
line-height: 1.2;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 1.35rem;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
margin-top: 2rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration-thickness: 1px;
|
||||||
|
text-underline-offset: 0.15em;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration-thickness: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
padding-left: 1.25em;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin-bottom: 0.35rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre,
|
||||||
|
code,
|
||||||
|
.astro-code {
|
||||||
|
font-family: "Berkeley Mono", monospace !important;
|
||||||
|
font-variant-ligatures: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-size: 0.88em;
|
||||||
|
padding: 0.15em 0.35em;
|
||||||
|
border-radius: 3px;
|
||||||
|
background: #e8e8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
code {
|
||||||
|
background: #222222;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
padding: 1rem 1.25rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow-x: auto;
|
||||||
|
white-space: pre;
|
||||||
|
word-wrap: normal;
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
background: #ebebeb;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
pre {
|
||||||
|
background: #222222;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pre code {
|
||||||
|
padding: 0;
|
||||||
|
background: none;
|
||||||
|
font-size: 0.85em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.astro-code,
|
||||||
|
.astro-code span {
|
||||||
|
color: var(--shiki-dark) !important;
|
||||||
|
background-color: var(--shiki-dark-bg) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
font-size: 0.95em;
|
||||||
|
}
|
||||||
|
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
text-align: left;
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
border-bottom: 1px solid #d0d0d0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
border-bottom-color: #2d2d2d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid #d0d0d0;
|
||||||
|
margin: 2.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
hr {
|
||||||
|
border-top-color: #2d2d2d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nav {
|
||||||
|
max-width: 50rem;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 1.5rem clamp(1.25rem, 5vw, 3rem) 0;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
opacity: 0.6;
|
||||||
|
transition: opacity 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav .title {
|
||||||
|
font-weight: 500;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav .sep {
|
||||||
|
opacity: 0.3;
|
||||||
|
margin: 0 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-nav {
|
||||||
|
position: fixed;
|
||||||
|
top: 6.5rem;
|
||||||
|
left: max(1rem, calc(50vw - 25rem - 2rem - 11rem));
|
||||||
|
width: 11rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-nav code {
|
||||||
|
font-size: 0.85em;
|
||||||
|
padding: 0.1em 0.25em;
|
||||||
|
border-radius: 2px;
|
||||||
|
background: #e8e8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.toc-nav code {
|
||||||
|
background: #222222;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 64em) {
|
||||||
|
.toc-nav {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-nav ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-nav li {
|
||||||
|
margin-bottom: 0.45rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-nav a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
opacity: 0.6;
|
||||||
|
transition: opacity 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-nav a:hover,
|
||||||
|
.toc-nav a.active {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
59
site/src/themes.mjs
Normal file
59
site/src/themes.mjs
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
export const midnight = {
|
||||||
|
name: "midnight",
|
||||||
|
type: "dark",
|
||||||
|
colors: {
|
||||||
|
"editor.background": "#222222",
|
||||||
|
"editor.foreground": "#e0e0e0",
|
||||||
|
},
|
||||||
|
tokenColors: [
|
||||||
|
{
|
||||||
|
scope: [
|
||||||
|
"storage.type",
|
||||||
|
"storage.modifier",
|
||||||
|
"keyword.control",
|
||||||
|
"keyword.operator.new",
|
||||||
|
],
|
||||||
|
settings: { foreground: "#7aa2f7" },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: [
|
||||||
|
"string.quoted",
|
||||||
|
"constant.numeric",
|
||||||
|
"constant.language",
|
||||||
|
"constant.character",
|
||||||
|
"number",
|
||||||
|
],
|
||||||
|
settings: { foreground: "#98c379" },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const daylight = {
|
||||||
|
name: "daylight",
|
||||||
|
type: "light",
|
||||||
|
colors: {
|
||||||
|
"editor.background": "#ebebeb",
|
||||||
|
"editor.foreground": "#1a1a1a",
|
||||||
|
},
|
||||||
|
tokenColors: [
|
||||||
|
{
|
||||||
|
scope: [
|
||||||
|
"storage.type",
|
||||||
|
"storage.modifier",
|
||||||
|
"keyword.control",
|
||||||
|
"keyword.operator.new",
|
||||||
|
],
|
||||||
|
settings: { foreground: "#3b5bdb" },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: [
|
||||||
|
"string.quoted",
|
||||||
|
"constant.numeric",
|
||||||
|
"constant.language",
|
||||||
|
"constant.character",
|
||||||
|
"number",
|
||||||
|
],
|
||||||
|
settings: { foreground: "#2d7f3e" },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
10
site/tsconfig.json
Normal file
10
site/tsconfig.json
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"extends": "astro/tsconfigs/strict",
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@layouts/*": ["src/layouts/*"],
|
||||||
|
"@components/*": ["src/components/*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue