Skip to content
Open
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
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,32 @@ npx shadcn@latest add https://tinte.dev/api/preset/one-hunter
configs (Alacritty, Kitty, Warp, Windows Terminal), and 19+ formats from the same
source of truth.

## Provider capability matrix

This table is generated from the legacy web provider list and the provider
modules. Run `bun run generate:provider-matrix` after changing either source.

<!-- provider-matrix:start -->
| Provider | Status | Module |
| --- | --- | --- |
| shadcn/ui | Implemented | `packages/providers/src/providers/shadcn.ts` |
| VS Code | Implemented | `packages/providers/src/providers/vscode.ts` |
| Cursor | Planned | — |
| Shiki | Implemented | `packages/providers/src/providers/shiki.ts` |
| Zed | Implemented | `packages/providers/src/providers/zed.ts` |
| Warp | Implemented | `packages/providers/src/providers/warp.ts` |
| Alacritty | Implemented | `packages/providers/src/providers/alacritty.ts` |
| Windows Terminal | Implemented | `packages/providers/src/providers/windows-terminal.ts` |
| Kitty | Implemented | `packages/providers/src/providers/kitty.ts` |
| Ghostty | Planned | — |
| JetBrains | Planned | — |
| Slack | Implemented | `packages/providers/src/providers/slack.ts` |
| Replit | Planned | — |
| Neovim | Planned | — |
| Obsidian | Planned | — |
| GIMP | Implemented | `packages/providers/src/providers/gimp.ts` |
<!-- provider-matrix:end -->

## Preset API (shadcn v4)

Every public Tinte theme is installable as a shadcn `registry:base` item:
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
"generate:design": "bun run generate:artifacts && bun run generate:plugin",
"generate:artifacts": "bun packages/cli/src/cli.ts build --config ./tinte.config.json --out ./apps/web/public/design",
"generate:plugin": "bun packages/cli/src/cli.ts build --plugin --config ./tinte.config.json --out ./apps/web/public/plugin",
"generate:provider-matrix": "bun scripts/generate-provider-matrix.ts",
"check:provider-matrix": "bun scripts/generate-provider-matrix.ts --check",
"check:staged": "biome check --write --staged",
"validate:commit-msg": "node scripts/validate-commit-msg.mjs",
"prepare": "simple-git-hooks"
Expand Down
98 changes: 98 additions & 0 deletions scripts/generate-provider-matrix.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { readdir, readFile, writeFile } from "node:fs/promises";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";

const root = join(dirname(fileURLToPath(import.meta.url)), "..");
const providerConfigPath = join(root, "apps/web/src/config/providers.ts");
const providerModulesPath = join(root, "packages/providers/src/providers");
const readmePath = join(root, "README.md");
const startMarker = "<!-- provider-matrix:start -->";
const endMarker = "<!-- provider-matrix:end -->";
const aliases: Record<string, string> = {
"shadcn/ui": "shadcn",
"VS Code": "vscode",
"Windows Terminal": "windows-terminal",
};

function providerFileStem(provider: string) {
return (
aliases[provider] ??
provider
.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/(^-|-$)/g, "")
);
}

function readProviderNames(source: string) {
const match = source.match(
/export const ALL_PROVIDERS = \[([\s\S]*?)\]\s+as const;/,
);
if (!match) {
throw new Error("Could not find ALL_PROVIDERS in the web provider config");
}

const providers = [...match[1].matchAll(/"([^"]+)"/g)].map(
([, provider]) => provider,
);
if (providers.length === 0 || new Set(providers).size !== providers.length) {
throw new Error("ALL_PROVIDERS must contain unique provider names");
}
return providers;
}

function renderMatrix(providers: string[], providerModules: Set<string>) {
const rows = providers.map((provider) => {
const stem = providerFileStem(provider);
const implemented = providerModules.has(stem);
const module = implemented
? `\`packages/providers/src/providers/${stem}.ts\``
: "—";
return `| ${provider} | ${implemented ? "Implemented" : "Planned"} | ${module} |`;
});

return [
startMarker,
"| Provider | Status | Module |",
"| --- | --- | --- |",
...rows,
endMarker,
].join("\n");
}

const [providerConfig, providerEntries, readme] = await Promise.all([
readFile(providerConfigPath, "utf8"),
readdir(providerModulesPath, { withFileTypes: true }),
readFile(readmePath, "utf8"),
]);
const providers = readProviderNames(providerConfig);
const providerModules = new Set(
providerEntries
.filter((entry) => entry.isFile() && entry.name.endsWith(".ts"))
.map((entry) => entry.name.slice(0, -3)),
);
const start = readme.indexOf(startMarker);
const end = readme.indexOf(endMarker);
if (start === -1 || end === -1 || end < start) {
throw new Error("README provider matrix markers are missing or out of order");
}

const matrix = renderMatrix(providers, providerModules);
const updatedReadme = `${readme.slice(0, start)}${matrix}${readme.slice(
end + endMarker.length,
)}`;

if (process.argv.includes("--check")) {
if (updatedReadme !== readme) {
console.error("Provider capability matrix is out of date");
process.exit(1);
}
console.log(
`Provider capability matrix is current (${providers.length} providers)`,
);
} else {
await writeFile(readmePath, updatedReadme);
console.log(
`Updated provider capability matrix (${providers.length} providers)`,
);
}