| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -86,7 +86,7 @@ if (import.meta.client) { | |||
| 86 | 86 | > | |
| 87 | 87 | <NuxtPage /> | |
| 88 | 88 | </main> | |
| 89 | - <LazySiteFooter hydrate-never /> | ||
| 89 | + <LazySiteFooter hydrate-on-visible /> | ||
| 90 | 90 | </div> | |
| 91 | 91 | </template> | |
| 92 | 92 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,17 +1,15 @@ | |||
| 1 | 1 | <script setup lang="ts"> | |
| 2 | 2 | import type { ContributorsResponse } from '#shared/types' | |
| 3 | 3 | ||
| 4 | - // Server-rendered: a client-only avatar row lands after hydration and pushes the colophon down. | ||
| 5 | - const { data: credits } = await useFetch<ContributorsResponse>('/api/v1/contributors', { | ||
| 4 | + // Server-rendered: a client-only credit line lands after hydration and pushes the colophon down. | ||
| 5 | + // Only the count survives into the payload; the avatars and profiles are not drawn here. | ||
| 6 | + const { data: credits } = await useFetch('/api/v1/contributors', { | ||
| 6 | 7 | key: 'footer-contributors', | |
| 7 | - // The colophon never hydrates, so the avatar list need not go into the payload. | ||
| 8 | - serialize: false, | ||
| 8 | + /** Named in the template: danielroe, qwerzl, florian-lefebvre. Zero when GitHub is rate-limited. */ | ||
| 9 | + transform: (response: ContributorsResponse) => ({ others: Math.max(0, (response.contributors?.length ?? 0) - 3) }), | ||
| 9 | 10 | }) | |
| 10 | 11 | ||
| 11 | - const contributors = computed(() => credits.value?.contributors ?? []) | ||
| 12 | - | ||
| 13 | - /** Named above: danielroe, qwerzl, florian-lefebvre. Zero when GitHub is rate-limited. */ | ||
| 14 | - const others = computed(() => Math.max(0, contributors.value.length - 3)) | ||
| 12 | + const others = computed(() => credits.value?.others ?? 0) | ||
| 15 | 13 | </script> | |
| 16 | 14 | ||
| 17 | 15 | <template> | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,5 +1,10 @@ | |||
| 1 | 1 | import { createContentClient } from 'comark-content/client' | |
| 2 | 2 | ||
| 3 | 3 | export const clientContent = createContentClient({ | |
| 4 | - fetch: $fetch, | ||
| 4 | + /* | ||
| 5 | + * `responseType: 'json'` rather than a bare `$fetch`: the endpoints are prerendered to | ||
| 6 | + * extensionless files, and a page whose own prerender runs after one of them is handed that | ||
| 7 | + * file with no content type, which `ofetch` leaves as a string. | ||
| 8 | + */ | ||
| 9 | + fetch: (request, options) => $fetch(request as string, { ...options, responseType: 'json' }), | ||
| 5 | 10 | }) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -54,7 +54,7 @@ usePageSeo({ | |||
| 54 | 54 | >Back to the start</NuxtLink> | |
| 55 | 55 | </div> | |
| 56 | 56 | </main> | |
| 57 | - <LazySiteFooter hydrate-never /> | ||
| 57 | + <LazySiteFooter hydrate-on-visible /> | ||
| 58 | 58 | </div> | |
| 59 | 59 | </template> | |
| 60 | 60 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -211,9 +211,14 @@ export default defineNuxtConfig({ | |||
| 211 | 211 | 'prerender:routes': async ({ routes }) => { | |
| 212 | 212 | const { content } = await import('./server/utils/content.ts') | |
| 213 | 213 | const pages = new Set(proseRoutes) | |
| 214 | - for (const { path } of await content.list()) { | ||
| 214 | + const paths = (await content.list()).map((file: { path: string }) => file.path) | ||
| 215 | + for (const path of paths) { | ||
| 215 | 216 | routes.add(path) | |
| 216 | - routes.add(`/api/content/get/${path.replace(/^\//, '')}`) | ||
| 217 | + // Each endpoint is prerendered to a file, so `/docs`, which is also the parent of every | ||
| 218 | + // chapter, would have to be a file and a directory at once. It is left to the server. | ||
| 219 | + if (!paths.some((other: string) => other.startsWith(`${path}/`))) { | ||
| 220 | + routes.add(`/api/content/get/${path.replace(/^\//, '')}`) | ||
| 221 | + } | ||
| 217 | 222 | pages.add(path) | |
| 218 | 223 | } | |
| 219 | 224 | for (const page of pages) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,6 +1,31 @@ | |||
| 1 | + import { existsSync } from 'node:fs' | ||
| 2 | + import { fileURLToPath } from 'node:url' | ||
| 3 | + import type { Driver } from 'unstorage' | ||
| 1 | 4 | import { comarkContent } from 'comark-content' | |
| 2 | - import fs from 'comark-content/sources/fs' | ||
| 5 | + import fsSource from 'comark-content/sources/fs' | ||
| 6 | + import unstorageSource from 'comark-content/sources/unstorage' | ||
| 7 | + import { useStorage } from 'nitro/storage' | ||
| 3 | 8 | ||
| 4 | - export const content = comarkContent({ | ||
| 5 | - source: fs('./content'), | ||
| 6 | - }) | ||
| 9 | + /** | ||
| 10 | + * `content/` is next to this module only when it is loaded from source, which is how | ||
| 11 | + * `nuxt.config.ts` lists the pages to prerender before nitro exists. Anywhere the server has been | ||
| 12 | + * bundled the markdown is read back from the `content` server asset instead, because a deployment | ||
| 13 | + * has no `content/` directory. | ||
| 14 | + */ | ||
| 15 | + const contentDir = fileURLToPath(new URL('../../content', import.meta.url)) | ||
| 16 | + | ||
| 17 | + /** The `content` server asset, as the driver `unstorageSource` wants rather than a `Storage`. */ | ||
| 18 | + function assetDriver(): Driver { | ||
| 19 | + const storage = useStorage('assets:content') | ||
| 20 | + return { | ||
| 21 | + name: 'server-assets', | ||
| 22 | + options: {}, | ||
| 23 | + getKeys: () => storage.getKeys(), | ||
| 24 | + hasItem: key => storage.hasItem(key), | ||
| 25 | + getItem: key => storage.getItem(key), | ||
| 26 | + } | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + const source = existsSync(contentDir) ? fsSource(contentDir) : unstorageSource({ driver: assetDriver() }) | ||
| 30 | + | ||
| 31 | + export const content = comarkContent({ source }) | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments