diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 5927c34..1b330c9 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -6,6 +6,20 @@ on:
- develop
jobs:
+ lint:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Setup Bun
+ uses: oven-sh/setup-bun@v2
+
+ - name: Lint all code
+ run: bunx prettier --check .
+
build:
env:
GH_TOKEN: ${{ github.token }}
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1 @@
+{}
diff --git a/README.md b/README.md
index 2ad20ea..d0073ca 100644
--- a/README.md
+++ b/README.md
@@ -12,10 +12,10 @@ This is a great process for bug fixes, simple features and purely additive chang
However, if you are making a significant change to the way Vortex functions, you may need to write an RFC first. Some example changes that would require an RFC:
-* Making a risky change to the format, such as adding new required fields to file metadata
-* Rearchitecting core components of Vortex, or wide-ranging refactors that might break language bindings
-* Creating new libraries or SDKs that we expect others to adopt
-* Making changes to subsystems that are likely to affect performance if not done thoughfully, such as the core IO traits
+- Making a risky change to the format, such as adding new required fields to file metadata
+- Rearchitecting core components of Vortex, or wide-ranging refactors that might break language bindings
+- Creating new libraries or SDKs that we expect others to adopt
+- Making changes to subsystems that are likely to affect performance if not done thoughfully, such as the core IO traits
## Process
@@ -70,3 +70,14 @@ Remove the build output:
```sh
bun run clean
```
+
+### Formatting
+
+We use [`prettiest`](https://prettier.io/) to format the code and documents, and check it in CI.
+
+Running it is as easy as:
+
+```sh
+bunx prettier --write .
+bunx prettier --check .
+```
diff --git a/bun.lock b/bun.lock
index fb39207..f87bb78 100644
--- a/bun.lock
+++ b/bun.lock
@@ -1,11 +1,11 @@
{
"lockfileVersion": 1,
- "configVersion": 1,
"workspaces": {
"": {
"name": "vortexrfc",
"devDependencies": {
"@types/bun": "latest",
+ "prettier": "^3.8.1",
},
"peerDependencies": {
"typescript": "^5",
@@ -19,6 +19,8 @@
"bun-types": ["bun-types@1.3.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-+UBWWOakIP4Tswh0Bt0QD0alpTY8cb5hvgiYeWCMet9YukHbzuruIEeXC2D7nMJPB12kbh8C7XJykSexEqGKJg=="],
+ "prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="],
+
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
"undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
diff --git a/index.ts b/index.ts
index 0b1f5a9..9d6b2a8 100644
--- a/index.ts
+++ b/index.ts
@@ -74,9 +74,17 @@ const LIVE_RELOAD_SCRIPT = `
})();
`;
-function baseHTML(title: string, content: string, cssPath: string = "styles.css", liveReload: boolean = false, repoUrl: string | null = null): string {
+function baseHTML(
+ title: string,
+ content: string,
+ cssPath: string = "styles.css",
+ liveReload: boolean = false,
+ repoUrl: string | null = null,
+): string {
const basePath = cssPath === "styles.css" ? "./" : "../";
- const githubLink = repoUrl ? `${ICON_GITHUB}` : "";
+ const githubLink = repoUrl
+ ? `${ICON_GITHUB}`
+ : "";
return `
@@ -119,24 +127,31 @@ function escapeHTML(str: string): string {
.replace(/"/g, """);
}
-function indexPage(rfcs: RFC[], repoUrl: string | null, liveReload: boolean = false): string {
+function indexPage(
+ rfcs: RFC[],
+ repoUrl: string | null,
+ liveReload: boolean = false,
+): string {
// Sort in reverse numeric order (newest first)
const sorted = [...rfcs].sort((a, b) => b.number.localeCompare(a.number));
- const list = sorted.map(rfc => {
- const dateStr = rfc.git.accepted ? formatDate(rfc.git.accepted.date) : "";
+ const list = sorted
+ .map((rfc) => {
+ const dateStr = rfc.git.accepted ? formatDate(rfc.git.accepted.date) : "";
- let authorHTML = "";
- if (rfc.git.author && rfc.git.accepted) {
- const commitUrl = repoUrl ? `${repoUrl}/commit/${rfc.git.accepted.hash}` : `https://github.com/${rfc.git.author.login}`;
- authorHTML = `
+ let authorHTML = "";
+ if (rfc.git.author && rfc.git.accepted) {
+ const commitUrl = repoUrl
+ ? `${repoUrl}/commit/${rfc.git.accepted.hash}`
+ : `https://github.com/${rfc.git.author.login}`;
+ authorHTML = `
${rfc.git.author.login}
`;
- }
+ }
- return `
+ return `
RFC ${rfc.number}
@@ -144,7 +159,8 @@ function indexPage(rfcs: RFC[], repoUrl: string | null, liveReload: boolean = fa
${dateStr}
${authorHTML}
`;
- }).join("\n");
+ })
+ .join("\n");
const content = `
Request for Comments
@@ -164,7 +180,11 @@ function formatDate(date: Date): string {
});
}
-function rfcPage(rfc: RFC, repoUrl: string | null, liveReload: boolean = false): string {
+function rfcPage(
+ rfc: RFC,
+ repoUrl: string | null,
+ liveReload: boolean = false,
+): string {
let gitHeader = "";
if (rfc.git.accepted || rfc.git.author) {
@@ -218,7 +238,13 @@ function rfcPage(rfc: RFC, repoUrl: string | null, liveReload: boolean = false):
${rfc.html}
`;
- return baseHTML(`RFC ${rfc.number} - ${rfc.title}`, content, "../styles.css", liveReload, repoUrl);
+ return baseHTML(
+ `RFC ${rfc.number} - ${rfc.title}`,
+ content,
+ "../styles.css",
+ liveReload,
+ repoUrl,
+ );
}
function parseRFCNumber(filename: string): string {
@@ -245,10 +271,14 @@ async function getGitHubRepoUrl(): Promise {
}
}
-async function getGitHubAuthor(repoPath: string, commitHash: string): Promise {
+async function getGitHubAuthor(
+ repoPath: string,
+ commitHash: string,
+): Promise {
try {
// Use gh CLI to fetch commit info from GitHub API
- const result = await $`gh api repos/${repoPath}/commits/${commitHash} --jq '.author.login, .author.avatar_url, .author.html_url'`.quiet();
+ const result =
+ await $`gh api repos/${repoPath}/commits/${commitHash} --jq '.author.login, .author.avatar_url, .author.html_url'`.quiet();
const lines = result.stdout.toString().trim().split("\n");
if (lines.length >= 3 && lines[0] && lines[1] && lines[2]) {
@@ -264,9 +294,13 @@ async function getGitHubAuthor(repoPath: string, commitHash: string): Promise {
+async function getGitHistory(
+ filepath: string,
+ repoPath: string | null,
+): Promise {
try {
- const result = await $`git log --follow --format=%H\ %aI -- ${filepath}`.quiet();
+ const result =
+ await $`git log --follow --format=%H\ %aI -- ${filepath}`.quiet();
const lines = result.stdout.toString().trim().split("\n").filter(Boolean);
if (lines.length === 0) {
@@ -284,7 +318,9 @@ async function getGitHistory(filepath: string, repoPath: string | null): Promise
const oldest = parseCommit(lines[lines.length - 1]!);
// Fetch author info from the first commit
- const author = repoPath ? await getGitHubAuthor(repoPath, oldest.hash) : null;
+ const author = repoPath
+ ? await getGitHubAuthor(repoPath, oldest.hash)
+ : null;
// If only one commit, or same commit, don't show lastUpdated
if (lines.length === 1 || mostRecent.hash === oldest.hash) {
@@ -479,7 +515,7 @@ async function startDevServer() {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
- "Connection": "keep-alive",
+ Connection: "keep-alive",
},
});
}
@@ -503,9 +539,11 @@ async function startDevServer() {
if (isDev) {
startDevServer().catch(console.error);
} else {
- build().then(count => {
- if (count > 0) {
- console.log("Output directory: ./dist/");
- }
- }).catch(console.error);
+ build()
+ .then((count) => {
+ if (count > 0) {
+ console.log("Output directory: ./dist/");
+ }
+ })
+ .catch(console.error);
}
diff --git a/package.json b/package.json
index fd90889..b539045 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,8 @@
"clean": "rm -rf dist"
},
"devDependencies": {
- "@types/bun": "latest"
+ "@types/bun": "latest",
+ "prettier": "^3.8.1"
},
"peerDependencies": {
"typescript": "^5"
diff --git a/styles.css b/styles.css
index d74bf70..4f65a45 100644
--- a/styles.css
+++ b/styles.css
@@ -59,7 +59,16 @@ html {
}
body {
- font-family: "Inter", "SF Pro Display", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
+ font-family:
+ "Inter",
+ "SF Pro Display",
+ -apple-system,
+ BlinkMacSystemFont,
+ "Segoe UI",
+ Roboto,
+ Helvetica,
+ Arial,
+ sans-serif;
background: var(--bg);
color: var(--fg);
line-height: 1.6;
@@ -130,7 +139,9 @@ header h1 a:hover {
height: 36px;
border-radius: 50%;
color: var(--fg-muted);
- transition: color 0.15s ease, box-shadow 0.15s ease;
+ transition:
+ color 0.15s ease,
+ box-shadow 0.15s ease;
}
.github-link:hover {
@@ -174,17 +185,33 @@ main {
min-height: calc(100vh - 200px);
}
-h1, h2, h3, h4, h5, h6 {
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
font-weight: 600;
margin-top: 2rem;
margin-bottom: 1rem;
color: var(--accent);
}
-h1 { font-size: 1.75rem; margin-top: 0; }
-h2 { font-size: 1.375rem; }
-h3 { font-size: 1.125rem; }
-h4, h5, h6 { font-size: 1rem; }
+h1 {
+ font-size: 1.75rem;
+ margin-top: 0;
+}
+h2 {
+ font-size: 1.375rem;
+}
+h3 {
+ font-size: 1.125rem;
+}
+h4,
+h5,
+h6 {
+ font-size: 1rem;
+}
p {
margin-bottom: 1rem;
@@ -200,7 +227,8 @@ a:hover {
text-decoration: underline;
}
-ul, ol {
+ul,
+ol {
margin-bottom: 1rem;
padding-left: 1.5rem;
}
@@ -210,7 +238,8 @@ li {
}
code {
- font-family: "IBM Plex Mono", "SF Mono", "Menlo", "Monaco", "Consolas", monospace;
+ font-family:
+ "IBM Plex Mono", "SF Mono", "Menlo", "Monaco", "Consolas", monospace;
background: var(--code-bg);
padding: 0.125rem 0.375rem;
border-radius: 3px;
@@ -218,7 +247,8 @@ code {
}
pre {
- font-family: "IBM Plex Mono", "SF Mono", "Menlo", "Monaco", "Consolas", monospace;
+ font-family:
+ "IBM Plex Mono", "SF Mono", "Menlo", "Monaco", "Consolas", monospace;
background: var(--code-bg);
border: 1px solid var(--border);
border-radius: 4px;
@@ -254,7 +284,8 @@ table {
margin-bottom: 1rem;
}
-th, td {
+th,
+td {
border: 1px solid var(--border);
padding: 0.5rem 0.75rem;
text-align: left;
@@ -278,7 +309,9 @@ th {
padding: 0.75rem 1rem;
margin: 0 -1rem;
border-radius: 4px;
- transition: box-shadow 0.15s ease, background 0.15s ease;
+ transition:
+ box-shadow 0.15s ease,
+ background 0.15s ease;
}
.rfc-list li:hover {
@@ -306,7 +339,8 @@ th {
}
.rfc-item .rfc-number {
- font-family: "IBM Plex Mono", "SF Mono", "Menlo", "Monaco", "Consolas", monospace;
+ font-family:
+ "IBM Plex Mono", "SF Mono", "Menlo", "Monaco", "Consolas", monospace;
color: var(--fg-muted);
font-size: 0.875rem;
flex-shrink: 0;