diff options
| -rw-r--r-- | nuldoc-src/commands/build.ts | 145 | ||||
| -rw-r--r-- | nuldoc-src/config.ts | 1 | ||||
| -rw-r--r-- | nuldoc-src/docbook/document.ts | 56 | ||||
| -rw-r--r-- | nuldoc-src/page.ts | 5 | ||||
| -rw-r--r-- | nuldoc-src/pages/about.ts (renamed from nuldoc-src/templates/about.ts) | 24 | ||||
| -rw-r--r-- | nuldoc-src/pages/post.ts (renamed from nuldoc-src/templates/post.ts) | 45 | ||||
| -rw-r--r-- | nuldoc-src/pages/post_list.ts (renamed from nuldoc-src/templates/post_list.ts) | 49 | ||||
| -rw-r--r-- | nuldoc-src/pages/tag.ts (renamed from nuldoc-src/templates/tag.ts) | 53 | ||||
| -rw-r--r-- | nuldoc-src/pages/utils.ts (renamed from nuldoc-src/templates/utils.ts) | 0 |
9 files changed, 156 insertions, 222 deletions
diff --git a/nuldoc-src/commands/build.ts b/nuldoc-src/commands/build.ts index 90aaab9..ef529e0 100644 --- a/nuldoc-src/commands/build.ts +++ b/nuldoc-src/commands/build.ts @@ -3,27 +3,32 @@ import { ensureDir } from "std/fs/mod.ts"; import { expandGlob } from "std/fs/expand_glob.ts"; import { Config } from "../config.ts"; import { parseDocBookFile } from "../docbook/parse.ts"; -import { Document } from "../docbook/document.ts"; import { Page } from "../page.ts"; import { render } from "../render.ts"; -import convertPost from "../templates/post.ts"; -import convertPostList from "../templates/post_list.ts"; -import convertTag from "../templates/tag.ts"; -import generateAbout from "../templates/about.ts"; +import { generateAboutPage } from "../pages/about.ts"; +import { + generatePostPage, + getPostCreatedDate, + PostPage, +} from "../pages/post.ts"; +import { generatePostListPage } from "../pages/post_list.ts"; +import { generateTagPage } from "../pages/tag.ts"; export async function runBuildCommand(config: Config) { - const posts = await generatePosts(config); - await generateTags(posts, config); - await generatePostList(posts, config); - await generateAboutPage(config); + const posts = await buildPostPages(config); + await buildPostListPage(posts, config); + await buildTagPages(posts, config); + await buildAboutPage(config); await copyStaticFiles(config); } -async function generatePosts(config: Config) { +async function buildPostPages(config: Config) { const sourceDir = join(Deno.cwd(), config.locations.contentDir, "posts"); const postFiles = await collectPostFiles(sourceDir); const posts = await parsePosts(postFiles, config); - await outputPosts(posts, config); + for (const post of posts) { + await writePage(post, config); + } return posts; } @@ -39,70 +44,35 @@ async function collectPostFiles(sourceDir: string): Promise<string[]> { async function parsePosts( postFiles: string[], config: Config, -): Promise<Document[]> { +): Promise<PostPage[]> { const posts = []; for (const postFile of postFiles) { posts.push( - await convertPost(await parseDocBookFile(postFile, config), config), + await generatePostPage(await parseDocBookFile(postFile, config), config), ); } return posts; } -async function outputPosts(posts: Document[], config: Config) { - const cwd = Deno.cwd(); - const contentDir = join(cwd, config.locations.contentDir); - const destDir = join(cwd, config.locations.destDir); - for (const post of posts) { - const destFilePath = join( - post.sourceFilePath.replace(contentDir, destDir).replace(".xml", ""), - "index.html", - ); - await ensureDir(dirname(destFilePath)); - await writePage(docToPage(post, destFilePath)); - } -} - -async function generatePostList(posts: Document[], config: Config) { - const postList = await buildPostListDoc(posts, config); - await outputPostList(postList, config); -} - -async function buildPostListDoc( - posts: Document[], - config: Config, -): Promise<Document> { - return await convertPostList(posts, config); -} - -async function outputPostList(postList: Document, config: Config) { - const cwd = Deno.cwd(); - const destDir = join(cwd, config.locations.destDir); - const destFilePath = join(destDir, "posts", "index.html"); - await ensureDir(dirname(destFilePath)); - await writePage(docToPage(postList, destFilePath)); -} - -async function generateAboutPage(config: Config) { - const aboutDoc = await generateAbout(config); - await outputAboutPage(aboutDoc, config); +async function buildPostListPage(posts: PostPage[], config: Config) { + const postListPage = await generatePostListPage(posts, config); + await writePage(postListPage, config); } -async function outputAboutPage(about: Document, config: Config) { - const cwd = Deno.cwd(); - const destDir = join(cwd, config.locations.destDir); - const destFilePath = join(destDir, "about", "index.html"); - await ensureDir(dirname(destFilePath)); - await writePage(docToPage(about, destFilePath)); +async function buildAboutPage(config: Config) { + const aboutPage = await generateAboutPage(config); + await writePage(aboutPage, config); } -async function generateTags(posts: Document[], config: Config) { +async function buildTagPages(posts: PostPage[], config: Config) { const tagsAndPosts = collectTags(posts); - const tagDocs = await buildTagDocs(tagsAndPosts, config); - await outputTags(tagDocs, config); + for (const [tag, posts] of tagsAndPosts) { + const tagPage = await generateTagPage(tag, posts, config); + await writePage(tagPage, config); + } } -function collectTags(posts: Document[]): [string, Document[]][] { +function collectTags(posts: PostPage[]): [string, PostPage[]][] { const tagsAndPosts = new Map(); for (const post of posts) { for (const tag of post.tags) { @@ -113,13 +83,13 @@ function collectTags(posts: Document[]): [string, Document[]][] { } } - const result: [string, Document[]][] = []; + const result: [string, PostPage[]][] = []; for (const tag of Array.from(tagsAndPosts.keys()).sort()) { result.push([ tag, - tagsAndPosts.get(tag).sort((a: Document, b: Document) => { - const ta = a.getCreatedDate(); - const tb = b.getCreatedDate(); + tagsAndPosts.get(tag).sort((a: PostPage, b: PostPage) => { + const ta = getPostCreatedDate(a); + const tb = getPostCreatedDate(b); if (ta > tb) return -1; if (ta < tb) return 1; return 0; @@ -129,35 +99,6 @@ function collectTags(posts: Document[]): [string, Document[]][] { return result; } -async function buildTagDocs( - tagsAndPosts: [string, Document[]][], - config: Config, -): Promise<[string, Document][]> { - const docs: [string, Document][] = []; - for (const [tag, posts] of tagsAndPosts) { - docs.push([tag, await buildTagDoc(tag, posts, config)]); - } - return docs; -} - -async function buildTagDoc( - tag: string, - posts: Document[], - config: Config, -): Promise<Document> { - return await convertTag(tag, posts, config); -} - -async function outputTags(tagDocs: [string, Document][], config: Config) { - const cwd = Deno.cwd(); - const destDir = join(cwd, config.locations.destDir); - for (const [tag, tagDoc] of tagDocs) { - const destFilePath = join(destDir, "tags", tag, "index.html"); - await ensureDir(dirname(destFilePath)); - await writePage(docToPage(tagDoc, destFilePath)); - } -} - async function copyStaticFiles(config: Config) { const globPattern = joinGlobs([Deno.cwd(), config.locations.staticDir, "*"]); for await (const entry of expandGlob(globPattern)) { @@ -170,14 +111,12 @@ async function copyStaticFiles(config: Config) { } } -async function writePage(page: Page) { - await Deno.writeTextFile(page.destFilePath, render(page.root, page.renderer)); -} - -function docToPage(d: Document, p: string): Page { - return { - root: d.root, - renderer: "html", - destFilePath: p, - }; +async function writePage(page: Page, config: Config) { + const destFilePath = join( + Deno.cwd(), + config.locations.destDir, + page.destFilePath, + ); + await ensureDir(dirname(destFilePath)); + await Deno.writeTextFile(destFilePath, render(page.root, page.renderer)); } diff --git a/nuldoc-src/config.ts b/nuldoc-src/config.ts index 74521b3..91b4844 100644 --- a/nuldoc-src/config.ts +++ b/nuldoc-src/config.ts @@ -3,7 +3,6 @@ export const config = { contentDir: "/content", destDir: "/public", staticDir: "/static", - templateDir: "/templates", }, rendering: { html: { diff --git a/nuldoc-src/docbook/document.ts b/nuldoc-src/docbook/document.ts index ae3159a..9f3221b 100644 --- a/nuldoc-src/docbook/document.ts +++ b/nuldoc-src/docbook/document.ts @@ -9,7 +9,7 @@ import { innerText, } from "../dom.ts"; -export class Document { +export type Document = { root: Element; sourceFilePath: string; link: string; @@ -17,41 +17,7 @@ export class Document { summary: string; // TODO: should it be markup text? tags: string[]; revisions: Revision[]; - - constructor( - root: Element, - sourceFilePath: string, - link: string, - title: string, - summary: string, - tags: string[], - revisions: Revision[], - ) { - this.root = root; - this.sourceFilePath = sourceFilePath; - this.link = link; - this.title = title; - this.summary = summary; - this.tags = tags; - this.revisions = revisions; - } - - getLatestRevision(): Revision { - return this.revisions[this.revisions.length - 1]; - } - - getOldestRevision(): Revision { - return this.revisions[0]; - } - - getUpdatedDate(): string { - return this.getLatestRevision().date; - } - - getCreatedDate(): string { - return this.getOldestRevision().date; - } -} +}; export function createNewDocumentFromRootElement( root: Element, @@ -130,13 +96,13 @@ export function createNewDocumentFromRootElement( const cwd = Deno.cwd(); const contentDir = join(cwd, config.locations.contentDir); const link = sourceFilePath.replace(contentDir, "").replace(".xml", "/"); - return new Document( - root, - sourceFilePath, - link, - title, - summary, - tags, - revisions, - ); + return { + root: root, + sourceFilePath: sourceFilePath, + link: link, + title: title, + summary: summary, + tags: tags, + revisions: revisions, + }; } diff --git a/nuldoc-src/page.ts b/nuldoc-src/page.ts index 970265e..f4a6166 100644 --- a/nuldoc-src/page.ts +++ b/nuldoc-src/page.ts @@ -1,8 +1,9 @@ import { Element } from "./dom.ts"; import { RendererType } from "./render.ts"; -export type Page = { +export interface Page { root: Element; renderer: RendererType; destFilePath: string; -}; + href: string; +} diff --git a/nuldoc-src/templates/about.ts b/nuldoc-src/pages/about.ts index 2f20aa9..bba4031 100644 --- a/nuldoc-src/templates/about.ts +++ b/nuldoc-src/pages/about.ts @@ -1,5 +1,5 @@ -import { Document } from "../docbook/document.ts"; import { Config } from "../config.ts"; +import { Page } from "../page.ts"; import { el, linkElement, @@ -8,9 +8,9 @@ import { text, } from "./utils.ts"; -export default async function generateAbout( - config: Config, -): Promise<Document> { +export type AboutPage = Page; + +export async function generateAboutPage(config: Config): Promise<AboutPage> { const head = el( "head", [], @@ -103,13 +103,11 @@ export default async function generateAbout( head, body, ); - return new Document( - el("__root__", [], html), - "<about>", - "/about/", - "About", - "このサイトの著者について", - [], - [], - ); + + return { + root: el("__root__", [], html), + renderer: "html", + destFilePath: "/about/index.html", + href: "/about/", + }; } diff --git a/nuldoc-src/templates/post.ts b/nuldoc-src/pages/post.ts index 51b9aa9..a431c37 100644 --- a/nuldoc-src/templates/post.ts +++ b/nuldoc-src/pages/post.ts @@ -1,6 +1,9 @@ +import { join } from "std/path/mod.ts"; +import { Config } from "../config.ts"; import { Element } from "../dom.ts"; import { Document } from "../docbook/document.ts"; -import { Config } from "../config.ts"; +import { Page } from "../page.ts"; +import { Revision } from "../revision.ts"; import { el, linkElement, @@ -9,10 +12,25 @@ import { text, } from "./utils.ts"; -export default async function convertPost( +export interface PostPage extends Page { + title: string; + summary: string; + tags: string[]; + revisions: Revision[]; +} + +export function getPostCreatedDate(page: { revisions: Revision[] }): string { + return page.revisions[0].date; +} + +export function getPostUpdatedDate(page: { revisions: Revision[] }): string { + return page.revisions[page.revisions.length - 1].date; +} + +export async function generatePostPage( doc: Document, config: Config, -): Promise<Document> { +): Promise<PostPage> { const headChildren = [ metaElement([["charset", "UTF-8"]]), metaElement([["name", "viewport"], [ @@ -22,7 +40,7 @@ export default async function convertPost( metaElement([["name", "author"], ["content", config.blog.author]]), metaElement([["name", "copyright"], [ "content", - `© ${doc.getCreatedDate().substring(0, 4)} ${config.blog.author}`, + `© ${getPostCreatedDate(doc).substring(0, 4)} ${config.blog.author}`, ]]), metaElement([["name", "description"], ["content", doc.summary]]), ]; @@ -169,6 +187,21 @@ export default async function convertPost( head, body, ); - doc.root = el("__root__", [], html); - return doc; + + const cwd = Deno.cwd(); + const contentDir = join(cwd, config.locations.contentDir); + const destFilePath = join( + doc.sourceFilePath.replace(contentDir, "").replace(".xml", ""), + "index.html", + ); + return { + root: el("__root__", [], html), + renderer: "html", + destFilePath: destFilePath, + href: destFilePath.replace("index.html", ""), + title: doc.title, + summary: doc.summary, + tags: doc.tags, + revisions: doc.revisions, + }; } diff --git a/nuldoc-src/templates/post_list.ts b/nuldoc-src/pages/post_list.ts index f75b8e1..e22316e 100644 --- a/nuldoc-src/templates/post_list.ts +++ b/nuldoc-src/pages/post_list.ts @@ -1,5 +1,6 @@ -import { Document } from "../docbook/document.ts"; import { Config } from "../config.ts"; +import { Page } from "../page.ts"; +import { getPostCreatedDate, getPostUpdatedDate, PostPage } from "./post.ts"; import { el, linkElement, @@ -8,19 +9,13 @@ import { text, } from "./utils.ts"; -export default async function convertPostList( - posts: Document[], +export type PostListPage = Page; + +export async function generatePostListPage( + posts: PostPage[], config: Config, -): Promise<Document> { - const doc = new Document( - el("__root__", []), - "<postList>", - "/posts/", - "投稿一覧", - "投稿した記事の一覧", - [], - [], - ); +): Promise<PostListPage> { + const pageTitle = "投稿一覧"; const head = el( "head", @@ -35,9 +30,9 @@ export default async function convertPostList( "content", `© ${config.blog.siteCopyrightYear} ${config.blog.author}`, ]]), - metaElement([["name", "description"], ["content", doc.summary]]), + metaElement([["name", "description"], ["content", "投稿した記事の一覧"]]), linkElement("icon", "/favicon.svg", "image/svg+xml"), - el("title", [], text(`${doc.title} | ${config.blog.siteName}`)), + el("title", [], text(`${pageTitle} | ${config.blog.siteName}`)), await stylesheetLinkElement("/style.css", config), ); const body = el( @@ -84,12 +79,12 @@ export default async function convertPostList( el( "h1", [], - text(doc.title), + text(pageTitle), ), ), ...Array.from(posts).sort((a, b) => { - const ta = a.getCreatedDate(); - const tb = b.getCreatedDate(); + const ta = getPostCreatedDate(a); + const tb = getPostCreatedDate(b); if (ta > tb) return -1; if (ta < tb) return 1; return 0; @@ -99,7 +94,7 @@ export default async function convertPostList( [["class", "post-entry"]], el( "a", - [["href", post.link]], + [["href", post.href]], el( "header", [["class", "entry-header"]], @@ -116,16 +111,16 @@ export default async function convertPostList( text("Posted on"), el( "time", - [["datetime", post.getCreatedDate()]], - text(post.getCreatedDate()), + [["datetime", getPostCreatedDate(post)]], + text(getPostCreatedDate(post)), ), ...(post.revisions.length > 1 ? [ text(", updated on "), el("time", [[ "datetime", - post.getUpdatedDate(), - ]], text(post.getUpdatedDate())), + getPostUpdatedDate(post), + ]], text(getPostUpdatedDate(post))), ] : []), ), @@ -148,6 +143,10 @@ export default async function convertPostList( body, ); - doc.root.children = [html]; - return doc; + return { + root: el("__root__", [], html), + renderer: "html", + destFilePath: "/posts/index.html", + href: "/posts/", + }; } diff --git a/nuldoc-src/templates/tag.ts b/nuldoc-src/pages/tag.ts index 8aeac58..51aedcd 100644 --- a/nuldoc-src/templates/tag.ts +++ b/nuldoc-src/pages/tag.ts @@ -1,5 +1,6 @@ -import { Document } from "../docbook/document.ts"; import { Config } from "../config.ts"; +import { Page } from "../page.ts"; +import { getPostCreatedDate, getPostUpdatedDate, PostPage } from "./post.ts"; import { el, linkElement, @@ -8,22 +9,16 @@ import { text, } from "./utils.ts"; -export default async function convertTag( - tag: string, - posts: Document[], - config: Config, -): Promise<Document> { - const tagLabel = (config.blog.tagLabels as { [key: string]: string })[tag]; +export type TagPage = Page; - const doc = new Document( - el("__root__", []), - `<tag:${tag}>`, - `/tags/${tag}/`, - `タグ「${tagLabel}」一覧`, - `タグ「${tagLabel}」のついた記事一覧`, - [], - [], - ); +export async function generateTagPage( + tagSlug: string, + posts: PostPage[], + config: Config, +): Promise<TagPage> { + const tagLabel = + (config.blog.tagLabels as { [key: string]: string })[tagSlug]; + const pageTitle = `タグ「${tagLabel}」一覧`; const headChildren = [ metaElement([["charset", "UTF-8"]]), @@ -35,16 +30,16 @@ export default async function convertTag( metaElement([["name", "copyright"], [ "content", `© ${ - posts[posts.length - 1].getCreatedDate().substring(0, 4) + getPostCreatedDate(posts[posts.length - 1]).substring(0, 4) } ${config.blog.author}`, ]]), metaElement([["name", "description"], [ "content", - doc.summary, + `タグ「${tagLabel}」のついた記事一覧`, ]]), metaElement([["name", "keywords"], ["content", tagLabel]]), linkElement("icon", "/favicon.svg", "image/svg+xml"), - el("title", [], text(`${doc.title} | ${config.blog.siteName}`)), + el("title", [], text(`${pageTitle} | ${config.blog.siteName}`)), await stylesheetLinkElement("/style.css", config), ]; const head = el("head", [], ...headChildren); @@ -86,14 +81,14 @@ export default async function convertTag( el( "main", [["class", "main"]], - el("header", [["class", "page-header"]], el("h1", [], text(doc.title))), + el("header", [["class", "page-header"]], el("h1", [], text(pageTitle))), ...posts.map((post) => el( "article", [["class", "post-entry"]], el( "a", - [["href", post.link]], + [["href", post.href]], el( "header", [["class", "entry-header"]], @@ -110,16 +105,16 @@ export default async function convertTag( text("Posted on"), el( "time", - [["datetime", post.getCreatedDate()]], - text(post.getCreatedDate()), + [["datetime", getPostCreatedDate(post)]], + text(getPostCreatedDate(post)), ), ...(post.revisions.length > 1 ? [ text(", updated on "), el("time", [[ "datetime", - post.getUpdatedDate(), - ]], text(post.getUpdatedDate())), + getPostUpdatedDate(post), + ]], text(getPostUpdatedDate(post))), ] : []), ), @@ -142,6 +137,10 @@ export default async function convertTag( body, ); - doc.root.children = [html]; - return doc; + return { + root: el("__root__", [], html), + renderer: "html", + destFilePath: `/tags/${tagSlug}/index.html`, + href: `/tags/${tagSlug}/`, + }; } diff --git a/nuldoc-src/templates/utils.ts b/nuldoc-src/pages/utils.ts index 018c460..018c460 100644 --- a/nuldoc-src/templates/utils.ts +++ b/nuldoc-src/pages/utils.ts |
