vitepress-plugin-report-issue
Ctrl+Enter on any VitePress page opens a modal that packs the URL, the current page title and the selected fragment into a pre-filled /<owner>/<repo>/issues/new?title=...&body=...&labels=... link on Forgejo/Gitea. The user then presses "Submit" inside the tracker UI they are already logged into.
No backend, no tokens, no CORS: the plugin only assembles a URL and hands it to the browser. Everything a documentation bug reporter needs is to read the page, highlight the problematic snippet and press the shortcut.
Installation
pnpm add @ampernic/vitepress-plugin-report-issuePackages in the @ampernic scope are published to the Forgejo registry. When installing outside of npm, add .npmrc to the project root:
@ampernic:registry=https://altlinux.space/api/packages/ampernic/npm/Usage
Registered as a Vue plugin in enhanceApp; the dialog is mounted once in the layout.
// .vitepress/theme/index.ts
import DefaultTheme from 'vitepress/theme'
import { h } from 'vue'
import ReportIssuePlugin, { ReportIssueDialog } from '@ampernic/vitepress-plugin-report-issue'
export default {
extends: DefaultTheme,
enhanceApp({ app }) {
app.use(ReportIssuePlugin, {
repo: 'alt-docs/docs-vitepress',
origin: 'https://altlinux.space',
labels: ['documentation'],
shortcut: 'ctrl-enter',
locale: 'en',
})
},
Layout: () => h(DefaultTheme.Layout, null, {
'layout-top': () => h(ReportIssueDialog),
}),
}The plugin binds a global keydown handler and opens the modal on a matching shortcut. The same option, passed as a prop to <ReportIssueDialog>, overrides the plugin config: handy when a specific subsection needs to file into a different repository.
Through createSharedConfig in @ampernic/vitepress-theme-alt-docs the same options are wired via the reportIssue field.
Options
| Option | Type | Default | Description |
|---|---|---|---|
repo | string | -- | Required. owner/name slug of a Forgejo/Gitea repository |
origin | string | 'https://altlinux.space' | Base of the Forgejo/Gitea instance |
labels | string[] | [] | Labels attached to the issue through the query |
shortcut | 'ctrl-enter' | 'meta-enter' | 'ctrl-enter' | Trigger shortcut. meta-enter is Cmd+Enter on macOS |
locale | string | useData().lang | Overrides the dialog UI language |
fallbackLocale | string | 'en' | Locale fallback when the current one has no translation |
messages | Partial<Record<string, Partial<Messages>>> | {} | Point translations of specific strings per locale |
Localization
ru and en are bundled. Extra locales are supplied via messages; the field keys live in Messages (every string a user can see). Adding German:
app.use(ReportIssuePlugin, {
repo: 'my-org/my-docs',
messages: {
de: {
title: 'Dokumentationsfehler melden',
submit: 'Bei Forgejo weiter',
},
},
})Why URL, not POST
A URL pre-fill opens the issue creation form in the Forgejo UI where the user is already authenticated. No service token, no configured CORS, no custom rate limit. When the project grows to headless submission (a mobile app, an iframe embed), the same assembled URL can be pushed to /api/v1/repos/{owner}/{repo}/issues with a personal token.