From 71aba3df235dc9a8acbee0e33980b30ba4ce44d4 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sat, 18 Mar 2023 18:53:05 +0900 Subject: refactor: add components/*.ts for shared components --- nuldoc-src/components/global_footer.ts | 12 +++ nuldoc-src/components/global_header.ts | 37 ++++++++ nuldoc-src/components/page_layout.ts | 89 ++++++++++++++++++ nuldoc-src/dom.ts | 21 +++++ nuldoc-src/pages/about.ts | 87 ++++------------- nuldoc-src/pages/post.ts | 103 +++++---------------- nuldoc-src/pages/post_list.ts | 84 ++++------------- nuldoc-src/pages/tag.ts | 91 ++++-------------- nuldoc-src/pages/utils.ts | 51 ---------- public/posts/2021-03-30/phperkaigi-2021/index.html | 6 +- .../index.html | 4 +- .../python-unbound-local-error/index.html | 4 +- .../ruby-detect-running-implementation/index.html | 2 +- .../ruby-then-keyword-and-case-in/index.html | 4 +- .../rust-where-are-primitive-types-from/index.html | 2 +- .../index.html | 2 +- .../vim-swap-order-of-selected-lines/index.html | 2 +- .../2022-04-09/phperkaigi-2022-tokens/index.html | 6 +- public/posts/2022-05-01/phperkaigi-2022/index.html | 6 +- .../php-conference-okinawa-code-golf/index.html | 6 +- .../index.html | 2 +- .../phperkaigi-2023-unused-token-quiz-1/index.html | 4 +- .../setup-server-for-this-site/index.html | 2 +- .../phperkaigi-2023-unused-token-quiz-2/index.html | 4 +- .../phperkaigi-2023-unused-token-quiz-3/index.html | 4 +- 25 files changed, 260 insertions(+), 375 deletions(-) create mode 100644 nuldoc-src/components/global_footer.ts create mode 100644 nuldoc-src/components/global_header.ts create mode 100644 nuldoc-src/components/page_layout.ts delete mode 100644 nuldoc-src/pages/utils.ts diff --git a/nuldoc-src/components/global_footer.ts b/nuldoc-src/components/global_footer.ts new file mode 100644 index 0000000..4c9d245 --- /dev/null +++ b/nuldoc-src/components/global_footer.ts @@ -0,0 +1,12 @@ +import { Config } from "../config.ts"; +import { el, Element, text } from "../dom.ts"; + +export function globalFooter(config: Config): Element { + return el( + "footer", + [["class", "footer"]], + text( + `© ${config.blog.siteCopyrightYear} ${config.blog.author}`, + ), + ); +} diff --git a/nuldoc-src/components/global_header.ts b/nuldoc-src/components/global_header.ts new file mode 100644 index 0000000..4f7df3b --- /dev/null +++ b/nuldoc-src/components/global_header.ts @@ -0,0 +1,37 @@ +import { Config } from "../config.ts"; +import { el, Element, text } from "../dom.ts"; + +export function globalHeader(config: Config): Element { + return el( + "header", + [["class", "header"]], + el( + "nav", + [["class", "nav"]], + el( + "ul", + [], + el( + "li", + [["class", "logo"]], + el("a", [["href", "/"]], text(config.blog.siteName)), + ), + el( + "li", + [], + el("a", [["href", "/about"]], text("About")), + ), + el( + "li", + [], + el("a", [["href", "/posts"]], text("Posts")), + ), + el( + "li", + [], + el("a", [["href", "/slides"]], text("Slides")), + ), + ), + ), + ); +} diff --git a/nuldoc-src/components/page_layout.ts b/nuldoc-src/components/page_layout.ts new file mode 100644 index 0000000..d76e3b2 --- /dev/null +++ b/nuldoc-src/components/page_layout.ts @@ -0,0 +1,89 @@ +import { crypto, toHashString } from "std/crypto/mod.ts"; +import { join } from "std/path/mod.ts"; +import { Config } from "../config.ts"; +import { el, Element, text } from "../dom.ts"; + +type Params = { + metaCopyrightYear: number; + metaDescription: string; + metaKeywords: string[]; + metaTitle: string; + requiresSyntaxHighlight: boolean; +}; + +export async function pageLayout( + { + metaCopyrightYear, + metaDescription, + metaKeywords, + metaTitle, + requiresSyntaxHighlight, + }: Params, + body: Element, + config: Config, +): Promise { + const head = el( + "head", + [], + metaElement([["charset", "UTF-8"]]), + metaElement([["name", "viewport"], [ + "content", + "width=device-width, initial-scale=1.0", + ]]), + metaElement([["name", "author"], ["content", config.blog.author]]), + metaElement([["name", "copyright"], [ + "content", + `© ${metaCopyrightYear} ${config.blog.author}`, + ]]), + metaElement([["name", "description"], [ + "content", + metaDescription, + ]]), + ...(metaKeywords.length === 0 ? [] : [ + metaElement([["name", "keywords"], [ + "content", + metaKeywords.join(","), + ]]), + ]), + linkElement("icon", "/favicon.svg", "image/svg+xml"), + el("title", [], text(`${metaTitle} | ${config.blog.siteName}`)), + await stylesheetLinkElement("/style.css", config), + ...( + requiresSyntaxHighlight + ? [await stylesheetLinkElement("/hl.css", config)] + : [] + ), + ); + return el( + "html", + [["lang", "ja-JP"]], + head, + body, + ); +} + +async function stylesheetLinkElement( + fileName: string, + config: Config, +): Promise { + const filePath = join(Deno.cwd(), config.locations.staticDir, fileName); + const content = (await Deno.readFile(filePath)).buffer; + const hash = toHashString(await crypto.subtle.digest("MD5", content), "hex"); + return el("link", [["rel", "stylesheet"], ["href", `${fileName}?h=${hash}`]]); +} + +function metaElement(attrs: [string, string][]): Element { + return el("meta", attrs); +} + +function linkElement( + rel: string, + href: string, + type: string | null, +): Element { + const attrs: [string, string][] = [["rel", rel], ["href", href]]; + if (type !== null) { + attrs.push(["type", type]); + } + return el("link", attrs); +} diff --git a/nuldoc-src/dom.ts b/nuldoc-src/dom.ts index 626d400..d8f53d7 100644 --- a/nuldoc-src/dom.ts +++ b/nuldoc-src/dom.ts @@ -84,3 +84,24 @@ export function forEachChildRecursively(e: Element, f: (n: Node) => void) { }; forEachChild(e, g); } + +export function text(content: string): Text { + return { + kind: "text", + content: content, + raw: false, + }; +} + +export function el( + name: string, + attrs: [string, string][], + ...children: Node[] +): Element { + return { + kind: "element", + name: name, + attributes: new Map(attrs), + children: children, + }; +} diff --git a/nuldoc-src/pages/about.ts b/nuldoc-src/pages/about.ts index bba4031..4f98930 100644 --- a/nuldoc-src/pages/about.ts +++ b/nuldoc-src/pages/about.ts @@ -1,72 +1,17 @@ +import { globalFooter } from "../components/global_footer.ts"; +import { globalHeader } from "../components/global_header.ts"; +import { pageLayout } from "../components/page_layout.ts"; import { Config } from "../config.ts"; +import { el, text } from "../dom.ts"; import { Page } from "../page.ts"; -import { - el, - linkElement, - metaElement, - stylesheetLinkElement, - text, -} from "./utils.ts"; export type AboutPage = Page; export async function generateAboutPage(config: Config): Promise { - const head = el( - "head", - [], - metaElement([["charset", "UTF-8"]]), - metaElement([["name", "viewport"], [ - "content", - "width=device-width, initial-scale=1.0", - ]]), - metaElement([["name", "author"], ["content", config.blog.author]]), - metaElement([["name", "copyright"], [ - "content", - `© ${config.blog.siteCopyrightYear} ${config.blog.author}`, - ]]), - metaElement([["name", "description"], [ - "content", - "このサイトの著者について", - ]]), - linkElement("icon", "/favicon.svg", "image/svg+xml"), - el("title", [], text(`About | ${config.blog.siteName}`)), - await stylesheetLinkElement("/style.css", config), - ); const body = el( "body", [["class", "single"]], - el( - "header", - [["class", "header"]], - el( - "nav", - [["class", "nav"]], - el( - "ul", - [], - el( - "li", - [["class", "logo"]], - el("a", [["href", "/"]], text(config.blog.siteName)), - ), - el( - "li", - [], - el("a", [["href", "/about"]], text("About")), - ), - el( - "li", - [], - el("a", [["href", "/posts"]], text("Posts")), - ), - el( - "li", - [], - el("a", [["href", "/slides"]], text("Slides")), - ), - ), - ), - ), + globalHeader(config), el( "main", [["class", "main"]], @@ -89,19 +34,19 @@ export async function generateAboutPage(config: Config): Promise { ), ), ), - el( - "footer", - [["class", "footer"]], - text( - `© ${config.blog.siteCopyrightYear} ${config.blog.author}`, - ), - ), + globalFooter(config), ); - const html = el( - "html", - [["lang", "ja-JP"]], - head, + + const html = await pageLayout( + { + metaCopyrightYear: config.blog.siteCopyrightYear, + metaDescription: "このサイトの著者について", + metaKeywords: [], + metaTitle: "About", + requiresSyntaxHighlight: false, + }, body, + config, ); return { diff --git a/nuldoc-src/pages/post.ts b/nuldoc-src/pages/post.ts index a431c37..597a667 100644 --- a/nuldoc-src/pages/post.ts +++ b/nuldoc-src/pages/post.ts @@ -1,16 +1,12 @@ import { join } from "std/path/mod.ts"; +import { globalFooter } from "../components/global_footer.ts"; +import { globalHeader } from "../components/global_header.ts"; +import { pageLayout } from "../components/page_layout.ts"; import { Config } from "../config.ts"; -import { Element } from "../dom.ts"; +import { el, Element, text } from "../dom.ts"; import { Document } from "../docbook/document.ts"; import { Page } from "../page.ts"; import { Revision } from "../revision.ts"; -import { - el, - linkElement, - metaElement, - stylesheetLinkElement, - text, -} from "./utils.ts"; export interface PostPage extends Page { title: string; @@ -31,71 +27,10 @@ export async function generatePostPage( doc: Document, config: Config, ): Promise { - const headChildren = [ - metaElement([["charset", "UTF-8"]]), - metaElement([["name", "viewport"], [ - "content", - "width=device-width, initial-scale=1.0", - ]]), - metaElement([["name", "author"], ["content", config.blog.author]]), - metaElement([["name", "copyright"], [ - "content", - `© ${getPostCreatedDate(doc).substring(0, 4)} ${config.blog.author}`, - ]]), - metaElement([["name", "description"], ["content", doc.summary]]), - ]; - if (doc.tags.length !== 0) { - headChildren.push( - metaElement([["name", "keywords"], [ - "content", - doc.tags.map((slug) => - (config.blog.tagLabels as { [key: string]: string })[slug] - ).join(","), - ]]), - ); - } - headChildren.push(linkElement("icon", "/favicon.svg", "image/svg+xml")); - headChildren.push( - el("title", [], text(`${doc.title} | ${config.blog.siteName}`)), - ); - headChildren.push(await stylesheetLinkElement("/style.css", config)); - headChildren.push(await stylesheetLinkElement("/hl.css", config)); - const head = el("head", [], ...headChildren); const body = el( "body", [["class", "single"]], - el( - "header", - [["class", "header"]], - el( - "nav", - [["class", "nav"]], - el( - "ul", - [], - el( - "li", - [["class", "logo"]], - el("a", [["href", "/"]], text(config.blog.siteName)), - ), - el( - "li", - [], - el("a", [["href", "/about"]], text("About")), - ), - el( - "li", - [], - el("a", [["href", "/posts"]], text("Posts")), - ), - el( - "li", - [], - el("a", [["href", "/slides"]], text("Slides")), - ), - ), - ), - ), + globalHeader(config), el( "main", [["class", "main"]], @@ -120,7 +55,7 @@ export async function generatePostPage( [["class", "tag"]], el( "a", - [["href", `/tags/${slug}`]], + [["href", `/tags/${slug}/`]], text( (config.blog.tagLabels as { [key: string]: string; @@ -173,19 +108,23 @@ export async function generatePostPage( ), ), ), - el( - "footer", - [["class", "footer"]], - text( - `© ${config.blog.siteCopyrightYear} ${config.blog.author}`, - ), - ), + globalFooter(config), ); - const html = el( - "html", - [["lang", "ja-JP"]], - head, + + const html = await pageLayout( + { + metaCopyrightYear: parseInt( + getPostCreatedDate(doc).substring(0, 4), + ), + metaDescription: doc.summary, + metaKeywords: doc.tags.map((slug) => + (config.blog.tagLabels as { [key: string]: string })[slug] + ), + metaTitle: doc.title, + requiresSyntaxHighlight: true, + }, body, + config, ); const cwd = Deno.cwd(); diff --git a/nuldoc-src/pages/post_list.ts b/nuldoc-src/pages/post_list.ts index e22316e..09d1942 100644 --- a/nuldoc-src/pages/post_list.ts +++ b/nuldoc-src/pages/post_list.ts @@ -1,13 +1,10 @@ +import { globalFooter } from "../components/global_footer.ts"; +import { globalHeader } from "../components/global_header.ts"; +import { pageLayout } from "../components/page_layout.ts"; import { Config } from "../config.ts"; +import { el, text } from "../dom.ts"; import { Page } from "../page.ts"; import { getPostCreatedDate, getPostUpdatedDate, PostPage } from "./post.ts"; -import { - el, - linkElement, - metaElement, - stylesheetLinkElement, - text, -} from "./utils.ts"; export type PostListPage = Page; @@ -17,59 +14,10 @@ export async function generatePostListPage( ): Promise { const pageTitle = "投稿一覧"; - const head = el( - "head", - [], - metaElement([["charset", "UTF-8"]]), - metaElement([["name", "viewport"], [ - "content", - "width=device-width, initial-scale=1.0", - ]]), - metaElement([["name", "author"], ["content", config.blog.author]]), - metaElement([["name", "copyright"], [ - "content", - `© ${config.blog.siteCopyrightYear} ${config.blog.author}`, - ]]), - metaElement([["name", "description"], ["content", "投稿した記事の一覧"]]), - linkElement("icon", "/favicon.svg", "image/svg+xml"), - el("title", [], text(`${pageTitle} | ${config.blog.siteName}`)), - await stylesheetLinkElement("/style.css", config), - ); const body = el( "body", [["class", "list"]], - el( - "header", - [["class", "header"]], - el( - "nav", - [["class", "nav"]], - el( - "ul", - [], - el( - "li", - [["class", "logo"]], - el("a", [["href", "/"]], text(config.blog.siteName)), - ), - el( - "li", - [], - el("a", [["href", "/about"]], text("About")), - ), - el( - "li", - [], - el("a", [["href", "/posts"]], text("Posts")), - ), - el( - "li", - [], - el("a", [["href", "/slides"]], text("Slides")), - ), - ), - ), - ), + globalHeader(config), el( "main", [["class", "main"]], @@ -128,19 +76,19 @@ export async function generatePostListPage( ) ), ), - el( - "footer", - [["class", "footer"]], - text( - `© ${config.blog.siteCopyrightYear} ${config.blog.author}`, - ), - ), + globalFooter(config), ); - const html = el( - "html", - [["lang", "ja-JP"]], - head, + + const html = await pageLayout( + { + metaCopyrightYear: config.blog.siteCopyrightYear, + metaDescription: "投稿した記事の一覧", + metaKeywords: [], + metaTitle: pageTitle, + requiresSyntaxHighlight: false, + }, body, + config, ); return { diff --git a/nuldoc-src/pages/tag.ts b/nuldoc-src/pages/tag.ts index 51aedcd..c9eaf7e 100644 --- a/nuldoc-src/pages/tag.ts +++ b/nuldoc-src/pages/tag.ts @@ -1,13 +1,10 @@ +import { globalFooter } from "../components/global_footer.ts"; +import { globalHeader } from "../components/global_header.ts"; +import { pageLayout } from "../components/page_layout.ts"; import { Config } from "../config.ts"; +import { el, text } from "../dom.ts"; import { Page } from "../page.ts"; import { getPostCreatedDate, getPostUpdatedDate, PostPage } from "./post.ts"; -import { - el, - linkElement, - metaElement, - stylesheetLinkElement, - text, -} from "./utils.ts"; export type TagPage = Page; @@ -20,64 +17,10 @@ export async function generateTagPage( (config.blog.tagLabels as { [key: string]: string })[tagSlug]; const pageTitle = `タグ「${tagLabel}」一覧`; - const headChildren = [ - metaElement([["charset", "UTF-8"]]), - metaElement([["name", "viewport"], [ - "content", - "width=device-width, initial-scale=1.0", - ]]), - metaElement([["name", "author"], ["content", config.blog.author]]), - metaElement([["name", "copyright"], [ - "content", - `© ${ - getPostCreatedDate(posts[posts.length - 1]).substring(0, 4) - } ${config.blog.author}`, - ]]), - metaElement([["name", "description"], [ - "content", - `タグ「${tagLabel}」のついた記事一覧`, - ]]), - metaElement([["name", "keywords"], ["content", tagLabel]]), - linkElement("icon", "/favicon.svg", "image/svg+xml"), - el("title", [], text(`${pageTitle} | ${config.blog.siteName}`)), - await stylesheetLinkElement("/style.css", config), - ]; - const head = el("head", [], ...headChildren); const body = el( "body", [["class", "list"]], - el( - "header", - [["class", "header"]], - el( - "nav", - [["class", "nav"]], - el( - "ul", - [], - el( - "li", - [["class", "logo"]], - el("a", [["href", "/"]], text(config.blog.siteName)), - ), - el( - "li", - [], - el("a", [["href", "/about"]], text("About")), - ), - el( - "li", - [], - el("a", [["href", "/posts"]], text("Posts")), - ), - el( - "li", - [], - el("a", [["href", "/slides"]], text("Slides")), - ), - ), - ), - ), + globalHeader(config), el( "main", [["class", "main"]], @@ -122,19 +65,21 @@ export async function generateTagPage( ) ), ), - el( - "footer", - [["class", "footer"]], - text( - `© ${config.blog.siteCopyrightYear} ${config.blog.author}`, - ), - ), + globalFooter(config), ); - const html = el( - "html", - [["lang", "ja-JP"]], - head, + + const html = await pageLayout( + { + metaCopyrightYear: parseInt( + getPostCreatedDate(posts[posts.length - 1]).substring(0, 4), + ), + metaDescription: `タグ「${tagLabel}」のついた記事一覧`, + metaKeywords: [tagLabel], + metaTitle: pageTitle, + requiresSyntaxHighlight: false, + }, body, + config, ); return { diff --git a/nuldoc-src/pages/utils.ts b/nuldoc-src/pages/utils.ts deleted file mode 100644 index 018c460..0000000 --- a/nuldoc-src/pages/utils.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { join } from "std/path/mod.ts"; -import { crypto, toHashString } from "std/crypto/mod.ts"; -import { Element, Node, Text } from "../dom.ts"; -import { Config } from "../config.ts"; - -export function text(content: string): Text { - return { - kind: "text", - content: content, - raw: false, - }; -} - -export function el( - name: string, - attrs: [string, string][], - ...children: Node[] -): Element { - return { - kind: "element", - name: name, - attributes: new Map(attrs), - children: children, - }; -} - -export async function stylesheetLinkElement( - fileName: string, - config: Config, -): Promise { - const filePath = join(Deno.cwd(), config.locations.staticDir, fileName); - const content = (await Deno.readFile(filePath)).buffer; - const hash = toHashString(await crypto.subtle.digest("MD5", content), "hex"); - return el("link", [["rel", "stylesheet"], ["href", `${fileName}?h=${hash}`]]); -} - -export function metaElement(attrs: [string, string][]): Element { - return el("meta", attrs); -} - -export function linkElement( - rel: string, - href: string, - type: string | null, -): Element { - const attrs: [string, string][] = [["rel", rel], ["href", href]]; - if (type !== null) { - attrs.push(["type", type]); - } - return el("link", attrs); -} diff --git a/public/posts/2021-03-30/phperkaigi-2021/index.html b/public/posts/2021-03-30/phperkaigi-2021/index.html index 3cc1e38..2adff51 100644 --- a/public/posts/2021-03-30/phperkaigi-2021/index.html +++ b/public/posts/2021-03-30/phperkaigi-2021/index.html @@ -37,13 +37,13 @@

PHPerKaigi 2021

diff --git a/public/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html b/public/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html index 6716c43..75ae666 100644 --- a/public/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html +++ b/public/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html @@ -37,10 +37,10 @@

【C++】 属性構文の属性名にはキーワードが使える

diff --git a/public/posts/2021-10-02/python-unbound-local-error/index.html b/public/posts/2021-10-02/python-unbound-local-error/index.html index 01a64b4..a39be48 100644 --- a/public/posts/2021-10-02/python-unbound-local-error/index.html +++ b/public/posts/2021-10-02/python-unbound-local-error/index.html @@ -37,10 +37,10 @@

【Python】 クロージャとUnboundLocalError: local variable 'x' referenced before assignment

diff --git a/public/posts/2021-10-02/ruby-detect-running-implementation/index.html b/public/posts/2021-10-02/ruby-detect-running-implementation/index.html index ef9b7a9..4a2315c 100644 --- a/public/posts/2021-10-02/ruby-detect-running-implementation/index.html +++ b/public/posts/2021-10-02/ruby-detect-running-implementation/index.html @@ -37,7 +37,7 @@

【Ruby】 自身を実行している処理系の種類を判定する

diff --git a/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html b/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html index d027ec6..765121c 100644 --- a/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html +++ b/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html @@ -37,10 +37,10 @@

【Ruby】 then キーワードと case in

diff --git a/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html b/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html index 60e326d..7fc44c9 100644 --- a/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html +++ b/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html @@ -37,7 +37,7 @@

Rust のプリミティブ型はどこからやって来るか

diff --git a/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html b/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html index 46e3218..f2b0ba5 100644 --- a/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html +++ b/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html @@ -37,7 +37,7 @@

【Vim】 autocmd events の BufWrite/BufWritePre の違い

diff --git a/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html b/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html index 2470434..5dacbd0 100644 --- a/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html +++ b/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html @@ -37,7 +37,7 @@

Vimで選択した行の順番を入れ替える

diff --git a/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html b/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html index 7e9a000..78f76c4 100644 --- a/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html +++ b/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html @@ -37,13 +37,13 @@

PHPerKaigi 2022 トークン問題の解説

diff --git a/public/posts/2022-05-01/phperkaigi-2022/index.html b/public/posts/2022-05-01/phperkaigi-2022/index.html index 923543f..02d6c40 100644 --- a/public/posts/2022-05-01/phperkaigi-2022/index.html +++ b/public/posts/2022-05-01/phperkaigi-2022/index.html @@ -37,13 +37,13 @@

PHPerKaigi 2022

diff --git a/public/posts/2022-08-27/php-conference-okinawa-code-golf/index.html b/public/posts/2022-08-27/php-conference-okinawa-code-golf/index.html index 408228b..6e82f8f 100644 --- a/public/posts/2022-08-27/php-conference-okinawa-code-golf/index.html +++ b/public/posts/2022-08-27/php-conference-okinawa-code-golf/index.html @@ -37,13 +37,13 @@

PHP カンファレンス沖縄で出題されたコードゴルフの問題を解いてみた

diff --git a/public/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/index.html b/public/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/index.html index 5cf3564..e946180 100644 --- a/public/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/index.html +++ b/public/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/index.html @@ -37,7 +37,7 @@

【PHP】 fizzbuzz を書く。1行あたり2文字で。

diff --git a/public/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/index.html b/public/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/index.html index 6c100a9..6c9b1e2 100644 --- a/public/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/index.html +++ b/public/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/index.html @@ -37,10 +37,10 @@

PHPerKaigi 2023: ボツになったトークン問題 その 1

diff --git a/public/posts/2022-10-28/setup-server-for-this-site/index.html b/public/posts/2022-10-28/setup-server-for-this-site/index.html index ab629fc..cce6ff8 100644 --- a/public/posts/2022-10-28/setup-server-for-this-site/index.html +++ b/public/posts/2022-10-28/setup-server-for-this-site/index.html @@ -37,7 +37,7 @@

【備忘録】 このサイト用の VPS をセットアップしたときのメモ

diff --git a/public/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2/index.html b/public/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2/index.html index 57c6119..e97d3e1 100644 --- a/public/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2/index.html +++ b/public/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2/index.html @@ -37,10 +37,10 @@

PHPerKaigi 2023: ボツになったトークン問題 その 2

diff --git a/public/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3/index.html b/public/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3/index.html index 607a65e..c98ee98 100644 --- a/public/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3/index.html +++ b/public/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3/index.html @@ -37,10 +37,10 @@

PHPerKaigi 2023: ボツになったトークン問題 その 3

-- cgit v1.2.3-70-g09d2