Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
100 changes: 100 additions & 0 deletions .github/workflows/a11y.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Accessibility audit — WCAG 2.1 AA
#
# Runs pa11y-ci against the built VitePress docs to ensure the homepage and
# key pages remain WCAG 2.1 AA compliant.
#
# Triggers:
# - push to main touching docs/** or this workflow / config
# - every pull_request touching the same paths
# - workflow_dispatch (manual run)
#
# Strategy:
# 1. Build the docs with `bun run docs:build:a11y` (sets VITEPRESS_HOSTNAME=
# http://localhost:4173 so the generated sitemap.xml contains localhost
# URLs that pa11y-ci can reach directly)
# 2. Start `vitepress preview` in the background (serves on port 4173)
# 3. Wait until the server is accepting connections
# 4. Run pa11y-ci configured in .pa11yci.json (WCAG 2.1 AA, errors only)
#
# Chrome: Ubuntu-latest ships google-chrome-stable. We skip Puppeteer's own
# Chromium download (PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1) and point directly to
# the system Chrome via PUPPETEER_EXECUTABLE_PATH at runtime. This cuts ~200 MB
# from every CI run.
name: Accessibility audit (WCAG 2.1 AA)

on:
push:
branches: [main]
paths:
- "docs/**"
- ".github/workflows/a11y.yml"
- ".pa11yci.json"
pull_request:
paths:
- "docs/**"
- ".github/workflows/a11y.yml"
- ".pa11yci.json"
workflow_dispatch:

# One audit at a time per branch; cancel stale runs on new push.
concurrency:
group: a11y-${{ github.ref }}
cancel-in-progress: true

jobs:
audit:
name: WCAG 2.1 AA pages audit
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v6

- name: Setup Bun
uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2.1.3cf28ddc73e819eb6fa29df6b34ef8921c743461 # v2.1.3
with:
bun-version: latest

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Build docs (a11y — sitemap will use localhost URLs)
run: bun run docs:build:a11y

# Start VitePress preview in the background; base URL: /github-code-search/
# --port 4173 matches the URLs in .pa11yci.json
- name: Start VitePress preview server
run: bun run docs:preview -- --port 4173 &

# Poll until the preview server responds (max 60 s = 30 × 2 s).
- name: Wait for preview server to be ready
run: |
echo "Waiting for VitePress preview on http://localhost:4173/github-code-search/ …"
for i in $(seq 1 30); do
if curl -sf http://localhost:4173/github-code-search/ > /dev/null 2>&1; then
echo "Server ready after $((i * 2)) seconds."
exit 0
fi
echo "Attempt $i/30 — retrying in 2 s …"
sleep 2
done
echo "ERROR: preview server did not start within 60 seconds." >&2
exit 1

# Run the audit. The env vars tell Puppeteer (used by pa11y) to use the
# pre-installed system Chrome instead of downloading a Chromium binary.
- name: Run accessibility audit (pa11y-ci)
env:
PUPPETEER_EXECUTABLE_PATH: /usr/bin/google-chrome-stable
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: "1"
run: bun run docs:a11y

# Upload the pa11y-ci JSON report as an artifact so failures are
# easy to inspect without re-running the workflow.
- name: Upload audit report
if: always()
uses: actions/upload-artifact@v4
with:
name: pa11y-ci-report
path: a11y-report.json
if-no-files-found: ignore
2 changes: 1 addition & 1 deletion .github/workflows/cd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
uses: actions/checkout@v6

- name: Setup Bun
uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # v2.1.2
uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2.1.3d267786b128fe76c2f16a390aa2448b815359f3 # v2.1.2
with:
bun-version: latest

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
uses: actions/checkout@v6

- name: Setup Bun
uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # v2.1.2
uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2.1.3d267786b128fe76c2f16a390aa2448b815359f3 # v2.1.2
with:
bun-version: latest

Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,13 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v4.2.2
uses: actions/checkout@v6
with:
# Needed to fetch the gh-pages storage branch for versioned snapshots.
fetch-depth: 0

- name: Setup Bun
uses: oven-sh/setup-bun@v2.1.2
uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2.1.32.1.3
with:
bun-version: latest

Expand Down Expand Up @@ -127,7 +127,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v4.2.2
uses: actions/checkout@v6
with:
# Full history needed to push to gh-pages and commit versions.json to main.
fetch-depth: 0
Expand All @@ -146,7 +146,7 @@ jobs:
echo "major=$MAJOR" >> "$GITHUB_OUTPUT"

- name: Setup Bun
uses: oven-sh/setup-bun@v2.1.2
uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2.1.32.1.3
with:
bun-version: latest

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ dist/
coverage/
.env
*.local
a11y-report.json

# VitePress
docs/.vitepress/cache
Expand Down
17 changes: 17 additions & 0 deletions .pa11yci.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"defaults": {
"standard": "WCAG2AA",
"reporters": ["cli", ["json", { "fileName": "./a11y-report.json" }]],
"level": "error",
"wait": 1500,
"timeout": 60000,
"chromeLaunchConfig": {
"args": ["--no-sandbox", "--disable-setuid-sandbox", "--disable-dev-shm-usage"]
},
"ignore": [
"WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.BgImage",
"WCAG2AA.Principle1.Guideline1_4.1_4_3.G145.BgImage",
"WCAG2AA.Principle4.Guideline4_1.4_1_1.F77"
]
}
}
49 changes: 45 additions & 4 deletions docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,13 @@ export default defineConfig({
content: "https://fulll.github.io/github-code-search/social-preview.png",
},
],
["meta", { property: "og:url", content: "https://fulll.github.io/github-code-search/" }],
[
"meta",
{
property: "og:url",
content: "https://fulll.github.io/github-code-search/",
},
],
// ── Twitter Card ────────────────────────────────────────────────────────
["meta", { name: "twitter:card", content: "summary_large_image" }],
["meta", { name: "twitter:title", content: "github-code-search" }],
Expand Down Expand Up @@ -158,11 +164,40 @@ export default defineConfig({
const svgPath = fileURLToPath(new URL("../public/social-preview.svg", import.meta.url));
const pngPath = fileURLToPath(new URL("../public/social-preview.png", import.meta.url));
const svg = readFileSync(svgPath, "utf-8");
const resvg = new Resvg(svg, { fitTo: { mode: "width", value: 1200 } });
const resvg = new Resvg(svg, {
fitTo: { mode: "width", value: 1200 },
});
writeFileSync(pngPath, resvg.render().asPng());
},
},
],
// ── Chunk splitting ──────────────────────────────────────────────────────
// Mermaid alone is >900 kB minified; split it + the d3 sub-tree into
// dedicated async chunks to eliminate the Rollup 500 kB warning and
// improve long-term caching. No generic vendor catch-all — VitePress
// internals (mark.js etc.) need Rollup's default resolution.
build: {
// Mermaid (bundled with d3) is legitimately large (~2.4 MB minified).
// 2500 kB threshold avoids the Rollup warning without masking real bloat
// on other chunks (next largest is katex at ~260 kB).
chunkSizeWarningLimit: 2500,
rollupOptions: {
output: {
manualChunks(id: string) {
// Mermaid + d3 must be co-located (circular dependency between them).
if (
id.includes("node_modules/mermaid") ||
id.includes("node_modules/vitepress-plugin-mermaid") ||
id.includes("node_modules/d3") ||
id.includes("node_modules/dagre-d3-es") ||
id.includes("node_modules/internmap") ||
id.includes("node_modules/robust-predicates")
)
return "mermaid";
},
},
},
},
},

themeConfig: {
Expand Down Expand Up @@ -305,13 +340,19 @@ export default defineConfig({
// ── Markdown ──────────────────────────────────────────────────────────────
markdown: {
theme: {
light: "github-light",
// github-light-high-contrast fixes WCAG AA contrast for Shiki tokens
// (github-light has #D73A49 4.24:1, #6A737D 4.46:1, #22863A 4.28:1 — all below 4.5:1)
light: "github-light-high-contrast",
dark: "github-dark",
},
},

// ── Sitemap ───────────────────────────────────────────────────────────────
// VITEPRESS_HOSTNAME overrides the default for local/CI a11y audits:
// VITEPRESS_HOSTNAME=http://localhost:4173 vitepress build docs
// → sitemap.xml contains localhost URLs that pa11y-ci can reach directly.
sitemap: {
hostname: "https://fulll.github.io/github-code-search/",
hostname:
(process.env.VITEPRESS_HOSTNAME ?? "https://fulll.github.io") + "/github-code-search/",
},
Comment on lines 353 to 356
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sitemap.hostname is hard-coded to "/github-code-search/", but this docs site’s base is derived from process.env.VITEPRESS_BASE. For versioned/snapshot builds (e.g. /github-code-search/v2/) this will generate incorrect sitemap URLs and can break docs:a11y (pa11y follows URLs from the sitemap). Consider composing hostname from VITEPRESS_HOSTNAME + VITEPRESS_BASE (normalized with leading/trailing slash) instead of hard-coding the path segment.

Copilot uses AI. Check for mistakes.
});
23 changes: 14 additions & 9 deletions docs/.vitepress/theme/ComparisonTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,18 @@ const ROWS: Row[] = [
<strong>org-wide code audits and interactive triage</strong>.
</p>
<table class="ct-table">
<caption class="sr-only">
Feature comparison between gh search code and github-code-search
</caption>
<thead>
<tr>
<th class="ct-th-feature"></th>
<th class="ct-th-tool">
<th class="ct-th-feature" scope="col" aria-label="Feature"></th>
<th class="ct-th-tool" scope="col">
<div class="ct-tool-header">
<span class="ct-tool-name ct-tool-alt">gh search code</span>
</div>
</th>
<th class="ct-th-tool">
<th class="ct-th-tool" scope="col">
<div class="ct-tool-header">
<span class="ct-tool-name ct-tool-brand">github-code-search</span>
<span class="ct-badge">Purpose-built</span>
Expand Down Expand Up @@ -132,12 +135,12 @@ const ROWS: Row[] = [
</span>
</td>
<td class="ct-cell">
<span v-if="row.gh" class="ct-check">✓</span>
<span v-else class="ct-cross">✗</span>
<span v-if="row.gh" class="ct-check" aria-label="Yes">✓</span>
<span v-else class="ct-cross" aria-label="No">✗</span>
</td>
<td class="ct-cell">
<span v-if="row.gcs" class="ct-check">✓</span>
<span v-else class="ct-cross">✗</span>
<span v-if="row.gcs" class="ct-check" aria-label="Yes">✓</span>
<span v-else class="ct-cross" aria-label="No">✗</span>
</td>
</tr>
</tbody>
Expand Down Expand Up @@ -248,7 +251,8 @@ thead tr {
}

.ct-tool-alt {
color: var(--vp-c-text-3);
/* Fix: var(--vp-c-text-3) = 2.87:1, below WCAG AA 4.5:1. text-2 ≥ 5.4:1. */
color: var(--vp-c-text-2);
}

.ct-tool-brand {
Expand Down Expand Up @@ -323,7 +327,8 @@ thead tr {
.ct-feature-desc {
font-size: 13px;
font-weight: 400;
color: var(--vp-c-text-3);
/* Fix: var(--vp-c-text-3) ≈ 2.87:1, below WCAG AA. text-1 ensures ≥4.5:1. */
color: var(--vp-c-text-1);
line-height: 1.45;
}

Expand Down
20 changes: 10 additions & 10 deletions docs/.vitepress/theme/HowItWorks.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<section class="hiw-section">
<section class="hiw-section" aria-labelledby="hiw-heading">
<div class="hiw-header">
<h2 class="hiw-title">How it works</h2>
<h2 id="hiw-heading" class="hiw-title">How it works</h2>
<p class="hiw-subtitle">From query to structured output in three steps.</p>
</div>

Expand Down Expand Up @@ -229,17 +229,17 @@

.hiw-step-badge {
display: inline-block;
font-size: 11px;
font-size: 12px;
font-weight: 600;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--vp-c-brand-1);
margin-bottom: 4px;
margin-bottom: 5px;
}

.hiw-step-title {
margin: 0 0 6px;
font-size: 17px;
margin: 0 0 8px;
font-size: 18px;
font-weight: 700;
letter-spacing: -0.01em;
color: var(--vp-c-text-1);
Expand All @@ -249,8 +249,8 @@

.hiw-step-desc {
margin: 0;
font-size: 14px;
line-height: 1.7;
font-size: 15px;
line-height: 1.75;
color: var(--vp-c-text-2);
}

Expand Down Expand Up @@ -284,11 +284,11 @@ kbd {
}

.hiw-step-title {
font-size: 15px;
font-size: 16px;
}

.hiw-step-desc {
font-size: 13px;
font-size: 14px;
}
}
</style>
Loading