diff --git a/README.md b/README.md index 5a48d0e..e6ba73d 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ -![Host Patrol Web UI Screenshot](https://github.com/vst/hostpatrol/assets/374793/88e33afd-7b0b-45b6-a542-01c5994af076) +![Host Patrol Web UI Screenshot](https://github.com/vst/hostpatrol/assets/374793/416e1135-fe9a-4998-8acc-de07dd62c88b) Host Patrol (`hostpatrol`) is a command-line application to retrieve information from remote hosts. The information is retrieved over SSH diff --git a/website/next.config.mjs b/website/next.config.mjs index 7fee4b0..30c70bb 100644 --- a/website/next.config.mjs +++ b/website/next.config.mjs @@ -1,4 +1,5 @@ import createMDX from '@next/mdx'; +import rehypePrettyCode from 'rehype-pretty-code'; /** @type {import('next').NextConfig} */ const nextConfig = { @@ -17,6 +18,18 @@ const nextConfig = { pageExtensions: ['js', 'jsx', 'md', 'mdx', 'ts', 'tsx'], }; -const withMDX = createMDX({}) +const withMDX = createMDX({ + options: { + remarkPlugins: [], + rehypePlugins: [ + [ + rehypePrettyCode, + { + theme: 'dracula', + }, + ], + ], + }, +}); export default withMDX(nextConfig); diff --git a/website/package-lock.json b/website/package-lock.json index 80fbdfe..df95394 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -22,7 +22,9 @@ "react-dom": "^18", "react-icons": "^5.1.0", "react-toastify": "^10.0.5", - "recharts": "^2.12.3" + "recharts": "^2.12.3", + "rehype-pretty-code": "^0.13.1", + "shiki": "^1.3.0" }, "devDependencies": { "@tailwindcss/typography": "^0.5.12", @@ -2763,6 +2765,11 @@ "dev": true, "license": "MIT" }, + "node_modules/@shikijs/core": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.3.0.tgz", + "integrity": "sha512-7fedsBfuILDTBmrYZNFI8B6ATTxhQAasUHllHmjvSZPnoq4bULWoTpHwmuQvZ8Aq03/tAa2IGo6RXqWtHdWaCA==" + }, "node_modules/@swc/helpers": { "version": "0.5.2", "license": "Apache-2.0", @@ -4233,6 +4240,17 @@ "node": ">=10.13.0" } }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/es-abstract": { "version": "1.22.5", "dev": true, @@ -5347,6 +5365,54 @@ "node": ">= 0.4" } }, + "node_modules/hast-util-from-html": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.1.tgz", + "integrity": "sha512-RXQBLMl9kjKVNkJTIO6bZyb2n+cUH8LFaSSzo82jiLT6Tfc+Pt7VQCS+/h3YwG4jaNE2TA2sdJisGWR+aJrp0g==", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.1.0", + "hast-util-from-parse5": "^8.0.0", + "parse5": "^7.0.0", + "vfile": "^6.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.1.tgz", + "integrity": "sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^8.0.0", + "property-information": "^6.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-to-estree": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.0.tgz", @@ -5413,6 +5479,18 @@ "inline-style-parser": "0.2.3" } }, + "node_modules/hast-util-to-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.0.tgz", + "integrity": "sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-whitespace": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", @@ -5425,6 +5503,22 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hastscript": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-8.0.0.tgz", + "integrity": "sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/ignore": { "version": "5.3.1", "dev": true, @@ -7316,6 +7410,22 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" }, + "node_modules/parse-numeric-range": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz", + "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==" + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/path-exists": { "version": "4.0.0", "dev": true, @@ -7972,6 +8082,39 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/rehype-parse": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.0.tgz", + "integrity": "sha512-WG7nfvmWWkCR++KEkZevZb/uw41E8TsH4DsY9UxsTbIXCVGbAs4S+r8FrQ+OtH5EEQAs+5UxKC42VinkmpA1Yw==", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-from-html": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-pretty-code": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/rehype-pretty-code/-/rehype-pretty-code-0.13.1.tgz", + "integrity": "sha512-Lw3cZohiw5J2NMMD0M11W9HlIKrZ7JjxfJmY0nxVa/HG5oMT+kkhcrUEFB5ajaEk/E9uR8+n9AmQbGJci9/TqA==", + "dependencies": { + "@types/hast": "^3.0.4", + "hast-util-to-string": "^3.0.0", + "parse-numeric-range": "^1.3.0", + "rehype-parse": "^9.0.0", + "unified": "^11.0.4", + "unist-util-visit": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "shiki": "^1.0.0" + } + }, "node_modules/remark-mdx": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.0.1.tgz", @@ -8313,6 +8456,14 @@ "node": ">=8" } }, + "node_modules/shiki": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.3.0.tgz", + "integrity": "sha512-9aNdQy/etMXctnPzsje1h1XIGm9YfRcSksKOGqZWXA/qP9G18/8fpz5Bjpma8bOgz3tqIpjERAd6/lLjFyzoww==", + "dependencies": { + "@shikijs/core": "1.3.0" + } + }, "node_modules/side-channel": { "version": "1.0.6", "dev": true, @@ -9212,6 +9363,19 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/vfile-location": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.2.tgz", + "integrity": "sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/vfile-message": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", @@ -9259,6 +9423,15 @@ "node": ">=10.13.0" } }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/webpack": { "version": "5.91.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.91.0.tgz", diff --git a/website/package.json b/website/package.json index 66eaac0..4429389 100644 --- a/website/package.json +++ b/website/package.json @@ -8,7 +8,7 @@ "start": "next start", "lint": "next lint", "format-check": "prettier --check \"src/**/*.{ts,tsx,md,mdx}\"", - "format": "prettier --write \"src/**/*.{ts,tsx,md,mdx}\"", + "format": "prettier --write \"src/**/*.{ts,tsx,md,mdx,css}\" next.config.mjs", "check": "npm run format-check && npm run lint && npm run build" }, "dependencies": { @@ -26,7 +26,9 @@ "react-dom": "^18", "react-icons": "^5.1.0", "react-toastify": "^10.0.5", - "recharts": "^2.12.3" + "recharts": "^2.12.3", + "rehype-pretty-code": "^0.13.1", + "shiki": "^1.3.0" }, "devDependencies": { "@tailwindcss/typography": "^0.5.12", diff --git a/website/src/app/(landing)/page.tsx b/website/src/app/(landing)/page.tsx index 6b9390c..6e50010 100644 --- a/website/src/app/(landing)/page.tsx +++ b/website/src/app/(landing)/page.tsx @@ -34,7 +34,9 @@ function Hero() {
- +
+ +
@@ -90,10 +92,10 @@ function Hero() {
App screenshot
diff --git a/website/src/app/(pages)/layout.tsx b/website/src/app/(pages)/layout.tsx index 7163fd0..7b209f9 100644 --- a/website/src/app/(pages)/layout.tsx +++ b/website/src/app/(pages)/layout.tsx @@ -1,3 +1,3 @@ export default function MdxLayout({ children }: { children: React.ReactNode }) { - return
{children}
; + return
{children}
; } diff --git a/website/src/app/(pages)/quickstart/page.mdx b/website/src/app/(pages)/quickstart/page.mdx index c71914e..c9d082c 100644 --- a/website/src/app/(pages)/quickstart/page.mdx +++ b/website/src/app/(pages)/quickstart/page.mdx @@ -51,7 +51,7 @@ nix profile install --file https://github.com/vst/hostpatrol/archive/v. Instead of providing hosts one-by-one, you can use a configuration file. For example given a configuration file `config.yaml` like this: -```yaml +```yaml showLineNumbers ## List of known SSH public keys for all hosts. knownSshKeys: - gh:some-github-user diff --git a/website/src/app/globals.css b/website/src/app/globals.css index 7af9b64..62a7eb5 100644 --- a/website/src/app/globals.css +++ b/website/src/app/globals.css @@ -3,5 +3,29 @@ @tailwind utilities; .text-balance { - text-wrap: balance; + text-wrap: balance; +} + +code { + counter-reset: line; +} + +code > [data-line]::before { + counter-increment: line; + content: counter(line); + + /* Other styling */ + display: inline-block; + width: 1rem; + margin-right: 1rem; + text-align: right; + color: gray; +} + +code[data-line-numbers-max-digits='2'] > [data-line]::before { + width: 2rem; +} + +code[data-line-numbers-max-digits='3'] > [data-line]::before { + width: 3rem; }