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
12 changes: 10 additions & 2 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,21 @@ on:
paths:
- 'site/**'
- '.github/workflows/docs.yml'
pull_request:
paths:
- 'site/**'
- '.github/workflows/docs.yml'
workflow_dispatch:

permissions:
contents: read
pages: write
id-token: write

# Pull requests only build; each gets its own group so it never queues behind a deploy.
concurrency:
group: pages
cancel-in-progress: false
group: ${{ github.event_name == 'pull_request' && format('docs-{0}', github.ref) || 'pages' }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
build:
Expand All @@ -34,16 +39,19 @@ jobs:
cache: npm
cache-dependency-path: site/package-lock.json
- uses: actions/configure-pages@v6.0.0
if: github.event_name != 'pull_request'
- run: npm ci
working-directory: site
- run: npm run build
working-directory: site
- uses: actions/upload-pages-artifact@v5.0.0
if: github.event_name != 'pull_request'
with:
path: site/.vitepress/dist

deploy:
needs: build
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
environment:
name: github-pages
Expand Down
142 changes: 69 additions & 73 deletions site/.vitepress/theme/HeroInstall.vue
Original file line number Diff line number Diff line change
@@ -1,97 +1,93 @@
<script setup lang="ts">
import { ref } from 'vue'
import { useData } from 'vitepress'
import { computed, onMounted, ref } from 'vue'
import { useData, withBase } from 'vitepress'

type Platform = 'windows' | 'unix' | 'python'

const { frontmatter } = useData()
const selected = ref<Platform>('windows')
const copied = ref(false)

const choices = computed(() => [
{ key: 'windows' as const, prompt: '>', label: frontmatter.value.install?.windowsLabel || 'Windows', command: frontmatter.value.install?.windows },
{ key: 'unix' as const, prompt: '$', label: frontmatter.value.install?.unixLabel || 'Linux / macOS / Termux', command: frontmatter.value.install?.unix },
{ key: 'python' as const, prompt: '$', label: frontmatter.value.install?.pythonLabel || 'Python (uv)', command: frontmatter.value.install?.python },
])
const active = computed(() => choices.value.find(c => c.key === selected.value) || choices.value[0])
const moreLink = computed(() => withBase(frontmatter.value.install?.moreLink ?? '/installation'))

// The page is prerendered with Windows selected; switch to the visitor's platform after hydration.
onMounted(() => {
if (!/Windows/i.test(navigator.userAgent)) selected.value = 'unix'
})

function select(key: Platform) {
selected.value = key
copied.value = false
}

async function copy() {
if (!active.value?.command) return
try {
await navigator.clipboard.writeText(frontmatter.value.install.command)
await navigator.clipboard.writeText(active.value.command)
copied.value = true
setTimeout(() => (copied.value = false), 1600)
} catch {
// Clipboard access can be blocked; the command stays selectable.
// Clipboard permissions vary by browser; the command remains selectable.
}
}
</script>

<template>
<div v-if="frontmatter.install" class="install">
<span class="install-label">{{ frontmatter.install.label }}</span>
<code class="install-command"><span class="prompt">$</span> {{ frontmatter.install.command }}</code>
<button class="install-copy" type="button" :aria-label="frontmatter.install.copy" @click="copy">
{{ copied ? frontmatter.install.copied : frontmatter.install.copy }}
</button>
<div v-if="frontmatter.install" class="installer">
<div class="installer-heading">{{ frontmatter.install.label }}</div>
<div class="installer-tabs" role="group" :aria-label="frontmatter.install.label">
<button
v-for="choice in choices"
:key="choice.key"
type="button"
class="installer-tab"
:class="{ active: selected === choice.key }"
:aria-pressed="selected === choice.key"
@click="select(choice.key)"
>{{ choice.label }}</button>
</div>
<div class="installer-command">
<code><span class="prompt">{{ active.prompt }}</span> {{ active.command }}</code>
<button type="button" class="installer-copy" @click="copy">
{{ copied ? frontmatter.install.copied : frontmatter.install.copy }}
</button>
<span class="visually-hidden" aria-live="polite">{{ copied ? frontmatter.install.copied : '' }}</span>
</div>
<a class="installer-more" :href="moreLink">{{ frontmatter.install.moreLabel }} →</a>
</div>
</template>

<style scoped>
.install {
display: flex;
align-items: center;
gap: 12px;
box-sizing: border-box;
width: 100%;
max-width: 420px;
margin-top: 28px;
padding: 8px 8px 8px 14px;
border: 1px solid var(--vp-c-divider);
border-radius: 10px;
background: var(--vp-c-bg-elv);
}

.install-label {
flex: none;
font-size: 12px;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
color: var(--vp-c-text-3);
}

.install-command {
flex: 1;
min-width: 0;
overflow-x: auto;
white-space: nowrap;
font-family: var(--vp-font-family-mono);
font-size: 14px;
color: var(--vp-c-text-1);
background: none;
.installer { width: 100%; max-width: 580px; margin-top: 26px; }
.installer-heading { margin-bottom: 10px; font-size: 13px; font-weight: 600; color: var(--vp-c-text-2); }
.installer-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.installer-tab {
padding: 5px 10px; border: 1px solid var(--vp-c-divider); border-radius: 7px;
font-size: 12px; line-height: 1.6; color: var(--vp-c-text-2); background: var(--vp-c-bg-elv);
}

.prompt {
color: var(--vp-c-brand-1);
user-select: none;
.installer-tab:hover { border-color: var(--vp-c-brand-2); }
.installer-tab.active { color: var(--vp-c-brand-1); border-color: var(--vp-c-brand-1); background: var(--vp-c-brand-soft); }
.installer-command {
display: flex; align-items: center; gap: 10px; padding: 12px;
border: 1px solid var(--vp-c-divider); border-radius: 9px;
background: var(--vp-code-block-bg);
}

.install-copy {
flex: none;
padding: 4px 12px;
border: 1px solid var(--vp-c-divider);
border-radius: 6px;
font-size: 13px;
font-weight: 500;
color: var(--vp-c-text-2);
transition: border-color 0.2s, color 0.2s;
.installer-command code {
flex: 1; min-width: 0; overflow-x: auto; white-space: nowrap;
font-size: 12px; line-height: 1.6; color: var(--vp-c-text-1);
}

.install-copy:hover {
border-color: var(--vp-c-brand-1);
color: var(--vp-c-brand-1);
}

@media (min-width: 640px) {
.install {
margin-top: 32px;
}
}

@media (max-width: 960px) {
.install {
margin-left: auto;
margin-right: auto;
}
.prompt { color: var(--vp-c-brand-1); user-select: none; }
.installer-copy {
flex: none; padding: 5px 10px; border: 1px solid var(--vp-c-divider);
border-radius: 6px; font-size: 12px; font-weight: 600; color: var(--vp-c-text-2);
}
.installer-copy:hover { color: var(--vp-c-brand-1); border-color: var(--vp-c-brand-1); }
.installer-more { display: inline-block; margin-top: 9px; font-size: 12px; color: var(--vp-c-brand-1); }
@media (max-width: 959px) { .installer { margin-left: auto; margin-right: auto; } }
</style>
6 changes: 6 additions & 0 deletions site/.vitepress/theme/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@
max-width: 560px;
}

/* Korean wraps between words, not between syllables. */
:lang(ko) .VPHome {
word-break: keep-all;
overflow-wrap: break-word;
}

/* Hero: a tinted band in the accent colour, demo in the right column on wide screens. */
.VPHome {
overflow-x: clip;
Expand Down
11 changes: 9 additions & 2 deletions site/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,17 @@ hero:
link: https://github.com/NaNIsaac/codigest

install:
label: Install
command: uv tool install codigest
label: Install Codigest
windowsLabel: Windows
unixLabel: Linux / macOS / Termux
pythonLabel: Python (uv)
windows: 'irm https://raw.githubusercontent.com/NaNIsaac/codigest/main/install.ps1 | iex'
unix: 'curl -fsSL https://raw.githubusercontent.com/NaNIsaac/codigest/main/install.sh | sh'
python: 'uv tool install codigest'
copy: Copy
copied: Copied
moreLabel: All installation options
moreLink: /installation

demo:
alt: cdg cap runs a failing pytest, then cdg pack bundles the failure, the test file it names and the changed file
Expand Down
11 changes: 9 additions & 2 deletions site/ko/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,17 @@ hero:
link: https://github.com/NaNIsaac/codigest

install:
label: 설치
command: uv tool install codigest
label: Codigest 설치
windowsLabel: Windows
unixLabel: Linux / macOS / Termux
pythonLabel: Python (uv)
windows: 'irm https://raw.githubusercontent.com/NaNIsaac/codigest/main/install.ps1 | iex'
unix: 'curl -fsSL https://raw.githubusercontent.com/NaNIsaac/codigest/main/install.sh | sh'
python: 'uv tool install codigest'
copy: 복사
copied: 복사됨
moreLabel: 설치 방법 자세히 보기
moreLink: /ko/installation

demo:
alt: cdg cap으로 실패하는 pytest를 실행한 뒤, cdg pack이 실패 출력과 오류가 가리키는 테스트 파일, 바뀐 파일을 묶는 화면
Expand Down
Loading