feat(docs): serve versioned documentation via Astro middleware#4929
Draft
brian-mulier-p wants to merge 6 commits into
Draft
feat(docs): serve versioned documentation via Astro middleware#4929brian-mulier-p wants to merge 6 commits into
brian-mulier-p wants to merge 6 commits into
Conversation
Contributor
☁️ Cloudflare Worker Preview Deployed!🔗 https://ks-feat-versioned-docs-docs.kestra-io.workers.dev ## 🔦 Lighthouse Benchmark
Scores (0–100, higher is better)
Core Web Vitals (lower is better)
Legend🟢 improved · 🔻 regressed · (blank) no significant change |
5876137 to
289b0cc
Compare
| const onVersionChange = (event: Event) => { | ||
| const version = (event.target as HTMLSelectElement).value | ||
| if (!version) return | ||
| window.location.href = versionedHref(version, window.location.pathname) |
d130fe3 to
405fa71
Compare
Serve kestra.io/docs/{MAJOR.MINOR}/{path} (e.g. /docs/1.3/...) for past
releases by fetching raw markdown from api.kestra.io and rendering it
inline through a standalone HTML page, while the latest /docs stays the
Astro static site.
- Middleware (regex-gated) detects /docs/{major.minor}/... and short-
circuits routing; non-numeric first segments (the latest docs) are left
untouched; a 404 from the API redirects to the version home.
- renderVersionedDoc builds a standalone page (createMarkdownProcessor,
shiki off since themes aren't bundled in the Worker) with a version
selector and noindex. remark-directive plus a small throw-free transform
style the known MDC components (alert/collapse/badge) and let unknown /
relic ::blocks degrade to a plain <div> with content preserved (no "::"
leak), mirroring the Kestra UI MDC unknown-component fallback.
- versionedDocs helpers: version discovery (>=0.19 integer-compare float
guard), API path mapping, href + frontmatter helpers. The newest version
is folded into a single "Latest (X)" selector entry (pointing at the
static /docs) instead of appearing twice.
- Version selector added to the latest-docs sidebar (NavSideBar.vue).
- Version list cached per worker isolate with a 10-minute TTL.
- vitest + 32 unit tests, oxlint clean.
Refs kestra-io/kestra-ee#7397
Fetch the docs-children endpoint per version and render a tree-like nav sidebar on the standalone JS-less versioned pages. The active leaf gets aria-current and its ancestors render <details open> server-side, so the current section is expanded without JS; a small inline script handles the collapse toggle and scrolls the active link into view. buildDocTree relies on the parent-prefix invariant (verified across all served versions) and drops hideSidebar pages and their subtree to match the latest-docs sidebar. getDocChildren memoizes per version and fails soft to an empty map, so the page degrades to a single column on error.
Swap the versioned-doc renderer's parser from remark-directive (via Astro's createMarkdownProcessor) to @nuxtjs/mdc's createMarkdownParser, keeping JS-less HTML output via a hand-written serializer. This parses both MDC dialects natively: - 0.19-0.24 `::` block components - 1.0/1.1 `:::` fenced components (incl. `:buttons='[...]'` JSON props) so HomePageButtons CTA rows now actually render on 1.1 (the original complaint) and on the `::`-era pages, instead of leaking or being stripped. Drops the HOMEPAGE_BUTTONS_RE / stripUnsupportedMdc pre-processing those formats needed. Confined to renderVersionedDoc.ts (+ test) for easy revert; the now-dead versionedDocs.ts exports are left in place.
18a3001 to
42172d7
Compare
The homepage button labels were invisible: `.vd-content a` (link color, specificity 0,1,1) overrode `.vd-button` (0,1,0), painting the text the same purple as the background. Mirror the live HomePageButtons instead — first button primary, the rest secondary — using `.vd-content .vd-button*` selectors that win the cascade, with colors from the design tokens (primary #631bff/white with the inset glow; secondary themed light/dark).
Re-point every asset reference (img/source/video[+poster]/audio) in a
versioned doc page at the versioned asset API, so a versioned page serves
versioned resources — mirroring the in-app ProseImg + doc store.
- isVersionedAssetRef + versionedAssetUrl: root-absolute refs with a file
extension are rewritten to ${api}/docs${src}/versions/{ver}.0 (prepends the
/docs domain to the verbatim ref, like the in-app resourceUrl); external,
protocol-relative and relative refs are left untouched.
- rewriteAssetUrls: tree pre-pass mutating props.src/poster before serialize.
- apiUrl DI param (default api.kestra.io/v1), wired from middleware's API_URL.
Versioned doc pages now reference assets served from api.kestra.io, but the site CSP img-src had no kestra domain, so the browser blocked every versioned image. Add https://*.kestra.io (matching script-src/connect-src).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Serve
kestra.io/docs/{MAJOR.MINOR}/{path}(e.g./docs/1.3/...) for past releases by fetching raw markdown from api.kestra.io and rendering it inline through a standalone HTML page. The latest/docsstays the Astro static site.What
/docs/{major.minor}/...and short-circuits routing. Non-numeric first segments (the latest docs) are left untouched; a 404 from the API redirects to the version home.renderVersionedDocbuilds a standalone page (createMarkdownProcessor, shiki off — themes aren't bundled in the Worker) withnoindex.remark-directive+ a small throw-free transform style the known MDC components (::alert/::collapse/::badge) and let unknown/relic::blocks degrade to a plain<div>with content preserved (no::leak), mirroring the Kestra UI MDC unknown-component fallback.:::HomePageButtonscarries its CTAs in a:buttons='[…]'Vue-bind attribute that is invalidremark-directivesyntax (so it leaked as literal text) — now parsed and rendered as a styled link row.HomePageHeader/WhatsNew/BigChildCards/…) are stripped instead of emitting stray empty<div>s.:PluginCount(an inline island) rendered as a block<div>that split its paragraph — unstyled inline directives now render as<span>.prefers-color-scheme), the full top-level nav (Product / Solutions / Plugins / Learn / Company / Pricing) as click-to-toggle dropdowns that collapse into a hamburger drawer on mobile, Contact Sales + Get Started CTAs, and the version selector. One tiny inline, framework-free script drives the menu (no asset graph).versionedDocshelpers: version discovery (>=0.19integer-compare float guard), API path mapping, href + frontmatter helpers, nav data +HomePageButtonsparsing.NavSideBar.vue).wrangler dev+astro dev(desktop dropdowns, mobile hamburger drawer, click-toggle path).Limitations
:PluginCountrenders empty — the live count is a JS island with no SSR equivalent on this standalone page; the surrounding prose is intact, just without the number.Closes https://github.com/kestra-io/kestra-ee/issues/7397