aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--nuldoc-src/commands/build.ts145
-rw-r--r--nuldoc-src/config.ts1
-rw-r--r--nuldoc-src/docbook/document.ts56
-rw-r--r--nuldoc-src/page.ts5
-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",
- `&copy; ${doc.getCreatedDate().substring(0, 4)} ${config.blog.author}`,
+ `&copy; ${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",
`&copy; ${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",
`&copy; ${
- 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