diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-11-02 22:03:42 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-11-02 22:03:42 +0900 |
| commit | fc651662cb9dd86dcb3010ba6cf35399b7c25587 (patch) | |
| tree | 2bc54e43cf8ada8a0250ce997e7cc86a58fd913a /services/nuldoc/nuldoc-src | |
| parent | 4536c5ebaea16c291e8e1cd932b934302d7620ac (diff) | |
| download | nsfisis.dev-fc651662cb9dd86dcb3010ba6cf35399b7c25587.tar.gz nsfisis.dev-fc651662cb9dd86dcb3010ba6cf35399b7c25587.tar.zst nsfisis.dev-fc651662cb9dd86dcb3010ba6cf35399b7c25587.zip | |
feat(nuldoc): Update generator for multi-site structure
Diffstat (limited to 'services/nuldoc/nuldoc-src')
21 files changed, 134 insertions, 46 deletions
diff --git a/services/nuldoc/nuldoc-src/commands/build.ts b/services/nuldoc/nuldoc-src/commands/build.ts index 8c8de8f..8250e04 100644 --- a/services/nuldoc/nuldoc-src/commands/build.ts +++ b/services/nuldoc/nuldoc-src/commands/build.ts @@ -27,15 +27,21 @@ export async function runBuildCommand(config: Config) { await buildPostListPage(posts, config); const slides = await buildSlidePages(config); await buildSlideListPage(slides, config); - const tags = await buildTagPages(posts, slides, config); - await buildTagListPage(tags, config); + const postTags = await buildTagPages(posts, "blog", config); + await buildTagListPage(postTags, "blog", config); + const slidesTags = await buildTagPages(slides, "slides", config); + await buildTagListPage(slidesTags, "slides", config); await buildHomePage(config); await buildAboutPage(slides, config); - await buildNotFoundPage(config); + await buildNotFoundPage("default", config); + await buildNotFoundPage("about", config); + await buildNotFoundPage("blog", config); + await buildNotFoundPage("slides", config); await buildFeedOfAllContents(posts, slides, config); await copyStaticFiles(config); await copySlidesFiles(slides, config); - await copyAssetFiles(config); + await copyBlogAssetFiles(config); + await copySlidesAssetFiles(config); } async function buildPostPages(config: Config): Promise<PostPage[]> { @@ -90,6 +96,7 @@ async function buildPostListPage(posts: PostPage[], config: Config) { "posts", `投稿一覧|${config.blog.siteName}`, posts, + "blog", config, ); await writePage(postFeedPage, config); @@ -135,6 +142,7 @@ async function buildSlideListPage(slides: SlidePage[], config: Config) { "slides", `スライド一覧|${config.blog.siteName}`, slides, + "slides", config, ); await writePage(slideFeedPage, config); @@ -150,8 +158,11 @@ async function buildAboutPage(slides: SlidePage[], config: Config) { await writePage(aboutPage, config); } -async function buildNotFoundPage(config: Config) { - const notFoundPage = await generateNotFoundPage(config); +async function buildNotFoundPage( + site: "default" | "about" | "blog" | "slides", + config: Config, +) { + const notFoundPage = await generateNotFoundPage(site, config); await writePage(notFoundPage, config); } @@ -165,26 +176,28 @@ async function buildFeedOfAllContents( "all", config.blog.siteName, [...posts, ...slides], + "default", config, ); await writePage(feed, config); } async function buildTagPages( - posts: PostPage[], - slides: SlidePage[], + pages: TaggedPage[], + site: "blog" | "slides", config: Config, ): Promise<TagPage[]> { - const tagsAndPages = collectTags([...posts, ...slides]); + const tagsAndPages = collectTags(pages); const tags = []; for (const [tag, pages] of tagsAndPages) { - const tagPage = await generateTagPage(tag, pages, config); + const tagPage = await generateTagPage(tag, pages, site, config); await writePage(tagPage, config); const tagFeedPage = await generateFeedPageFromEntries( tagPage.href, `tag-${tag}`, `タグ「${getTagLabel(config, tag)}」一覧|${config.blog.siteName}`, pages, + site, config, ); await writePage(tagFeedPage, config); @@ -193,8 +206,12 @@ async function buildTagPages( return tags; } -async function buildTagListPage(tags: TagPage[], config: Config) { - const tagListPage = await generateTagListPage(tags, config); +async function buildTagListPage( + tags: TagPage[], + site: "blog" | "slides", + config: Config, +) { + const tagListPage = await generateTagListPage(tags, site, config); await writePage(tagListPage, config); } @@ -226,14 +243,20 @@ function collectTags(taggedPages: TaggedPage[]): [string, TaggedPage[]][] { } async function copyStaticFiles(config: Config) { - const globPattern = joinGlobs([Deno.cwd(), config.locations.staticDir, "*"]); - for await (const entry of expandGlob(globPattern)) { - const src = entry.path; - const dst = src.replace( + for (const site of Object.keys(config.sites)) { + const globPattern = joinGlobs([ + Deno.cwd(), config.locations.staticDir, - config.locations.destDir, - ); - await Deno.copyFile(src, dst); + "*", + ]); + for await (const entry of expandGlob(globPattern)) { + const src = entry.path; + const dst = src.replace( + config.locations.staticDir, + join(config.locations.destDir, site), + ); + await Deno.copyFile(src, dst); + } } } @@ -244,16 +267,41 @@ async function copySlidesFiles(slides: SlidePage[], config: Config) { for (const slide of slides) { const src = join(contentDir, slide.slideLink); - const dst = join(destDir, slide.slideLink); + const dst = join(destDir, "slides", slide.slideLink); await ensureDir(dirname(dst)); await Deno.copyFile(src, dst); } } -async function copyAssetFiles(config: Config) { +async function copyBlogAssetFiles(config: Config) { const cwd = Deno.cwd(); - const contentDir = join(cwd, config.locations.contentDir); - const destDir = join(cwd, config.locations.destDir); + const contentDir = join(cwd, config.locations.contentDir, "posts"); + const destDir = join(cwd, config.locations.destDir, "blog"); + + const globPattern = joinGlobs([contentDir, "**", "*"]); + for await (const { isFile, path } of expandGlob(globPattern)) { + if (!isFile) continue; + + // Skip .dj, .toml, .pdf files + if ( + path.endsWith(".dj") || + path.endsWith(".toml") || + path.endsWith(".pdf") + ) { + continue; + } + + const src = path; + const dst = join(destDir, "posts", relative(contentDir, path)); + await ensureDir(dirname(dst)); + await Deno.copyFile(src, dst); + } +} + +async function copySlidesAssetFiles(config: Config) { + const cwd = Deno.cwd(); + const contentDir = join(cwd, config.locations.contentDir, "slides"); + const destDir = join(cwd, config.locations.destDir, "slides"); const globPattern = joinGlobs([contentDir, "**", "*"]); for await (const { isFile, path } of expandGlob(globPattern)) { @@ -269,7 +317,7 @@ async function copyAssetFiles(config: Config) { } const src = path; - const dst = join(destDir, relative(contentDir, path)); + const dst = join(destDir, "slides", relative(contentDir, path)); await ensureDir(dirname(dst)); await Deno.copyFile(src, dst); } @@ -279,6 +327,7 @@ async function writePage(page: Page, config: Config) { const destFilePath = join( Deno.cwd(), config.locations.destDir, + page.site, page.destFilePath, ); await ensureDir(dirname(destFilePath)); diff --git a/services/nuldoc/nuldoc-src/components/GlobalFooter.tsx b/services/nuldoc/nuldoc-src/components/GlobalFooter.tsx index 757bece..6a8d8f6 100644 --- a/services/nuldoc/nuldoc-src/components/GlobalFooter.tsx +++ b/services/nuldoc/nuldoc-src/components/GlobalFooter.tsx @@ -3,7 +3,7 @@ import { Config } from "../config.ts"; export default function GlobalFooter({ config }: { config: Config }) { return ( <footer className="footer"> - {`© ${config.blog.siteCopyrightYear} ${config.blog.author}`} + {`© ${config.site.copyrightYear} ${config.blog.author}`} </footer> ); } diff --git a/services/nuldoc/nuldoc-src/config.ts b/services/nuldoc/nuldoc-src/config.ts index adcb563..e6af58c 100644 --- a/services/nuldoc/nuldoc-src/config.ts +++ b/services/nuldoc/nuldoc-src/config.ts @@ -13,11 +13,26 @@ const ConfigSchema = z.object({ indentWidth: z.number(), }), }), + site: z.object({ + copyrightYear: z.number(), + }), + sites: z.object({ + default: z.object({ + fqdn: z.string(), + }), + about: z.object({ + fqdn: z.string(), + }), + blog: z.object({ + fqdn: z.string(), + }), + slides: z.object({ + fqdn: z.string(), + }), + }), blog: z.object({ author: z.string(), - fqdn: z.string(), siteName: z.string(), - siteCopyrightYear: z.number(), postsPerPage: z.number().default(10), tagLabels: z.record(z.string(), z.string()), }), diff --git a/services/nuldoc/nuldoc-src/generators/about.ts b/services/nuldoc/nuldoc-src/generators/about.ts index 6663a19..711c167 100644 --- a/services/nuldoc/nuldoc-src/generators/about.ts +++ b/services/nuldoc/nuldoc-src/generators/about.ts @@ -17,7 +17,8 @@ export async function generateAboutPage( return { root: html, renderer: "html", - destFilePath: "/about/index.html", - href: "/about/", + site: "about", + destFilePath: "/index.html", + href: "/", }; } diff --git a/services/nuldoc/nuldoc-src/generators/atom.ts b/services/nuldoc/nuldoc-src/generators/atom.ts index 6ad07b4..bcd9ba0 100644 --- a/services/nuldoc/nuldoc-src/generators/atom.ts +++ b/services/nuldoc/nuldoc-src/generators/atom.ts @@ -33,13 +33,16 @@ export async function generateFeedPageFromEntries( feedSlug: string, feedTitle: string, entries: Array<PostPage | SlidePage>, + site: "default" | "blog" | "slides", config: Config, ): Promise<Page> { const entries_: Entry[] = []; for (const entry of entries) { entries_.push({ id: `urn:uuid:${entry.uuid}`, - linkToAlternate: `https://${config.blog.fqdn}${entry.href}`, + linkToAlternate: `https://${ + "event" in entry ? config.sites.slides.fqdn : config.sites.blog.fqdn + }${entry.href}`, title: entry.title, summary: entry.description, published: dateToRfc3339String(entry.published), @@ -58,10 +61,12 @@ export async function generateFeedPageFromEntries( const feedPath = `${alternateLink}${BASE_NAME}`; const feed: Feed = { author: config.blog.author, - icon: `https://${config.blog.fqdn}/favicon.svg`, - id: `tag:${config.blog.fqdn},${config.blog.siteCopyrightYear}:${feedSlug}`, - linkToSelf: `https://${config.blog.fqdn}${feedPath}`, - linkToAlternate: `https://${config.blog.fqdn}${alternateLink}`, + icon: `https://${config.sites[site].fqdn}/favicon.svg`, + id: `tag:${ + config.sites[site].fqdn + },${config.site.copyrightYear}:${feedSlug}`, + linkToSelf: `https://${config.sites[site].fqdn}${feedPath}`, + linkToAlternate: `https://${config.sites[site].fqdn}${alternateLink}`, title: feedTitle, updated: entries_.reduce( (latest, entry) => entry.updated > latest ? entry.updated : latest, @@ -73,6 +78,7 @@ export async function generateFeedPageFromEntries( return { root: await renderToDOM(AtomPage({ feed: feed })), renderer: "xml", + site, destFilePath: feedPath, href: feedPath, }; diff --git a/services/nuldoc/nuldoc-src/generators/home.ts b/services/nuldoc/nuldoc-src/generators/home.ts index 679dd39..ac91637 100644 --- a/services/nuldoc/nuldoc-src/generators/home.ts +++ b/services/nuldoc/nuldoc-src/generators/home.ts @@ -13,6 +13,7 @@ export async function generateHomePage(config: Config): Promise<HomePage> { return { root: html, renderer: "html", + site: "default", destFilePath: "/index.html", href: "/", }; diff --git a/services/nuldoc/nuldoc-src/generators/not_found.ts b/services/nuldoc/nuldoc-src/generators/not_found.ts index f5a81c8..81fdb35 100644 --- a/services/nuldoc/nuldoc-src/generators/not_found.ts +++ b/services/nuldoc/nuldoc-src/generators/not_found.ts @@ -6,6 +6,7 @@ import { Page } from "../page.ts"; export type NotFoundPage = Page; export async function generateNotFoundPage( + site: "default" | "about" | "blog" | "slides", config: Config, ): Promise<NotFoundPage> { const html = await renderToDOM( @@ -15,6 +16,7 @@ export async function generateNotFoundPage( return { root: html, renderer: "html", + site, destFilePath: "/404.html", href: "/404.html", }; diff --git a/services/nuldoc/nuldoc-src/generators/post.ts b/services/nuldoc/nuldoc-src/generators/post.ts index 0e2a955..4e08f88 100644 --- a/services/nuldoc/nuldoc-src/generators/post.ts +++ b/services/nuldoc/nuldoc-src/generators/post.ts @@ -50,6 +50,7 @@ export async function generatePostPage( return { root: html, renderer: "html", + site: "blog", destFilePath: destFilePath, href: destFilePath.replace("index.html", ""), title: doc.title, diff --git a/services/nuldoc/nuldoc-src/generators/post_list.ts b/services/nuldoc/nuldoc-src/generators/post_list.ts index b05f7ee..6a21dd8 100644 --- a/services/nuldoc/nuldoc-src/generators/post_list.ts +++ b/services/nuldoc/nuldoc-src/generators/post_list.ts @@ -57,6 +57,7 @@ async function generatePostListPage( return { root: html, renderer: "html", + site: "blog", destFilePath, href, }; diff --git a/services/nuldoc/nuldoc-src/generators/slide.ts b/services/nuldoc/nuldoc-src/generators/slide.ts index cd28879..feab583 100644 --- a/services/nuldoc/nuldoc-src/generators/slide.ts +++ b/services/nuldoc/nuldoc-src/generators/slide.ts @@ -37,6 +37,7 @@ export async function generateSlidePage( return { root: html, renderer: "html", + site: "slides", destFilePath: destFilePath, href: destFilePath.replace("index.html", ""), title: slide.title, diff --git a/services/nuldoc/nuldoc-src/generators/slide_list.ts b/services/nuldoc/nuldoc-src/generators/slide_list.ts index abebe10..9f766ed 100644 --- a/services/nuldoc/nuldoc-src/generators/slide_list.ts +++ b/services/nuldoc/nuldoc-src/generators/slide_list.ts @@ -17,6 +17,7 @@ export async function generateSlideListPage( return { root: html, renderer: "html", + site: "slides", destFilePath: "/slides/index.html", href: "/slides/", }; diff --git a/services/nuldoc/nuldoc-src/generators/tag.ts b/services/nuldoc/nuldoc-src/generators/tag.ts index dbd8ef9..11335c6 100644 --- a/services/nuldoc/nuldoc-src/generators/tag.ts +++ b/services/nuldoc/nuldoc-src/generators/tag.ts @@ -14,15 +14,17 @@ export interface TagPage extends Page { export async function generateTagPage( tagSlug: string, pages: TaggedPage[], + site: "blog" | "slides", config: Config, ): Promise<TagPage> { const html = await renderToDOM( - TagPage(tagSlug, pages, config), + TagPage(tagSlug, pages, site, config), ); return { root: html, renderer: "html", + site, destFilePath: `/tags/${tagSlug}/index.html`, href: `/tags/${tagSlug}/`, tagSlug: tagSlug, diff --git a/services/nuldoc/nuldoc-src/generators/tag_list.ts b/services/nuldoc/nuldoc-src/generators/tag_list.ts index 7baad8c..76b0fe5 100644 --- a/services/nuldoc/nuldoc-src/generators/tag_list.ts +++ b/services/nuldoc/nuldoc-src/generators/tag_list.ts @@ -8,6 +8,7 @@ export type TagListPage = Page; export async function generateTagListPage( tags: TagPage[], + site: "blog" | "slides", config: Config, ): Promise<TagListPage> { const html = await renderToDOM( @@ -17,6 +18,7 @@ export async function generateTagListPage( return { root: html, renderer: "html", + site, destFilePath: "/tags/index.html", href: "/tags/", }; diff --git a/services/nuldoc/nuldoc-src/page.ts b/services/nuldoc/nuldoc-src/page.ts index f4a6166..26cb4de 100644 --- a/services/nuldoc/nuldoc-src/page.ts +++ b/services/nuldoc/nuldoc-src/page.ts @@ -4,6 +4,7 @@ import { RendererType } from "./render.ts"; export interface Page { root: Element; renderer: RendererType; + site: "default" | "about" | "blog" | "slides"; destFilePath: string; href: string; } diff --git a/services/nuldoc/nuldoc-src/pages/AboutPage.tsx b/services/nuldoc/nuldoc-src/pages/AboutPage.tsx index 3d6583a..109c2a2 100644 --- a/services/nuldoc/nuldoc-src/pages/AboutPage.tsx +++ b/services/nuldoc/nuldoc-src/pages/AboutPage.tsx @@ -13,7 +13,7 @@ export default function AboutPage( ) { return ( <PageLayout - metaCopyrightYear={config.blog.siteCopyrightYear} + metaCopyrightYear={config.site.copyrightYear} metaDescription="このサイトの著者について" metaTitle={`About|${config.blog.siteName}`} config={config} @@ -91,7 +91,9 @@ export default function AboutPage( return 0; }).map((slide) => ( <li> - <a href={slide.href}> + <a + href={`https://${config.sites.slides.fqdn}${slide.href}`} + > {`${ dateToString(getPostPublishedDate(slide)) }: ${slide.event} (${slide.talkType})`} diff --git a/services/nuldoc/nuldoc-src/pages/HomePage.tsx b/services/nuldoc/nuldoc-src/pages/HomePage.tsx index 8850d03..20ef312 100644 --- a/services/nuldoc/nuldoc-src/pages/HomePage.tsx +++ b/services/nuldoc/nuldoc-src/pages/HomePage.tsx @@ -6,10 +6,10 @@ import { Config } from "../config.ts"; export default function HomePage(config: Config) { return ( <PageLayout - metaCopyrightYear={config.blog.siteCopyrightYear} + metaCopyrightYear={config.site.copyrightYear} metaDescription="nsfisis のブログサイト" metaTitle={config.blog.siteName} - metaAtomFeedHref={`https://${config.blog.fqdn}/atom.xml`} + metaAtomFeedHref={`https://${config.sites.default.fqdn}/atom.xml`} config={config} > <body className="single"> diff --git a/services/nuldoc/nuldoc-src/pages/NotFoundPage.tsx b/services/nuldoc/nuldoc-src/pages/NotFoundPage.tsx index 9631fef..f9e46b4 100644 --- a/services/nuldoc/nuldoc-src/pages/NotFoundPage.tsx +++ b/services/nuldoc/nuldoc-src/pages/NotFoundPage.tsx @@ -8,7 +8,7 @@ export default function NotFoundPage( ) { return ( <PageLayout - metaCopyrightYear={config.blog.siteCopyrightYear} + metaCopyrightYear={config.site.copyrightYear} metaDescription="リクエストされたページが見つかりません" metaTitle={`Page Not Found|${config.blog.siteName}`} config={config} diff --git a/services/nuldoc/nuldoc-src/pages/PostListPage.tsx b/services/nuldoc/nuldoc-src/pages/PostListPage.tsx index b825f69..25c5885 100644 --- a/services/nuldoc/nuldoc-src/pages/PostListPage.tsx +++ b/services/nuldoc/nuldoc-src/pages/PostListPage.tsx @@ -20,10 +20,10 @@ export default function PostListPage( return ( <PageLayout - metaCopyrightYear={config.blog.siteCopyrightYear} + metaCopyrightYear={config.site.copyrightYear} metaDescription={metaDescription} metaTitle={metaTitle} - metaAtomFeedHref={`https://${config.blog.fqdn}/posts/atom.xml`} + metaAtomFeedHref={`https://${config.sites.blog.fqdn}/posts/atom.xml`} config={config} > <body className="list"> diff --git a/services/nuldoc/nuldoc-src/pages/SlideListPage.tsx b/services/nuldoc/nuldoc-src/pages/SlideListPage.tsx index bc4b895..bcbef6d 100644 --- a/services/nuldoc/nuldoc-src/pages/SlideListPage.tsx +++ b/services/nuldoc/nuldoc-src/pages/SlideListPage.tsx @@ -15,10 +15,10 @@ export default function SlideListPage( return ( <PageLayout - metaCopyrightYear={config.blog.siteCopyrightYear} + metaCopyrightYear={config.site.copyrightYear} metaDescription="登壇したイベントで使用したスライドの一覧" metaTitle={`${pageTitle}|${config.blog.siteName}`} - metaAtomFeedHref={`https://${config.blog.fqdn}/slides/atom.xml`} + metaAtomFeedHref={`https://${config.sites.slides.fqdn}/slides/atom.xml`} config={config} > <body className="list"> diff --git a/services/nuldoc/nuldoc-src/pages/TagListPage.tsx b/services/nuldoc/nuldoc-src/pages/TagListPage.tsx index cdb83ea..12e09ae 100644 --- a/services/nuldoc/nuldoc-src/pages/TagListPage.tsx +++ b/services/nuldoc/nuldoc-src/pages/TagListPage.tsx @@ -12,7 +12,7 @@ export default function TagListPage( return ( <PageLayout - metaCopyrightYear={config.blog.siteCopyrightYear} + metaCopyrightYear={config.site.copyrightYear} metaDescription="タグの一覧" metaTitle={`${pageTitle}|${config.blog.siteName}`} config={config} diff --git a/services/nuldoc/nuldoc-src/pages/TagPage.tsx b/services/nuldoc/nuldoc-src/pages/TagPage.tsx index b2ffba5..641a2e6 100644 --- a/services/nuldoc/nuldoc-src/pages/TagPage.tsx +++ b/services/nuldoc/nuldoc-src/pages/TagPage.tsx @@ -10,6 +10,7 @@ import { TaggedPage } from "../generators/tagged_page.ts"; export default function TagPage( tagSlug: string, pages: TaggedPage[], + site: "blog" | "slides", config: Config, ) { const tagLabel = getTagLabel(config, tagSlug); @@ -21,7 +22,9 @@ export default function TagPage( metaDescription={`タグ「${tagLabel}」のついた記事またはスライドの一覧`} metaKeywords={[tagLabel]} metaTitle={`${pageTitle}|${config.blog.siteName}`} - metaAtomFeedHref={`https://${config.blog.fqdn}/tags/${tagSlug}/atom.xml`} + metaAtomFeedHref={`https://${ + config.sites[site].fqdn + }/tags/${tagSlug}/atom.xml`} config={config} > <body className="list"> |
