diff options
Diffstat (limited to 'services/nuldoc/nuldoc-src/components')
23 files changed, 385 insertions, 348 deletions
diff --git a/services/nuldoc/nuldoc-src/components/AboutGlobalHeader.ts b/services/nuldoc/nuldoc-src/components/AboutGlobalHeader.ts new file mode 100644 index 0000000..b6ef84c --- /dev/null +++ b/services/nuldoc/nuldoc-src/components/AboutGlobalHeader.ts @@ -0,0 +1,18 @@ +import { Config } from "../config.ts"; +import { elem, Element } from "../dom.ts"; + +export default function GlobalHeader({ config }: { config: Config }): Element { + return elem( + "header", + { class: "header" }, + elem( + "div", + { class: "site-logo" }, + elem( + "a", + { href: `https://${config.sites.default.fqdn}/` }, + "nsfisis.dev", + ), + ), + ); +} diff --git a/services/nuldoc/nuldoc-src/components/AboutGlobalHeader.tsx b/services/nuldoc/nuldoc-src/components/AboutGlobalHeader.tsx deleted file mode 100644 index 2df7296..0000000 --- a/services/nuldoc/nuldoc-src/components/AboutGlobalHeader.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { Config } from "../config.ts"; - -export default function GlobalHeader({ config }: { config: Config }) { - return ( - <header className="header"> - <div className="site-logo"> - <a href={`https://${config.sites.default.fqdn}/`}> - nsfisis.dev - </a> - </div> - </header> - ); -} diff --git a/services/nuldoc/nuldoc-src/components/BlogGlobalHeader.ts b/services/nuldoc/nuldoc-src/components/BlogGlobalHeader.ts new file mode 100644 index 0000000..034c2ab --- /dev/null +++ b/services/nuldoc/nuldoc-src/components/BlogGlobalHeader.ts @@ -0,0 +1,34 @@ +import { Config } from "../config.ts"; +import { elem, Element } from "../dom.ts"; + +export default function GlobalHeader({ config }: { config: Config }): Element { + return elem( + "header", + { class: "header" }, + elem( + "div", + { class: "site-logo" }, + elem( + "a", + { href: `https://${config.sites.default.fqdn}/` }, + "nsfisis.dev", + ), + ), + elem("div", { class: "site-name" }, config.sites.blog.siteName), + elem( + "nav", + { class: "nav" }, + elem( + "ul", + {}, + elem( + "li", + {}, + elem("a", { href: `https://${config.sites.about.fqdn}/` }, "About"), + ), + elem("li", {}, elem("a", { href: "/posts/" }, "Posts")), + elem("li", {}, elem("a", { href: "/tags/" }, "Tags")), + ), + ), + ); +} diff --git a/services/nuldoc/nuldoc-src/components/BlogGlobalHeader.tsx b/services/nuldoc/nuldoc-src/components/BlogGlobalHeader.tsx deleted file mode 100644 index 1f7fe6e..0000000 --- a/services/nuldoc/nuldoc-src/components/BlogGlobalHeader.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { Config } from "../config.ts"; - -export default function GlobalHeader({ config }: { config: Config }) { - return ( - <header className="header"> - <div className="site-logo"> - <a href={`https://${config.sites.default.fqdn}/`}> - nsfisis.dev - </a> - </div> - <div className="site-name"> - {config.sites.blog.siteName} - </div> - <nav className="nav"> - <ul> - <li> - <a href={`https://${config.sites.about.fqdn}/`}>About</a> - </li> - <li> - <a href="/posts/">Posts</a> - </li> - <li> - <a href="/tags/">Tags</a> - </li> - </ul> - </nav> - </header> - ); -} diff --git a/services/nuldoc/nuldoc-src/components/DefaultGlobalHeader.ts b/services/nuldoc/nuldoc-src/components/DefaultGlobalHeader.ts new file mode 100644 index 0000000..b6ef84c --- /dev/null +++ b/services/nuldoc/nuldoc-src/components/DefaultGlobalHeader.ts @@ -0,0 +1,18 @@ +import { Config } from "../config.ts"; +import { elem, Element } from "../dom.ts"; + +export default function GlobalHeader({ config }: { config: Config }): Element { + return elem( + "header", + { class: "header" }, + elem( + "div", + { class: "site-logo" }, + elem( + "a", + { href: `https://${config.sites.default.fqdn}/` }, + "nsfisis.dev", + ), + ), + ); +} diff --git a/services/nuldoc/nuldoc-src/components/DefaultGlobalHeader.tsx b/services/nuldoc/nuldoc-src/components/DefaultGlobalHeader.tsx deleted file mode 100644 index 2df7296..0000000 --- a/services/nuldoc/nuldoc-src/components/DefaultGlobalHeader.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { Config } from "../config.ts"; - -export default function GlobalHeader({ config }: { config: Config }) { - return ( - <header className="header"> - <div className="site-logo"> - <a href={`https://${config.sites.default.fqdn}/`}> - nsfisis.dev - </a> - </div> - </header> - ); -} diff --git a/services/nuldoc/nuldoc-src/components/GlobalFooter.ts b/services/nuldoc/nuldoc-src/components/GlobalFooter.ts new file mode 100644 index 0000000..835d73f --- /dev/null +++ b/services/nuldoc/nuldoc-src/components/GlobalFooter.ts @@ -0,0 +1,10 @@ +import { Config } from "../config.ts"; +import { elem, Element } from "../dom.ts"; + +export default function GlobalFooter({ config }: { config: Config }): Element { + return elem( + "footer", + { class: "footer" }, + `© ${config.site.copyrightYear} ${config.site.author}`, + ); +} diff --git a/services/nuldoc/nuldoc-src/components/GlobalFooter.tsx b/services/nuldoc/nuldoc-src/components/GlobalFooter.tsx deleted file mode 100644 index 9374aa7..0000000 --- a/services/nuldoc/nuldoc-src/components/GlobalFooter.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { Config } from "../config.ts"; - -export default function GlobalFooter({ config }: { config: Config }) { - return ( - <footer className="footer"> - {`© ${config.site.copyrightYear} ${config.site.author}`} - </footer> - ); -} diff --git a/services/nuldoc/nuldoc-src/components/PageLayout.ts b/services/nuldoc/nuldoc-src/components/PageLayout.ts new file mode 100644 index 0000000..19a8e86 --- /dev/null +++ b/services/nuldoc/nuldoc-src/components/PageLayout.ts @@ -0,0 +1,76 @@ +import { Config } from "../config.ts"; +import { elem, Element, Node } from "../dom.ts"; +import StaticStylesheet from "./StaticStylesheet.ts"; + +type Props = { + metaCopyrightYear: number; + metaDescription: string; + metaKeywords?: string[]; + metaTitle: string; + metaAtomFeedHref?: string; + requiresSyntaxHighlight?: boolean; + site: "default" | "about" | "blog" | "slides"; + config: Config; + children: Node; +}; + +export default async function PageLayout( + { + metaCopyrightYear, + metaDescription, + metaKeywords, + metaTitle, + metaAtomFeedHref, + requiresSyntaxHighlight: _, + site, + config, + children, + }: Props, +): Promise<Element> { + return elem( + "html", + { lang: "ja-JP" }, + elem( + "head", + {}, + elem("meta", { charset: "UTF-8" }), + elem("meta", { + name: "viewport", + content: "width=device-width, initial-scale=1.0", + }), + elem("meta", { name: "author", content: config.site.author }), + elem("meta", { + name: "copyright", + content: `© ${metaCopyrightYear} ${config.site.author}`, + }), + elem("meta", { name: "description", content: metaDescription }), + metaKeywords && metaKeywords.length !== 0 + ? elem("meta", { name: "keywords", content: metaKeywords.join(",") }) + : null, + elem("meta", { property: "og:type", content: "article" }), + elem("meta", { property: "og:title", content: metaTitle }), + elem("meta", { property: "og:description", content: metaDescription }), + elem("meta", { + property: "og:site_name", + content: config.sites[site].siteName, + }), + elem("meta", { property: "og:locale", content: "ja_JP" }), + elem("meta", { name: "Hatena::Bookmark", content: "nocomment" }), + metaAtomFeedHref + ? elem("link", { + rel: "alternate", + href: metaAtomFeedHref, + type: "application/atom+xml", + }) + : null, + elem("link", { + rel: "icon", + href: "/favicon.svg", + type: "image/svg+xml", + }), + elem("title", {}, metaTitle), + await StaticStylesheet({ fileName: "/style.css", config }), + ), + children, + ); +} diff --git a/services/nuldoc/nuldoc-src/components/PageLayout.tsx b/services/nuldoc/nuldoc-src/components/PageLayout.tsx deleted file mode 100644 index b32f229..0000000 --- a/services/nuldoc/nuldoc-src/components/PageLayout.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { Config } from "../config.ts"; -import { JSXNode } from "myjsx/jsx-runtime"; -import StaticStylesheet from "./StaticStylesheet.tsx"; - -type Props = { - metaCopyrightYear: number; - metaDescription: string; - metaKeywords?: string[]; - metaTitle: string; - metaAtomFeedHref?: string; - requiresSyntaxHighlight?: boolean; - site: "default" | "about" | "blog" | "slides"; - config: Config; - children: JSXNode; -}; - -export default function PageLayout( - { - metaCopyrightYear, - metaDescription, - metaKeywords, - metaTitle, - metaAtomFeedHref, - requiresSyntaxHighlight: _, - site, - config, - children, - }: Props, -) { - return ( - <html lang="ja-JP"> - <head> - <meta charset="UTF-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1.0" /> - <meta name="author" content={config.site.author} /> - <meta - name="copyright" - content={`© ${metaCopyrightYear} ${config.site.author}`} - /> - <meta name="description" content={metaDescription} /> - {metaKeywords && metaKeywords.length !== 0 && - <meta name="keywords" content={metaKeywords.join(",")} />} - <meta property="og:type" content="article" /> - <meta property="og:title" content={metaTitle} /> - <meta property="og:description" content={metaDescription} /> - <meta property="og:site_name" content={config.sites[site].siteName} /> - <meta property="og:locale" content="ja_JP" /> - {/* https://b.hatena.ne.jp/help/entry/nocomment */} - <meta name="Hatena::Bookmark" content="nocomment" /> - {metaAtomFeedHref && - ( - <link - rel="alternate" - href={metaAtomFeedHref} - type="application/atom+xml" - /> - )} - <link rel="icon" href="/favicon.svg" type="image/svg+xml" /> - <title>{metaTitle}</title> - <StaticStylesheet fileName="/style.css" config={config} /> - </head> - {children} - </html> - ); -} diff --git a/services/nuldoc/nuldoc-src/components/Pagination.tsx b/services/nuldoc/nuldoc-src/components/Pagination.ts index 84752c5..62e796b 100644 --- a/services/nuldoc/nuldoc-src/components/Pagination.tsx +++ b/services/nuldoc/nuldoc-src/components/Pagination.ts @@ -1,3 +1,5 @@ +import { elem, Element } from "../dom.ts"; + type Props = { currentPage: number; totalPages: number; @@ -6,55 +8,47 @@ type Props = { export default function Pagination( { currentPage, totalPages, basePath }: Props, -) { +): Element { if (totalPages <= 1) { - return <div></div>; + return elem("div", {}); } const pages = generatePageNumbers(currentPage, totalPages); - return ( - <nav className="pagination"> - <div className="pagination-prev"> - {currentPage > 1 - ? ( - <a href={pageUrlAt(basePath, currentPage - 1)}> - 前へ - </a> - ) - : null} - </div> - {pages.map((page) => { - if (page === "...") { - return ( - <div className="pagination-elipsis"> - … - </div> - ); - } else if (page === currentPage) { - return ( - <div className="pagination-page pagination-page-current"> - <span>{String(page)}</span> - </div> - ); - } else { - return ( - <div className="pagination-page"> - <a href={pageUrlAt(basePath, page)}>{String(page)}</a> - </div> - ); - } - })} - <div className="pagination-next"> - {currentPage < totalPages - ? ( - <a href={pageUrlAt(basePath, currentPage + 1)}> - 次へ - </a> - ) - : null} - </div> - </nav> + return elem( + "nav", + { class: "pagination" }, + elem( + "div", + { class: "pagination-prev" }, + currentPage > 1 + ? elem("a", { href: pageUrlAt(basePath, currentPage - 1) }, "前へ") + : null, + ), + ...pages.map((page) => { + if (page === "...") { + return elem("div", { class: "pagination-elipsis" }, "…"); + } else if (page === currentPage) { + return elem( + "div", + { class: "pagination-page pagination-page-current" }, + elem("span", {}, String(page)), + ); + } else { + return elem( + "div", + { class: "pagination-page" }, + elem("a", { href: pageUrlAt(basePath, page) }, String(page)), + ); + } + }), + elem( + "div", + { class: "pagination-next" }, + currentPage < totalPages + ? elem("a", { href: pageUrlAt(basePath, currentPage + 1) }, "次へ") + : null, + ), ); } diff --git a/services/nuldoc/nuldoc-src/components/PostPageEntry.ts b/services/nuldoc/nuldoc-src/components/PostPageEntry.ts new file mode 100644 index 0000000..75ad11c --- /dev/null +++ b/services/nuldoc/nuldoc-src/components/PostPageEntry.ts @@ -0,0 +1,49 @@ +import { + getPostPublishedDate, + getPostUpdatedDate, + postHasAnyUpdates, + PostPage, +} from "../generators/post.ts"; +import { dateToString } from "../revision.ts"; +import { Config } from "../config.ts"; +import { elem, Element } from "../dom.ts"; +import TagList from "./TagList.ts"; + +type Props = { post: PostPage; config: Config }; + +export default function PostPageEntry({ post, config }: Props): Element { + return elem( + "article", + { class: "post-entry" }, + elem( + "a", + { href: post.href }, + elem("header", { class: "entry-header" }, elem("h2", {}, post.title)), + elem( + "section", + { class: "entry-content" }, + elem("p", {}, post.description), + ), + elem( + "footer", + { class: "entry-footer" }, + elem( + "time", + { datetime: dateToString(getPostPublishedDate(post)) }, + dateToString(getPostPublishedDate(post)), + ), + " 投稿", + postHasAnyUpdates(post) ? "、" : null, + postHasAnyUpdates(post) + ? elem( + "time", + { datetime: dateToString(getPostUpdatedDate(post)) }, + dateToString(getPostUpdatedDate(post)), + ) + : null, + postHasAnyUpdates(post) ? " 更新" : null, + post.tags.length !== 0 ? TagList({ tags: post.tags, config }) : null, + ), + ), + ); +} diff --git a/services/nuldoc/nuldoc-src/components/PostPageEntry.tsx b/services/nuldoc/nuldoc-src/components/PostPageEntry.tsx deleted file mode 100644 index 23ca88a..0000000 --- a/services/nuldoc/nuldoc-src/components/PostPageEntry.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { - getPostPublishedDate, - getPostUpdatedDate, - postHasAnyUpdates, - PostPage, -} from "../generators/post.ts"; -import { dateToString } from "../revision.ts"; -import { Config } from "../config.ts"; -import TagList from "./TagList.tsx"; - -type Props = { post: PostPage; config: Config }; - -export default function PostPageEntry({ post, config }: Props) { - return ( - <article className="post-entry"> - <a href={post.href}> - <header className="entry-header"> - <h2>{post.title}</h2> - </header> - <section className="entry-content"> - <p>{post.description}</p> - </section> - <footer className="entry-footer"> - <time datetime={dateToString(getPostPublishedDate(post))}> - {dateToString(getPostPublishedDate(post))} - </time> - {" 投稿"} - { - // TODO(jsx): support Fragment and merge them. - postHasAnyUpdates(post) && "、" - } - {postHasAnyUpdates(post) && - ( - <time datetime={dateToString(getPostUpdatedDate(post))}> - {dateToString(getPostUpdatedDate(post))} - </time> - )} - {postHasAnyUpdates(post) && " 更新"} - {post.tags.length !== 0 && ( - <TagList tags={post.tags} config={config} /> - )} - </footer> - </a> - </article> - ); -} diff --git a/services/nuldoc/nuldoc-src/components/SlidePageEntry.ts b/services/nuldoc/nuldoc-src/components/SlidePageEntry.ts new file mode 100644 index 0000000..1dc5f1a --- /dev/null +++ b/services/nuldoc/nuldoc-src/components/SlidePageEntry.ts @@ -0,0 +1,49 @@ +import { + getPostPublishedDate, + getPostUpdatedDate, + postHasAnyUpdates, +} from "../generators/post.ts"; +import { SlidePage } from "../generators/slide.ts"; +import { dateToString } from "../revision.ts"; +import { Config } from "../config.ts"; +import { elem, Element } from "../dom.ts"; +import TagList from "./TagList.ts"; + +type Props = { slide: SlidePage; config: Config }; + +export default function SlidePageEntry({ slide, config }: Props): Element { + return elem( + "article", + { class: "post-entry" }, + elem( + "a", + { href: slide.href }, + elem( + "header", + { class: "entry-header" }, + elem("h2", {}, slide.description), + ), + elem("section", { class: "entry-content" }, elem("p", {}, slide.title)), + elem( + "footer", + { class: "entry-footer" }, + elem( + "time", + { datetime: dateToString(getPostPublishedDate(slide)) }, + dateToString(getPostPublishedDate(slide)), + ), + " 登壇", + postHasAnyUpdates(slide) ? "、" : null, + postHasAnyUpdates(slide) + ? elem( + "time", + { datetime: dateToString(getPostUpdatedDate(slide)) }, + dateToString(getPostUpdatedDate(slide)), + ) + : null, + postHasAnyUpdates(slide) ? " 更新" : null, + slide.tags.length !== 0 ? TagList({ tags: slide.tags, config }) : null, + ), + ), + ); +} diff --git a/services/nuldoc/nuldoc-src/components/SlidePageEntry.tsx b/services/nuldoc/nuldoc-src/components/SlidePageEntry.tsx deleted file mode 100644 index 2401765..0000000 --- a/services/nuldoc/nuldoc-src/components/SlidePageEntry.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { - getPostPublishedDate, - getPostUpdatedDate, - postHasAnyUpdates, -} from "../generators/post.ts"; -import { SlidePage } from "../generators/slide.ts"; -import { dateToString } from "../revision.ts"; -import { Config } from "../config.ts"; -import TagList from "./TagList.tsx"; - -type Props = { slide: SlidePage; config: Config }; - -export default function SlidePageEntry({ slide, config }: Props) { - return ( - <article className="post-entry"> - <a href={slide.href}> - <header className="entry-header"> - <h2>{slide.description}</h2> - </header> - <section className="entry-content"> - <p>{slide.title}</p> - </section> - <footer className="entry-footer"> - <time datetime={dateToString(getPostPublishedDate(slide))}> - {dateToString(getPostPublishedDate(slide))} - </time> - {" 登壇"} - { - // TODO(jsx): support Fragment and merge them. - postHasAnyUpdates(slide) && "、" - } - {postHasAnyUpdates(slide) && - ( - <time datetime={dateToString(getPostUpdatedDate(slide))}> - {dateToString(getPostUpdatedDate(slide))} - </time> - )} - {postHasAnyUpdates(slide) && " 更新"} - {slide.tags.length !== 0 && ( - <TagList tags={slide.tags} config={config} /> - )} - </footer> - </a> - </article> - ); -} diff --git a/services/nuldoc/nuldoc-src/components/SlidesGlobalHeader.ts b/services/nuldoc/nuldoc-src/components/SlidesGlobalHeader.ts new file mode 100644 index 0000000..902e12f --- /dev/null +++ b/services/nuldoc/nuldoc-src/components/SlidesGlobalHeader.ts @@ -0,0 +1,33 @@ +import { Config } from "../config.ts"; +import { elem, Element } from "../dom.ts"; + +export default function GlobalHeader({ config }: { config: Config }): Element { + return elem( + "header", + { class: "header" }, + elem( + "div", + { class: "site-logo" }, + elem( + "a", + { href: `https://${config.sites.default.fqdn}/` }, + "nsfisis.dev", + ), + ), + elem( + "nav", + { class: "nav" }, + elem( + "ul", + {}, + elem( + "li", + {}, + elem("a", { href: `https://${config.sites.about.fqdn}/` }, "About"), + ), + elem("li", {}, elem("a", { href: "/slides/" }, "Slides")), + elem("li", {}, elem("a", { href: "/tags/" }, "Tags")), + ), + ), + ); +} diff --git a/services/nuldoc/nuldoc-src/components/SlidesGlobalHeader.tsx b/services/nuldoc/nuldoc-src/components/SlidesGlobalHeader.tsx deleted file mode 100644 index 4d93240..0000000 --- a/services/nuldoc/nuldoc-src/components/SlidesGlobalHeader.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { Config } from "../config.ts"; - -export default function GlobalHeader({ config }: { config: Config }) { - return ( - <header className="header"> - <div className="site-logo"> - <a href={`https://${config.sites.default.fqdn}/`}> - nsfisis.dev - </a> - </div> - <nav className="nav"> - <ul> - <li> - <a href={`https://${config.sites.about.fqdn}/`}>About</a> - </li> - <li> - <a href="/slides/">Slides</a> - </li> - <li> - <a href="/tags/">Tags</a> - </li> - </ul> - </nav> - </header> - ); -} diff --git a/services/nuldoc/nuldoc-src/components/StaticScript.tsx b/services/nuldoc/nuldoc-src/components/StaticScript.ts index 0e3ab19..7df40fd 100644 --- a/services/nuldoc/nuldoc-src/components/StaticScript.tsx +++ b/services/nuldoc/nuldoc-src/components/StaticScript.ts @@ -1,5 +1,6 @@ import { join } from "@std/path"; import { Config } from "../config.ts"; +import { elem, Element } from "../dom.ts"; import { calculateFileHash } from "./utils.ts"; export default async function StaticScript( @@ -9,10 +10,11 @@ export default async function StaticScript( defer?: "true"; config: Config; }, -) { +): Promise<Element> { const filePath = join(Deno.cwd(), config.locations.staticDir, fileName); const hash = await calculateFileHash(filePath); - return ( - <script src={`${fileName}?h=${hash}`} type={type} defer={defer}></script> - ); + const attrs: Record<string, string> = { src: `${fileName}?h=${hash}` }; + if (type) attrs.type = type; + if (defer) attrs.defer = defer; + return elem("script", attrs); } diff --git a/services/nuldoc/nuldoc-src/components/StaticStylesheet.tsx b/services/nuldoc/nuldoc-src/components/StaticStylesheet.ts index 52b695e..43802d2 100644 --- a/services/nuldoc/nuldoc-src/components/StaticStylesheet.tsx +++ b/services/nuldoc/nuldoc-src/components/StaticStylesheet.ts @@ -1,11 +1,12 @@ import { join } from "@std/path"; import { Config } from "../config.ts"; +import { elem, Element } from "../dom.ts"; import { calculateFileHash } from "./utils.ts"; export default async function StaticStylesheet( { fileName, config }: { fileName: string; config: Config }, -) { +): Promise<Element> { const filePath = join(Deno.cwd(), config.locations.staticDir, fileName); const hash = await calculateFileHash(filePath); - return <link rel="stylesheet" href={`${fileName}?h=${hash}`} />; + return elem("link", { rel: "stylesheet", href: `${fileName}?h=${hash}` }); } diff --git a/services/nuldoc/nuldoc-src/components/TableOfContents.ts b/services/nuldoc/nuldoc-src/components/TableOfContents.ts new file mode 100644 index 0000000..ac4205a --- /dev/null +++ b/services/nuldoc/nuldoc-src/components/TableOfContents.ts @@ -0,0 +1,34 @@ +import { TocEntry, TocRoot } from "../djot/document.ts"; +import { elem, Element } from "../dom.ts"; + +type Props = { + toc: TocRoot; +}; + +export default function TableOfContents({ toc }: Props): Element { + return elem( + "nav", + { class: "toc" }, + elem("h2", {}, "目次"), + elem( + "ul", + {}, + ...toc.entries.map((entry) => TocEntryComponent({ entry })), + ), + ); +} + +function TocEntryComponent({ entry }: { entry: TocEntry }): Element { + return elem( + "li", + {}, + elem("a", { href: `#${entry.id}` }, entry.text), + entry.children.length > 0 + ? elem( + "ul", + {}, + ...entry.children.map((child) => TocEntryComponent({ entry: child })), + ) + : null, + ); +} diff --git a/services/nuldoc/nuldoc-src/components/TableOfContents.tsx b/services/nuldoc/nuldoc-src/components/TableOfContents.tsx deleted file mode 100644 index 29907d0..0000000 --- a/services/nuldoc/nuldoc-src/components/TableOfContents.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { TocEntry, TocRoot } from "../djot/document.ts"; - -type Props = { - toc: TocRoot; -}; - -export default function TableOfContents({ toc }: Props) { - return ( - <nav className="toc"> - <h2>目次</h2> - <ul> - {toc.entries.map((entry, index) => ( - <TocEntryComponent key={String(index)} entry={entry} /> - ))} - </ul> - </nav> - ); -} - -function TocEntryComponent({ entry }: { entry: TocEntry }) { - return ( - <li> - <a href={`#${entry.id}`}>{entry.text}</a> - {entry.children.length > 0 && ( - <ul> - {entry.children.map((child, index) => ( - <TocEntryComponent key={String(index)} entry={child} /> - ))} - </ul> - )} - </li> - ); -} diff --git a/services/nuldoc/nuldoc-src/components/TagList.ts b/services/nuldoc/nuldoc-src/components/TagList.ts new file mode 100644 index 0000000..540abe6 --- /dev/null +++ b/services/nuldoc/nuldoc-src/components/TagList.ts @@ -0,0 +1,17 @@ +import { Config, getTagLabel } from "../config.ts"; +import { elem, Element, text } from "../dom.ts"; + +type Props = { + tags: string[]; + config: Config; +}; + +export default function TagList({ tags, config }: Props): Element { + return elem( + "ul", + { class: "entry-tags" }, + ...tags.map((slug) => + elem("li", { class: "tag" }, text(getTagLabel(config, slug))) + ), + ); +} diff --git a/services/nuldoc/nuldoc-src/components/TagList.tsx b/services/nuldoc/nuldoc-src/components/TagList.tsx deleted file mode 100644 index 86ee70b..0000000 --- a/services/nuldoc/nuldoc-src/components/TagList.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { Config, getTagLabel } from "../config.ts"; - -type Props = { - tags: string[]; - config: Config; -}; - -export default function TagList({ tags, config }: Props) { - return ( - <ul className="entry-tags"> - {tags.map((slug) => ( - <li className="tag" key={slug}> - {getTagLabel(config, slug)} - </li> - ))} - </ul> - ); -} |
