mirror of
https://github.com/AlexxIT/go2rtc.git
synced 2026-04-22 15:47:06 +08:00
Add VitePress documentation site setup
Introduces VitePress configuration and theme files for documentation, updates the GitHub Pages workflow to build and deploy the new docs, and updates .gitignore for VitePress and Node artifacts. Adds necessary dependencies and scripts to package.json, and updates the ONVIF client example README title.
This commit is contained in:
@@ -2,7 +2,9 @@
|
||||
name: Deploy static content to Pages
|
||||
|
||||
on:
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
|
||||
@@ -14,7 +16,7 @@ permissions:
|
||||
# Allow one concurrent deployment
|
||||
concurrency:
|
||||
group: "pages"
|
||||
cancel-in-progress: true
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
# Single deploy job since we're just deploying
|
||||
@@ -25,13 +27,26 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 24
|
||||
package-manager-cache: false
|
||||
- name: Install dependencies
|
||||
run: npm install --no-package-lock
|
||||
- name: Build docs
|
||||
env:
|
||||
BASE_URL: /${{ github.event.repository.name }}/
|
||||
run: npm run docs:build
|
||||
- name: Setup Pages
|
||||
uses: actions/configure-pages@v4
|
||||
uses: actions/configure-pages@v5
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: './website'
|
||||
path: './.vitepress/dist'
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
|
||||
@@ -15,3 +15,9 @@ go2rtc_win*
|
||||
0_test.go
|
||||
|
||||
.DS_Store
|
||||
|
||||
.vitepress/cache
|
||||
.vitepress/dist
|
||||
|
||||
node_modules
|
||||
package-lock.json
|
||||
@@ -0,0 +1,160 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { defineConfig } from 'vitepress';
|
||||
|
||||
const repoRoot = path.resolve(__dirname, '..');
|
||||
const srcDir = repoRoot;
|
||||
const skipDirs = new Set(['.git', 'node_modules', '.vitepress', 'dist', 'scripts']);
|
||||
|
||||
function walkForReadmes(dir: string, results: string[]) {
|
||||
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
||||
if (entry.isDirectory()) {
|
||||
if (skipDirs.has(entry.name)) {
|
||||
continue;
|
||||
}
|
||||
walkForReadmes(path.join(dir, entry.name), results);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry.isFile() && entry.name === 'README.md') {
|
||||
results.push(path.join(dir, entry.name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function extractTitle(filePath: string) {
|
||||
const content = fs.readFileSync(filePath, 'utf8');
|
||||
const match = content.match(/^#\s+(.+)$/m);
|
||||
return match ? match[1].trim() : '';
|
||||
}
|
||||
|
||||
function toTitleCase(value: string) {
|
||||
return value
|
||||
.replace(/[-_]/g, ' ')
|
||||
.replace(/\b\w/g, (char) => char.toUpperCase());
|
||||
}
|
||||
|
||||
function toLink(routePath: string) {
|
||||
const clean = routePath.replace(/index\.md$/, '');
|
||||
return clean ? `/${clean}` : '/';
|
||||
}
|
||||
|
||||
const readmeFiles: string[] = [];
|
||||
walkForReadmes(srcDir, readmeFiles);
|
||||
|
||||
const readmePaths = readmeFiles
|
||||
.map((filePath) => path.relative(srcDir, filePath).replace(/\\/g, '/'))
|
||||
.sort();
|
||||
|
||||
const rewrites = Object.fromEntries(
|
||||
readmePaths.map((relPath) => [relPath, relPath.replace(/README\.md$/, 'index.md')])
|
||||
);
|
||||
|
||||
const groupOrder = ['', 'docker', 'api', 'pkg', 'internal', 'examples', 'www'];
|
||||
const groupTitles = new Map([
|
||||
['', 'Overview'],
|
||||
['api', 'API'],
|
||||
['pkg', 'Packages'],
|
||||
['internal', 'Internal'],
|
||||
['examples', 'Examples'],
|
||||
['docker', 'Docker'],
|
||||
['www', 'WWW'],
|
||||
]);
|
||||
|
||||
const groupedItems = new Map<string, Array<{ text: string; link: string }>>();
|
||||
|
||||
for (const relPath of readmePaths) {
|
||||
const filePath = path.join(srcDir, relPath);
|
||||
const segments = relPath.split('/');
|
||||
const groupKey = segments.length > 1 ? segments[0] : '';
|
||||
const routePath = rewrites[relPath];
|
||||
const link = toLink(routePath);
|
||||
const title = extractTitle(filePath);
|
||||
const fallback = segments.length > 1 ? segments[segments.length - 2] : 'Overview';
|
||||
const text = title || toTitleCase(fallback);
|
||||
|
||||
if (!groupedItems.has(groupKey)) {
|
||||
groupedItems.set(groupKey, []);
|
||||
}
|
||||
groupedItems.get(groupKey)?.push({ text, link });
|
||||
}
|
||||
|
||||
for (const items of groupedItems.values()) {
|
||||
items.sort((a, b) => a.text.localeCompare(b.text));
|
||||
}
|
||||
|
||||
const orderedGroups = [...groupedItems.entries()].sort((a, b) => {
|
||||
const indexA = groupOrder.indexOf(a[0]);
|
||||
const indexB = groupOrder.indexOf(b[0]);
|
||||
if (indexA !== -1 || indexB !== -1) {
|
||||
return (indexA === -1 ? Number.POSITIVE_INFINITY : indexA) -
|
||||
(indexB === -1 ? Number.POSITIVE_INFINITY : indexB);
|
||||
}
|
||||
return a[0].localeCompare(b[0]);
|
||||
});
|
||||
|
||||
const sidebar = orderedGroups.flatMap(([groupKey, items]) => {
|
||||
const groupTitle = groupTitles.get(groupKey) || toTitleCase(groupKey || 'Overview');
|
||||
if (items.length === 1) {
|
||||
const [item] = items;
|
||||
return [{ text: groupTitle, link: item.link }];
|
||||
}
|
||||
return [{
|
||||
text: groupTitle,
|
||||
collapsed: groupKey !== '',
|
||||
items,
|
||||
}];
|
||||
});
|
||||
|
||||
const nav = orderedGroups
|
||||
.filter(([, items]) => items.length > 0)
|
||||
.map(([groupKey, items]) => {
|
||||
if (groupKey === '') {
|
||||
return { text: groupTitles.get(groupKey) || 'Overview', link: '/' };
|
||||
}
|
||||
const landing = items.find((item) => item.link === `/${groupKey}/`) ?? items[0];
|
||||
return {
|
||||
text: groupTitles.get(groupKey) || toTitleCase(groupKey),
|
||||
link: landing.link,
|
||||
};
|
||||
});
|
||||
|
||||
export default defineConfig({
|
||||
lang: 'en-US',
|
||||
title: 'go2rtc Docs',
|
||||
description: 'go2rtc documentation',
|
||||
srcDir,
|
||||
base: process.env.BASE_URL || '/',
|
||||
cleanUrls: true,
|
||||
ignoreDeadLinks: true,
|
||||
rewrites,
|
||||
head: [
|
||||
['link', { rel: 'preconnect', href: 'https://fonts.googleapis.com' }],
|
||||
['link', { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: '' }],
|
||||
[
|
||||
'link',
|
||||
{
|
||||
rel: 'stylesheet',
|
||||
href:
|
||||
'https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&family=IBM+Plex+Sans:wght@400;500;600;700&display=swap',
|
||||
},
|
||||
],
|
||||
],
|
||||
markdown: {
|
||||
theme: {
|
||||
light: "catppuccin-latte",
|
||||
dark: "catppuccin-mocha",
|
||||
},
|
||||
},
|
||||
themeConfig: {
|
||||
nav,
|
||||
sidebar: {
|
||||
'/': sidebar,
|
||||
},
|
||||
outline: [2, 3],
|
||||
search: {
|
||||
provider: 'local',
|
||||
},
|
||||
socialLinks: [{ icon: "github", link: "https://github.com/AlexxIT/go2rtc" }],
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
.VPSidebarItem.level-1 {
|
||||
font-weight: 700;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import DefaultTheme from 'vitepress/theme';
|
||||
import "@catppuccin/vitepress/theme/mocha/mauve.css";
|
||||
import './custom.css';
|
||||
|
||||
export default DefaultTheme;
|
||||
@@ -1,4 +1,4 @@
|
||||
## Example
|
||||
## ONVIF Client
|
||||
|
||||
```shell
|
||||
go run examples/onvif_client/main.go http://admin:password@192.168.10.90 GetAudioEncoderConfigurations
|
||||
|
||||
@@ -37,8 +37,8 @@ Settings > Stream:
|
||||
|
||||
- Service: Custom
|
||||
- Server: rtmp://192.168.10.101/tmp
|
||||
- Stream Key: <empty>
|
||||
- Use auth: <disabled>
|
||||
- Stream Key: `<empty>`
|
||||
- Use auth: `<disabled>`
|
||||
|
||||
**OpenIPC**
|
||||
|
||||
|
||||
+10
-1
@@ -1,7 +1,13 @@
|
||||
{
|
||||
"devDependencies": {
|
||||
"eslint": "^8.44.0",
|
||||
"eslint-plugin-html": "^7.1.0"
|
||||
"eslint-plugin-html": "^7.1.0",
|
||||
"vitepress": "^2.0.0-alpha.15"
|
||||
},
|
||||
"scripts": {
|
||||
"docs:dev": "vitepress dev .",
|
||||
"docs:build": "vitepress build .",
|
||||
"docs:preview": "vitepress preview ."
|
||||
},
|
||||
"eslintConfig": {
|
||||
"env": {
|
||||
@@ -36,5 +42,8 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@catppuccin/vitepress": "^0.1.2"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user