From 997007d44743994661c4e642ca60649ed7d9448c Mon Sep 17 00:00:00 2001 From: "Mona,Lisa" Date: Fri, 26 May 2023 17:24:45 +0700 Subject: [PATCH] docs: add banner to v7 docs fix #1497 backport #1487 --- docs/.vitepress/components/Banner.vue | 108 ++++++++++++++++++++++++++ docs/.vitepress/components/shims.d.ts | 7 ++ docs/.vitepress/config.ts | 29 ++++++- docs/.vitepress/theme/index.ts | 20 ++++- docs/.vitepress/versions.ts | 70 ++++++++++++++++- 5 files changed, 228 insertions(+), 6 deletions(-) create mode 100644 docs/.vitepress/components/Banner.vue create mode 100644 docs/.vitepress/components/shims.d.ts diff --git a/docs/.vitepress/components/Banner.vue b/docs/.vitepress/components/Banner.vue new file mode 100644 index 00000000000..9eea81c9c8f --- /dev/null +++ b/docs/.vitepress/components/Banner.vue @@ -0,0 +1,108 @@ + + + + + + + diff --git a/docs/.vitepress/components/shims.d.ts b/docs/.vitepress/components/shims.d.ts new file mode 100644 index 00000000000..7ae275ab099 --- /dev/null +++ b/docs/.vitepress/components/shims.d.ts @@ -0,0 +1,7 @@ +declare const __BANNER__: string | false; + +declare module '*.vue' { + import type { DefineComponent } from 'vue'; + const component: DefineComponent; + export default component; +} diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 65294e08437..f96779f8982 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -1,7 +1,7 @@ import { defineConfig } from 'vitepress'; import { DefaultTheme } from 'vitepress/theme'; import { apiPages } from './api-pages'; -import { currentVersion, oldVersions } from './versions'; +import { currentVersion, oldVersions, versionBannerInfix } from './versions'; type SidebarGroup = DefaultTheme.SidebarGroup; @@ -51,7 +51,7 @@ function extendSideNav(current: SidebarGroup): SidebarGroup[] { return links; } -export default defineConfig({ +const config = defineConfig({ title: 'Faker', description, @@ -229,4 +229,29 @@ export default defineConfig({ }), }, }, + + vite: { + define: { + __BANNER__: versionBannerInfix ?? false, + }, + }, }); + +if (versionBannerInfix) { + config.head?.push([ + 'script', + { id: 'restore-banner-preference' }, + ` +(() => { + const restore = (key, cls, def = false) => { + const saved = localStorage.getItem(key); + if (saved ? saved !== 'false' && new Date() < saved : def) { + document.documentElement.classList.add(cls); + } + }; + restore('faker-version-banner', 'banner-dismissed'); +})();`, + ]); +} + +export default config; diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts index 2423da6bf18..8555a839b70 100644 --- a/docs/.vitepress/theme/index.ts +++ b/docs/.vitepress/theme/index.ts @@ -1,4 +1,22 @@ import DefaultTheme from 'vitepress/theme'; +import { defineAsyncComponent, h } from 'vue'; import './index.css'; -export default DefaultTheme; +export default { + ...DefaultTheme, + Layout() { + return h( + DefaultTheme.Layout, + null, + __BANNER__ + ? { + 'layout-top': () => + h( + defineAsyncComponent(() => import('../components/Banner.vue')), + { version: __BANNER__ } + ), + } + : null + ); + }, +}; diff --git a/docs/.vitepress/versions.ts b/docs/.vitepress/versions.ts index c82a5ee0792..2964557cee9 100644 --- a/docs/.vitepress/versions.ts +++ b/docs/.vitepress/versions.ts @@ -1,7 +1,71 @@ +import { execSync } from 'node:child_process'; +import * as semver from 'semver'; import { version } from '../../package.json'; -export const currentVersion = `v${version}`; +function readBranchName(): string { + return ( + execSync('git branch --show-current').toString('utf8').trim() || 'unknown' + ); +} +function readOtherLatestReleaseTagNames(): string[] { + const currentMajorVersion = semver.major(version); + const latestReleaseTagNames = execSync('git tag -l') + .toString('utf8') + .split('\n') + .filter((tag) => semver.valid(tag)) + .reduce>((acc, tag) => { + const majorVersion = semver.major(tag); + // Only consider tags for our deployed website versions, + // excluding the current major version. + if (majorVersion >= 6 && majorVersion !== currentMajorVersion) { + (acc[majorVersion] = acc[majorVersion] ?? []).push(tag); + } + return acc; + }, {}); + return Object.entries(latestReleaseTagNames) + .map(([major, tags]) => semver.maxSatisfying(tags, `^${major}`)) + .sort(semver.rcompare); +} + +// Set by netlify +const { + CONTEXT: deployContext = 'local', + BRANCH: branchName = readBranchName(), +} = process.env; + +const hiddenLink = + deployContext === 'production' + ? 'https://fakerjs.dev/' + : `https://${branchName}.fakerjs.dev/`; +const otherVersions = readOtherLatestReleaseTagNames(); +const isReleaseBranch = /^v\d+$/.test(branchName); + +export const versionBannerInfix: string | null = (() => { + if (deployContext === 'production') { + return null; + } + if (isReleaseBranch) { + return '"an old version"'; + } + if (branchName === 'next') { + return '"the next (unreleased) version"'; + } + return '"a development version"'; +})(); + +export const currentVersion = isReleaseBranch ? `v${version}` : branchName; export const oldVersions = [ - { version: 'v6.3.1', link: 'https://v6.fakerjs.dev/' }, -]; + { + version: 'latest', + link: 'https://fakerjs.dev/', + }, + { + version: 'next', + link: 'https://next.fakerjs.dev/', + }, + ...otherVersions.map((version) => ({ + version, + link: `https://v${semver.major(version)}.fakerjs.dev/`, + })), +].filter(({ link }) => link !== hiddenLink);