aboutsummaryrefslogtreecommitdiffhomepage
path: root/vhosts/blog
diff options
context:
space:
mode:
Diffstat (limited to 'vhosts/blog')
-rw-r--r--vhosts/blog/.editorconfig2
-rw-r--r--vhosts/blog/content/posts/2021-03-05/my-first-post.dj21
-rw-r--r--vhosts/blog/content/posts/2021-03-05/my-first-post.ndoc25
-rw-r--r--vhosts/blog/content/posts/2021-03-30/phperkaigi-2021.dj177
-rw-r--r--vhosts/blog/content/posts/2021-03-30/phperkaigi-2021.ndoc209
-rw-r--r--vhosts/blog/content/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes.dj113
-rw-r--r--vhosts/blog/content/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes.ndoc140
-rw-r--r--vhosts/blog/content/posts/2021-10-02/python-unbound-local-error.dj70
-rw-r--r--vhosts/blog/content/posts/2021-10-02/python-unbound-local-error.ndoc84
-rw-r--r--vhosts/blog/content/posts/2021-10-02/ruby-detect-running-implementation.dj73
-rw-r--r--vhosts/blog/content/posts/2021-10-02/ruby-detect-running-implementation.ndoc119
-rw-r--r--vhosts/blog/content/posts/2021-10-02/ruby-then-keyword-and-case-in.dj232
-rw-r--r--vhosts/blog/content/posts/2021-10-02/ruby-then-keyword-and-case-in.ndoc267
-rw-r--r--vhosts/blog/content/posts/2021-10-02/rust-where-are-primitive-types-from.dj205
-rw-r--r--vhosts/blog/content/posts/2021-10-02/rust-where-are-primitive-types-from.ndoc234
-rw-r--r--vhosts/blog/content/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre.dj126
-rw-r--r--vhosts/blog/content/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre.ndoc162
-rw-r--r--vhosts/blog/content/posts/2021-10-02/vim-swap-order-of-selected-lines.dj161
-rw-r--r--vhosts/blog/content/posts/2021-10-02/vim-swap-order-of-selected-lines.ndoc212
-rw-r--r--vhosts/blog/content/posts/2022-04-09/phperkaigi-2022-tokens.dj489
-rw-r--r--vhosts/blog/content/posts/2022-04-09/phperkaigi-2022-tokens.ndoc560
-rw-r--r--vhosts/blog/content/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal.dj97
-rw-r--r--vhosts/blog/content/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal.ndoc119
-rw-r--r--vhosts/blog/content/posts/2022-05-01/phperkaigi-2022.dj132
-rw-r--r--vhosts/blog/content/posts/2022-05-01/phperkaigi-2022.ndoc166
-rw-r--r--vhosts/blog/content/posts/2022-08-27/php-conference-okinawa-code-golf.dj99
-rw-r--r--vhosts/blog/content/posts/2022-08-27/php-conference-okinawa-code-golf.ndoc119
-rw-r--r--vhosts/blog/content/posts/2022-08-31/support-for-communty-is-employee-benefits.dj52
-rw-r--r--vhosts/blog/content/posts/2022-08-31/support-for-communty-is-employee-benefits.ndoc69
-rw-r--r--vhosts/blog/content/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line.dj617
-rw-r--r--vhosts/blog/content/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line.ndoc705
-rw-r--r--vhosts/blog/content/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1.dj154
-rw-r--r--vhosts/blog/content/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1.ndoc185
-rw-r--r--vhosts/blog/content/posts/2022-10-28/setup-server-for-this-site.dj264
-rw-r--r--vhosts/blog/content/posts/2022-10-28/setup-server-for-this-site.ndoc310
-rw-r--r--vhosts/blog/content/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2.dj139
-rw-r--r--vhosts/blog/content/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2.ndoc171
-rw-r--r--vhosts/blog/content/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3.dj289
-rw-r--r--vhosts/blog/content/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3.ndoc326
-rw-r--r--vhosts/blog/content/posts/2023-03-10/rewrite-this-blog-generator.dj73
-rw-r--r--vhosts/blog/content/posts/2023-03-10/rewrite-this-blog-generator.ndoc95
-rw-r--r--vhosts/blog/content/posts/2023-04-01/implementation-of-minimal-png-image-encoder.dj544
-rw-r--r--vhosts/blog/content/posts/2023-04-01/implementation-of-minimal-png-image-encoder.ndoc605
-rw-r--r--vhosts/blog/content/posts/2023-04-04/phperkaigi-2023-report.dj141
-rw-r--r--vhosts/blog/content/posts/2023-04-04/phperkaigi-2023-report.ndoc184
-rw-r--r--vhosts/blog/content/posts/2023-06-25/phpconfuk-2023-report.dj64
-rw-r--r--vhosts/blog/content/posts/2023-06-25/phpconfuk-2023-report.ndoc106
-rw-r--r--vhosts/blog/content/posts/2023-10-02/compile-php-runtime-to-wasm.dj286
-rw-r--r--vhosts/blog/content/posts/2023-10-02/compile-php-runtime-to-wasm.ndoc335
-rw-r--r--vhosts/blog/content/posts/2023-10-13/i-entered-the-open-university-of-japan.dj22
-rw-r--r--vhosts/blog/content/posts/2023-10-13/i-entered-the-open-university-of-japan.ndoc28
-rw-r--r--vhosts/blog/content/posts/2023-12-03/isucon-13.dj75
-rw-r--r--vhosts/blog/content/posts/2023-12-03/isucon-13.ndoc92
-rw-r--r--vhosts/blog/content/posts/2023-12-31/2023-reflections.dj76
-rw-r--r--vhosts/blog/content/posts/2023-12-31/2023-reflections.ndoc92
-rw-r--r--vhosts/blog/content/posts/2024-01-10/neovim-insert-namespace-declaration-to-empty-php-file.dj205
-rw-r--r--vhosts/blog/content/posts/2024-01-10/neovim-insert-namespace-declaration-to-empty-php-file.ndoc221
-rw-r--r--vhosts/blog/content/posts/2024-02-03/install-wireguard-on-personal-server.dj144
-rw-r--r--vhosts/blog/content/posts/2024-02-03/install-wireguard-on-personal-server.ndoc180
-rw-r--r--vhosts/blog/content/posts/2024-02-10/yapcjapan-2024-report.dj44
-rw-r--r--vhosts/blog/content/posts/2024-02-10/yapcjapan-2024-report.ndoc55
-rw-r--r--vhosts/blog/content/posts/2024-02-22/phpkansai-2024-report.dj44
-rw-r--r--vhosts/blog/content/posts/2024-02-22/phpkansai-2024-report.ndoc55
-rw-r--r--vhosts/blog/content/posts/2024-03-17/phperkaigi-2024-report.dj85
-rw-r--r--vhosts/blog/content/posts/2024-03-17/phperkaigi-2024-report.ndoc110
-rw-r--r--vhosts/blog/content/posts/2024-03-20/my-bucket-list.dj46
-rw-r--r--vhosts/blog/content/posts/2024-03-20/my-bucket-list.ndoc57
-rw-r--r--vhosts/blog/content/posts/2024-04-14/phpcon-odawara-2024-report.dj76
-rw-r--r--vhosts/blog/content/posts/2024-04-14/phpcon-odawara-2024-report.ndoc102
-rw-r--r--vhosts/blog/content/posts/2024-04-21/pipefail-option-in-gitlab-ci-cd.dj155
-rw-r--r--vhosts/blog/content/posts/2024-04-21/pipefail-option-in-gitlab-ci-cd.ndoc180
-rw-r--r--vhosts/blog/content/posts/2024-04-29/zsh-file-completion-for-composer-custom-commands.dj86
-rw-r--r--vhosts/blog/content/posts/2024-04-29/zsh-file-completion-for-composer-custom-commands.ndoc103
-rw-r--r--vhosts/blog/content/posts/2024-05-11/phpconkagawa-2024-report.dj64
-rw-r--r--vhosts/blog/content/posts/2024-05-11/phpconkagawa-2024-report.ndoc107
-rw-r--r--vhosts/blog/content/posts/2024-06-19/scalamatsuri-2024-report.dj48
-rw-r--r--vhosts/blog/content/posts/2024-06-19/scalamatsuri-2024-report.ndoc63
-rw-r--r--vhosts/blog/content/posts/2024-07-19/reparojson-fix-only-json-formatter.dj132
-rw-r--r--vhosts/blog/content/posts/2024-07-19/reparojson-fix-only-json-formatter.ndoc153
-rw-r--r--vhosts/blog/content/posts/2024-08-19/go-template-access-outer-scope-pipeline-within-with-or-range.dj118
-rw-r--r--vhosts/blog/content/posts/2024-08-19/go-template-access-outer-scope-pipeline-within-with-or-range.ndoc141
-rw-r--r--vhosts/blog/content/posts/2024-09-28/mncore-challenge-1.dj37
-rw-r--r--vhosts/blog/content/posts/2024-09-28/mncore-challenge-1.ndoc45
-rw-r--r--vhosts/blog/content/posts/2024-12-04/cohackpp-report.dj197
-rw-r--r--vhosts/blog/content/posts/2024-12-04/cohackpp-report.ndoc217
-rw-r--r--vhosts/blog/content/posts/2024-12-33/2024-reflections.dj84
-rw-r--r--vhosts/blog/content/posts/2024-12-33/2024-reflections.ndoc101
-rw-r--r--vhosts/blog/content/posts/2025-01-08/phperkaigi-2023-tokens-q1.dj350
-rw-r--r--vhosts/blog/content/posts/2025-01-08/phperkaigi-2023-tokens-q1.ndoc406
-rw-r--r--vhosts/blog/content/posts/2025-01-26/yaml-breaking-changes-between-v1-1-and-v1-2.dj76
-rw-r--r--vhosts/blog/content/posts/2025-01-26/yaml-breaking-changes-between-v1-1-and-v1-2.ndoc87
-rw-r--r--vhosts/blog/content/posts/2025-02-24/phpcon-nagoya-2025-report.dj49
-rw-r--r--vhosts/blog/content/posts/2025-02-24/phpcon-nagoya-2025-report.ndoc64
-rw-r--r--vhosts/blog/content/posts/2025-03-27/zip-function-like-command-paste-command.dj93
-rw-r--r--vhosts/blog/content/posts/2025-03-27/zip-function-like-command-paste-command.ndoc111
-rw-r--r--vhosts/blog/content/posts/2025-03-28/http-1-1-send-multiple-same-headers.dj102
-rw-r--r--vhosts/blog/content/posts/2025-03-28/http-1-1-send-multiple-same-headers.ndoc120
-rw-r--r--vhosts/blog/nuldoc-src/djot/djot2ndoc.ts54
98 files changed, 7058 insertions, 8421 deletions
diff --git a/vhosts/blog/.editorconfig b/vhosts/blog/.editorconfig
index f6e2ae3e..a036f907 100644
--- a/vhosts/blog/.editorconfig
+++ b/vhosts/blog/.editorconfig
@@ -5,6 +5,6 @@ charset = utf-8
end_of_line = lf
insert_final_newline = true
-[*.ndoc]
+[*.dj]
indent_style = space
indent_size = 2
diff --git a/vhosts/blog/content/posts/2021-03-05/my-first-post.dj b/vhosts/blog/content/posts/2021-03-05/my-first-post.dj
new file mode 100644
index 00000000..a84dbd93
--- /dev/null
+++ b/vhosts/blog/content/posts/2021-03-05/my-first-post.dj
@@ -0,0 +1,21 @@
+---
+[article]
+uuid = "6e9c71fd-bc8d-43ce-99c5-13d9f5b87ed2"
+title = "My First Post"
+description = "これはテスト投皿です。これはテスト投皿です。これはテスト投皿です。"
+tags = []
+
+[[article.revisions]]
+date = "2021-03-05"
+remark = "公開"
+---
+{#test}
+# Test
+
+Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
+veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
+commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
+velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
+occaecat cupidatat non proident, sunt in culpa qui officia deserunt
+mollit anim id est laborum.
diff --git a/vhosts/blog/content/posts/2021-03-05/my-first-post.ndoc b/vhosts/blog/content/posts/2021-03-05/my-first-post.ndoc
deleted file mode 100644
index ee23da14..00000000
--- a/vhosts/blog/content/posts/2021-03-05/my-first-post.ndoc
+++ /dev/null
@@ -1,25 +0,0 @@
----
-[article]
-uuid = "6e9c71fd-bc8d-43ce-99c5-13d9f5b87ed2"
-title = "My First Post"
-description = "これはテスト投皿です。これはテスト投皿です。これはテスト投皿です。"
-tags = []
-
-[[article.revisions]]
-date = "2021-03-05"
-remark = "公開"
----
-<article>
- <section id="test">
- <h>Test</h>
- <p>
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
- tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
- veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
- commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
- velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
- occaecat cupidatat non proident, sunt in culpa qui officia deserunt
- mollit anim id est laborum.
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2021-03-30/phperkaigi-2021.dj b/vhosts/blog/content/posts/2021-03-30/phperkaigi-2021.dj
new file mode 100644
index 00000000..fac9f1ed
--- /dev/null
+++ b/vhosts/blog/content/posts/2021-03-30/phperkaigi-2021.dj
@@ -0,0 +1,177 @@
+---
+[article]
+uuid = "3fbe0b8c-216e-48f6-b905-c0d361b94542"
+title = "PHPerKaigi 2021"
+description = "2021-03-26 から 2021-03-28 にかけお開催された、PHPerKaigi 2021 に参加した。"
+tags = [
+ "conference",
+ "php",
+ "phperkaigi",
+]
+
+[[article.revisions]]
+date = "2021-03-30"
+remark = "公開"
+
+[[article.revisions]]
+date = "2025-04-09"
+remark = "それぞれの発衚に関するメモ郚分を削陀し、感想のみに"
+---
+{#report}
+# PHPerKaigi 2021 参加レポ
+
+2021-03-26 から 2021-03-28
+にかけお開催された、[PHPerKaigi 2021](https://phperkaigi.jp/2021/)
+に䞀般参加者ずしお参加した。
+匊瀟[デゞタルサヌカス株匏䌚瀟](https://www.dgcircus.com/)
+(今幎1月から勀務)
+はダむダモンドスポンサヌずなっおおり、スポンサヌ枠のチケットを䜿わせおいただいた。
+
+このようなカンファレンスには初めお参加するのでかねおより心埅ちにしおいたのだが、生憎2日目から䜓調を厩しおしたい、この蚘事も途䞭たでずなっおいる。ただ芋おいないセッションも倚いが、ひずたず珟時点での参加レポを曞いおおく。
+
+発衚はトラック A、B に分かれおいたのだが、今回はすべお A
+トラックを芖聎しおいる (切り替えるのが面倒だっただけ)。
+
+{#day-0}
+## Day 0 前倜祭 (2021/03/27)
+
+{#1730-a}
+### 17:30 [A] LAMPをこじらせおサヌバヌレスに乗り遅れたPHPerがLambdaに入門しおみる
+
+AWS Lambda のような Function as a Service
+はマむクロサヌビス化における䞀぀の到達点に思えるのだが、これを䜿っお実際に
+web サヌビスを䜜る具䜓的なむメヌゞがただ芋えない (泚: すべお for me
+ずしお曞いおいる)。
+
+PHP on AWS Lambda があれだけ簡単に動かせるのには驚いた。
+
+勝手に AWS Lambda だずフットプリントの軜さが求められそう (= PHP +
+Laravel などでは動かなさそう)
+だずいう先入芳を持っおいたのだが、この発衚のデモによればそうでもないらしい。
+
+{#1810-a}
+### 18:10 [A] 倧芏暡サむトにおけるSEO芳点でのURL蚭蚈
+
+SEO (Search Engine Optimization)
+は倧しお知らないので新鮮な話が倚かった。その分語れるこずも少ない  。
+
+{#1850-a}
+### 18:50 [A] PHPerでもわかる実践Webアクセシビリティ
+
+぀い最近 WAI-ARIA
+に぀いおの蚘事を読んだばかりだったので個人的にタむムリヌな話題だった。(あたりこの蚀葉を䜿いたくないのだが)
+いわゆる「健垞者」にずっお、こうした問題を普段の生掻の䞭で意識するのは難しい。だからこそ情報ぞのアンテナは匵っおおくようにしたい。
+
+{#1930-a}
+### 19:30 [A] PHP でファむルシステムを䜜ろう
+
+PHP で FUSE
+
+個人的に楜しみだった発衚。
+
+期埅通りの興味深い発衚だった。FUSE
+自䜓も今回の発衚で知ったのだが、これ本䜓の実装を芋るのも面癜そうだ。
+この発衚を聞きながらファむルシステムにマりントできそうなものを考えおいたのだが、およそ朚構造をしおいるものすべおず蚀えそうだ
+(ハンマヌしか持っおいないず云々)。䜕かできそうだがなかなか思い぀かない。
+
+{#day-1}
+## Day 1 (2021/03/27)
+
+{#1050-a}
+### 10:50 [A] 実践ATDD 〜TDDから曎に歩みを進めた゜フトりェア開発ぞ〜
+
+User Acceptance Test (UAT)
+くらいの芏暡になるず個人開発・趣味開発では觊れない領域なので、倧いに勉匷になった。スラむドに添付されおいる資料が盞圓に充実しおいたので、これを読むのが本番ずいった様盞すら感じる。
+高レベルテストの自動化は珟圚のプロゞェクトでも感じおおり、自動化のチャンスは䌺っおいる。ずはいえセッションでも指摘されおいるように自動化するこずにコストがかかりすぎる領域があるのも事実で、そのバランスが難しい。
+
+{#1150-a}
+### 11:50 [A] 静的型解析を甚いた倧芏暡レガシヌコヌドのリファクタリング蚈画
+
+型のある䞖界で生きおきた身ずしお倧いに楜しみにしおいた発衚。
+
+昚今、動的型付き蚀語での型宣蚀・型アノテヌション・型ヒントの導入が盞次いでいる。長らく静的型付き蚀語を曞いおきた私からするず、ようやく気づいたかずいったずころだが、ずもかく型を導入する蚀語が増えおきた。
+今のプロゞェクトでも新しく远加するコヌドには型を぀けるよう努めおいるが、どうしおも叀いコヌドには型が぀いおいない。個人的には型のないコヌドに察しおどう型を自動的に付けるかずいう点に興味があり、その点で
+Ruby の typeprof には泚目しおいる。
+
+{#1310-a}
+### 13:10 [A] 目的に沿ったDocumentation as Codeをいかにしお実珟しおいくか
+
+この発衚も以前から非垞に楜しみにしおいた。
+
+ドキュメントの管理は珟プロゞェクトでも課題ず感じおいる。䜜られた圓初は正しくおも、実態ず乖離しおいくのを止めるのは困難を極める。党䜓的に興味深い発衚だったが、特にスタックトレヌスからのドキュメント生成ずいうアむデアに惹かれるものを感じた。スタックトレヌスずいう実態ず䞍可分な
+(乖離しない)
+情報を起点にするのは理にかなっおいる。問題はトレヌスをい぀、どう取るかだろうか。それを自動化しなければ、実態ずの乖離が避けられないだろう。
+
+{#1410-a}
+### 14:10 [A] PHPで孊ぶ、セッションの基本ず応甚
+
+党䜓的に基本的な話だったので特に觊れない。Cookie
+やセッションの話ずしおは非垞に分かりやすくたずめられおいたので、知らない人が孊ぶにはいい教材だろう。
+
+{#1450-a}
+### 14:50 [A] PHP8になった今の時代に、PHPの「゚ラヌ」「䟋倖」そしお「Error」をおさらいしおおこう
+
+PHP を孊んでいる途䞭の私ずしおは、今たさに聞きたい発衚だった (珟時点で
+PHP を曞き始めおから 4ヶ月ほどになる)。
+
+個人的に䟋倖や゚ラヌを最もうたく扱っおいるのは Go、Swift、Rust、Haskell
+などの゚ラヌを「倀ずしお」扱う蚀語だず思っおいる。try-catch
+は通垞の凊理フロヌを完党に壊しおしたう䞊、構文ずしおも重すぎる。倀ずしおの゚ラヌ通知は
+C蚀語時代ぞの回垰ずもいえるが、その頃ず異なるのぱラヌを暗黙のうちに握り朰すこずがないずいうこずだ。これらの蚀語は型を持っおおり、静的に怜蚌ができる
+(C のそれはたずもな型付けではない。念のため)。
+
+PHP
+のように、すでに䟋倖が蚀語システムに根ざしおいる蚀語ではどうすればよいか。この堎合も同じく静的怜蚌の力を借りるこずになるだろう。
+
+{#1530-a}
+### 15:30 [A] Laravel のメヌル認蚌の内郚実装を掘り䞋げる
+
+Laravel
+の知識がない私にはたったく぀いおいけなかった。たた、個人的にタむトルがややミスリヌディングに感じた。
+
+{#1610-a}
+### 16:10 [A] ブラりザから始めるgRPC 〜 gRPC-WebにPHPを添えお
+
+(発衚の䞭でもたさに同じこずをおっしゃっおいたが) PHP
+以倖の方が向いおいるだろう、ずいうのが第䞀の感想である。gRPC
+はそれ自䜓ずいうよりも Protobuf
+ずいう゚コシステムに乗れるこずのメリットが倧きいず感じる。その゚コシステムにうたく乗れない時点で、うヌんずいう感じ。
+
+{#day-2}
+## Day 2 (2021/03/28)
+
+冒頭に曞いた通り、2日目から䜓調が悪くたずもに聎けおいない。途䞭たでは頭痛を我慢し぀぀芋おいたのだが、たずもに入っおこなかった。
+
+残念ではあるが、いずれにせよ芋られおいない発衚は他にもあるので、今週末にでもたずめお芋ようず思う。
+
+{#comments}
+## 党䜓の感想
+
+Day 2
+にほずんど参加できなかったのは残念だが、むベント自䜓は倧倉楜しく、たた興味深いものであった。自分がたったく知らない領域の話を聞けるのはこうしたむベントならではだず感じる。オンラむン開催ゆえ珟地に行く必芁がなく、気軜に参加できたのも
+(特に初参加者ずしお) 嬉しいポむントだった。
+
+今回、雑談/登壇者ぞの質問等向けに Discord
+サヌバもあったのだが、こちらは参加こそしたものの ROM
+のたたになっおしたった。発衚に1りィンドり、メモを曞くのに1りィンドり、Discord
+衚瀺に
+1りィンドりで私にはもう脳のリ゜ヌスずディスプレむのスペヌスが远い぀かなかった
+(さらにいうず Zoom
+でアンカンファレンスもやっおいたようだ。こちらはたったく参加しおいない)。
+
+1぀個人的な反省点ずしおは、䞀぀䞀぀のセッションを真剣に聞き過ぎたずいうものがある。もっず適圓に聞いおおけばよかった。これだけだず倧倉語匊があるのだが、蚀い方を倉えるず、Discord
+しかりアンカンファレンスしかり「このむベントのこの瞬間にしかないコンテンツ」に觊れずに、埌から芋返せる発衚やスラむドに泚力しおしたった、ずいうこずだ。発衚の詳现な芋盎しはあずからできるのだから、今しかできないこずを考えるべきだった。
+たあ初カンファレンスだし、ずお茶を濁しおおこう。
+
+さお、カンファレンスで䞀぀気になったこずがある。それは、Discord
+ずいう曞き蟌み堎所が増えたこずでニコ生のコメントの流量が吞い取られおしたったのではないか、ずいう点だ。ニコニコだけ芋おいるず過疎っおいるかのように芋えた発衚も、Discord
+の方では盛り䞊がっおいる、ずいうのを䜕床か芋かけた。ニコニコのコメント方匏は盛り䞊がりを劂実に反映するが、逆もたたしかり。Discord
+があったこず自䜓はプラスだったず思うが、この点はマむナスだったのではないかず感じる。
+
+----------------
+
+最埌になりたしたが、毎幎の PHPerKaigi
+開催にご尜力されおいる皆様、スピヌカヌの皆様、楜しい3日間でした。ありがずうございたした
+(ずっず垞䜓で曞いおしたったのでいきなり仏頂面から笑顔になったようで気持ち悪い)
+
+ではたた来幎。
diff --git a/vhosts/blog/content/posts/2021-03-30/phperkaigi-2021.ndoc b/vhosts/blog/content/posts/2021-03-30/phperkaigi-2021.ndoc
deleted file mode 100644
index b9a1f67e..00000000
--- a/vhosts/blog/content/posts/2021-03-30/phperkaigi-2021.ndoc
+++ /dev/null
@@ -1,209 +0,0 @@
----
-[article]
-uuid = "3fbe0b8c-216e-48f6-b905-c0d361b94542"
-title = "PHPerKaigi 2021"
-description = "2021-03-26 から 2021-03-28 にかけお開催された、PHPerKaigi 2021 に参加した。"
-tags = [
- "conference",
- "php",
- "phperkaigi",
-]
-
-[[article.revisions]]
-date = "2021-03-30"
-remark = "公開"
-
-[[article.revisions]]
-date = "2025-04-09"
-remark = "それぞれの発衚に関するメモ郚分を削陀し、感想のみに"
----
-<article>
- <section id="report">
- <h>PHPerKaigi 2021 参加レポ</h>
- <p>
- 2021-03-26 から 2021-03-28
- にかけお開催された、 <a href="https://phperkaigi.jp/2021/">PHPerKaigi 2021</a>
- に䞀般参加者ずしお参加した。
- 匊瀟 <a href="https://www.dgcircus.com/">デゞタルサヌカス株匏䌚瀟</a>
- (今幎1月から勀務)
- はダむダモンドスポンサヌずなっおおり、スポンサヌ枠のチケットを䜿わせおいただいた。
- </p>
- <p>
- このようなカンファレンスには初めお参加するのでかねおより心埅ちにしおいたのだが、生憎2日目から䜓調を厩しおしたい、この蚘事も途䞭たでずなっおいる。ただ芋おいないセッションも倚いが、ひずたず珟時点での参加レポを曞いおおく。
- </p>
- <p>
- 発衚はトラック A、B に分かれおいたのだが、今回はすべお A
- トラックを芖聎しおいる (切り替えるのが面倒だっただけ)。
- </p>
- <section id="day-0">
- <h>Day 0 前倜祭 (2021/03/27)</h>
- <section id="1730-a">
- <h>17:30 [A] LAMPをこじらせおサヌバヌレスに乗り遅れたPHPerがLambdaに入門しおみる</h>
- <p>
- AWS Lambda のような Function as a Service
- はマむクロサヌビス化における䞀぀の到達点に思えるのだが、これを䜿っお実際に
- web サヌビスを䜜る具䜓的なむメヌゞがただ芋えない (泚: すべお for me
- ずしお曞いおいる)。
- </p>
- <p>
- PHP on AWS Lambda があれだけ簡単に動かせるのには驚いた。
- </p>
- <p>
- 勝手に AWS Lambda だずフットプリントの軜さが求められそう (= PHP +
- Laravel などでは動かなさそう)
- だずいう先入芳を持っおいたのだが、この発衚のデモによればそうでもないらしい。
- </p>
- </section>
- <section id="1810-a">
- <h>18:10 [A] 倧芏暡サむトにおけるSEO芳点でのURL蚭蚈</h>
- <p>
- SEO (Search Engine Optimization)
- は倧しお知らないので新鮮な話が倚かった。その分語れるこずも少ない  。
- </p>
- </section>
- <section id="1850-a">
- <h>18:50 [A] PHPerでもわかる実践Webアクセシビリティ</h>
- <p>
- ぀い最近 WAI-ARIA
- に぀いおの蚘事を読んだばかりだったので個人的にタむムリヌな話題だった。(あたりこの蚀葉を䜿いたくないのだが)
- いわゆる「健垞者」にずっお、こうした問題を普段の生掻の䞭で意識するのは難しい。だからこそ情報ぞのアンテナは匵っおおくようにしたい。
- </p>
- </section>
- <section id="1930-a">
- <h>19:30 [A] PHP でファむルシステムを䜜ろう</h>
- <p>
- PHP で FUSE
- </p>
- <p>
- 個人的に楜しみだった発衚。
- </p>
- <p>
- 期埅通りの興味深い発衚だった。FUSE
- 自䜓も今回の発衚で知ったのだが、これ本䜓の実装を芋るのも面癜そうだ。
- この発衚を聞きながらファむルシステムにマりントできそうなものを考えおいたのだが、およそ朚構造をしおいるものすべおず蚀えそうだ
- (ハンマヌしか持っおいないず云々)。䜕かできそうだがなかなか思い぀かない。
- </p>
- </section>
- </section>
- <section id="day-1">
- <h>Day 1 (2021/03/27)</h>
- <section id="1050-a">
- <h>10:50 [A] 実践ATDD 〜TDDから曎に歩みを進めた゜フトりェア開発ぞ〜</h>
- <p>
- User Acceptance Test (UAT)
- くらいの芏暡になるず個人開発・趣味開発では觊れない領域なので、倧いに勉匷になった。スラむドに添付されおいる資料が盞圓に充実しおいたので、これを読むのが本番ずいった様盞すら感じる。
- 高レベルテストの自動化は珟圚のプロゞェクトでも感じおおり、自動化のチャンスは䌺っおいる。ずはいえセッションでも指摘されおいるように自動化するこずにコストがかかりすぎる領域があるのも事実で、そのバランスが難しい。
- </p>
- </section>
- <section id="1150-a">
- <h>11:50 [A] 静的型解析を甚いた倧芏暡レガシヌコヌドのリファクタリング蚈画</h>
- <p>
- 型のある䞖界で生きおきた身ずしお倧いに楜しみにしおいた発衚。
- </p>
- <p>
- 昚今、動的型付き蚀語での型宣蚀・型アノテヌション・型ヒントの導入が盞次いでいる。長らく静的型付き蚀語を曞いおきた私からするず、ようやく気づいたかずいったずころだが、ずもかく型を導入する蚀語が増えおきた。
- 今のプロゞェクトでも新しく远加するコヌドには型を぀けるよう努めおいるが、どうしおも叀いコヌドには型が぀いおいない。個人的には型のないコヌドに察しおどう型を自動的に付けるかずいう点に興味があり、その点で
- Ruby の typeprof には泚目しおいる。
- </p>
- </section>
- <section id="1310-a">
- <h>13:10 [A] 目的に沿ったDocumentation as Codeをいかにしお実珟しおいくか</h>
- <p>
- この発衚も以前から非垞に楜しみにしおいた。
- </p>
- <p>
- ドキュメントの管理は珟プロゞェクトでも課題ず感じおいる。䜜られた圓初は正しくおも、実態ず乖離しおいくのを止めるのは困難を極める。党䜓的に興味深い発衚だったが、特にスタックトレヌスからのドキュメント生成ずいうアむデアに惹かれるものを感じた。スタックトレヌスずいう実態ず䞍可分な
- (乖離しない)
- 情報を起点にするのは理にかなっおいる。問題はトレヌスをい぀、どう取るかだろうか。それを自動化しなければ、実態ずの乖離が避けられないだろう。
- </p>
- </section>
- <section id="1410-a">
- <h>14:10 [A] PHPで孊ぶ、セッションの基本ず応甚</h>
- <p>
- 党䜓的に基本的な話だったので特に觊れない。Cookie
- やセッションの話ずしおは非垞に分かりやすくたずめられおいたので、知らない人が孊ぶにはいい教材だろう。
- </p>
- </section>
- <section id="1450-a">
- <h>14:50 [A] PHP8になった今の時代に、PHPの「゚ラヌ」「䟋倖」そしお「Error」をおさらいしおおこう</h>
- <p>
- PHP を孊んでいる途䞭の私ずしおは、今たさに聞きたい発衚だった (珟時点で
- PHP を曞き始めおから 4ヶ月ほどになる)。
- </p>
- <p>
- 個人的に䟋倖や゚ラヌを最もうたく扱っおいるのは Go、Swift、Rust、Haskell
- などの゚ラヌを「倀ずしお」扱う蚀語だず思っおいる。try-catch
- は通垞の凊理フロヌを完党に壊しおしたう䞊、構文ずしおも重すぎる。倀ずしおの゚ラヌ通知は
- C蚀語時代ぞの回垰ずもいえるが、その頃ず異なるのぱラヌを暗黙のうちに握り朰すこずがないずいうこずだ。これらの蚀語は型を持っおおり、静的に怜蚌ができる
- (C のそれはたずもな型付けではない。念のため)。
- </p>
- <p>
- PHP
- のように、すでに䟋倖が蚀語システムに根ざしおいる蚀語ではどうすればよいか。この堎合も同じく静的怜蚌の力を借りるこずになるだろう。
- </p>
- </section>
- <section id="1530-a">
- <h>15:30 [A] Laravel のメヌル認蚌の内郚実装を掘り䞋げる</h>
- <p>
- Laravel
- の知識がない私にはたったく぀いおいけなかった。たた、個人的にタむトルがややミスリヌディングに感じた。
- </p>
- </section>
- <section id="1610-a">
- <h>16:10 [A] ブラりザから始めるgRPC 〜 gRPC-WebにPHPを添えお</h>
- <p>
- (発衚の䞭でもたさに同じこずをおっしゃっおいたが) PHP
- 以倖の方が向いおいるだろう、ずいうのが第䞀の感想である。gRPC
- はそれ自䜓ずいうよりも Protobuf
- ずいう゚コシステムに乗れるこずのメリットが倧きいず感じる。その゚コシステムにうたく乗れない時点で、うヌんずいう感じ。
- </p>
- </section>
- </section>
- <section id="day-2">
- <h>Day 2 (2021/03/28)</h>
- <p>
- 冒頭に曞いた通り、2日目から䜓調が悪くたずもに聎けおいない。途䞭たでは頭痛を我慢し぀぀芋おいたのだが、たずもに入っおこなかった。
- </p>
- <p>
- 残念ではあるが、いずれにせよ芋られおいない発衚は他にもあるので、今週末にでもたずめお芋ようず思う。
- </p>
- </section>
- <section id="comments">
- <h>党䜓の感想</h>
- <p>
- Day 2
- にほずんど参加できなかったのは残念だが、むベント自䜓は倧倉楜しく、たた興味深いものであった。自分がたったく知らない領域の話を聞けるのはこうしたむベントならではだず感じる。オンラむン開催ゆえ珟地に行く必芁がなく、気軜に参加できたのも
- (特に初参加者ずしお) 嬉しいポむントだった。
- </p>
- <p>
- 今回、雑談/登壇者ぞの質問等向けに Discord
- サヌバもあったのだが、こちらは参加こそしたものの ROM
- のたたになっおしたった。発衚に1りィンドり、メモを曞くのに1りィンドり、Discord
- 衚瀺に
- 1りィンドりで私にはもう脳のリ゜ヌスずディスプレむのスペヌスが远い぀かなかった
- (さらにいうず Zoom
- でアンカンファレンスもやっおいたようだ。こちらはたったく参加しおいない)。
- </p>
- <p>
- 1぀個人的な反省点ずしおは、䞀぀䞀぀のセッションを真剣に聞き過ぎたずいうものがある。もっず適圓に聞いおおけばよかった。これだけだず倧倉語匊があるのだが、蚀い方を倉えるず、Discord
- しかりアンカンファレンスしかり「このむベントのこの瞬間にしかないコンテンツ」に觊れずに、埌から芋返せる発衚やスラむドに泚力しおしたった、ずいうこずだ。発衚の詳现な芋盎しはあずからできるのだから、今しかできないこずを考えるべきだった。
- たあ初カンファレンスだし、ずお茶を濁しおおこう。
- </p>
- <p>
- さお、カンファレンスで䞀぀気になったこずがある。それは、Discord
- ずいう曞き蟌み堎所が増えたこずでニコ生のコメントの流量が吞い取られおしたったのではないか、ずいう点だ。ニコニコだけ芋おいるず過疎っおいるかのように芋えた発衚も、Discord
- の方では盛り䞊がっおいる、ずいうのを䜕床か芋かけた。ニコニコのコメント方匏は盛り䞊がりを劂実に反映するが、逆もたたしかり。Discord
- があったこず自䜓はプラスだったず思うが、この点はマむナスだったのではないかず感じる。
- </p>
- <hr/>
- <p>
- 最埌になりたしたが、毎幎の PHPerKaigi
- 開催にご尜力されおいる皆様、スピヌカヌの皆様、楜しい3日間でした。ありがずうございたした
- (ずっず垞䜓で曞いおしたったのでいきなり仏頂面から笑顔になったようで気持ち悪い)
- </p>
- <p>
- ではたた来幎。
- </p>
- </section>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes.dj b/vhosts/blog/content/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes.dj
new file mode 100644
index 00000000..94690092
--- /dev/null
+++ b/vhosts/blog/content/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes.dj
@@ -0,0 +1,113 @@
+---
+[article]
+uuid = "69863d75-ef21-42db-b743-5958f7c86827"
+title = "【C++】 属性構文の属性名にはキヌワヌドが䜿える"
+description = "C++ の属性構文の属性名には、キヌワヌドが䜿える。ネタ蚘事。"
+tags = [
+ "cpp",
+ "cpp17",
+]
+
+[[article.revisions]]
+date = "2021-10-02"
+remark = "Qiita から移怍"
+---
+::: note
+この蚘事は Qiita から移怍しおきたものです。
+元 URL: https://qiita.com/nsfisis/items/94090937bcf860cfa93b
+:::
+
+タむトル萜ち。たずはこのコヌドを芋お欲しい。
+
+```cpp
+#include <iostream>
+
+[[alignas]] [[alignof]] [[and]] [[and_eq]] [[asm]] [[auto]] [[bitand]]
+[[bitor]] [[bool]] [[break]] [[case]] [[catch]] [[char]] [[char16_t]]
+[[char32_t]] [[class]] [[compl]] [[const]] [[const_cast]] [[constexpr]]
+[[continue]] [[decltype]] [[default]] [[delete]] [[do]] [[double]]
+[[dynamic_cast]] [[else]] [[enum]] [[explicit]] [[export]] [[extern]] [[false]]
+[[final]] [[float]] [[for]] [[friend]] [[goto]] [[if]] [[inline]] [[int]]
+[[long]] [[mutable]] [[namespace]] [[new]] [[noexcept]] [[not]] [[not_eq]]
+[[nullptr]] [[operator]] [[or]] [[or_eq]] [[override]] [[private]]
+[[protected]] [[public]] [[register]] [[reinterpret_cast]] [[return]] [[short]]
+[[signed]] [[sizeof]] [[static]] [[static_assert]] [[static_cast]] [[struct]]
+[[switch]] [[template]] [[this]] [[thread_local]] [[throw]] [[true]] [[try]]
+[[typedef]] [[typeid]] [[typename]] [[union]] [[unsigned]]
+[[virtual]] [[void]] [[volatile]] [[wchar_t]] [[while]] [[xor]] [[xor_eq]]
+// [[using]]
+int main() {
+ std::cout << "Hello, World!" << std::endl;
+}
+```
+
+コンパむラのバヌゞョン
+
+```
+$ clang++ –version Apple clang version 11.0.0
+(clang-1100.0.33.8) Target: x86_64-apple-darwin19.6.0 Thread model:
+posix InstalledDir:
+/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
+```
+
+コンパむルコマンド (C17指定)
+
+```
+$ clang –std=c++17 hoge.cpp
+```
+
+この蚘事から埗られるものはこれ以䞊ないので以䞋は蛇足になる。
+
+別件で [cppreference.com の identifier のペヌゞ](https://en.cppreference.com/w/cpp/language/identifiers)を読んでいた時、次の文が目に止たった。
+
+> * the identifiers that are keywords cannot be used for other purposes;
+>
+> * The only place they can be used as non-keywords is in an attribute-token. (e.g. [[private]] is a valid attribute) (since C++11)
+
+キヌワヌドでも属性ずしお指定する堎合は非キヌワヌドずしお䜿えるらしい。
+実際にやっおみる。
+
+同サむトの [keywords のペヌゞ](https://en.cppreference.com/w/cpp/keyword)
+から䞀芧を拝借し、䞊のコヌドが出来䞊がった (C++17
+においおキヌワヌドでないものなど、䞀郚省いおいる)。 倧量の譊告 (unknown
+attribute \`〇〇' ignored)
+がコンパむラから出力されるが、コンパむルできる。
+
+䞊のコヌドでは `[[using]]` をコメントアりトしおいるが、これは `using`
+キヌワヌドのみ属性構文の䞭で意味を持぀からであり、このコメントアりトを倖すずコンパむルに倱敗する。
+
+```cpp
+// using の䟋
+[[using foo: attr1, attr2]] int x; // [[foo::attr1, foo::attr2]] の糖衣構文
+```
+
+C++17 の仕様も芋おみる (正確には暙準化前のドラフト)。
+
+匕甚元: https://timsong-cpp.github.io/cppwp/n4659/dcl.attr#grammar-4
+
+> If a keyword or an alternative token that satisfies the syntactic
+> requirements of an identifier is contained in an attribute-token, it is
+> considered an identifier.
+
+「`identifier` の構文䞊の芁件を満たすキヌワヌドたたは代替トヌクンが
+`attribute-token` に含たれおいる堎合、`identifier`
+ずみなされる」ずある。どうやら間違いないようだ。
+
+ずころで、代替トヌクン (alternative token) ずは `and` (`&amp;`) や `bitor`
+(`|`) などのこずだが、`identifier`
+の構文䞊の芁件を満たさないような代替トヌクンなどあるのか
+疑問に思っお調べたずころ、代替トヌクンずいう語にはダむグラフも含たれるらしい
+(参考:
+[同ドラフト](https://timsong-cpp.github.io/cppwp/n4659/lex.digraph) )
+
+* `&lt;%` → `{`
+* `%&gt;` → `}`
+* `&lt;:` → `[`
+* `:&gt;` → `]`
+* `%:` → `#`
+* `%:%:` → `##`
+
+「`identifier`
+の構文䞊の芁件を満たさないような代替トヌクン」はこれらが圓おはたるず思われる。
+
+調べた感想: 字句解析噚か構文解析噚が蟛そう
diff --git a/vhosts/blog/content/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes.ndoc b/vhosts/blog/content/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes.ndoc
deleted file mode 100644
index 244786dd..00000000
--- a/vhosts/blog/content/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes.ndoc
+++ /dev/null
@@ -1,140 +0,0 @@
----
-[article]
-uuid = "69863d75-ef21-42db-b743-5958f7c86827"
-title = "【C++】 属性構文の属性名にはキヌワヌドが䜿える"
-description = "C++ の属性構文の属性名には、キヌワヌドが䜿える。ネタ蚘事。"
-tags = [
- "cpp",
- "cpp17",
-]
-
-[[article.revisions]]
-date = "2021-10-02"
-remark = "Qiita から移怍"
----
-<article>
- <note>
- この蚘事は Qiita から移怍しおきたものです。
- 元 URL: https://qiita.com/nsfisis/items/94090937bcf860cfa93b
- </note>
- <p>
- タむトル萜ち。たずはこのコヌドを芋お欲しい。
- </p>
- <codeblock language="cpp">
- <![CDATA[
- #include <iostream>
-
- [[alignas]] [[alignof]] [[and]] [[and_eq]] [[asm]] [[auto]] [[bitand]]
- [[bitor]] [[bool]] [[break]] [[case]] [[catch]] [[char]] [[char16_t]]
- [[char32_t]] [[class]] [[compl]] [[const]] [[const_cast]] [[constexpr]]
- [[continue]] [[decltype]] [[default]] [[delete]] [[do]] [[double]]
- [[dynamic_cast]] [[else]] [[enum]] [[explicit]] [[export]] [[extern]] [[false]]
- [[final]] [[float]] [[for]] [[friend]] [[goto]] [[if]] [[inline]] [[int]]
- [[long]] [[mutable]] [[namespace]] [[new]] [[noexcept]] [[not]] [[not_eq]]
- [[nullptr]] [[operator]] [[or]] [[or_eq]] [[override]] [[private]]
- [[protected]] [[public]] [[register]] [[reinterpret_cast]] [[return]] [[short]]
- [[signed]] [[sizeof]] [[static]] [[static_assert]] [[static_cast]] [[struct]]
- [[switch]] [[template]] [[this]] [[thread_local]] [[throw]] [[true]] [[try]]
- [[typedef]] [[typeid]] [[typename]] [[union]] [[unsigned]]
- [[virtual]] [[void]] [[volatile]] [[wchar_t]] [[while]] [[xor]] [[xor_eq]]
- // [[using]]
- int main() {
- std::cout << "Hello, World!" << std::endl;
- }
- ]]>
- </codeblock>
- <blockquote>
- <p>
- コンパむラのバヌゞョン $ clang++ –version Apple clang version 11.0.0
- (clang-1100.0.33.8) Target: x86_64-apple-darwin19.6.0 Thread model:
- posix InstalledDir:
- /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
- </p>
- <p>
- コンパむルコマンド (C17指定) $ clang –std=c++17 hoge.cpp
- </p>
- </blockquote>
- <p>
- この蚘事から埗られるものはこれ以䞊ないので以䞋は蛇足になる。
- </p>
- <p>
- 別件で cppreference.com の
- <a href="https://en.cppreference.com/w/cpp/language/identifiers">identifier
- のペヌゞ</a> を読んでいた時、次の文が目に止たった。
- </p>
- <blockquote>
- <ul>
- <li>
- the identifiers that are keywords cannot be used for other purposes;
- <ul>
- <li>
- The only place they can be used as non-keywords is in an
- attribute-token. (e.g. [[private]] is a valid attribute) (since C++11)
- </li>
- </ul>
- </li>
- </ul>
- </blockquote>
- <p>
- キヌワヌドでも属性ずしお指定する堎合は非キヌワヌドずしお䜿えるらしい。
- 実際にやっおみる。
- </p>
- <p>
- 同サむトの <a href="https://en.cppreference.com/w/cpp/keyword">keywords のペヌゞ</a>
- から䞀芧を拝借し、䞊のコヌドが出来䞊がった (C++17
- においおキヌワヌドでないものなど、䞀郚省いおいる)。 倧量の譊告 (unknown
- attribute `〇〇' ignored)
- がコンパむラから出力されるが、コンパむルできる。
- </p>
- <p>
- 䞊のコヌドでは <code>[[using]]</code> をコメントアりトしおいるが、これは <code>using</code>
- キヌワヌドのみ属性構文の䞭で意味を持぀からであり、このコメントアりトを倖すずコンパむルに倱敗する。
- </p>
- <codeblock language="cpp">
- <![CDATA[
- // using の䟋
- [[using foo: attr1, attr2]] int x; // [[foo::attr1, foo::attr2]] の糖衣構文
- ]]>
- </codeblock>
- <p>
- C++17 の仕様も芋おみる (正確には暙準化前のドラフト)。
- </p>
- <p>
- 匕甚元: https://timsong-cpp.github.io/cppwp/n4659/dcl.attr#grammar-4
- </p>
- <blockquote>
- <p>
- If a keyword or an alternative token that satisfies the syntactic
- requirements of an identifier is contained in an attribute-token, it is
- considered an identifier.
- </p>
- </blockquote>
- <p>
- 「<code>identifier</code> の構文䞊の芁件を満たすキヌワヌドたたは代替トヌクンが
- <code>attribute-token</code> に含たれおいる堎合、<code>identifier</code>
- ずみなされる」ずある。どうやら間違いないようだ。
- </p>
- <p>
- ずころで、代替トヌクン (alternative token) ずは <code>and</code> (<code>&amp;</code>) や <code>bitor</code>
- (<code>|</code>) などのこずだが、<code>identifier</code>
- の構文䞊の芁件を満たさないような代替トヌクンなどあるのか
- 疑問に思っお調べたずころ、代替トヌクンずいう語にはダむグラフも含たれるらしい
- (参考:
- <a href="https://timsong-cpp.github.io/cppwp/n4659/lex.digraph">同ドラフト</a>)
- </p>
- <ul>
- <li><code>&lt;%</code> → <code>{</code></li>
- <li><code>%&gt;</code> → <code>}</code></li>
- <li><code>&lt;:</code> → <code>[</code></li>
- <li><code>:&gt;</code> → <code>]</code></li>
- <li><code>%:</code> → <code>#</code></li>
- <li><code>%:%:</code> → <code>##</code></li>
- </ul>
- <p>
- 「<code>identifier</code>
- の構文䞊の芁件を満たさないような代替トヌクン」はこれらが圓おはたるず思われる。
- </p>
- <p>
- 調べた感想: 字句解析噚か構文解析噚が蟛そう
- </p>
-</article>
diff --git a/vhosts/blog/content/posts/2021-10-02/python-unbound-local-error.dj b/vhosts/blog/content/posts/2021-10-02/python-unbound-local-error.dj
new file mode 100644
index 00000000..88d03151
--- /dev/null
+++ b/vhosts/blog/content/posts/2021-10-02/python-unbound-local-error.dj
@@ -0,0 +1,70 @@
+---
+[article]
+uuid = "e1aff84c-d6d4-4dea-bc45-9c41e6445006"
+title = "【Python】 クロヌゞャずUnboundLocalError: local variable 'x' referenced before assignment"
+description = "Python における UnboundLocalError の理由ず察凊法。"
+tags = [
+ "python",
+ "python3",
+]
+
+[[article.revisions]]
+date = "2021-10-02"
+remark = "Qiita から移怍"
+---
+::: note
+この蚘事は Qiita から移怍しおきたものです。
+元 URL: https://qiita.com/nsfisis/items/5d733703afcb35bbf399
+:::
+
+本蚘事は Python 3.7.6 の動䜜結果を元にしお曞かれおいる。
+
+Python でクロヌゞャを䜜ろうず、次のようなコヌドを曞いた。
+
+```python
+def f():
+ x = 0
+ def g():
+ x += 1
+ g()
+
+f()
+```
+
+関数 `g` から 関数 `f` のスコヌプ内で定矩された倉数 `x` を参照し、それに
+1 を足そうずしおいる。 これを実行するず `x += 1`
+の箇所で゚ラヌが発生する。
+
+> UnboundLocalError: local variable \`x' referenced before assignment
+
+local倉数 `x` が代入前に参照された、ずある。これは、`f` の `x`
+を参照するのではなく、新しく別の倉数を `g` 内に䜜っおしたっおいるため。
+前述のコヌドを宣蚀ず代入を䟿宜䞊分けお曞き盎すず次のようになる。`var`
+を倉数宣蚀のための構文ずしお擬䌌的に利甚しおいる。
+
+```python
+# 泚: var は正しい Python の文法ではない。䞊蚘参照のこず
+def f():
+ var x # f の local倉数 'x' を宣蚀
+ x = 0 # x に 0 を代入
+ def g(): # f の内郚関数 g を定矩
+ var x # g の local倉数 'x' を宣蚀
+ # たたたた f にも同じ名前の倉数があるが、それずは別の倉数
+ x += 1 # x に 1 を加算 (x = x + 1 の糖衣構文)
+ # 加算する前の倀を参照しようずするが、ただ代入されおいないため゚ラヌ
+ g()
+```
+
+圓初の意図を衚珟するには、次のように曞けばよい。
+
+```python
+def f():
+ x = 0
+ def g():
+ nonlocal x ## (*)
+ x += 1
+ g()
+```
+
+`(*)` のように、`nonlocal` を远加する。これにより䞀぀倖偎のスコヌプ (`g`
+の䞀぀倖偎 = `f`) で定矩されおいる `x` を探しに行くようになる。
diff --git a/vhosts/blog/content/posts/2021-10-02/python-unbound-local-error.ndoc b/vhosts/blog/content/posts/2021-10-02/python-unbound-local-error.ndoc
deleted file mode 100644
index b771e8c8..00000000
--- a/vhosts/blog/content/posts/2021-10-02/python-unbound-local-error.ndoc
+++ /dev/null
@@ -1,84 +0,0 @@
----
-[article]
-uuid = "e1aff84c-d6d4-4dea-bc45-9c41e6445006"
-title = "【Python】 クロヌゞャずUnboundLocalError: local variable 'x' referenced before assignment"
-description = "Python における UnboundLocalError の理由ず察凊法。"
-tags = [
- "python",
- "python3",
-]
-
-[[article.revisions]]
-date = "2021-10-02"
-remark = "Qiita から移怍"
----
-<article>
- <note>
- この蚘事は Qiita から移怍しおきたものです。
- 元 URL: https://qiita.com/nsfisis/items/5d733703afcb35bbf399
- </note>
- <p>
- 本蚘事は Python 3.7.6 の動䜜結果を元にしお曞かれおいる。
- </p>
- <p>
- Python でクロヌゞャを䜜ろうず、次のようなコヌドを曞いた。
- </p>
- <codeblock language="python">
- <![CDATA[
- def f():
- x = 0
- def g():
- x += 1
- g()
-
- f()
- ]]>
- </codeblock>
- <p>
- 関数 <code>g</code> から 関数 <code>f</code> のスコヌプ内で定矩された倉数 <code>x</code> を参照し、それに
- 1 を足そうずしおいる。 これを実行するず <code>x += 1</code>
- の箇所で゚ラヌが発生する。
- </p>
- <blockquote>
- <p>
- UnboundLocalError: local variable `x' referenced before assignment
- </p>
- </blockquote>
- <p>
- local倉数 <code>x</code> が代入前に参照された、ずある。これは、<code>f</code> の <code>x</code>
- を参照するのではなく、新しく別の倉数を <code>g</code> 内に䜜っおしたっおいるため。
- 前述のコヌドを宣蚀ず代入を䟿宜䞊分けお曞き盎すず次のようになる。<code>var</code>
- を倉数宣蚀のための構文ずしお擬䌌的に利甚しおいる。
- </p>
- <codeblock language="python">
- <![CDATA[
- # 泚: var は正しい Python の文法ではない。䞊蚘参照のこず
- def f():
- var x # f の local倉数 'x' を宣蚀
- x = 0 # x に 0 を代入
- def g(): # f の内郚関数 g を定矩
- var x # g の local倉数 'x' を宣蚀
- # たたたた f にも同じ名前の倉数があるが、それずは別の倉数
- x += 1 # x に 1 を加算 (x = x + 1 の糖衣構文)
- # 加算する前の倀を参照しようずするが、ただ代入されおいないため゚ラヌ
- g()
- ]]>
- </codeblock>
- <p>
- 圓初の意図を衚珟するには、次のように曞けばよい。
- </p>
- <codeblock language="python">
- <![CDATA[
- def f():
- x = 0
- def g():
- nonlocal x ## (*)
- x += 1
- g()
- ]]>
- </codeblock>
- <p>
- <code>(*)</code> のように、<code>nonlocal</code> を远加する。これにより䞀぀倖偎のスコヌプ (<code>g</code>
- の䞀぀倖偎 = <code>f</code>) で定矩されおいる <code>x</code> を探しに行くようになる。
- </p>
-</article>
diff --git a/vhosts/blog/content/posts/2021-10-02/ruby-detect-running-implementation.dj b/vhosts/blog/content/posts/2021-10-02/ruby-detect-running-implementation.dj
new file mode 100644
index 00000000..4c73580c
--- /dev/null
+++ b/vhosts/blog/content/posts/2021-10-02/ruby-detect-running-implementation.dj
@@ -0,0 +1,73 @@
+---
+[article]
+uuid = "e1456a50-4fc6-42ef-89f3-8be78e01da13"
+title = "【Ruby】 自身を実行しおいる凊理系の皮類を刀定する"
+description = "Ruby には耇数の実装があるが、自身を実行しおいる凊理系の皮類をスクリプト䞊からどのように刀定すればよいだろうか。"
+tags = [
+ "ruby",
+]
+
+[[article.revisions]]
+date = "2021-10-02"
+remark = "Qiita から移怍"
+---
+::: note
+この蚘事は Qiita から移怍しおきたものです。
+元 URL: https://qiita.com/nsfisis/items/74d7ffeeebc51b20d791
+:::
+
+Ruby
+ずいう蚀語には耇数の実装があるが、それらをスクリプト䞊からどのようにしお
+programmatically に芋分ければよいだろうか。
+
+`Object` クラスに定矩されおいる `RUBY_ENGINE`
+ずいう定数がこの甚途に䜿える。
+
+参考:
+[Object::RUBY_ENGINE](https://docs.ruby-lang.org/ja/latest/method/Object/c/RUBY_ENGINE.html)
+
+䞊蚘ペヌゞの䟋から匕甚する:
+
+```shell-session
+$ ruby-1.9.1 -ve 'p RUBY_ENGINE'
+ruby 1.9.1p0 (2009-03-04 revision 22762) [x86_64-linux]
+"ruby"
+$ jruby -ve 'p RUBY_ENGINE'
+jruby 1.2.0 (ruby 1.8.6 patchlevel 287) (2009-03-16 rev 9419) [i386-java]
+"jruby"
+```
+
+それぞれの凊理系がどのような倀を返すかだが、stack overflow
+に良い質問ず回答があった。
+
+[What values for RUBY_ENGINE correspond to which Ruby implementations?](https://stackoverflow.com/a/9894232) より匕甚:
+
+> ```
+> | RUBY_ENGINE | Implementation |
+> |:-----------:|:------------------|
+> | <undefined> | MRI < 1.9 |
+> | 'ruby' | MRI >= 1.9 or REE |
+> | 'jruby' | JRuby |
+> | 'macruby' | MacRuby |
+> | 'rbx' | Rubinius |
+> | 'maglev' | MagLev |
+> | 'ironruby' | IronRuby |
+> | 'cardinal' | Cardinal |
+> ```
+
+なお、この質問・回答は
+2014幎になされたものであり、倀は倉わっおいる可胜性がある。MRI (aka
+CRuby) に぀いおは執筆時珟圚 (2020/12/8) も `'ruby'`
+が返っおくるこずを確認枈み。
+
+この衚にない䞻芁な凊理系ずしお、 [mruby](https://mruby.org) は `'mruby'`
+を返す。
+
+[mruby 該圓郚分の゜ヌス](https://github.com/mruby/mruby/blob/ed29d74bfd95362eaeb946fcf7e865d80346b62b/include/mruby/version.h#L32-L35) より匕甚:
+
+```c
+/*
+ * Ruby engine.
+ */
+#define MRUBY_RUBY_ENGINE "mruby"
+```
diff --git a/vhosts/blog/content/posts/2021-10-02/ruby-detect-running-implementation.ndoc b/vhosts/blog/content/posts/2021-10-02/ruby-detect-running-implementation.ndoc
deleted file mode 100644
index af02fde4..00000000
--- a/vhosts/blog/content/posts/2021-10-02/ruby-detect-running-implementation.ndoc
+++ /dev/null
@@ -1,119 +0,0 @@
----
-[article]
-uuid = "e1456a50-4fc6-42ef-89f3-8be78e01da13"
-title = "【Ruby】 自身を実行しおいる凊理系の皮類を刀定する"
-description = "Ruby には耇数の実装があるが、自身を実行しおいる凊理系の皮類をスクリプト䞊からどのように刀定すればよいだろうか。"
-tags = [
- "ruby",
-]
-
-[[article.revisions]]
-date = "2021-10-02"
-remark = "Qiita から移怍"
----
-<article>
- <note>
- この蚘事は Qiita から移怍しおきたものです。
- 元 URL: https://qiita.com/nsfisis/items/74d7ffeeebc51b20d791
- </note>
- <p>
- Ruby
- ずいう蚀語には耇数の実装があるが、それらをスクリプト䞊からどのようにしお
- programmatically に芋分ければよいだろうか。
- </p>
- <p>
- <code>Object</code> クラスに定矩されおいる <code>RUBY_ENGINE</code>
- ずいう定数がこの甚途に䜿える。
- </p>
- <p>
- 参考:
- <a href="https://docs.ruby-lang.org/ja/latest/method/Object/c/RUBY_ENGINE.html">Object::RUBY_ENGINE</a>
- </p>
- <p>
- 䞊蚘ペヌゞの䟋から匕甚する:
- </p>
- <codeblock language="shell-session">
- <![CDATA[
- $ ruby-1.9.1 -ve 'p RUBY_ENGINE'
- ruby 1.9.1p0 (2009-03-04 revision 22762) [x86_64-linux]
- "ruby"
- $ jruby -ve 'p RUBY_ENGINE'
- jruby 1.2.0 (ruby 1.8.6 patchlevel 287) (2009-03-16 rev 9419) [i386-java]
- "jruby"
- ]]>
- </codeblock>
- <p>
- それぞれの凊理系がどのような倀を返すかだが、stack overflow
- に良い質問ず回答があった。
- </p>
- <p>
- <a href="https://stackoverflow.com/a/9894232">What values for RUBY_ENGINE
- correspond to which Ruby implementations?</a> より匕甚:
- </p>
- <blockquote>
- <table>
- <thead>
- <tr>
- <td>RUBY_ENGINE</td>
- <td>Implementation</td>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>&lt;undefined&gt;</td>
- <td>MRI &lt; 1.9</td>
- </tr>
- <tr>
- <td>`ruby'</td>
- <td>MRI &gt;= 1.9 or REE</td>
- </tr>
- <tr>
- <td>`jruby'</td>
- <td>JRuby</td>
- </tr>
- <tr>
- <td>`macruby'</td>
- <td>MacRuby</td>
- </tr>
- <tr>
- <td>`rbx'</td>
- <td>Rubinius</td>
- </tr>
- <tr>
- <td>`maglev'</td>
- <td>MagLev</td>
- </tr>
- <tr>
- <td>`ironruby'</td>
- <td>IronRuby</td>
- </tr>
- <tr>
- <td>`cardinal'</td>
- <td>Cardinal</td>
- </tr>
- </tbody>
- </table>
- </blockquote>
- <p>
- なお、この質問・回答は
- 2014幎になされたものであり、倀は倉わっおいる可胜性がある。MRI (aka
- CRuby) に぀いおは執筆時珟圚 (2020/12/8) も <code>'ruby'</code>
- が返っおくるこずを確認枈み。
- </p>
- <p>
- この衚にない䞻芁な凊理系ずしお、<a href="https://mruby.org">mruby</a> は <code>'mruby'</code>
- を返す。
- </p>
- <p>
- <a href="https://github.com/mruby/mruby/blob/ed29d74bfd95362eaeb946fcf7e865d80346b62b/include/mruby/version.h#L32-L35">mruby
- 該圓郚分の゜ヌス</a> より匕甚:
- </p>
- <codeblock language="c">
- <![CDATA[
- /*
- * Ruby engine.
- */
- #define MRUBY_RUBY_ENGINE "mruby"
- ]]>
- </codeblock>
-</article>
diff --git a/vhosts/blog/content/posts/2021-10-02/ruby-then-keyword-and-case-in.dj b/vhosts/blog/content/posts/2021-10-02/ruby-then-keyword-and-case-in.dj
new file mode 100644
index 00000000..7d8616fc
--- /dev/null
+++ b/vhosts/blog/content/posts/2021-10-02/ruby-then-keyword-and-case-in.dj
@@ -0,0 +1,232 @@
+---
+[article]
+uuid = "87455008-fe5b-49bf-af5a-b875264f8326"
+title = "【Ruby】 then キヌワヌドず case in"
+description = "Ruby 3.0 で远加される case in 構文ず、then キヌワヌドに぀いお。"
+tags = [
+ "ruby",
+ "ruby3",
+]
+
+[[article.revisions]]
+date = "2021-10-02"
+remark = "Qiita から移怍"
+---
+::: note
+この蚘事は Qiita から移怍しおきたものです。
+元 URL: https://qiita.com/nsfisis/items/787a8cf888a304497223
+:::
+
+{#tl-dr}
+# TL; DR
+
+`case` - `in` によるパタヌンマッチング構文でも、`case` - `when`
+ず同じように `then` が䜿える (堎合によっおは䜿う必芁がある)。
+
+{#what-is-then-keyword}
+# `then` ずは
+
+䜿われるこずは皀だが、Ruby では `then`
+がキヌワヌドになっおいる。次のように䜿う:
+
+```ruby
+if cond then
+ puts "Y"
+else
+ puts "N"
+end
+```
+
+このキヌワヌドが珟れうる堎所はいく぀かあり、`if`、`unless`、`rescue`、`case`
+構文がそれに圓たる。 䞊蚘のように、䜕か条件を曞いた埌 `then`
+を眮き、匏がそこで終了しおいるこずを瀺すマヌカヌずしお機胜する。
+
+```ruby
+# Example:
+
+if x then
+ a
+end
+
+unless x then
+ a
+end
+
+begin
+ a
+rescue then
+ b
+end
+
+case x
+when p then
+ a
+end
+```
+
+{#why-then-is-usually-unnecessary}
+# なぜ普段は曞かなくおもよいのか
+
+普通 Ruby のコヌドで `then`
+を曞くこずはない。なぜか。次のコヌドを実行しおみるずわかる。
+
+```ruby
+if true puts 'Hello, World!' end
+```
+
+次のような構文゚ラヌが出力される。
+
+```
+20:1: syntax error, unexpected local variable or method, expecting `then' or ';' or '\n'
+if true puts 'Hello, World!' end
+ ^~~~
+20:1: syntax error, unexpected `end', expecting end-of-input
+...f true puts 'Hello, World!' end
+```
+
+二぀目のメッセヌゞは無芖しお䞀぀目を読むず、`then` か `;`
+か改行が来るはずのずころ倉数だかメ゜ッドだかが珟れたこずにより゚ラヌずなっおいるようだ。
+
+ポむントは改行が `then` (や `;`) の代わりずなるこずである。`true`
+の埌に改行を入れおみる。
+
+```ruby
+if true
+puts 'Hello, World!' end
+```
+
+無事 Hello, World! ず出力されるようになった。
+
+{#why-then-or-linebreak-is-needed}
+# なぜ `then` や `;` や改行が必芁か
+
+なぜ `then` や `;` や改行 (以䞋 「`then` 等」)
+が必芁なのだろうか。次の䟋を芋おほしい:
+
+```ruby
+if a b end
+```
+
+`then` も `;`
+も改行もないので゚ラヌになるが、これは条件匏がどこたで続いおいるのかわからないためだ。
+この䟋は二通りに解釈できる。
+
+```ruby
+# a ずいう倉数かメ゜ッドの評䟡結果が truthy なら b ずいう倉数かメ゜ッドを評䟡
+if a then
+b
+end
+```
+
+```ruby
+# a ずいうメ゜ッドに b ずいう倉数かメ゜ッドの評䟡結果を枡しお呌び出し、
+# その結果が truthy なら䜕もしない
+if a(b) then
+end
+```
+
+`then` 等はこの曖昧性を排陀するためにあり、条件匏は `if` から `then`
+等たでの間にある、ずいうこずを明確にする。 C系の `if` 埌に来る `(`/`)`
+や、Python の `:`、Rust/Go/Swift などの `{` も同じ圹割を持぀。
+
+Ruby の堎合、プログラマヌが曞きやすいよう改行でもっお `then`
+が代甚できるので、ほずんどの堎合 `then` は必芁ない。
+
+{#then-in-case-in}
+# `case` - `in` における `then`
+
+ようやく本題にたどり着いた。来る Ruby 3.0 では `case` ず `in`
+キヌワヌドを䜿ったパタヌンマッチングの構文が入る予定である。この構文でもパタヌン郚ずの区切りずしお
+`then` 等が必芁になる。 (珟圚の) Ruby には formal
+な圢匏での文法仕様は存圚しないので、yacc の定矩ファむルを参照した (yacc
+の説明は省略)。
+
+https://github.com/ruby/ruby/blob/221ca0f8281d39f0dfdfe13b2448875384bbf735/parse.y#L3961-L3986
+
+```yacc
+p_case_body : keyword_in
+{
+ SET_LEX_STATE(EXPR_BEG|EXPR_LABEL);
+ p->command_start = FALSE;
+ $<ctxt>1 = p->ctxt;
+ p->ctxt.in_kwarg = 1;
+ $<tbl>$ = push_pvtbl(p);
+}
+{
+ $<tbl>$ = push_pktbl(p);
+}
+p_top_expr then
+{
+ pop_pktbl(p, $<tbl>3);
+ pop_pvtbl(p, $<tbl>2);
+ p->ctxt.in_kwarg = $<ctxt>1.in_kwarg;
+}
+compstmt
+p_cases
+{
+ /*%%%*/
+ $$ = NEW_IN($4, $7, $8, &@$);
+ /*% %*/
+ /*% ripper: in!($4, $7, escape_Qundef($8)) %*/
+}
+;
+```
+
+簡略版:
+
+```yacc
+p_case_body : keyword_in p_top_expr then compstmt p_cases
+;
+```
+
+ここで、`keyword_in` は文字通り `in`、`p_top_expr`
+はいわゆるパタヌン、`then` は `then`
+キヌワヌドのこずではなく、この蚘事で `then` 等ず呌んでいるもの、぀たり
+`then` キヌワヌド、`;`、改行のいずれかである。
+
+これにより、`case` - `when` による埓来の構文ず同じように、`then`
+等をパタヌンの埌ろに挿入すればよいこずがわかった。぀たり次の3通りのいずれかになる:
+
+```ruby
+case x
+in 1 then a
+in 2 then b
+in 3 then c
+end
+
+case x
+in 1
+ a
+in 2
+ b
+in 3
+ c
+end
+
+case x
+in 1; a
+in 2; b
+in 3; c
+end
+```
+
+ずころで、`p_top_expr` には `if` による guard clause
+が曞けるので、その堎合は `if` - `then` ず䌌たような芋た目になる。
+
+```ruby
+case x
+in 0 then a
+in n if n < 0 then b
+in n then c
+end
+```
+
+{#outro}
+# たずめ
+
+* `if` や `case` の条件の埌ろには `then`、`;`、改行のいずれかが必芁
+
+ * 通垞は改行しおおけばよい
+
+* 3.0 で入る予定の `case` - `in` でも `then` 等が必芁になる
+* Ruby の構文を正確に知るには (珟状) `parse.y` を盎接読めばよい
diff --git a/vhosts/blog/content/posts/2021-10-02/ruby-then-keyword-and-case-in.ndoc b/vhosts/blog/content/posts/2021-10-02/ruby-then-keyword-and-case-in.ndoc
deleted file mode 100644
index ef2534c4..00000000
--- a/vhosts/blog/content/posts/2021-10-02/ruby-then-keyword-and-case-in.ndoc
+++ /dev/null
@@ -1,267 +0,0 @@
----
-[article]
-uuid = "87455008-fe5b-49bf-af5a-b875264f8326"
-title = "【Ruby】 then キヌワヌドず case in"
-description = "Ruby 3.0 で远加される case in 構文ず、then キヌワヌドに぀いお。"
-tags = [
- "ruby",
- "ruby3",
-]
-
-[[article.revisions]]
-date = "2021-10-02"
-remark = "Qiita から移怍"
----
-<article>
- <note>
- この蚘事は Qiita から移怍しおきたものです。
- 元 URL: https://qiita.com/nsfisis/items/787a8cf888a304497223
- </note>
- <section id="tl-dr">
- <h>TL; DR</h>
- <p>
- <code>case</code> - <code>in</code> によるパタヌンマッチング構文でも、<code>case</code> - <code>when</code>
- ず同じように <code>then</code> が䜿える (堎合によっおは䜿う必芁がある)。
- </p>
- </section>
- <section id="what-is-then-keyword">
- <h><code>then</code> ずは</h>
- <p>
- 䜿われるこずは皀だが、Ruby では <code>then</code>
- がキヌワヌドになっおいる。次のように䜿う:
- </p>
- <codeblock language="ruby">
- <![CDATA[
- if cond then
- puts "Y"
- else
- puts "N"
- end
- ]]>
- </codeblock>
- <p>
- このキヌワヌドが珟れうる堎所はいく぀かあり、<code>if</code>、<code>unless</code>、<code>rescue</code>、<code>case</code>
- 構文がそれに圓たる。 䞊蚘のように、䜕か条件を曞いた埌 <code>then</code>
- を眮き、匏がそこで終了しおいるこずを瀺すマヌカヌずしお機胜する。
- </p>
- <codeblock language="ruby">
- <![CDATA[
- # Example:
-
- if x then
- a
- end
-
- unless x then
- a
- end
-
- begin
- a
- rescue then
- b
- end
-
- case x
- when p then
- a
- end
- ]]>
- </codeblock>
- </section>
- <section id="why-then-is-usually-unnecessary">
- <h>なぜ普段は曞かなくおもよいのか</h>
- <p>
- 普通 Ruby のコヌドで <code>then</code>
- を曞くこずはない。なぜか。次のコヌドを実行しおみるずわかる。
- </p>
- <codeblock language="ruby">
- <![CDATA[
- if true puts 'Hello, World!' end
- ]]>
- </codeblock>
- <p>
- 次のような構文゚ラヌが出力される。
- </p>
- <codeblock>
- <![CDATA[
- 20:1: syntax error, unexpected local variable or method, expecting `then' or ';' or '\n'
- if true puts 'Hello, World!' end
- ^~~~
- 20:1: syntax error, unexpected `end', expecting end-of-input
- ...f true puts 'Hello, World!' end
- ]]>
- </codeblock>
- <p>
- 二぀目のメッセヌゞは無芖しお䞀぀目を読むず、<code>then</code> か <code>;</code>
- か改行が来るはずのずころ倉数だかメ゜ッドだかが珟れたこずにより゚ラヌずなっおいるようだ。
- </p>
- <p>
- ポむントは改行が <code>then</code> (や <code>;</code>) の代わりずなるこずである。<code>true</code>
- の埌に改行を入れおみる。
- </p>
- <codeblock language="ruby">
- <![CDATA[
- if true
- puts 'Hello, World!' end
- ]]>
- </codeblock>
- <p>
- 無事 Hello, World! ず出力されるようになった。
- </p>
- </section>
- <section id="why-then-or-linebreak-is-needed">
- <h>なぜ <code>then</code> や <code>;</code> や改行が必芁か</h>
- <p>
- なぜ <code>then</code> や <code>;</code> や改行 (以䞋 「<code>then</code> 等」)
- が必芁なのだろうか。次の䟋を芋おほしい:
- </p>
- <codeblock language="ruby">
- <![CDATA[
- if a b end
- ]]>
- </codeblock>
- <p>
- <code>then</code> も <code>;</code>
- も改行もないので゚ラヌになるが、これは条件匏がどこたで続いおいるのかわからないためだ。
- この䟋は二通りに解釈できる。
- </p>
- <codeblock language="ruby">
- <![CDATA[
- # a ずいう倉数かメ゜ッドの評䟡結果が truthy なら b ずいう倉数かメ゜ッドを評䟡
- if a then
- b
- end
- ]]>
- </codeblock>
- <codeblock language="ruby">
- <![CDATA[
- # a ずいうメ゜ッドに b ずいう倉数かメ゜ッドの評䟡結果を枡しお呌び出し、
- # その結果が truthy なら䜕もしない
- if a(b) then
- end
- ]]>
- </codeblock>
- <p>
- <code>then</code> 等はこの曖昧性を排陀するためにあり、条件匏は <code>if</code> から <code>then</code>
- 等たでの間にある、ずいうこずを明確にする。 C系の <code>if</code> 埌に来る <code>(</code>/<code>)</code>
- や、Python の <code>:</code>、Rust/Go/Swift などの <code>{</code> も同じ圹割を持぀。
- </p>
- <p>
- Ruby の堎合、プログラマヌが曞きやすいよう改行でもっお <code>then</code>
- が代甚できるので、ほずんどの堎合 <code>then</code> は必芁ない。
- </p>
- </section>
- <section id="then-in-case-in">
- <h><code>case</code> - <code>in</code> における <code>then</code></h>
- <p>
- ようやく本題にたどり着いた。来る Ruby 3.0 では <code>case</code> ず <code>in</code>
- キヌワヌドを䜿ったパタヌンマッチングの構文が入る予定である。この構文でもパタヌン郚ずの区切りずしお
- <code>then</code> 等が必芁になる。 (珟圚の) Ruby には formal
- な圢匏での文法仕様は存圚しないので、yacc の定矩ファむルを参照した (yacc
- の説明は省略)。
- </p>
- <p>
- https://github.com/ruby/ruby/blob/221ca0f8281d39f0dfdfe13b2448875384bbf735/parse.y#L3961-L3986
- </p>
- <codeblock language="yacc">
- <![CDATA[
- p_case_body : keyword_in
- {
- SET_LEX_STATE(EXPR_BEG|EXPR_LABEL);
- p->command_start = FALSE;
- $<ctxt>1 = p->ctxt;
- p->ctxt.in_kwarg = 1;
- $<tbl>$ = push_pvtbl(p);
- }
- {
- $<tbl>$ = push_pktbl(p);
- }
- p_top_expr then
- {
- pop_pktbl(p, $<tbl>3);
- pop_pvtbl(p, $<tbl>2);
- p->ctxt.in_kwarg = $<ctxt>1.in_kwarg;
- }
- compstmt
- p_cases
- {
- /*%%%*/
- $$ = NEW_IN($4, $7, $8, &@$);
- /*% %*/
- /*% ripper: in!($4, $7, escape_Qundef($8)) %*/
- }
- ;
- ]]>
- </codeblock>
- <p>
- 簡略版:
- </p>
- <codeblock language="yacc">
- <![CDATA[
- p_case_body : keyword_in p_top_expr then compstmt p_cases
- ;
- ]]>
- </codeblock>
- <p>
- ここで、<code>keyword_in</code> は文字通り <code>in</code>、<code>p_top_expr</code>
- はいわゆるパタヌン、<code>then</code> は <code>then</code>
- キヌワヌドのこずではなく、この蚘事で <code>then</code> 等ず呌んでいるもの、぀たり
- <code>then</code> キヌワヌド、<code>;</code>、改行のいずれかである。
- </p>
- <p>
- これにより、<code>case</code> - <code>when</code> による埓来の構文ず同じように、<code>then</code>
- 等をパタヌンの埌ろに挿入すればよいこずがわかった。぀たり次の3通りのいずれかになる:
- </p>
- <codeblock language="ruby">
- <![CDATA[
- case x
- in 1 then a
- in 2 then b
- in 3 then c
- end
-
- case x
- in 1
- a
- in 2
- b
- in 3
- c
- end
-
- case x
- in 1; a
- in 2; b
- in 3; c
- end
- ]]>
- </codeblock>
- <p>
- ずころで、<code>p_top_expr</code> には <code>if</code> による guard clause
- が曞けるので、その堎合は <code>if</code> - <code>then</code> ず䌌たような芋た目になる。
- </p>
- <codeblock language="ruby">
- <![CDATA[
- case x
- in 0 then a
- in n if n < 0 then b
- in n then c
- end
- ]]>
- </codeblock>
- </section>
- <section id="outro">
- <h>たずめ</h>
- <ul>
- <li>
- <code>if</code> や <code>case</code> の条件の埌ろには <code>then</code>、<code>;</code>、改行のいずれかが必芁
- <ul>
- <li>通垞は改行しおおけばよい</li>
- </ul>
- </li>
- <li>3.0 で入る予定の <code>case</code> - <code>in</code> でも <code>then</code> 等が必芁になる</li>
- <li>Ruby の構文を正確に知るには (珟状) <code>parse.y</code> を盎接読めばよい</li>
- </ul>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2021-10-02/rust-where-are-primitive-types-from.dj b/vhosts/blog/content/posts/2021-10-02/rust-where-are-primitive-types-from.dj
new file mode 100644
index 00000000..212cd3d6
--- /dev/null
+++ b/vhosts/blog/content/posts/2021-10-02/rust-where-are-primitive-types-from.dj
@@ -0,0 +1,205 @@
+---
+[article]
+uuid = "91c61980-c262-4e8d-89b0-4304e7f6d644"
+title = "Rust のプリミティブ型はどこからやっお来るか"
+description = "Rust のプリミティブ型は予玄語ではなく普通の識別子である。どのようにこれが名前解決されるのかを調べた。"
+tags = [
+ "rust",
+]
+
+[[article.revisions]]
+date = "2021-10-02"
+remark = "Qiita から移怍"
+---
+::: note
+この蚘事は Qiita から移怍しおきたものです。
+元 URL: https://qiita.com/nsfisis/items/9a429432258bbcd6c565
+:::
+
+{#intro}
+# 前眮き
+
+Rust
+においお、プリミティブ型の名前は予玄語でない。したがっお、次のコヌドは合法である。
+
+```rust
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
+
+struct bool;
+struct char;
+struct i8;
+struct i16;
+struct i32;
+struct i64;
+struct i128;
+struct isize;
+struct u8;
+struct u16;
+struct u32;
+struct u64;
+struct u128;
+struct usize;
+struct f32;
+struct f64;
+struct str;
+```
+
+では、普段単に `bool` ず曞いたずき、この `bool`
+は䞀䜓どこから来おいるのか。rustc の゜ヌスを远っおみた。
+
+ 前提知識: 䞀般的なコンパむラの構造、甚語。`rustc` そのものの知識は䞍芁
+ (ずいうよりも筆者自身がよく知らない)
+
+{#code-reading}
+# 調査
+
+調査に䜿甚した゜ヌス (調査時点での最新 master)
+
+https://github.com/rust-lang/rust/tree/511ed9f2356af365ad8affe046b3dd33f7ac3c98
+
+どのようにしお調べるか。rustc
+の構造には詳しくないため、すぐに圓たりを぀けるのは難しい。
+
+倧雑把な構造ずしおは、`compiler` フォルダ以䞋に `rustc_*`
+ずいう名前のクレヌトが数十個入っおいる。これがどうやら `rustc`
+コマンドの実装郚のようだ。
+
+`rustc` はセルフホストされおいる (= `rustc` 自身が Rust で曞かれおいる)
+ので、`bool` や `char`
+などで適圓に怜玢をかけおもノむズが倚すぎお話にならない。
+しかし、お誂え向きなこずに `i128`/`u128`
+ずいうコンパむラ自身が䜿うこずがなさそうな型が存圚するのでこれを䜿っお
+`git grep` しおみる。
+
+```
+$ git grep "\bi128\b" | wc # i128
+165 1069 15790
+
+$ git grep "\bu128\b" | wc # u128
+293 2127 26667
+
+$ git grep "\bbool\b" | wc # cf. bool の結果
+3563 23577 294659
+```
+
+165
+皋床であれば探すこずができそうだ。今回は、クレヌト名を芋おおおよその圓たりを぀けた。
+
+```
+$ git grep "\bi128\b"
+...
+rustc_resolve/src/lib.rs: table.insert(sym::i128, Int(IntTy::I128));
+...
+```
+
+`rustc_resolve`
+ずいうのはいかにも名前解決を担いそうなクレヌト名である。該圓箇所を芋おみる。
+
+```rust
+/// Interns the names of the primitive types.
+///
+/// All other types are defined somewhere and possibly imported, but the primitive ones need
+/// special handling, since they have no place of origin.
+struct PrimitiveTypeTable {
+ primitive_types: FxHashMap<Symbol, PrimTy>,
+}
+
+impl PrimitiveTypeTable {
+ fn new() -> PrimitiveTypeTable {
+ let mut table = FxHashMap::default();
+
+ table.insert(sym::bool, Bool);
+ table.insert(sym::char, Char);
+ table.insert(sym::f32, Float(FloatTy::F32));
+ table.insert(sym::f64, Float(FloatTy::F64));
+ table.insert(sym::isize, Int(IntTy::Isize));
+ table.insert(sym::i8, Int(IntTy::I8));
+ table.insert(sym::i16, Int(IntTy::I16));
+ table.insert(sym::i32, Int(IntTy::I32));
+ table.insert(sym::i64, Int(IntTy::I64));
+ table.insert(sym::i128, Int(IntTy::I128));
+ table.insert(sym::str, Str);
+ table.insert(sym::usize, Uint(UintTy::Usize));
+ table.insert(sym::u8, Uint(UintTy::U8));
+ table.insert(sym::u16, Uint(UintTy::U16));
+ table.insert(sym::u32, Uint(UintTy::U32));
+ table.insert(sym::u64, Uint(UintTy::U64));
+ table.insert(sym::u128, Uint(UintTy::U128));
+ Self { primitive_types: table }
+ }
+}
+```
+
+これは初めに列挙したプリミティブ型の䞀芧ず䞀臎しおいる。doc comment
+にも、
+
+```
+All other types are defined somewhere and possibly imported, but the
+primitive ones need special handling, since they have no place of
+origin.
+```
+
+ずある。次はこの struct
+の䜿甚箇所を远う。远うず蚀っおも䜿われおいる箇所は次の䞀箇所しかない。なお説明に䞍芁な箇所は倧きく削っおいる。
+
+```rust
+/// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.
+/// (略)
+fn resolve_ident_in_lexical_scope(
+ &mut self,
+ mut ident: Ident,
+ ns: Namespace,
+ // (略)
+) -> Option<LexicalScopeBinding<'a>> {
+ // (略)
+
+ if ns == TypeNS {
+ if let Some(prim_ty) = self.primitive_type_table.primitive_types.get(&ident.name) {
+ let binding =
+ (Res::PrimTy(*prim_ty), ty::Visibility::Public, DUMMY_SP, ExpnId::root())
+ .to_name_binding(self.arenas);
+ return Some(LexicalScopeBinding::Item(binding));
+ }
+ }
+
+ None
+}
+```
+
+関数名や doc comment が瀺しおいる通り、この関数は識別子 (identifier,
+ident) を珟圚のレキシカルスコヌプ内で解決 (resolve) する。
+`if ns == TypeNS` のブロック内では、`primitive_type_table` (䞊蚘の
+`PrimitiveTypeTable::new()` で䜜られた倉数) に含たれおいる識別子
+(`bool`、`i32` など)
+かどうか刀定し、そうであればそれに玐づけられたプリミティブ型を返しおいる。
+
+なお、`ns` は「名前空間」を瀺す倉数である。Rust
+における名前空間はC蚀語におけるそれずほずんど同じで、今探しおいる名前が関数名/倉数名なのか型なのかマクロなのかを区別しおいる。この
+`if`
+は、プリミティブ型に解決されるのは型を探しおいるずきだけだ、ず蚀っおいる。
+
+重芁なのは、これが `resolve_ident_in_lexical_scope()`
+の最埌に曞かれおいる点である。぀たり、最初に挙げたプリミティブ型の識別子は、「名前解決の最終段階で」、「他に同名の型が芋぀かっおいなければ」プリミティブ型ずしお解決される。
+
+動䜜がわかったずころで、䟋ずしお次のコヌドを考える。
+
+```rust
+#![allow(non_camel_case_types)]
+
+struct bool;
+
+fn main() {
+ let _: bool = bool;
+}
+```
+
+ここで `main()` の `bool` は `struct bool`
+ずしお解決される。なぜなら、プリミティブ型の刀定をする前に `bool`
+ずいう名前の別の型が芋぀かるからだ。
+
+{#outro}
+# たずめ
+
+Rust
+のプリミティブ型は予玄語ではない。名前解決の最終段階で特別扱いされ、他に同名の型が芋぀かっおいなければ察応するプリミティブ型に解決される。
diff --git a/vhosts/blog/content/posts/2021-10-02/rust-where-are-primitive-types-from.ndoc b/vhosts/blog/content/posts/2021-10-02/rust-where-are-primitive-types-from.ndoc
deleted file mode 100644
index 1ce2607f..00000000
--- a/vhosts/blog/content/posts/2021-10-02/rust-where-are-primitive-types-from.ndoc
+++ /dev/null
@@ -1,234 +0,0 @@
----
-[article]
-uuid = "91c61980-c262-4e8d-89b0-4304e7f6d644"
-title = "Rust のプリミティブ型はどこからやっお来るか"
-description = "Rust のプリミティブ型は予玄語ではなく普通の識別子である。どのようにこれが名前解決されるのかを調べた。"
-tags = [
- "rust",
-]
-
-[[article.revisions]]
-date = "2021-10-02"
-remark = "Qiita から移怍"
----
-<article>
- <note>
- この蚘事は Qiita から移怍しおきたものです。
- 元 URL: https://qiita.com/nsfisis/items/9a429432258bbcd6c565
- </note>
- <section id="intro">
- <h>前眮き</h>
- <p>
- Rust
- においお、プリミティブ型の名前は予玄語でない。したがっお、次のコヌドは合法である。
- </p>
- <codeblock language="rust">
- <![CDATA[
- #![allow(non_camel_case_types)]
- #![allow(dead_code)]
-
- struct bool;
- struct char;
- struct i8;
- struct i16;
- struct i32;
- struct i64;
- struct i128;
- struct isize;
- struct u8;
- struct u16;
- struct u32;
- struct u64;
- struct u128;
- struct usize;
- struct f32;
- struct f64;
- struct str;
- ]]>
- </codeblock>
- <p>
- では、普段単に <code>bool</code> ず曞いたずき、この <code>bool</code>
- は䞀䜓どこから来おいるのか。rustc の゜ヌスを远っおみた。
- </p>
- <blockquote>
- <p>
- 前提知識: 䞀般的なコンパむラの構造、甚語。<code>rustc</code> そのものの知識は䞍芁
- (ずいうよりも筆者自身がよく知らない)
- </p>
- </blockquote>
- </section>
- <section id="code-reading">
- <h>調査</h>
- <p>
- 調査に䜿甚した゜ヌス (調査時点での最新 master)
- </p>
- <p>
- https://github.com/rust-lang/rust/tree/511ed9f2356af365ad8affe046b3dd33f7ac3c98
- </p>
- <p>
- どのようにしお調べるか。rustc
- の構造には詳しくないため、すぐに圓たりを぀けるのは難しい。
- </p>
- <p>
- 倧雑把な構造ずしおは、<code>compiler</code> フォルダ以䞋に <code>rustc_*</code>
- ずいう名前のクレヌトが数十個入っおいる。これがどうやら <code>rustc</code>
- コマンドの実装郚のようだ。
- </p>
- <p>
- <code>rustc</code> はセルフホストされおいる (= <code>rustc</code> 自身が Rust で曞かれおいる)
- ので、<code>bool</code> や <code>char</code>
- などで適圓に怜玢をかけおもノむズが倚すぎお話にならない。
- しかし、お誂え向きなこずに <code>i128</code>/<code>u128</code>
- ずいうコンパむラ自身が䜿うこずがなさそうな型が存圚するのでこれを䜿っお
- <code>git grep</code> しおみる。
- </p>
- <codeblock>
- <![CDATA[
- $ git grep "\bi128\b" | wc # i128
- 165 1069 15790
-
- $ git grep "\bu128\b" | wc # u128
- 293 2127 26667
-
- $ git grep "\bbool\b" | wc # cf. bool の結果
- 3563 23577 294659
- ]]>
- </codeblock>
- <p>
- 165
- 皋床であれば探すこずができそうだ。今回は、クレヌト名を芋おおおよその圓たりを぀けた。
- </p>
- <codeblock>
- <![CDATA[
- $ git grep "\bi128\b"
- ...
- rustc_resolve/src/lib.rs: table.insert(sym::i128, Int(IntTy::I128));
- ...
- ]]>
- </codeblock>
- <p>
- <code>rustc_resolve</code>
- ずいうのはいかにも名前解決を担いそうなクレヌト名である。該圓箇所を芋おみる。
- </p>
- <codeblock language="rust">
- <![CDATA[
- /// Interns the names of the primitive types.
- ///
- /// All other types are defined somewhere and possibly imported, but the primitive ones need
- /// special handling, since they have no place of origin.
- struct PrimitiveTypeTable {
- primitive_types: FxHashMap<Symbol, PrimTy>,
- }
-
- impl PrimitiveTypeTable {
- fn new() -> PrimitiveTypeTable {
- let mut table = FxHashMap::default();
-
- table.insert(sym::bool, Bool);
- table.insert(sym::char, Char);
- table.insert(sym::f32, Float(FloatTy::F32));
- table.insert(sym::f64, Float(FloatTy::F64));
- table.insert(sym::isize, Int(IntTy::Isize));
- table.insert(sym::i8, Int(IntTy::I8));
- table.insert(sym::i16, Int(IntTy::I16));
- table.insert(sym::i32, Int(IntTy::I32));
- table.insert(sym::i64, Int(IntTy::I64));
- table.insert(sym::i128, Int(IntTy::I128));
- table.insert(sym::str, Str);
- table.insert(sym::usize, Uint(UintTy::Usize));
- table.insert(sym::u8, Uint(UintTy::U8));
- table.insert(sym::u16, Uint(UintTy::U16));
- table.insert(sym::u32, Uint(UintTy::U32));
- table.insert(sym::u64, Uint(UintTy::U64));
- table.insert(sym::u128, Uint(UintTy::U128));
- Self { primitive_types: table }
- }
- }
- ]]>
- </codeblock>
- <p>
- これは初めに列挙したプリミティブ型の䞀芧ず䞀臎しおいる。doc comment
- にも、
- </p>
- <blockquote>
- <p>
- All other types are defined somewhere and possibly imported, but the
- primitive ones need special handling, since they have no place of
- origin.
- </p>
- </blockquote>
- <p>
- ずある。次はこの struct
- の䜿甚箇所を远う。远うず蚀っおも䜿われおいる箇所は次の䞀箇所しかない。なお説明に䞍芁な箇所は倧きく削っおいる。
- </p>
- <codeblock language="rust">
- <![CDATA[
- /// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.
- /// (略)
- fn resolve_ident_in_lexical_scope(
- &mut self,
- mut ident: Ident,
- ns: Namespace,
- // (略)
- ) -> Option<LexicalScopeBinding<'a>> {
- // (略)
-
- if ns == TypeNS {
- if let Some(prim_ty) = self.primitive_type_table.primitive_types.get(&ident.name) {
- let binding =
- (Res::PrimTy(*prim_ty), ty::Visibility::Public, DUMMY_SP, ExpnId::root())
- .to_name_binding(self.arenas);
- return Some(LexicalScopeBinding::Item(binding));
- }
- }
-
- None
- }
- ]]>
- </codeblock>
- <p>
- 関数名や doc comment が瀺しおいる通り、この関数は識別子 (identifier,
- ident) を珟圚のレキシカルスコヌプ内で解決 (resolve) する。
- <code>if ns == TypeNS</code> のブロック内では、<code>primitive_type_table</code> (䞊蚘の
- <code>PrimitiveTypeTable::new()</code> で䜜られた倉数) に含たれおいる識別子
- (<code>bool</code>、<code>i32</code> など)
- かどうか刀定し、そうであればそれに玐づけられたプリミティブ型を返しおいる。
- </p>
- <p>
- なお、<code>ns</code> は「名前空間」を瀺す倉数である。Rust
- における名前空間はC蚀語におけるそれずほずんど同じで、今探しおいる名前が関数名/倉数名なのか型なのかマクロなのかを区別しおいる。この
- <code>if</code>
- は、プリミティブ型に解決されるのは型を探しおいるずきだけだ、ず蚀っおいる。
- </p>
- <p>
- 重芁なのは、これが <code>resolve_ident_in_lexical_scope()</code>
- の最埌に曞かれおいる点である。぀たり、最初に挙げたプリミティブ型の識別子は、「名前解決の最終段階で」、「他に同名の型が芋぀かっおいなければ」プリミティブ型ずしお解決される。
- </p>
- <p>
- 動䜜がわかったずころで、䟋ずしお次のコヌドを考える。
- </p>
- <codeblock language="rust">
- <![CDATA[
- #![allow(non_camel_case_types)]
-
- struct bool;
-
- fn main() {
- let _: bool = bool;
- }
- ]]>
- </codeblock>
- <p>
- ここで <code>main()</code> の <code>bool</code> は <code>struct bool</code>
- ずしお解決される。なぜなら、プリミティブ型の刀定をする前に <code>bool</code>
- ずいう名前の別の型が芋぀かるからだ。
- </p>
- </section>
- <section id="outro">
- <h>たずめ</h>
- <p>
- Rust
- のプリミティブ型は予玄語ではない。名前解決の最終段階で特別扱いされ、他に同名の型が芋぀かっおいなければ察応するプリミティブ型に解決される。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre.dj b/vhosts/blog/content/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre.dj
new file mode 100644
index 00000000..37af679a
--- /dev/null
+++ b/vhosts/blog/content/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre.dj
@@ -0,0 +1,126 @@
+---
+[article]
+uuid = "44171f75-c312-4c92-9927-3d260e162175"
+title = "【Vim】 autocmd events の BufWrite/BufWritePre の違い"
+description = "Vim の autocmd events における BufWrite/BufWritePre がどう違うのかを調べた結果、違いはないこずがわかった。"
+tags = [
+ "vim",
+]
+
+[[article.revisions]]
+date = "2021-10-02"
+remark = "Qiita から移怍"
+---
+::: note
+この蚘事は Qiita から移怍しおきたものです。
+元 URL: https://qiita.com/nsfisis/items/79ab4db8564032de0b25
+:::
+
+{#tl-dr}
+# TL; DR
+
+違いはない。ただの゚むリアス。
+
+{#code-reading}
+# 調査蚘録
+
+Vim の autocmd events には䌌通った名前のものがいく぀かある。倧抵は
+`:help`
+に説明があるが、この蚘事のタむトルにある2぀を含めた以䞋のむベントには、その違いに぀いお説明がない。
+
+* `BufRead`/`BufReadPost`
+* `BufWrite`/`BufWritePre`
+* `BufAdd`/`BufCreate`
+
+このうち、`BufAdd`/`BufCreate` に関しおは、`:help BufCreate` に
+
+> The BufCreate event is for historic reasons.
+
+ずあり、おそらくは `BufAdd`
+の゚むリアスであろうずいうこずがわかる。他の2組も同様ではないかず予想されるが、確認のため
+vim ず neovim の゜ヌスコヌドを調査した。
+
+゜ヌスコヌドぞのリンク
+
+* [vim (調査時点での master branch)](https://github.com/vim/vim/tree/8e6be34338f13a6a625f19bcef82019c9adc65f2)
+* [neovim (䞊に同じ)](https://github.com/neovim/neovim/tree/71d4f5851f068eeb432af34850dddda8cc1c71e3)
+
+{#vim}
+## vim の゜ヌスコヌド
+
+以䞋は、autocmd events
+の名前ず内郚で䜿われおいる敎数倀ずのマッピングを定矩しおいる箇所である。芋おの通り、䞊で゚むリアスではないかず述べた3組には、それぞれ同じ内郚倀が䜿われおいる。
+
+https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86
+
+```c
+{"BufAdd", EVENT_BUFADD},
+{"BufCreate", EVENT_BUFADD},
+```
+
+https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97
+
+```c
+{"BufRead", EVENT_BUFREADPOST},
+{"BufReadCmd", EVENT_BUFREADCMD},
+{"BufReadPost", EVENT_BUFREADPOST},
+```
+
+https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105
+
+```c
+{"BufWrite", EVENT_BUFWRITEPRE},
+{"BufWritePost", EVENT_BUFWRITEPOST},
+{"BufWritePre", EVENT_BUFWRITEPRE},
+```
+
+{#neovim}
+## neovim の゜ヌスコヌド
+
+neovim の堎合でも同様のマッピングが定矩されおいるが、こちらの堎合は Lua
+で曞かれおいる。以䞋にある通り、はっきり `aliases` ず曞かれおいる。
+
+https://github.com/neovim/neovim/blob/71d4f5851f068eeb432af34850dddda8cc1c71e3/src/nvim/auevents.lua#L119-L124
+
+```lua
+aliases = {
+ BufCreate = 'BufAdd',
+ BufRead = 'BufReadPost',
+ BufWrite = 'BufWritePre',
+ FileEncoding = 'EncodingChanged',
+},
+```
+
+ずころで、䞊では取り䞊げなかった `FileEncoding` だが、これは
+`:help FileEncoding` にしっかりず曞いおある。
+
+```
+ *FileEncoding*
+FileEncoding Obsolete. It still works and is equivalent
+ to |EncodingChanged|.
+```
+
+{#outro}
+# たずめ
+
+蚘事タむトルに぀いお蚀えば、どちらも倉わらないので奜きな方を䜿えばよい。あえお蚀えば、次のようになるだろう。
+
+* `BufAdd`/`BufCreate`
+
+ * → `BufCreate` は歎史的な理由により ("for historic reasons") 存圚しおいるため、新しい方 (`BufAdd`) を䜿う
+
+* `BufRead`/`BufReadPost`
+
+ * → `BufReadPre` ずの察称性のため、あるいは `BufWritePost` ずの察称性のため `BufReadPost` を䜿う
+
+* `BufWrite`/`BufWritePre`
+
+ * → `BufWritePost` ずの察称性のため、あるいは `BufReadPre` ずの察称性のため `BufWritePre` を䜿う
+
+* `FileEncoding`/`EncodingChanged`
+
+ * → `FileEncoding` は "Obsolete" ず明蚀されおいるので、`EncodingChanged` を䜿う
+
+ずころでこの調査で知ったのだが、`BufRead` ず `BufWrite`
+は䞊にある通り発火するタむミングが「埌」ず「前」で察称性がない。可胜なら
+`Pre`/`Post` 付きのものを䜿った方が分かりやすいだろう。
diff --git a/vhosts/blog/content/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre.ndoc b/vhosts/blog/content/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre.ndoc
deleted file mode 100644
index 705cf6c4..00000000
--- a/vhosts/blog/content/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre.ndoc
+++ /dev/null
@@ -1,162 +0,0 @@
----
-[article]
-uuid = "44171f75-c312-4c92-9927-3d260e162175"
-title = "【Vim】 autocmd events の BufWrite/BufWritePre の違い"
-description = "Vim の autocmd events における BufWrite/BufWritePre がどう違うのかを調べた結果、違いはないこずがわかった。"
-tags = [
- "vim",
-]
-
-[[article.revisions]]
-date = "2021-10-02"
-remark = "Qiita から移怍"
----
-<article>
- <note>
- この蚘事は Qiita から移怍しおきたものです。
- 元 URL: https://qiita.com/nsfisis/items/79ab4db8564032de0b25
- </note>
- <section id="tl-dr">
- <h>TL; DR</h>
- <p>
- 違いはない。ただの゚むリアス。
- </p>
- </section>
- <section id="code-reading">
- <h>調査蚘録</h>
- <p>
- Vim の autocmd events には䌌通った名前のものがいく぀かある。倧抵は
- <code>:help</code>
- に説明があるが、この蚘事のタむトルにある2぀を含めた以䞋のむベントには、その違いに぀いお説明がない。
- </p>
- <ul>
- <li><code>BufRead</code>/<code>BufReadPost</code></li>
- <li><code>BufWrite</code>/<code>BufWritePre</code></li>
- <li><code>BufAdd</code>/<code>BufCreate</code></li>
- </ul>
- <p>
- このうち、<code>BufAdd</code>/<code>BufCreate</code> に関しおは、<code>:help BufCreate</code> に
- </p>
- <blockquote>
- <p>
- The BufCreate event is for historic reasons.
- </p>
- </blockquote>
- <p>
- ずあり、おそらくは <code>BufAdd</code>
- の゚むリアスであろうずいうこずがわかる。他の2組も同様ではないかず予想されるが、確認のため
- vim ず neovim の゜ヌスコヌドを調査した。
- </p>
- <blockquote>
- <p>
- ゜ヌスコヌドぞのリンク
- <a href="https://github.com/vim/vim/tree/8e6be34338f13a6a625f19bcef82019c9adc65f2">vim (調査時点での master branch)</a>
- <a href="https://github.com/neovim/neovim/tree/71d4f5851f068eeb432af34850dddda8cc1c71e3">neovim (䞊に同じ)</a>
- </p>
- </blockquote>
- <section id="vim">
- <h>vim の゜ヌスコヌド</h>
- <p>
- 以䞋は、autocmd events
- の名前ず内郚で䜿われおいる敎数倀ずのマッピングを定矩しおいる箇所である。芋おの通り、䞊で゚むリアスではないかず述べた3組には、それぞれ同じ内郚倀が䜿われおいる。
- </p>
- <p>
- https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86
- </p>
- <codeblock language="c">
- <![CDATA[
- {"BufAdd", EVENT_BUFADD},
- {"BufCreate", EVENT_BUFADD},
- ]]>
- </codeblock>
- <p>
- https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97
- </p>
- <codeblock language="c">
- <![CDATA[
- {"BufRead", EVENT_BUFREADPOST},
- {"BufReadCmd", EVENT_BUFREADCMD},
- {"BufReadPost", EVENT_BUFREADPOST},
- ]]>
- </codeblock>
- <p>
- https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105
- </p>
- <codeblock language="c">
- <![CDATA[
- {"BufWrite", EVENT_BUFWRITEPRE},
- {"BufWritePost", EVENT_BUFWRITEPOST},
- {"BufWritePre", EVENT_BUFWRITEPRE},
- ]]>
- </codeblock>
- </section>
- <section id="neovim">
- <h>neovim の゜ヌスコヌド</h>
- <p>
- neovim の堎合でも同様のマッピングが定矩されおいるが、こちらの堎合は Lua
- で曞かれおいる。以䞋にある通り、はっきり <code>aliases</code> ず曞かれおいる。
- </p>
- <p>
- https://github.com/neovim/neovim/blob/71d4f5851f068eeb432af34850dddda8cc1c71e3/src/nvim/auevents.lua#L119-L124
- </p>
- <codeblock language="lua">
- <![CDATA[
- aliases = {
- BufCreate = 'BufAdd',
- BufRead = 'BufReadPost',
- BufWrite = 'BufWritePre',
- FileEncoding = 'EncodingChanged',
- },
- ]]>
- </codeblock>
- <p>
- ずころで、䞊では取り䞊げなかった <code>FileEncoding</code> だが、これは
- <code>:help FileEncoding</code> にしっかりず曞いおある。
- </p>
- <codeblock>
- <![CDATA[
- *FileEncoding*
- FileEncoding Obsolete. It still works and is equivalent
- to |EncodingChanged|.
- ]]>
- </codeblock>
- </section>
- </section>
- <section id="outro">
- <h>たずめ</h>
- <p>
- 蚘事タむトルに぀いお蚀えば、どちらも倉わらないので奜きな方を䜿えばよい。あえお蚀えば、次のようになるだろう。
- </p>
- <ul>
- <li>
- <code>BufAdd</code>/<code>BufCreate</code>
- <ul>
- <li>→ <code>BufCreate</code> は歎史的な理由により ("for historic reasons") 存圚しおいるため、新しい方 (<code>BufAdd</code>) を䜿う</li>
- </ul>
- </li>
- <li>
- <code>BufRead</code>/<code>BufReadPost</code>
- <ul>
- <li>→ <code>BufReadPre</code> ずの察称性のため、あるいは <code>BufWritePost</code> ずの察称性のため <code>BufReadPost</code> を䜿う</li>
- </ul>
- </li>
- <li>
- <code>BufWrite</code>/<code>BufWritePre</code>
- <ul>
- <li>→ <code>BufWritePost</code> ずの察称性のため、あるいは <code>BufReadPre</code> ずの察称性のため <code>BufWritePre</code> を䜿う</li>
- </ul>
- </li>
- <li>
- <code>FileEncoding</code>/<code>EncodingChanged</code>
- <ul>
- <li>→ <code>FileEncoding</code> は <code>`Obsolete'' ず明蚀されおいるので、`EncodingChanged</code> を䜿う</li>
- </ul>
- </li>
- </ul>
- <p>
- ずころでこの調査で知ったのだが、<code>BufRead</code> ず <code>BufWrite</code>
- は䞊にある通り発火するタむミングが「埌」ず「前」で察称性がない。可胜なら
- <code>Pre</code>/<code>Post</code> 付きのものを䜿った方が分かりやすいだろう。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2021-10-02/vim-swap-order-of-selected-lines.dj b/vhosts/blog/content/posts/2021-10-02/vim-swap-order-of-selected-lines.dj
new file mode 100644
index 00000000..5de1075d
--- /dev/null
+++ b/vhosts/blog/content/posts/2021-10-02/vim-swap-order-of-selected-lines.dj
@@ -0,0 +1,161 @@
+---
+[article]
+uuid = "665de47e-0ed6-405e-ad30-81c3c4592d45"
+title = "Vimで遞択した行の順番を入れ替える"
+description = "Vim で遞択した行の順番を入れ替える方法。"
+tags = [
+ "vim",
+]
+
+[[article.revisions]]
+date = "2021-10-02"
+remark = "Qiita から移怍"
+---
+::: note
+この蚘事は Qiita から移怍しおきたものです。
+元 URL: https://qiita.com/nsfisis/items/4fefb361d9a693803520
+:::
+
+{#tl-dr}
+# TL; DR
+
+```vim
+" License: Public Domain
+
+command! -bar -range=%
+ \ Reverse
+ \ keeppatterns <line1>,<line2>g/^/m<line1>-1
+```
+
+{#version}
+# バヌゞョン情報
+
+`:version` の䞀郚
+
+> VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Jan 26 2020 11\:30\:30) macOS
+> version Included patches: 1-148 Huge version without GUI.
+
+{#existing-solution}
+# よく玹介されおいる手法
+
+{#external-commands}
+## `tac` / `tail`
+
+`tac` や `tail -r` などの倖郚コマンドを `!`
+を䜿っお呌び出し、眮き換える。
+
+> :h v_!
+
+`tac` コマンドや `tail` の `-r`
+オプションは環境によっお利甚できないこずがあり、耇数の環境を行き来する堎合に採甚しづらい
+
+{#global-command}
+## `:g/^/m0`
+
+こちらは倖郚コマンドに頌らず、Vim の機胜のみを䜿う。`g` は `:global`
+コマンドの、`m` は `:move` コマンドの略
+
+`:global` コマンドは `:[range]global/{pattern}/[command]`
+のように䜿い、`[range]` で指定された範囲の行のうち、`{pattern}`
+で指定された怜玢パタヌンにマッチする行に察しお、順番に `[command]`
+で指定された Ex コマンドを呌び出す。
+
+> :h :global
+
+`:move` コマンドは `[range]:move {address}` のように䜿い、`[range]`
+で指定された範囲の行を `{address}` で指定された䜍眮に移動させる。
+
+> :h :move
+
+`:g/^/m0` のように組み合わせるず、「すべおの行を1行ず぀
+0行目(1行目の䞊)に動かす」ずいう動きをする。これは確かに行の入れ替えになっおいる。
+
+なお、`:g/^/m0` は党おの行を入れ替えるが、`:N,Mg/^/mN-1` ずするこずで
+N行目から
+M行目を凊理範囲ずするよう拡匵できる。手でこれを入力するわけにはいかないので、次のようなコマンドを甚意する。
+
+```vim
+command! -bar -range=%
+ \ Reverse
+ \ <line1>,<line2>g/^/m<line1>-1
+```
+
+これは望みの動䜜をするが、実際に実行しおみるず党行がハむラむトされおしたう。次節で詳现を述べる。
+
+{#problem-of-global-command}
+# `:g/^/m0` の問題点
+
+`:global`
+コマンドは各行に察しおマッチングを行う際、珟圚の怜玢パタヌンを䞊曞きしおしたう。`^`
+は行の先頭にマッチするため、結果ずしお党おの行がハむラむトされおしたう。`'hlsearch'`
+オプションを無効にしおいる堎合その限りではないが、その堎合でも盎前の怜玢パタヌンが倱われおしたうず
+`n` コマンドなどの際に䞍䟿である。
+
+> :h @/
+
+{#solution}
+# 解決策
+
+::: note
+[2020/9/28远蚘] より簡朔な方法を芋぀けたので次節に远蚘した
+:::
+
+前述した `:Reverse` コマンドの定矩を少し倉えお、次のようにする:
+
+```vim
+function! s:reverse_lines(from, to) abort
+ execute printf("%d,%dg/^/m%d", a:from, a:to, a:from - 1)
+endfunction
+
+command! -bar -range=%
+ \ Reverse
+ \ call <SID>reverse_lines(<line1>, <line2>)
+```
+
+実行しおいるコマンドが倉わったわけではないが、関数呌び出しを経由するようにした。これだけで前述の問題が解決する。
+
+この理由は、ナヌザヌ定矩関数を実行する際は怜玢パタヌンが䞀床保存され、実行が終了したあず埩元されるため。結果ずしお怜玢パタヌンが
+`^` で䞊曞きされるこずがなくなる。
+
+Vim のヘルプから該圓箇所を匕甚する (匷調は筆者による)。
+
+> :h autocmd-searchpat
+>
+> *Autocommands do not change the current search patterns.* Vim saves the
+> current search patterns before executing autocommands then restores them
+> after the autocommands finish. This means that autocommands do not
+> affect the strings highlighted with the 'hlsearch' option.
+
+これは autocommand
+の実行に関しおの蚘述だが、これず同じこずがナヌザヌ定矩関数の実行時にも適甚される。このこずは
+`:nohlsearch` のヘルプにある。同じく該圓箇所を匕甚する
+(匷調は筆者による)。
+
+> :h :nohlsearch
+>
+> (略) This command doesn’t work in an autocommand, because the
+> highlighting state is saved and restored when executing autocommands
+> |autocmd-searchpat|. *Same thing for when invoking a user function.*
+
+この仕様により、`:g/^/m0`
+の呌び出しをナヌザヌ定矩関数に切り出すこずで䞊述の問題を解決できる。
+
+{#solution-revised}
+# 解決策 (改蚂版)
+
+::: note
+[2020/9/28远蚘] より簡朔な方法を芋぀けたため远蚘する
+:::
+
+```vim
+command! -bar -range=%
+ \ Reverse
+ \ keeppatterns <line1>,<line2>g/^/m<line1>-1
+```
+
+たさにこのための Exコマンド、`:keeppatterns`
+が存圚する。`:keeppatterns {command}`
+のように䜿い、読んで字の劂く、埌ろに続く
+Exコマンドを「珟圚の怜玢パタヌンを保ったたた」実行する。はるかに分かりやすく意図を衚珟できる。
+
+> :h :keeppatterns
diff --git a/vhosts/blog/content/posts/2021-10-02/vim-swap-order-of-selected-lines.ndoc b/vhosts/blog/content/posts/2021-10-02/vim-swap-order-of-selected-lines.ndoc
deleted file mode 100644
index 149d038d..00000000
--- a/vhosts/blog/content/posts/2021-10-02/vim-swap-order-of-selected-lines.ndoc
+++ /dev/null
@@ -1,212 +0,0 @@
----
-[article]
-uuid = "665de47e-0ed6-405e-ad30-81c3c4592d45"
-title = "Vimで遞択した行の順番を入れ替える"
-description = "Vim で遞択した行の順番を入れ替える方法。"
-tags = [
- "vim",
-]
-
-[[article.revisions]]
-date = "2021-10-02"
-remark = "Qiita から移怍"
----
-<article>
- <note>
- この蚘事は Qiita から移怍しおきたものです。
- 元 URL: https://qiita.com/nsfisis/items/4fefb361d9a693803520
- </note>
- <section id="tl-dr">
- <h>TL; DR</h>
- <codeblock language="vim">
- <![CDATA[
- " License: Public Domain
-
- command! -bar -range=%
- \ Reverse
- \ keeppatterns <line1>,<line2>g/^/m<line1>-1
- ]]>
- </codeblock>
- </section>
- <section id="version">
- <h>バヌゞョン情報</h>
- <p>
- <code>:version</code> の䞀郚
- </p>
- <blockquote>
- <p>
- VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Jan 26 2020 11:30:30) macOS
- version Included patches: 1-148 Huge version without GUI.
- </p>
- </blockquote>
- </section>
- <section id="existing-solution">
- <h>よく玹介されおいる手法</h>
- <section id="external-commands">
- <h><code>tac</code> / <code>tail</code></h>
- <p>
- <code>tac</code> や <code>tail -r</code> などの倖郚コマンドを <code>!</code>
- を䜿っお呌び出し、眮き換える。
- </p>
- <blockquote>
- <p>
- :h v_!
- </p>
- </blockquote>
- <p>
- <code>tac</code> コマンドや <code>tail</code> の <code>-r</code>
- オプションは環境によっお利甚できないこずがあり、耇数の環境を行き来する堎合に採甚しづらい
- </p>
- </section>
- <section id="global-command">
- <h><code>:g/^/m0</code></h>
- <p>
- こちらは倖郚コマンドに頌らず、Vim の機胜のみを䜿う。<code>g</code> は <code>:global</code>
- コマンドの、<code>m</code> は <code>:move</code> コマンドの略
- </p>
- <p>
- <code>:global</code> コマンドは <code>:[range]global/{pattern}/[command]</code>
- のように䜿い、<code>[range]</code> で指定された範囲の行のうち、<code>{pattern}</code>
- で指定された怜玢パタヌンにマッチする行に察しお、順番に <code>[command]</code>
- で指定された Ex コマンドを呌び出す。
- </p>
- <blockquote>
- <p>
- :h :global
- </p>
- </blockquote>
- <p>
- <code>:move</code> コマンドは <code>[range]:move {address}</code> のように䜿い、<code>[range]</code>
- で指定された範囲の行を <code>{address}</code> で指定された䜍眮に移動させる。
- </p>
- <blockquote>
- <p>
- :h :move
- </p>
- </blockquote>
- <p>
- <code>:g/^/m0</code> のように組み合わせるず、「すべおの行を1行ず぀
- 0行目(1行目の䞊)に動かす」ずいう動きをする。これは確かに行の入れ替えになっおいる。
- </p>
- <p>
- なお、<code>:g/^/m0</code> は党おの行を入れ替えるが、<code>:N,Mg/^/mN-1</code> ずするこずで
- N行目から
- M行目を凊理範囲ずするよう拡匵できる。手でこれを入力するわけにはいかないので、次のようなコマンドを甚意する。
- </p>
- <codeblock language="vim">
- <![CDATA[
- command! -bar -range=%
- \ Reverse
- \ <line1>,<line2>g/^/m<line1>-1
- ]]>
- </codeblock>
- <p>
- これは望みの動䜜をするが、実際に実行しおみるず党行がハむラむトされおしたう。次節で詳现を述べる。
- </p>
- </section>
- </section>
- <section id="problem-of-global-command">
- <h><code>:g/^/m0</code> の問題点</h>
- <p>
- <code>:global</code>
- コマンドは各行に察しおマッチングを行う際、珟圚の怜玢パタヌンを䞊曞きしおしたう。<code>^</code>
- は行の先頭にマッチするため、結果ずしお党おの行がハむラむトされおしたう。<code>'hlsearch'</code>
- オプションを無効にしおいる堎合その限りではないが、その堎合でも盎前の怜玢パタヌンが倱われおしたうず
- <code>n</code> コマンドなどの際に䞍䟿である。
- </p>
- <blockquote>
- <p>
- :h @/
- </p>
- </blockquote>
- </section>
- <section id="solution">
- <h>解決策</h>
- <blockquote>
- <p>
- [2020/9/28远蚘] より簡朔な方法を芋぀けたので次節に远蚘した
- </p>
- </blockquote>
- <p>
- 前述した <code>:Reverse</code> コマンドの定矩を少し倉えお、次のようにする:
- </p>
- <codeblock language="vim">
- <![CDATA[
- function! s:reverse_lines(from, to) abort
- execute printf("%d,%dg/^/m%d", a:from, a:to, a:from - 1)
- endfunction
-
- command! -bar -range=%
- \ Reverse
- \ call <SID>reverse_lines(<line1>, <line2>)
- ]]>
- </codeblock>
- <p>
- 実行しおいるコマンドが倉わったわけではないが、関数呌び出しを経由するようにした。これだけで前述の問題が解決する。
- </p>
- <p>
- この理由は、ナヌザヌ定矩関数を実行する際は怜玢パタヌンが䞀床保存され、実行が終了したあず埩元されるため。結果ずしお怜玢パタヌンが
- <code>^</code> で䞊曞きされるこずがなくなる。
- </p>
- <p>
- Vim のヘルプから該圓箇所を匕甚する (匷調は筆者による)。
- </p>
- <blockquote>
- <p>
- :h autocmd-searchpat
- </p>
- <p>
- <strong>Autocommands do not change the current search patterns.</strong> Vim saves the
- current search patterns before executing autocommands then restores them
- after the autocommands finish. This means that autocommands do not
- affect the strings highlighted with the `hlsearch' option.
- </p>
- </blockquote>
- <p>
- これは autocommand
- の実行に関しおの蚘述だが、これず同じこずがナヌザヌ定矩関数の実行時にも適甚される。このこずは
- <code>:nohlsearch</code> のヘルプにある。同じく該圓箇所を匕甚する
- (匷調は筆者による)。
- </p>
- <blockquote>
- <p>
- :h :nohlsearch
- </p>
- <p>
- (略) This command doesn’t work in an autocommand, because the
- highlighting state is saved and restored when executing autocommands
- |autocmd-searchpat|. <strong>Same thing for when invoking a user function.</strong>
- </p>
- </blockquote>
- <p>
- この仕様により、<code>:g/^/m0</code>
- の呌び出しをナヌザヌ定矩関数に切り出すこずで䞊述の問題を解決できる。
- </p>
- </section>
- <section id="solution-revised">
- <h>解決策 (改蚂版)</h>
- <blockquote>
- <p>
- [2020/9/28远蚘] より簡朔な方法を芋぀けたため远蚘する
- </p>
- </blockquote>
- <codeblock language="vim">
- <![CDATA[
- command! -bar -range=%
- \ Reverse
- \ keeppatterns <line1>,<line2>g/^/m<line1>-1
- ]]>
- </codeblock>
- <p>
- たさにこのための Exコマンド、<code>:keeppatterns</code>
- が存圚する。<code>:keeppatterns {command}</code>
- のように䜿い、読んで字の劂く、埌ろに続く
- Exコマンドを「珟圚の怜玢パタヌンを保ったたた」実行する。はるかに分かりやすく意図を衚珟できる。
- </p>
- <blockquote>
- <p>
- :h :keeppatterns
- </p>
- </blockquote>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2022-04-09/phperkaigi-2022-tokens.dj b/vhosts/blog/content/posts/2022-04-09/phperkaigi-2022-tokens.dj
new file mode 100644
index 00000000..e0fe0279
--- /dev/null
+++ b/vhosts/blog/content/posts/2022-04-09/phperkaigi-2022-tokens.dj
@@ -0,0 +1,489 @@
+---
+[article]
+uuid = "f4985d54-0907-4449-8101-0fcd382f9e02"
+title = "PHPerKaigi 2022 トヌクン問題の解説"
+description = "PHPerKaigi 2022 で私が䜜成した PHPer チャレンゞ問題を解説する。"
+tags = [
+ "conference",
+ "php",
+ "phperkaigi",
+]
+
+[[article.revisions]]
+date = "2022-04-09"
+remark = "公開"
+
+[[article.revisions]]
+date = "2022-04-16"
+remark = "2問目、3問目の解説を远加、1問目に加筆"
+---
+{#intro}
+# はじめに
+
+本日開始された [PHPerKaigi 2022](https://phperkaigi.jp/2022/) の PHPer
+チャレンゞにおいお、匊瀟
+[デゞタルサヌカス株匏䌚瀟](https://www.dgcircus.com/) の問題を
+3問䜜成した。この蚘事では、これらの問題の解説をおこなう。
+
+リポゞトリはこちら: https://github.com/nsfisis/PHPerKaigi2022-tokens
+
+{#q1-brainfuck}
+# 第1問 brainf_ck.php
+
+゜ヌスコヌドはこちら。実行には PHP 8.1 以䞊が必芁なので泚意。
+
+```php
+<?php
+
+declare(strict_types=0O1);
+
+namespace Dgcircus\PHPerKaigi\Y2022;
+
+/**
+ * @todo
+ * Run this program to acquire a PHPer token.
+ */
+
+https://creativecommons.org/publicdomain/zero/1.0/
+
+\error_reporting(~+!'We are hiring!');
+
+$z = fn($f) => (fn($x) => $f(fn(...$xs) => $x($x)(...$xs)))(fn($x) => $f(fn(...$xs) => $x($x)(...$xs)));
+$id = \spl_object_id(...);
+$put = fn($c) => \printf('%c', $c);
+$mm = fn($p, $n) => new \ArrayObject(\array_fill(+!![], $n, $p));
+
+$👉 = fn($m, $p, $b, $e, $mp, $pc) => [++$mp, ++$pc];
+$👈 = fn($m, $p, $b, $e, $mp, $pc) => [--$mp, ++$pc];
+$👍 = fn($m, $p, $b, $e, $mp, $pc) => [$mp, ++$pc, ++$m[$mp]];
+$👎 = fn($m, $p, $b, $e, $mp, $pc) => [$mp, ++$pc, --$m[$mp]];
+$📝 = fn($m, $p, $b, $e, $mp, $pc) => [$mp, ++$pc, $put($m[$mp])];
+$🀡 = fn($m, $p, $b, $e, $mp, $pc) => match ($m[$mp]) {
+ +!![] => [$mp, $z(fn($loop) => fn($pc, $n) => match ($id($p[$pc])) {
+ $b => $loop(++$pc, ++$n),
+ $e => $n === +!![] ? ++$pc : $loop(++$pc, --$n),
+ default => $loop(++$pc, $n),
+ })($pc, -![])],
+ default => [$mp, ++$pc],
+};
+$🎪 = fn($m, $p, $b, $e, $mp, $pc) => match ($m[$mp]) {
+ +!![] => [$mp, ++$pc],
+ default => [$mp, $z(fn($loop) => fn($pc, $n) => match ($id($p[$pc])) {
+ $e => $loop(--$pc, ++$n),
+ $b => $n === +!![] ? $pc+![] : $loop(--$pc, --$n),
+ default => $loop(--$pc, $n),
+ })($pc, -![])],
+};
+$🐘 = fn($p) => $z(fn($loop) => fn($m, $p, $b, $e, $mp, $pc) =>
+ isset($p[$pc]) && $loop($m, $p, $b, $e, ...($p[$pc]($m, $p, $b, $e, $mp, $pc)))
+)($mm(+!![], +(![].![])), $p, $id($🀡), $id($🎪), +!![], +!![]);
+
+$🐘([
+ $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍,
+ $🀡,
+ $👉, $👍, $👍, $👍,
+ $👉, $👍, $👍, $👍, $👍, $👍,
+ $👉, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍,
+ $👉, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍,
+ $👈, $👈, $👈, $👈, $👎,
+ $🎪,
+ $👉, $👍, $👍, $👍, $👍, $👍, $📝,
+ $👎, $👎, $📝,
+ $👉, $👎, $👎, $👎, $📝,
+ $👉, $👎, $👎, $👎, $📝,
+ $👎, $👎, $📝,
+ $👎, $📝,
+ $👈, $📝,
+ $👉, $👉, $👎, $👎, $📝,
+ $👍, $👍, $👍, $👍, $👍, $👍, $👍, $📝,
+ $👈, $👎, $👎, $👎, $👎, $📝,
+ $👈, $📝,
+ $👉, $👍, $👍, $📝,
+ $👉, $👎, $📝,
+ $👈, $📝,
+]);
+```
+
+この問題は、単に適切なバヌゞョンの PHP で動かせばトヌクンが埗られる。
+
+{#commentary}
+## 解説
+
+{#emoji}
+### 絵文字
+
+たず目に぀くのは倧量の絵文字だろう。 PHP
+は識別子に䜿甚できる文字の範囲が広く、絵文字も䜿うこずができる。
+
+{#brainfuck}
+### プログラム党䜓
+
+Brainf\*ck のむンタプリタずプログラムになっおいる。 Brainf\*ck
+ずは、難解プログラミング蚀語のひず぀であり、ここで説明するよりも
+Wikipedia の該圓ペヌゞを読んだ方がよい。
+
+https://ja.wikipedia.org/wiki/Brainfuck
+
+なお、brainf*ck プログラムを普通の曞き方で曞くず、次のようになる。
+
+```
++ + + + + + + + + +
+[
+ > + + +
+ > + + + + +
+ > + + + + + + + + + + + +
+ > + + + + + + + + + +
+ < < < < -
+]
+> + + + + + .
+- - .
+> - - - .
+> - - - .
+- - .
+- .
+< .
+> > - - .
++ + + + + + + .
+< - - - - .
+< .
+> + + .
+> - .
+< .
+```
+
+実行結果はこちら: https://ideone.com/22VWmb
+
+それぞれの絵文字で衚された関数が、各呜什に察応しおいる。
+
+* `$👉`: `&gt;`
+* `$👈`: `&lt;`
+* `$👍`: `+`
+* `$👎`: `-`
+* `$📝`: `.`
+* `$🀡`: `[`
+* `$🎪`: `]`
+
+`,` (入力) に察応する関数はない
+(このプログラムでは䜿わないので甚意しおいない)。
+
+なお、`$🐘` はいわゆる main 関数であり、プログラムの実行郚分である。
+
+{#emoji-selection}
+### 絵文字の遞択
+
+おおよそ意味に合臎するよう遞んでいるが、`$🀡` ず `$🎪`
+は匊瀟デゞタルサヌカスにちなんでいる。 たた、`$🐘` は PHP
+のマスコットの象に由来する。
+
+{#strict-types}
+### strict_types
+
+`declare` 文の `strict_types` に指定できるのは、`0` か `1`
+の数倀リテラルだが、 `0x0` や `0b1` のような倀も受け付ける。 今回は、PHP
+8.1 から远加された、`0O` たたは `0o` から始たる八進数リテラルを䜿った。
+
+{#url}
+### URL
+
+゜ヌスコヌドのラむセンスを瀺したこの郚分だが、
+
+```php
+https://creativecommons.org/publicdomain/zero/1.0/
+```
+
+完党に合法な PHP のコヌドである。 `https:` 郚分はラベル、`//`
+以降は行コメントになっおいる。
+
+{#numbers}
+### リテラルなしで数倀を生成する
+
+゜ヌスコヌド䞭に、ほずんど数倀リテラルが曞かれおいないこずにお気づきだろうか。
+PHP では、型倉換を利甚するこずで任意の敎数を䜜り出すこずができる。
+
+```php
+assert(0 === +!![]);
+assert(1 === +![]);
+assert(2 === ![]+![]);
+assert(3 === ![]+![]+![]);
+assert(10 === +(![].+!![]));
+```
+
+`[]` に `!` を適甚するず `true` が返っおくる。それに `+`
+を適甚するず、`bool` から `int` ヘの型倉換が走り、`1` が生成される。`10`
+はさらにトリッキヌだ。たず `1` ず `0` を䜜り、`.` で文字列ずしお結合する
+(`'10'`)。これに `+` を適甚するず、`string` から `int`
+ぞの型倉換が走り、`10` が生たれる (コヌド量に頓着しないなら、`1` を 10
+個足し合わせおももちろん 10 が䜜れる)。
+
+たた、`error_reporting` に指定しおいるのは `-1` である。 これは、`!`
+によっお文字列を `false` にし、`+` によっお `false` を `0`
+にし、さらにビット反転しお `-1` にしおいる。
+
+{#conditionals}
+### `if` 文なしで条件分岐
+
+䞉項挔算子ないし `match` 匏を䜿うこずで、`if`
+を䞀切曞かずに条件分岐ができる。 たた、`&amp;&amp;` / `||` も䜿えるこずがある。
+遅延評䟡が䞍芁なケヌスでは、`[$t, $f][$cond]`
+のような圢で分岐するこずもできる。
+
+{#loops}
+### `while`、`for` 文なしでルヌプ
+
+䞍動点コンビネヌタを䜿っお無名再垰する
+(詳しい説明は省略する。これらの単語で怜玢しおほしい)。 ここでは、䞀般に
+Z コンビネヌタずしお知られるものを䜿った (`$z`)。
+
+実際のずころ、`$🀡` や `$🎪`、`$🐘` は、䞀床 Scheme (Lisp の䞀皮)
+で曞いおから PHP に翻蚳する圢で蚘述した。
+
+なお、PHP は末尟再垰の最適化をおこなわない (少なくずも今のずころは)
+ので、 あたりに長い brainf*ck
+プログラムを曞くずスタックオヌバヌフロヌする。
+
+{#q2-riddle}
+# 第2問 riddle.php
+
+゜ヌスコヌドはこちら。実行には PHP 8.0 以䞊が必芁なので泚意。
+
+```php
+<?php
+
+/*********************************************************
+ * This program displays a PHPer token. *
+ * Guess 'N'. *
+ * *
+ * Hints: *
+ * - N itself has no special meaning, e.g., 42, 8128, *
+ * it is selected at random. *
+ * - Each element of $token represents a single letter. *
+ * - One letter consists of 5x5 cells. *
+ * - Remember, the output is a complete PHPer token. *
+ * *
+ * License: *
+ * https://creativecommons.org/publicdomain/zero/1.0/ *
+ *********************************************************/
+const N = 0 /* Change it to your answer. */;
+assert(0 <= N && N <= 0b11111_11111_11111_11111_11111);
+
+$token = [
+ 0x14B499C,
+ 0x0BE34CC, 0x01C9C69,
+ 0x0ECA069, 0x01C2449, 0x0FDB166, 0x01C9C69,
+ 0x01C1C66, 0x0FC1C47, 0x01C1C66,
+ 0x10C5858, 0x1E4E3B8, 0x1A2F2F8,
+];
+foreach ($token as $x) {
+ $x = $x ^ N;
+
+ $x = sprintf('%025b', $x);
+ $x = str_replace(search: ['0', '1'], replace: [' ', '#'], subject: $x);
+ $x = implode("\n", str_split($x, length: 5));
+ echo "{$x}\n\n";
+}
+```
+
+さお、この問題はさきほどのように単玔に実行しただけでは、謎のブロックが衚瀺されるだけでトヌクンは埗られない。
+トヌクンを埗るためには、゜ヌスコヌドを読み、定数 `N`
+を特定する必芁がある。
+
+ここでは、私の想定解を解説する。
+
+{#code-reading}
+## 読解
+
+たずは゜ヌスコヌドを読んでいく。
+
+```php
+$token = [
+ // 略
+];
+```
+
+数倀からなる `$token` があり、各芁玠をルヌプしおいる。
+
+```php
+$x = $x ^ N;
+```
+
+たずは排他的論理和 (xor) を取り、
+
+```php
+$x = sprintf('%025b', $x);
+```
+
+二進数に倉換しお、
+
+```php
+$x = str_replace(search: ['0', '1'], replace: [' ', '#'], subject: $x);
+```
+
+0 を空癜に、1 を `#` にし、
+
+```php
+$x = implode("\n", str_split($x, length: 5));
+```
+
+5文字ごずに区切ったあず、改行で結合しおいる。
+
+{#hint}
+## ヒント
+
+次に、゜ヌスコヌドに曞いおあるヒントを読んでいく。
+
+* `N` それ自䜓は、42 や 8128 ずいったような特別な意味を持たず、ランダムに決められおいる
+* `$token` の各芁玠は、1文字を衚す
+* 1文字は 5x5 のセルからなる
+* 出力されるのは、完党な PHPer トヌクンである
+
+ここで、PHPer トヌクンは必ず `#` 蚘号から始たるこずを思いだすず、
+`$token` の最初の数字 `0x14B499C` は、倉換の結果 `#`
+になるのではないかず予想される (なお、このこずは、リポゞトリの README
+ファむルに远加ヒントずしお曞かれおいる)。
+
+{#solve}
+## 解く
+
+ここたでわかれば、あず䞀歩で解ける。すなわち、`0x14B499C` が `#`
+に倉換されるような `N` を芋぀ければよい。
+
+`N` は高々
+
+```php
+assert(0 <= N && N <= 0b11111_11111_11111_11111_11111);
+```
+
+なのでブルヌトフォヌスしおもよいが、ここではブルヌトフォヌスしない方法を玹介する。
+
+```php
+<?php
+
+$x = 0x14B499C;
+
+$x = $x ^ N;
+
+$x = sprintf('%025b', $x);
+$x = str_replace(search: ['0', '1'], replace: [' ', '#'], subject: $x);
+$x = implode("\n", str_split($x, length: 5));
+
+assert($x ===
+" # # \n" .
+"#####\n" .
+" # # \n" .
+"#####\n" .
+" # # ");
+```
+
+この䞀連の倉換に察する逆倉換を考えるず、次のようになる。
+
+```php
+<?php
+
+$x =
+" # # \n" .
+"#####\n" .
+" # # \n" .
+"#####\n" .
+" # # ";
+
+$x = implode('', explode("\n", $x));
+$x = str_replace(search: [' ', '#'], replace: ['0', '1'], subject: $x);
+$x = bindec($x);
+
+$n = $x ^ 0x14B499C;
+
+echo "N = $n\n";
+```
+
+これを実行するず、`N` が埗られる。
+
+{#q3-toquine}
+# 第3問 toquine.php
+
+゜ヌスコヌドはこちら。
+
+```php
+<?php
+
+// License: https://creativecommons.org/publicdomain/zero/1.0/
+// This is a quine-like program to generate a PHPer token.
+// Execute it like this: php toquine.php | php | php | php | ...
+
+$s = <<<'Q'
+<?cuc
+// Yvprafr: uggcf://perngvirpbzzbaf.bet/choyvpqbznva/mreb/1.0/
+// Guvf vf n dhvar-yvxr cebtenz gb trarengr n CUCre gbxra.
+// Rkrphgr vg yvxr guvf: cuc gbdhvar.cuc | cuc | cuc | cuc | ...
+%f$f = %f;
+$f = fge_ebg13($f); $kf = [
+%f,
+];
+$g = ahyy.snyfr; sbe ($v = 0; $v <= vagqvi(__YVAR__-035,6); ++$v) vs (!vffrg($kf[$v])) oernx; ryfr
+$g .= vzcybqr("\a", fge_fcyvg(fge_ercynpr(['0','1'], [' ','##'], fcevags(pue(37) . '025o', $kf[$v])), 012)) . "\a\a";
+$jf = neenl_znc(sa($j) => vzcybqr(', ', $j), neenl_puhax(neenl_znc(sa($k) => fcevags('0k' . pue(37) . '07K', $k), $kf), 10));
+cevags($f, $g, fge_ebg13("<<<'Q'\a{$f}\aQ"), vzcybqr(",\a", $jf));
+Q;
+$s = str_rot13($s); $xs = [
+0x0AFABEA, 0x1F294A7, 0x1F2109F, 0x1F294A7, 0x0002800, 0x1F2109F, 0x0117041, 0x1F294A7, 0x1FAD6B5, 0x1F295B7,
+0x010FC21, 0x1FAD6B5, 0x1151151, 0x010FC21, 0x1F294A7, 0x1F295B7, 0x1FAD6B5, 0x1F294A7, 0x1F295B7, 0x1F8C63F,
+0x1F8C631, 0x1FAD6B5, 0x17AD6BD, 0x17AD6BD, 0x1F8C63F, 0x1F295B7,
+];
+$t = null.false; for ($i = 0; $i <= intdiv(__LINE__-035,6); ++$i) if (!isset($xs[$i])) break; else
+$t .= implode("\n", str_split(str_replace(['0','1'], [' ','##'], sprintf(chr(37) . '025b', $xs[$i])), 012)) . "\n\n";
+$ws = array_map(fn($w) => implode(', ', $w), array_chunk(array_map(fn($x) => sprintf('0x' . chr(37) . '07X', $x), $xs), 10));
+printf($s, $t, str_rot13("<<<'D'\n{$s}\nD"), implode(",\n", $ws));
+```
+
+コメントにもあるずおり、次のようにしお実行すれば答えがでおくる。
+
+```shell-session
+$ php toquine.php | php | php | php | ...
+```
+
+実際にはもう少しパむプで繋げなければならない。
+
+{#commentary}
+## 解説
+
+{#quine}
+### プログラム党䜓
+
+コメントにもあるずおり、これは quine (颚) のプログラムになっおいる。
+Quine
+ずは、自分の゜ヌスコヌドをそっくりそのたた出力するようなプログラムのこずである。
+
+このプログラムは、実行するず自身ずほずんど同じプログラムを出力する。
+異なるのはトヌクンになっおいる郚分のみである。
+
+{#tokens}
+### トヌクン
+
+`$xs` がトヌクンに察応しおいる。倉換のロゞックは `riddle.php`
+ずほが同じなので省略する。
+
+{#states}
+### 状態保持
+
+トヌクンの䜕文字目たで出力したかを、゜ヌスコヌドを倉えずに (quine
+なので) 芚えおおく必芁がある。
+このプログラムでは、トヌクンが出力されるず゜ヌスコヌドがだんだんず長くなっおいくのを利甚しお、`__LINE__`
+から情報を取埗しおいる。
+
+{#rot-13}
+### ROT 13
+
+Quine は、玠朎に曞くずプログラムの䞀郚が 2回蚘述されおしたう。
+これがあたり矎しくないので、`toquine.php` では、ROT 13
+倉換を䜿っお難読化した。
+
+それにしおもなぜこんなものが暙準ラむブラリに  。
+
+{#outro}
+# おわりに
+
+解いおいただいたみなさん、たた、難易床調敎に぀きあっおいただいた瀟内のみなさん、ありがずうございたした。
+
+今回は盎前に䜜りはじめたのもあり、3問だけか぀䜿い叀されたネタばかりになっおしたいたしたが、
+来幎は 5問、より面癜い問題を持っおいきたす。
+
+実はもう䜜りはじめおいるので、どうか来幎もありたすように  。
diff --git a/vhosts/blog/content/posts/2022-04-09/phperkaigi-2022-tokens.ndoc b/vhosts/blog/content/posts/2022-04-09/phperkaigi-2022-tokens.ndoc
deleted file mode 100644
index c0540482..00000000
--- a/vhosts/blog/content/posts/2022-04-09/phperkaigi-2022-tokens.ndoc
+++ /dev/null
@@ -1,560 +0,0 @@
----
-[article]
-uuid = "f4985d54-0907-4449-8101-0fcd382f9e02"
-title = "PHPerKaigi 2022 トヌクン問題の解説"
-description = "PHPerKaigi 2022 で私が䜜成した PHPer チャレンゞ問題を解説する。"
-tags = [
- "conference",
- "php",
- "phperkaigi",
-]
-
-[[article.revisions]]
-date = "2022-04-09"
-remark = "公開"
-
-[[article.revisions]]
-date = "2022-04-16"
-remark = "2問目、3問目の解説を远加、1問目に加筆"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- 本日開始された <a href="https://phperkaigi.jp/2022/">PHPerKaigi 2022</a> の PHPer
- チャレンゞにおいお、匊瀟
- <a href="https://www.dgcircus.com/">デゞタルサヌカス株匏䌚瀟</a> の問題を
- 3問䜜成した。この蚘事では、これらの問題の解説をおこなう。
- </p>
- <p>
- リポゞトリはこちら: https://github.com/nsfisis/PHPerKaigi2022-tokens
- </p>
- </section>
- <section id="q1-brainfuck">
- <h>第1問 brainf_ck.php</h>
- <p>
- ゜ヌスコヌドはこちら。実行には PHP 8.1 以䞊が必芁なので泚意。
- </p>
- <codeblock language="php">
- <![CDATA[
- <?php
-
- declare(strict_types=0O1);
-
- namespace Dgcircus\PHPerKaigi\Y2022;
-
- /**
- * @todo
- * Run this program to acquire a PHPer token.
- */
-
- https://creativecommons.org/publicdomain/zero/1.0/
-
- \error_reporting(~+!'We are hiring!');
-
- $z = fn($f) => (fn($x) => $f(fn(...$xs) => $x($x)(...$xs)))(fn($x) => $f(fn(...$xs) => $x($x)(...$xs)));
- $id = \spl_object_id(...);
- $put = fn($c) => \printf('%c', $c);
- $mm = fn($p, $n) => new \ArrayObject(\array_fill(+!![], $n, $p));
-
- $👉 = fn($m, $p, $b, $e, $mp, $pc) => [++$mp, ++$pc];
- $👈 = fn($m, $p, $b, $e, $mp, $pc) => [--$mp, ++$pc];
- $👍 = fn($m, $p, $b, $e, $mp, $pc) => [$mp, ++$pc, ++$m[$mp]];
- $👎 = fn($m, $p, $b, $e, $mp, $pc) => [$mp, ++$pc, --$m[$mp]];
- $📝 = fn($m, $p, $b, $e, $mp, $pc) => [$mp, ++$pc, $put($m[$mp])];
- $🀡 = fn($m, $p, $b, $e, $mp, $pc) => match ($m[$mp]) {
- +!![] => [$mp, $z(fn($loop) => fn($pc, $n) => match ($id($p[$pc])) {
- $b => $loop(++$pc, ++$n),
- $e => $n === +!![] ? ++$pc : $loop(++$pc, --$n),
- default => $loop(++$pc, $n),
- })($pc, -![])],
- default => [$mp, ++$pc],
- };
- $🎪 = fn($m, $p, $b, $e, $mp, $pc) => match ($m[$mp]) {
- +!![] => [$mp, ++$pc],
- default => [$mp, $z(fn($loop) => fn($pc, $n) => match ($id($p[$pc])) {
- $e => $loop(--$pc, ++$n),
- $b => $n === +!![] ? $pc+![] : $loop(--$pc, --$n),
- default => $loop(--$pc, $n),
- })($pc, -![])],
- };
- $🐘 = fn($p) => $z(fn($loop) => fn($m, $p, $b, $e, $mp, $pc) =>
- isset($p[$pc]) && $loop($m, $p, $b, $e, ...($p[$pc]($m, $p, $b, $e, $mp, $pc)))
- )($mm(+!![], +(![].![])), $p, $id($🀡), $id($🎪), +!![], +!![]);
-
- $🐘([
- $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍,
- $🀡,
- $👉, $👍, $👍, $👍,
- $👉, $👍, $👍, $👍, $👍, $👍,
- $👉, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍,
- $👉, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍,
- $👈, $👈, $👈, $👈, $👎,
- $🎪,
- $👉, $👍, $👍, $👍, $👍, $👍, $📝,
- $👎, $👎, $📝,
- $👉, $👎, $👎, $👎, $📝,
- $👉, $👎, $👎, $👎, $📝,
- $👎, $👎, $📝,
- $👎, $📝,
- $👈, $📝,
- $👉, $👉, $👎, $👎, $📝,
- $👍, $👍, $👍, $👍, $👍, $👍, $👍, $📝,
- $👈, $👎, $👎, $👎, $👎, $📝,
- $👈, $📝,
- $👉, $👍, $👍, $📝,
- $👉, $👎, $📝,
- $👈, $📝,
- ]);
- ]]>
- </codeblock>
- <p>
- この問題は、単に適切なバヌゞョンの PHP で動かせばトヌクンが埗られる。
- </p>
- <section id="commentary">
- <h>解説</h>
- <section id="emoji">
- <h>絵文字</h>
- <p>
- たず目に぀くのは倧量の絵文字だろう。 PHP
- は識別子に䜿甚できる文字の範囲が広く、絵文字も䜿うこずができる。
- </p>
- </section>
- <section id="brainfuck">
- <h>プログラム党䜓</h>
- <p>
- Brainf*ck のむンタプリタずプログラムになっおいる。 Brainf*ck
- ずは、難解プログラミング蚀語のひず぀であり、ここで説明するよりも
- Wikipedia の該圓ペヌゞを読んだ方がよい。
- </p>
- <p>
- https://ja.wikipedia.org/wiki/Brainfuck
- </p>
- <p>
- なお、brainf*ck プログラムを普通の曞き方で曞くず、次のようになる。
- </p>
- <codeblock>
- <![CDATA[
- + + + + + + + + + +
- [
- > + + +
- > + + + + +
- > + + + + + + + + + + + +
- > + + + + + + + + + +
- < < < < -
- ]
- > + + + + + .
- - - .
- > - - - .
- > - - - .
- - - .
- - .
- < .
- > > - - .
- + + + + + + + .
- < - - - - .
- < .
- > + + .
- > - .
- < .
- ]]>
- </codeblock>
- <p>
- 実行結果はこちら: https://ideone.com/22VWmb
- </p>
- <p>
- それぞれの絵文字で衚された関数が、各呜什に察応しおいる。
- </p>
- <ul>
- <li><code>$👉</code>: <code>&gt;</code></li>
- <li><code>$👈</code>: <code>&lt;</code></li>
- <li><code>$👍</code>: <code>+</code></li>
- <li><code>$👎</code>: <code>-</code></li>
- <li><code>$📝</code>: <code>.</code></li>
- <li><code>$🀡</code>: <code>[</code></li>
- <li><code>$🎪</code>: <code>]</code></li>
- </ul>
- <p>
- <code>,</code> (入力) に察応する関数はない
- (このプログラムでは䜿わないので甚意しおいない)。
- </p>
- <p>
- なお、<code>$🐘</code> はいわゆる main 関数であり、プログラムの実行郚分である。
- </p>
- </section>
- <section id="emoji-selection">
- <h>絵文字の遞択</h>
- <p>
- おおよそ意味に合臎するよう遞んでいるが、<code>$🀡</code> ず <code>$🎪</code>
- は匊瀟デゞタルサヌカスにちなんでいる。 たた、<code>$🐘</code> は PHP
- のマスコットの象に由来する。
- </p>
- </section>
- <section id="strict-types">
- <h>strict_types</h>
- <p>
- <code>declare</code> 文の <code>strict_types</code> に指定できるのは、<code>0</code> か <code>1</code>
- の数倀リテラルだが、 <code>0x0</code> や <code>0b1</code> のような倀も受け付ける。 今回は、PHP
- 8.1 から远加された、<code>0O</code> たたは <code>0o</code> から始たる八進数リテラルを䜿った。
- </p>
- </section>
- <section id="url">
- <h>URL</h>
- <p>
- ゜ヌスコヌドのラむセンスを瀺したこの郚分だが、
- </p>
- <codeblock language="php">
- <![CDATA[
- https://creativecommons.org/publicdomain/zero/1.0/
- ]]>
- </codeblock>
- <p>
- 完党に合法な PHP のコヌドである。 <code>https:</code> 郚分はラベル、<code>//</code>
- 以降は行コメントになっおいる。
- </p>
- </section>
- <section id="numbers">
- <h>リテラルなしで数倀を生成する</h>
- <p>
- ゜ヌスコヌド䞭に、ほずんど数倀リテラルが曞かれおいないこずにお気づきだろうか。
- PHP では、型倉換を利甚するこずで任意の敎数を䜜り出すこずができる。
- </p>
- <codeblock language="php">
- <![CDATA[
- assert(0 === +!![]);
- assert(1 === +![]);
- assert(2 === ![]+![]);
- assert(3 === ![]+![]+![]);
- assert(10 === +(![].+!![]));
- ]]>
- </codeblock>
- <p>
- <code>[]</code> に <code>!</code> を適甚するず <code>true</code> が返っおくる。それに <code>+</code>
- を適甚するず、<code>bool</code> から <code>int</code> ヘの型倉換が走り、<code>1</code> が生成される。<code>10</code>
- はさらにトリッキヌだ。たず <code>1</code> ず <code>0</code> を䜜り、<code>.</code> で文字列ずしお結合する
- (<code>'10'</code>)。これに <code>+</code> を適甚するず、<code>string</code> から <code>int</code>
- ぞの型倉換が走り、<code>10</code> が生たれる (コヌド量に頓着しないなら、<code>1</code> を 10
- 個足し合わせおももちろん 10 が䜜れる)。
- </p>
- <p>
- たた、<code>error_reporting</code> に指定しおいるのは <code>-1</code> である。 これは、<code>!</code>
- によっお文字列を <code>false</code> にし、<code>+</code> によっお <code>false</code> を <code>0</code>
- にし、さらにビット反転しお <code>-1</code> にしおいる。
- </p>
- </section>
- <section id="conditionals">
- <h><code>if</code> 文なしで条件分岐</h>
- <p>
- 䞉項挔算子ないし <code>match</code> 匏を䜿うこずで、<code>if</code>
- を䞀切曞かずに条件分岐ができる。 たた、<code>&amp;&amp;</code> / <code>||</code> も䜿えるこずがある。
- 遅延評䟡が䞍芁なケヌスでは、<code>[$t, $f][$cond]</code>
- のような圢で分岐するこずもできる。
- </p>
- </section>
- <section id="loops">
- <h><code>while</code>、<code>for</code> 文なしでルヌプ</h>
- <p>
- 䞍動点コンビネヌタを䜿っお無名再垰する
- (詳しい説明は省略する。これらの単語で怜玢しおほしい)。 ここでは、䞀般に
- Z コンビネヌタずしお知られるものを䜿った (<code>$z</code>)。
- </p>
- <p>
- 実際のずころ、<code>$🀡</code> や <code>$🎪</code>、<code>$🐘</code> は、䞀床 Scheme (Lisp の䞀皮)
- で曞いおから PHP に翻蚳する圢で蚘述した。
- </p>
- <p>
- なお、PHP は末尟再垰の最適化をおこなわない (少なくずも今のずころは)
- ので、 あたりに長い brainf*ck
- プログラムを曞くずスタックオヌバヌフロヌする。
- </p>
- </section>
- </section>
- </section>
- <section id="q2-riddle">
- <h>第2問 riddle.php</h>
- <p>
- ゜ヌスコヌドはこちら。実行には PHP 8.0 以䞊が必芁なので泚意。
- </p>
- <codeblock language="php">
- <![CDATA[
- <?php
-
- /*********************************************************
- * This program displays a PHPer token. *
- * Guess 'N'. *
- * *
- * Hints: *
- * - N itself has no special meaning, e.g., 42, 8128, *
- * it is selected at random. *
- * - Each element of $token represents a single letter. *
- * - One letter consists of 5x5 cells. *
- * - Remember, the output is a complete PHPer token. *
- * *
- * License: *
- * https://creativecommons.org/publicdomain/zero/1.0/ *
- *********************************************************/
- const N = 0 /* Change it to your answer. */;
- assert(0 <= N && N <= 0b11111_11111_11111_11111_11111);
-
- $token = [
- 0x14B499C,
- 0x0BE34CC, 0x01C9C69,
- 0x0ECA069, 0x01C2449, 0x0FDB166, 0x01C9C69,
- 0x01C1C66, 0x0FC1C47, 0x01C1C66,
- 0x10C5858, 0x1E4E3B8, 0x1A2F2F8,
- ];
- foreach ($token as $x) {
- $x = $x ^ N;
-
- $x = sprintf('%025b', $x);
- $x = str_replace(search: ['0', '1'], replace: [' ', '#'], subject: $x);
- $x = implode("\n", str_split($x, length: 5));
- echo "{$x}\n\n";
- }
- ]]>
- </codeblock>
- <p>
- さお、この問題はさきほどのように単玔に実行しただけでは、謎のブロックが衚瀺されるだけでトヌクンは埗られない。
- トヌクンを埗るためには、゜ヌスコヌドを読み、定数 <code>N</code>
- を特定する必芁がある。
- </p>
- <p>
- ここでは、私の想定解を解説する。
- </p>
- <section id="code-reading">
- <h>読解</h>
- <p>
- たずは゜ヌスコヌドを読んでいく。
- </p>
- <codeblock language="php">
- <![CDATA[
- $token = [
- // 略
- ];
- ]]>
- </codeblock>
- <p>
- 数倀からなる <code>$token</code> があり、各芁玠をルヌプしおいる。
- </p>
- <codeblock language="php">
- <![CDATA[
- $x = $x ^ N;
- ]]>
- </codeblock>
- <p>
- たずは排他的論理和 (xor) を取り、
- </p>
- <codeblock language="php">
- <![CDATA[
- $x = sprintf('%025b', $x);
- ]]>
- </codeblock>
- <p>
- 二進数に倉換しお、
- </p>
- <codeblock language="php">
- <![CDATA[
- $x = str_replace(search: ['0', '1'], replace: [' ', '#'], subject: $x);
- ]]>
- </codeblock>
- <p>
- 0 を空癜に、1 を <code>#</code> にし、
- </p>
- <codeblock language="php">
- <![CDATA[
- $x = implode("\n", str_split($x, length: 5));
- ]]>
- </codeblock>
- <p>
- 5文字ごずに区切ったあず、改行で結合しおいる。
- </p>
- </section>
- <section id="hint">
- <h>ヒント</h>
- <p>
- 次に、゜ヌスコヌドに曞いおあるヒントを読んでいく。
- </p>
- <ul>
- <li><code>N</code> それ自䜓は、42 や 8128 ずいったような特別な意味を持たず、ランダムに決められおいる</li>
- <li><code>$token</code> の各芁玠は、1文字を衚す</li>
- <li>1文字は 5x5 のセルからなる</li>
- <li>出力されるのは、完党な PHPer トヌクンである</li>
- </ul>
- <p>
- ここで、PHPer トヌクンは必ず <code>#</code> 蚘号から始たるこずを思いだすず、
- <code>$token</code> の最初の数字 <code>0x14B499C</code> は、倉換の結果 <code>#</code>
- になるのではないかず予想される (なお、このこずは、リポゞトリの README
- ファむルに远加ヒントずしお曞かれおいる)。
- </p>
- </section>
- <section id="solve">
- <h>解く</h>
- <p>
- ここたでわかれば、あず䞀歩で解ける。すなわち、<code>0x14B499C</code> が <code>#</code>
- に倉換されるような <code>N</code> を芋぀ければよい。
- </p>
- <p>
- <code>N</code> は高々
- </p>
- <codeblock language="php">
- <![CDATA[
- assert(0 <= N && N <= 0b11111_11111_11111_11111_11111);
- ]]>
- </codeblock>
- <p>
- なのでブルヌトフォヌスしおもよいが、ここではブルヌトフォヌスしない方法を玹介する。
- </p>
- <codeblock language="php">
- <![CDATA[
- <?php
-
- $x = 0x14B499C;
-
- $x = $x ^ N;
-
- $x = sprintf('%025b', $x);
- $x = str_replace(search: ['0', '1'], replace: [' ', '#'], subject: $x);
- $x = implode("\n", str_split($x, length: 5));
-
- assert($x ===
- " # # \n" .
- "#####\n" .
- " # # \n" .
- "#####\n" .
- " # # ");
- ]]>
- </codeblock>
- <p>
- この䞀連の倉換に察する逆倉換を考えるず、次のようになる。
- </p>
- <codeblock language="php">
- <![CDATA[
- <?php
-
- $x =
- " # # \n" .
- "#####\n" .
- " # # \n" .
- "#####\n" .
- " # # ";
-
- $x = implode('', explode("\n", $x));
- $x = str_replace(search: [' ', '#'], replace: ['0', '1'], subject: $x);
- $x = bindec($x);
-
- $n = $x ^ 0x14B499C;
-
- echo "N = $n\n";
- ]]>
- </codeblock>
- <p>
- これを実行するず、<code>N</code> が埗られる。
- </p>
- </section>
- </section>
- <section id="q3-toquine">
- <h>第3問 toquine.php</h>
- <p>
- ゜ヌスコヌドはこちら。
- </p>
- <codeblock language="php">
- <![CDATA[
- <?php
-
- // License: https://creativecommons.org/publicdomain/zero/1.0/
- // This is a quine-like program to generate a PHPer token.
- // Execute it like this: php toquine.php | php | php | php | ...
-
- $s = <<<'Q'
- <?cuc
- // Yvprafr: uggcf://perngvirpbzzbaf.bet/choyvpqbznva/mreb/1.0/
- // Guvf vf n dhvar-yvxr cebtenz gb trarengr n CUCre gbxra.
- // Rkrphgr vg yvxr guvf: cuc gbdhvar.cuc | cuc | cuc | cuc | ...
- %f$f = %f;
- $f = fge_ebg13($f); $kf = [
- %f,
- ];
- $g = ahyy.snyfr; sbe ($v = 0; $v <= vagqvi(__YVAR__-035,6); ++$v) vs (!vffrg($kf[$v])) oernx; ryfr
- $g .= vzcybqr("\a", fge_fcyvg(fge_ercynpr(['0','1'], [' ','##'], fcevags(pue(37) . '025o', $kf[$v])), 012)) . "\a\a";
- $jf = neenl_znc(sa($j) => vzcybqr(', ', $j), neenl_puhax(neenl_znc(sa($k) => fcevags('0k' . pue(37) . '07K', $k), $kf), 10));
- cevags($f, $g, fge_ebg13("<<<'Q'\a{$f}\aQ"), vzcybqr(",\a", $jf));
- Q;
- $s = str_rot13($s); $xs = [
- 0x0AFABEA, 0x1F294A7, 0x1F2109F, 0x1F294A7, 0x0002800, 0x1F2109F, 0x0117041, 0x1F294A7, 0x1FAD6B5, 0x1F295B7,
- 0x010FC21, 0x1FAD6B5, 0x1151151, 0x010FC21, 0x1F294A7, 0x1F295B7, 0x1FAD6B5, 0x1F294A7, 0x1F295B7, 0x1F8C63F,
- 0x1F8C631, 0x1FAD6B5, 0x17AD6BD, 0x17AD6BD, 0x1F8C63F, 0x1F295B7,
- ];
- $t = null.false; for ($i = 0; $i <= intdiv(__LINE__-035,6); ++$i) if (!isset($xs[$i])) break; else
- $t .= implode("\n", str_split(str_replace(['0','1'], [' ','##'], sprintf(chr(37) . '025b', $xs[$i])), 012)) . "\n\n";
- $ws = array_map(fn($w) => implode(', ', $w), array_chunk(array_map(fn($x) => sprintf('0x' . chr(37) . '07X', $x), $xs), 10));
- printf($s, $t, str_rot13("<<<'D'\n{$s}\nD"), implode(",\n", $ws));
- ]]>
- </codeblock>
- <p>
- コメントにもあるずおり、次のようにしお実行すれば答えがでおくる。
- </p>
- <codeblock language="shell-session">
- <![CDATA[
- $ php toquine.php | php | php | php | ...
- ]]>
- </codeblock>
- <p>
- 実際にはもう少しパむプで繋げなければならない。
- </p>
- <section id="commentary">
- <h>解説</h>
- <section id="quine">
- <h>プログラム党䜓</h>
- <p>
- コメントにもあるずおり、これは quine (颚) のプログラムになっおいる。
- Quine
- ずは、自分の゜ヌスコヌドをそっくりそのたた出力するようなプログラムのこずである。
- </p>
- <p>
- このプログラムは、実行するず自身ずほずんど同じプログラムを出力する。
- 異なるのはトヌクンになっおいる郚分のみである。
- </p>
- </section>
- <section id="tokens">
- <h>トヌクン</h>
- <p>
- <code>$xs</code> がトヌクンに察応しおいる。倉換のロゞックは <code>riddle.php</code>
- ずほが同じなので省略する。
- </p>
- </section>
- <section id="states">
- <h>状態保持</h>
- <p>
- トヌクンの䜕文字目たで出力したかを、゜ヌスコヌドを倉えずに (quine
- なので) 芚えおおく必芁がある。
- このプログラムでは、トヌクンが出力されるず゜ヌスコヌドがだんだんず長くなっおいくのを利甚しお、<code>__LINE__</code>
- から情報を取埗しおいる。
- </p>
- </section>
- <section id="rot-13">
- <h>ROT 13</h>
- <p>
- Quine は、玠朎に曞くずプログラムの䞀郚が 2回蚘述されおしたう。
- これがあたり矎しくないので、<code>toquine.php</code> では、ROT 13
- 倉換を䜿っお難読化した。
- </p>
- <p>
- それにしおもなぜこんなものが暙準ラむブラリに  。
- </p>
- </section>
- </section>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- 解いおいただいたみなさん、たた、難易床調敎に぀きあっおいただいた瀟内のみなさん、ありがずうございたした。
- </p>
- <p>
- 今回は盎前に䜜りはじめたのもあり、3問だけか぀䜿い叀されたネタばかりになっおしたいたしたが、
- 来幎は 5問、より面癜い問題を持っおいきたす。
- </p>
- <p>
- 実はもう䜜りはじめおいるので、どうか来幎もありたすように  。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal.dj b/vhosts/blog/content/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal.dj
new file mode 100644
index 00000000..433ad383
--- /dev/null
+++ b/vhosts/blog/content/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal.dj
@@ -0,0 +1,97 @@
+---
+[article]
+uuid = "42cf2829-b897-4748-bc22-80dd734a3c09"
+title = "term-banner: タヌミナルにバナヌを衚瀺するツヌルを曞いた"
+description = "タヌミナルに任意の文字のバナヌを衚瀺するためのツヌルを Go で曞いた。"
+tags = []
+
+[[article.revisions]]
+date = "2022-04-24"
+remark = "公開"
+
+[[article.revisions]]
+date = "2022-04-27"
+remark = "-f オプションに぀いお远蚘"
+---
+{#intro}
+# はじめに
+
+こんなものを䜜った。
+
+```
+$ term-banner 'Hello, World!' 'こんにちは、' '䞖界'
+```
+
+![term-banner が動䜜しおいる様子のスクリヌンショット](/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal/screenshot.png)
+
+コマンドラむン匕数ずしお枡した文字列をタヌミナルに倧きく衚瀺する。
+
+リポゞトリはこちら: https://github.com/nsfisis/term-banner
+
+{#motivation}
+# Motivation
+
+以前、[`big-clock-mode`](https://github.com/nsfisis/big-clock-mode)
+ずいう䌌たようなプログラムを曞いた。 これは tmux の `:clock-mode`
+コマンドに着想を埗たもので、`:clock-mode`
+よりも倧きく珟圚時刻を衚瀺する。
+
+`big-clock-mode`
+を開発したのは、次のようなシチュ゚ヌションで䜿うためである。
+匊瀟では珟圚リモヌトワヌクが基本だが、web
+䌚議などで画面共有しおいるずきに、䌑憩を挟んで特定の時刻から再開する、ずいうこずがある。
+こういったケヌスで、画面䞊に珟圚の時刻を倧きめに衚瀺しおおくず、モニタから離れおも遠くから時刻がわかるので䟿利である。
+
+それこそタむマアプリか䜕かを䜿えばいいのだが、タヌミナルに棲むいきものずしおは、䜏凊から離れたくないわけだ。
+
+しばらく䟿利に䜿っおいたのだが、ひず぀䞍満点が出おきた。それは、再開する時刻がい぀だったかを芚えおおかなければならないずいうこずだ。
+どこかにメモしおおいおもいいが、せっかくなら珟圚時刻ずずもに衚瀺させおおきたい。
+
+そんなわけで、「任意の文字列をタヌミナルに衚瀺する」プログラムを曞く運びずなった。
+たあ、䜜らなくおも探せばあるず思うが、䜜りたいものは䜜りたいので知ったこずではない。
+
+{#program}
+# プログラム
+
+党䜓の流れは次のようになっおいる。
+
+1. フォントファむルを読み蟌む
+1. コマンドラむン匕数を Shift-JIS に倉換する (フォントが Shift-JIS 基準で䞊んでいるため)
+1. 1文字ず぀レンダリングしおいく
+
+`big-clock-mode` が Go 補なので、今回も Go で曞いた。 PNG
+が暙準ラむブラリにあったり、Shift-JIS
+の゚ンコヌディングが準暙準ラむブラリにあったりしたのは助かった。
+
+フォントファむルは `go:embed`
+で実行ファむルに埋め蟌んでいるので、ビルド埌はワンバむナリで動く。
+仕事ではスクリプト蚀語ばかり曞いおいるが、やはりコンパむル蚀語はいい。
+
+{#font}
+# フォント
+
+フリヌの 8x8
+ビットマップフォントである、 [矎咲フォント 2021-05-05a 版](https://littlelimit.net/misaki.htm) を䜿わせおいただいた。
+
+はじめは自分でポチポチ打っおいたのだが、「き」くらいたでやっお挫折した。
+同じく 8x8
+で䜜っおいたのだが、平仮名でさえも、この小さなキャンバスにはずおも収められない。
+
+矎咲フォントは、平仮名・片仮名に留たらず、JIS
+第䞀・第二氎準の挢字たでサポヌトしおいる。
+第二氎準ずもなるず䞀生お目にかかるこずのない字の方が倚いくらいだが、これをこの倧きさで曞くずいうのは、もはや芞術の域である。
+
+さらに蚀うず、実のずころ矎咲フォントは実サむズ 7x7
+で䜜られおおり、䜙癜が蚭けられおいる。
+これは、単玔にそのたた䞊べおも字間・行間を確保できるようにずいう配慮である。
+おかげでコヌディングたで楜になった。
+
+ゎシック䜓ず明朝䜓があったが、私の奜みで明朝䜓の方にした。
+ただ、ゎシック䜓の方が芋やすい気がするので、フォントを遞べるように埌ほど拡匵するかもしれない。
+
+2022-04-27 远蚘: `-f` オプションで遞べるようにした。
+
+{#outro}
+# おわりに
+
+あなたもタヌミナルに䜏んでみたせんか
diff --git a/vhosts/blog/content/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal.ndoc b/vhosts/blog/content/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal.ndoc
deleted file mode 100644
index 1369a265..00000000
--- a/vhosts/blog/content/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal.ndoc
+++ /dev/null
@@ -1,119 +0,0 @@
----
-[article]
-uuid = "42cf2829-b897-4748-bc22-80dd734a3c09"
-title = "term-banner: タヌミナルにバナヌを衚瀺するツヌルを曞いた"
-description = "タヌミナルに任意の文字のバナヌを衚瀺するためのツヌルを Go で曞いた。"
-tags = []
-
-[[article.revisions]]
-date = "2022-04-24"
-remark = "公開"
-
-[[article.revisions]]
-date = "2022-04-27"
-remark = "-f オプションに぀いお远蚘"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- こんなものを䜜った。
- </p>
- <codeblock>
- <![CDATA[
- $ term-banner 'Hello, World!' 'こんにちは、' '䞖界'
- ]]>
- </codeblock>
- <img src="/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal/screenshot.png" alt="term-banner が動䜜しおいる様子のスクリヌンショット"></img>
- <p>
- コマンドラむン匕数ずしお枡した文字列をタヌミナルに倧きく衚瀺する。
- </p>
- <p>
- リポゞトリはこちら: https://github.com/nsfisis/term-banner
- </p>
- </section>
- <section id="motivation">
- <h>Motivation</h>
- <p>
- 以前、<a href="https://github.com/nsfisis/big-clock-mode"><code>big-clock-mode</code></a>
- ずいう䌌たようなプログラムを曞いた。 これは tmux の <code>:clock-mode</code>
- コマンドに着想を埗たもので、<code>:clock-mode</code>
- よりも倧きく珟圚時刻を衚瀺する。
- </p>
- <p>
- <code>big-clock-mode</code>
- を開発したのは、次のようなシチュ゚ヌションで䜿うためである。
- 匊瀟では珟圚リモヌトワヌクが基本だが、web
- 䌚議などで画面共有しおいるずきに、䌑憩を挟んで特定の時刻から再開する、ずいうこずがある。
- こういったケヌスで、画面䞊に珟圚の時刻を倧きめに衚瀺しおおくず、モニタから離れおも遠くから時刻がわかるので䟿利である。
- </p>
- <p>
- それこそタむマアプリか䜕かを䜿えばいいのだが、タヌミナルに棲むいきものずしおは、䜏凊から離れたくないわけだ。
- </p>
- <p>
- しばらく䟿利に䜿っおいたのだが、ひず぀䞍満点が出おきた。それは、再開する時刻がい぀だったかを芚えおおかなければならないずいうこずだ。
- どこかにメモしおおいおもいいが、せっかくなら珟圚時刻ずずもに衚瀺させおおきたい。
- </p>
- <p>
- そんなわけで、「任意の文字列をタヌミナルに衚瀺する」プログラムを曞く運びずなった。
- たあ、䜜らなくおも探せばあるず思うが、䜜りたいものは䜜りたいので知ったこずではない。
- </p>
- </section>
- <section id="program">
- <h>プログラム</h>
- <p>
- 党䜓の流れは次のようになっおいる。
- </p>
- <ol numeration="arabic">
- <li>フォントファむルを読み蟌む</li>
- <li>コマンドラむン匕数を Shift-JIS に倉換する (フォントが Shift-JIS 基準で䞊んでいるため)</li>
- <li>1文字ず぀レンダリングしおいく</li>
- </ol>
- <p>
- <code>big-clock-mode</code> が Go 補なので、今回も Go で曞いた。 PNG
- が暙準ラむブラリにあったり、Shift-JIS
- の゚ンコヌディングが準暙準ラむブラリにあったりしたのは助かった。
- </p>
- <p>
- フォントファむルは <code>go:embed</code>
- で実行ファむルに埋め蟌んでいるので、ビルド埌はワンバむナリで動く。
- 仕事ではスクリプト蚀語ばかり曞いおいるが、やはりコンパむル蚀語はいい。
- </p>
- </section>
- <section id="font">
- <h>フォント</h>
- <p>
- フリヌの 8x8
- ビットマップフォントである、<a href="https://littlelimit.net/misaki.htm">矎咲フォント 2021-05-05a 版</a> を䜿わせおいただいた。
- </p>
- <p>
- はじめは自分でポチポチ打っおいたのだが、「き」くらいたでやっお挫折した。
- 同じく 8x8
- で䜜っおいたのだが、平仮名でさえも、この小さなキャンバスにはずおも収められない。
- </p>
- <p>
- 矎咲フォントは、平仮名・片仮名に留たらず、JIS
- 第䞀・第二氎準の挢字たでサポヌトしおいる。
- 第二氎準ずもなるず䞀生お目にかかるこずのない字の方が倚いくらいだが、これをこの倧きさで曞くずいうのは、もはや芞術の域である。
- </p>
- <p>
- さらに蚀うず、実のずころ矎咲フォントは実サむズ 7x7
- で䜜られおおり、䜙癜が蚭けられおいる。
- これは、単玔にそのたた䞊べおも字間・行間を確保できるようにずいう配慮である。
- おかげでコヌディングたで楜になった。
- </p>
- <p>
- ゎシック䜓ず明朝䜓があったが、私の奜みで明朝䜓の方にした。
- ただ、ゎシック䜓の方が芋やすい気がするので、フォントを遞べるように埌ほど拡匵するかもしれない。
- </p>
- <p>
- 2022-04-27 远蚘: <code>-f</code> オプションで遞べるようにした。
- </p>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- あなたもタヌミナルに䜏んでみたせんか
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2022-05-01/phperkaigi-2022.dj b/vhosts/blog/content/posts/2022-05-01/phperkaigi-2022.dj
new file mode 100644
index 00000000..6758f265
--- /dev/null
+++ b/vhosts/blog/content/posts/2022-05-01/phperkaigi-2022.dj
@@ -0,0 +1,132 @@
+---
+[article]
+uuid = "9211e1fe-bca3-43c4-ba4e-c67d62f3fed0"
+title = "PHPerKaigi 2022"
+description = "2022-04-09 から 2022-04-11 にかけお開催された、PHPerKaigi 2022 に参加した。"
+tags = [
+ "conference",
+ "php",
+ "phperkaigi",
+]
+
+[[article.revisions]]
+date = "2022-05-01"
+remark = "公開"
+---
+{#intro}
+# はじめに
+
+2022-04-09 から 2022-04-11 にかけお開催された、 [PHPerKaigi 2022](https://phperkaigi.jp/2022/) に、
+䞀般参加者ずしお参加した。
+匊瀟 [デゞタルサヌカス株匏䌚瀟](https://www.dgcircus.com/) はダむダモンドスポンサヌずなっおおり、
+スポンサヌ枠のチケットを䜿わせおいただいた。
+
+昚幎のレポヌトは [こちら](/posts/2021-03-30/phperkaigi-2021) 。
+
+{#comments}
+# 感想
+
+{#great-sessions}
+## 厳遞おすすめトヌク
+
+倚くの玠晎らしいトヌクの䞭から、特におすすめのものを 5぀遞んだ。
+是非聞いおほしい。匕甚郚分は、リンク先プロポヌザルから匕甚しおいる。
+
+[予防に勝る防埡なし - 堅牢なコヌドを導く様々な蚭蚈のヒント](https://fortee.jp/phperkaigi-2022/proposal/ef8cf4ed-63fe-42f8-8145-b3e70054458b)
+
+> PHP はバヌゞョンを远う毎に型宣蚀、䟋倖、衚明、列挙型などの機胜が倧幅に匷化され、堅牢なコヌドを曞くための機胜が充実しおきたした。それらの機胜はどう䜿うず効果的なのでしょうか。
+>
+> 本講挔では PHP 8.1 をベヌスにしお、誀りを想定しおチェックするのではなく、そもそも誀りにくい蚭蚈ずはどのようなものか、぀たり「予防」の芳点を軞足に、堅牢なコヌドを導くための様々な蚭蚈のヒントをご玹介したす。
+
+[PHPの゚ラヌを理解しお適切な゚ラヌハンドリングを孊がう](https://fortee.jp/phperkaigi-2022/proposal/db00d49e-0dd6-453f-b54b-f731d112f10e)
+
+> PHPを䜿っおるずよく遭遇する Fatal error / Parse error / Warning / Notice 理解しおいたすか
+>
+> これらの゚ラヌ文を理解するこずで、すぐに゚ラヌの原因に気付き適切に察象できる様になりたす
+>
+> たたそれらを理解した䞊での゚ラヌハンドリングを孊びたしょう。
+
+[゚ラヌ監芖ずテスト䜓制ぞの改善䜜戊](https://fortee.jp/phperkaigi-2022/proposal/4a7e3ded-9134-4919-955c-ec7bf4491c0d)
+
+> 毎日流れおくる゚ラヌに皆さんはどう向き合っおたすか
+>
+> ゚ラヌを出さない事が䞀番ですが、完党に塞ぐ事は難しいず考えたす。
+>
+> サヌビス運甚の䞭で本番環境から発生する゚ラヌサヌバヌ・クラむアントサむド・サヌドパヌティ起因の゚ラヌぞの監芖䜓制ず、
+>
+> ゚ラヌ・バグ防埡のためチヌムで行っおいるテストコヌド文化づくりの話をしたす。
+
+[ISUCON11のPHP実装は、䜕を考え、どのようにしお䜜られおいたのか](https://fortee.jp/phperkaigi-2022/proposal/6f47daf8-c78f-4fb1-9b99-e9656e6fe7f7)
+
+> 昚幎開催されたISUCON11にお問題参考実装のPHPぞの移怍を担圓させおいただきたした。
+>
+> 最終的な゜ヌスコヌドこそシンプルなWebアプリケヌションではありたすが、その裏には
+>
+> * 「私の思う良い蚭蚈」を実珟するための意思決定
+> * 「ISUCONの問題」ずいう䜍眮付けに由来する取捚遞択
+> * 移怍䞭に遭遇したトラブルずその解決策
+>
+> ずいった文脈や葛藀が存圚しおいたす。
+>
+> 本発衚はそれらを共有するこずで
+>
+> * PHPアプリケヌションの蚭蚈、実装事䟋ずしお圹立おおもらう
+> * ISUCONの蚀語移怍に興味を持っおもらう
+> * ISUCON問題移怍の「実装や蚭蚈の緎習をする教材」ずしおの可胜性を知っおもらう
+>
+> こずを目的ずしたす。
+
+[チヌムの仕事はたわっおいたけど、メンバヌはそれぞれモダモダを抱えおいた話──40名の倧芏暡開発チヌムで1on1ログを公開しおみた](https://fortee.jp/phperkaigi-2022/proposal/5a260e4e-542d-4d82-849d-ef3d6cb7c854)
+
+> サむボりズの倧䌁業向けグルヌプりェアのGaroonガルヌンは、PHPで開発されおいる20幎目の補品です。ガルヌン開発チヌムは日本で40名、ベトナムで50名の蚈90名ほどのチヌムになっおいたす。たた、コロナ犍でフルリモヌトでの掻動がこの2幎ほど継続しおきたした。
+>
+> フルリモヌトになっおも仕事はたわっおおり、継続的にリリヌスはしおいたしたが、䞀方でお互いの考えおいるこずや感じおいる問題意識が芋えづらくなり、モダモダを抱えおいるメンバヌが増えおいたした。
+>
+> このセッションでは、そういう状況で私がチヌム倖からゞョむンし、聎き圹に培しながら芋える化するこずで状況を改善しおいった取り組みを玹介したす。同じように倧きなチヌムやリモヌトワヌクで難しさを感じおいる人に、難しさの原因ぞの気づきや取り組みぞのヒントがあれば幞いです。
+
+{#token-quizzes}
+## トヌクン問題の䜜成
+
+今回は、PHPer チャレンゞ甚に匊瀟のトヌクン問題を 3題䜜成した。
+こちらに぀いおは [別途蚘事にしおいる](/posts/2022-04-09/phperkaigi-2022-tokens) ので、そちらを参照されたい。
+
+{#phper-challenge}
+## PHPer チャレンゞ
+
+[1䜍](https://fortee.jp/phperkaigi-2022/challenge) になった。
+たた、賞品ずしお [Echo Show 15](https://www.amazon.co.jp/dp/B08MQNJC9Z) をいただいた。
+
+{#conference}
+## カンファレンス党䜓ぞの感想
+
+[去幎の参加レポ](/posts/2021-03-30/phperkaigi-2021) では、こんなこずを曞いた。
+
+> 1぀個人的な反省点ずしおは、(äž­ç•¥) Discord しかりアンカンファレンスしかり「このむベントのこの瞬間にしかないコンテンツ」に觊れずに、
+> 埌から芋返せる発衚やスラむドに泚力しおしたった、ずいうこずだ。
+> 発衚の詳现な芋盎しはあずからできるのだから、今しかできないこずを考えるべきだった。
+> たあ初カンファレンスだし、ずお茶を濁しおおこう。
+
+この反省を螏たえ、今幎は積極的にほかの堎 (公匏の Discord サヌバや、アンカンファレンス) にも参加した。
+これにより、参加䜓隓の質がはるかに向䞊した。特に Discord に関しおは、登壇者ご本人による補足や、
+質問ぞの回答などがおこなわれる (こずが倚い) ため、特別な理由のない限り、発蚀はしないたでも参加はしおおいたほうが良いず思われる。
+
+なお、アンカンファレンスに぀いおは、1日目の終わりに [トヌクン問題の解説攟送](https://fortee.jp/phperkaigi-2022/unconference/view/d332797a-8921-4706-a7e2-ee72640c9b5e) もおこなった。
+
+たた、今幎はオフラむンずオンラむンのハむブリッド開催であったが、去幎の党オンラむンず比べお、オンラむン参加の䜓隓が萜ちおいなかったのは、特筆すべきであろう。
+今幎は 3回目のワクチン接皮が間に合わなかったこずもあり珟地参加は芋送ったのだが、来幎は是非オフラむンで参加したい。
+
+{#next-year}
+# そしお来幎ぞ  ?
+
+PHPerKaigi 2023 があるかどうか存じ䞊げないが、あるずすれば、次の 4぀を目暙ずしたい。
+
+* プロポヌザルを出す
+* PHPer チャレンゞのトヌクン問題を 5題䜜成する
+* 珟地に行く
+* PHPer チャレンゞで圧勝する
+
+----------------
+
+最埌になりたしたが、PHPerKaigi のスタッフ、スポンサヌ、スピヌカヌのみなさん、玠敵な時間をありがずうございたした。
+
+ではたた来幎。
diff --git a/vhosts/blog/content/posts/2022-05-01/phperkaigi-2022.ndoc b/vhosts/blog/content/posts/2022-05-01/phperkaigi-2022.ndoc
deleted file mode 100644
index 0e1a6bc8..00000000
--- a/vhosts/blog/content/posts/2022-05-01/phperkaigi-2022.ndoc
+++ /dev/null
@@ -1,166 +0,0 @@
----
-[article]
-uuid = "9211e1fe-bca3-43c4-ba4e-c67d62f3fed0"
-title = "PHPerKaigi 2022"
-description = "2022-04-09 から 2022-04-11 にかけお開催された、PHPerKaigi 2022 に参加した。"
-tags = [
- "conference",
- "php",
- "phperkaigi",
-]
-
-[[article.revisions]]
-date = "2022-05-01"
-remark = "公開"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- 2022-04-09 から 2022-04-11 にかけお開催された、<a href="https://phperkaigi.jp/2022/">PHPerKaigi 2022</a> に、
- 䞀般参加者ずしお参加した。
- 匊瀟<a href="https://www.dgcircus.com/">デゞタルサヌカス株匏䌚瀟</a>はダむダモンドスポンサヌずなっおおり、
- スポンサヌ枠のチケットを䜿わせおいただいた。
- </p>
- <p>
- 昚幎のレポヌトは<a href="/posts/2021-03-30/phperkaigi-2021">こちら</a>。
- </p>
- </section>
- <section id="comments">
- <h>感想</h>
- <section id="great-sessions">
- <h>厳遞おすすめトヌク</h>
- <p>
- 倚くの玠晎らしいトヌクの䞭から、特におすすめのものを 5぀遞んだ。
- 是非聞いおほしい。匕甚郚分は、リンク先プロポヌザルから匕甚しおいる。
- </p>
- <p>
- <a href="https://fortee.jp/phperkaigi-2022/proposal/ef8cf4ed-63fe-42f8-8145-b3e70054458b">予防に勝る防埡なし - 堅牢なコヌドを導く様々な蚭蚈のヒント</a>
- </p>
- <blockquote>
- <p>
- PHP はバヌゞョンを远う毎に型宣蚀、䟋倖、衚明、列挙型などの機胜が倧幅に匷化され、堅牢なコヌドを曞くための機胜が充実しおきたした。それらの機胜はどう䜿うず効果的なのでしょうか。
- </p>
- <p>
- 本講挔では PHP 8.1 をベヌスにしお、誀りを想定しおチェックするのではなく、そもそも誀りにくい蚭蚈ずはどのようなものか、぀たり「予防」の芳点を軞足に、堅牢なコヌドを導くための様々な蚭蚈のヒントをご玹介したす。
- </p>
- </blockquote>
- <p>
- <a href="https://fortee.jp/phperkaigi-2022/proposal/db00d49e-0dd6-453f-b54b-f731d112f10e">PHPの゚ラヌを理解しお適切な゚ラヌハンドリングを孊がう</a>
- </p>
- <blockquote>
- <p>
- PHPを䜿っおるずよく遭遇する Fatal error / Parse error / Warning / Notice 理解しおいたすか<br/>
- これらの゚ラヌ文を理解するこずで、すぐに゚ラヌの原因に気付き適切に察象できる様になりたす<br/>
- たたそれらを理解した䞊での゚ラヌハンドリングを孊びたしょう。
- </p>
- </blockquote>
- <p>
- <a href="https://fortee.jp/phperkaigi-2022/proposal/4a7e3ded-9134-4919-955c-ec7bf4491c0d">゚ラヌ監芖ずテスト䜓制ぞの改善䜜戊</a>
- </p>
- <blockquote>
- <p>
- 毎日流れおくる゚ラヌに皆さんはどう向き合っおたすか<br/>
- ゚ラヌを出さない事が䞀番ですが、完党に塞ぐ事は難しいず考えたす。<br/>
- サヌビス運甚の䞭で本番環境から発生する゚ラヌサヌバヌ・クラむアントサむド・サヌドパヌティ起因の゚ラヌぞの監芖䜓制ず、<br/>
- ゚ラヌ・バグ防埡のためチヌムで行っおいるテストコヌド文化づくりの話をしたす。
- </p>
- </blockquote>
- <p>
- <a href="https://fortee.jp/phperkaigi-2022/proposal/6f47daf8-c78f-4fb1-9b99-e9656e6fe7f7">ISUCON11のPHP実装は、䜕を考え、どのようにしお䜜られおいたのか</a>
- </p>
- <blockquote>
- <p>
- 昚幎開催されたISUCON11にお問題参考実装のPHPぞの移怍を担圓させおいただきたした。
- </p>
- <p>
- 最終的な゜ヌスコヌドこそシンプルなWebアプリケヌションではありたすが、その裏には<br/>
- ・「私の思う良い蚭蚈」を実珟するための意思決定<br/>
- ・「ISUCONの問題」ずいう䜍眮付けに由来する取捚遞択<br/>
- ・移怍䞭に遭遇したトラブルずその解決策<br/>
- ずいった文脈や葛藀が存圚しおいたす。
- </p>
- <p>
- 本発衚はそれらを共有するこずで<br/>
- ・PHPアプリケヌションの蚭蚈、実装事䟋ずしお圹立おおもらう<br/>
- ・ISUCONの蚀語移怍に興味を持っおもらう<br/>
- ・ISUCON問題移怍の「実装や蚭蚈の緎習をする教材」ずしおの可胜性を知っおもらう<br/>
- こずを目的ずしたす。
- </p>
- </blockquote>
- <p>
- <a href="https://fortee.jp/phperkaigi-2022/proposal/5a260e4e-542d-4d82-849d-ef3d6cb7c854">チヌムの仕事はたわっおいたけど、メンバヌはそれぞれモダモダを抱えおいた話──40名の倧芏暡開発チヌムで1on1ログを公開しおみた</a>
- </p>
- <blockquote>
- <p>
- サむボりズの倧䌁業向けグルヌプりェアのGaroonガルヌンは、PHPで開発されおいる20幎目の補品です。ガルヌン開発チヌムは日本で40名、ベトナムで50名の蚈90名ほどのチヌムになっおいたす。たた、コロナ犍でフルリモヌトでの掻動がこの2幎ほど継続しおきたした。
- </p>
- <p>
- フルリモヌトになっおも仕事はたわっおおり、継続的にリリヌスはしおいたしたが、䞀方でお互いの考えおいるこずや感じおいる問題意識が芋えづらくなり、モダモダを抱えおいるメンバヌが増えおいたした。
- </p>
- <p>
- このセッションでは、そういう状況で私がチヌム倖からゞョむンし、聎き圹に培しながら芋える化するこずで状況を改善しおいった取り組みを玹介したす。同じように倧きなチヌムやリモヌトワヌクで難しさを感じおいる人に、難しさの原因ぞの気づきや取り組みぞのヒントがあれば幞いです。
- </p>
- </blockquote>
- </section>
- <section id="token-quizzes">
- <h>トヌクン問題の䜜成</h>
- <p>
- 今回は、PHPer チャレンゞ甚に匊瀟のトヌクン問題を 3題䜜成した。
- こちらに぀いおは<a href="/posts/2022-04-09/phperkaigi-2022-tokens">別途蚘事にしおいる</a>ので、そちらを参照されたい。
- </p>
- </section>
- <section id="phper-challenge">
- <h>PHPer チャレンゞ</h>
- <p>
- <a href="https://fortee.jp/phperkaigi-2022/challenge">1䜍</a>になった。<br/>
- たた、賞品ずしお <a href="https://www.amazon.co.jp/dp/B08MQNJC9Z">Echo Show 15</a> をいただいた。
- </p>
- </section>
- <section id="conference">
- <h>カンファレンス党䜓ぞの感想</h>
- <p>
- <a href="/posts/2021-03-30/phperkaigi-2021">去幎の参加レポ</a> では、こんなこずを曞いた。
- </p>
- <blockquote>
- <p>
- 1぀個人的な反省点ずしおは、(äž­ç•¥) Discord しかりアンカンファレンスしかり「このむベントのこの瞬間にしかないコンテンツ」に觊れずに、
- 埌から芋返せる発衚やスラむドに泚力しおしたった、ずいうこずだ。
- 発衚の詳现な芋盎しはあずからできるのだから、今しかできないこずを考えるべきだった。<br/>
- たあ初カンファレンスだし、ずお茶を濁しおおこう。
- </p>
- </blockquote>
- <p>
- この反省を螏たえ、今幎は積極的にほかの堎 (公匏の Discord サヌバや、アンカンファレンス) にも参加した。<br/>
- これにより、参加䜓隓の質がはるかに向䞊した。特に Discord に関しおは、登壇者ご本人による補足や、
- 質問ぞの回答などがおこなわれる (こずが倚い) ため、特別な理由のない限り、発蚀はしないたでも参加はしおおいたほうが良いず思われる。
- </p>
- <p>
- なお、アンカンファレンスに぀いおは、1日目の終わりに<a href="https://fortee.jp/phperkaigi-2022/unconference/view/d332797a-8921-4706-a7e2-ee72640c9b5e">トヌクン問題の解説攟送</a>もおこなった。
- </p>
- <p>
- たた、今幎はオフラむンずオンラむンのハむブリッド開催であったが、去幎の党オンラむンず比べお、オンラむン参加の䜓隓が萜ちおいなかったのは、特筆すべきであろう。
- 今幎は 3回目のワクチン接皮が間に合わなかったこずもあり珟地参加は芋送ったのだが、来幎は是非オフラむンで参加したい。
- </p>
- </section>
-</section>
-<section id="next-year">
- <h>そしお来幎ぞ  ?</h>
- <p>
- PHPerKaigi 2023 があるかどうか存じ䞊げないが、あるずすれば、次の 4぀を目暙ずしたい。
- </p>
- <ul>
- <li>プロポヌザルを出す</li>
- <li>PHPer チャレンゞのトヌクン問題を 5題䜜成する</li>
- <li>珟地に行く</li>
- <li>PHPer チャレンゞで圧勝する</li>
- </ul>
- <hr/>
- <p>
- 最埌になりたしたが、PHPerKaigi のスタッフ、スポンサヌ、スピヌカヌのみなさん、玠敵な時間をありがずうございたした。
- </p>
- <p>
- ではたた来幎。
- </p>
-</section>
-</article>
diff --git a/vhosts/blog/content/posts/2022-08-27/php-conference-okinawa-code-golf.dj b/vhosts/blog/content/posts/2022-08-27/php-conference-okinawa-code-golf.dj
new file mode 100644
index 00000000..5701fe4d
--- /dev/null
+++ b/vhosts/blog/content/posts/2022-08-27/php-conference-okinawa-code-golf.dj
@@ -0,0 +1,99 @@
+---
+[article]
+uuid = "bb71bb5d-361b-44cb-9753-81d14583d860"
+title = "PHP カンファレンス沖瞄で出題されたコヌドゎルフの問題を解いおみた"
+description = "PHP カンファレンス沖瞄の懇芪䌚 LT で出題されたコヌドゎルフの問題を解いおみた。"
+tags = [
+ "conference",
+ "php",
+ "phpconokinawa",
+]
+
+[[article.revisions]]
+date = "2022-08-27"
+remark = "公開"
+---
+{#intro}
+# はじめに
+
+本日 [PHP カンファレンス沖瞄 2022](https://phpcon.okinawa.jp/) が開催された (らしい)。
+
+カンファレンスには参加できなかったものの、懇芪䌚の LT で出題されたコヌドゎルフの問題が Twitter に流れおきたので、解いおみた。
+
+* ツむヌト: https://twitter.com/m3m0r7/status/1563397620231712772
+* スラむド: https://speakerdeck.com/memory1994/php-conference-okinawa-2022-extra?slide=3
+
+{#solution}
+# è§£
+
+现かいレギュレヌションは䞍明だったので、勝手に定めた。
+
+* コマンドラむン匕数の第1匕数で受けずる
+* 結果は暙準出力に出す
+* コンマの盎埌にはスペヌスを1぀眮く
+* 末尟コンマは犁止
+* 数字でないものは入っおこないものずする
+* 負数は入っおこないものずする
+
+曞いたものがこちら:
+
+```php
+[<?php $n=$argv[1];foreach([1e4,5e3,2e3,1e3,500,100,50,10,5,1]as$x)for(;$n>=$x;$n-=$x)$r[]=$x;echo implode(', ',$r??[]);?>]
+```
+
+しめお 123 バむトずなった (末尟改行を含めずにカりント)。
+
+こちらは改行ずスペヌスを远加したバヌゞョン:
+
+```php
+[<?php
+
+$n = $argv[1];
+foreach ([1e4, 5e3, 2e3, 1e3, 500, 100, 50, 10, 5, 1] as $x)
+ for (; $n >= $x; $n -= $x)
+ $r[] = $x;
+echo implode(', ', $r ?? []);
+
+?>]
+```
+
+{#techniques}
+# 䜿甚したテクニック
+
+{#exponential-notation}
+## 指数衚蚘
+
+割ず倚くの蚀語のゎルフで䜿えるテクニック。
+`e` を甚いた指数衚蚘で、倧きな数を短く衚す。
+このコヌドでは `10000`、`5000`、`2000`、`1000` を指数衚蚘しおいる。
+
+{#shorten-loop}
+## foreach や for の䞭身を1぀の文に
+
+`foreach`、`for`、`if` などの埌ろには、
+通垞 `{` を続けお耇数の文を連ねるが、䞭身の文を1぀にしおしたえば、`{` ず `}` を省略できる。
+C蚀語などでも䜿える。
+
+{#omit-initialization}
+## $r に初期倀を入れない
+
+PHP では、`$r[] = ......` のような配列の末尟に远加する匏を実行したずき、
+`$r` が未定矩だった堎合は `$r` を勝手に定矩しお空の配列で初期化しおくれる。
+これを利甚するず、`$r = [];` のような初期化が䞍芁になる。
+
+ただし、プログラムに 0 が枡されるずルヌプを䞀床も回らないので、`$r` が未定矩になっおしたい、
+`implode()` に枡すずころで゚ラヌになる。
+それを防ぐために `$r ?? []` を䜿っおいる。
+
+もし 0 が枡されたケヌスを無芖するなら、これが䞍芁になるので 4 バむト瞮む。
+
+{#put-text-outside-php-tag}
+## PHP タグの倖に文字列を眮く
+
+PHP では、`&lt;?php` `?&gt;` で囲われた郚分の倖偎にある文字列は、そのたた出力される。
+今回のケヌスでは、先頭ず末尟に必ず `[` ず `]` を出力するので、そのたた曞いおやればよい。
+
+{#outro}
+# おわりに
+
+最埌になりたしたが、 [めもりヌ](https://twitter.com/m3m0r7) さん、楜しい問題をありがずうございたした。
diff --git a/vhosts/blog/content/posts/2022-08-27/php-conference-okinawa-code-golf.ndoc b/vhosts/blog/content/posts/2022-08-27/php-conference-okinawa-code-golf.ndoc
deleted file mode 100644
index 056ac438..00000000
--- a/vhosts/blog/content/posts/2022-08-27/php-conference-okinawa-code-golf.ndoc
+++ /dev/null
@@ -1,119 +0,0 @@
----
-[article]
-uuid = "bb71bb5d-361b-44cb-9753-81d14583d860"
-title = "PHP カンファレンス沖瞄で出題されたコヌドゎルフの問題を解いおみた"
-description = "PHP カンファレンス沖瞄の懇芪䌚 LT で出題されたコヌドゎルフの問題を解いおみた。"
-tags = [
- "conference",
- "php",
- "phpconokinawa",
-]
-
-[[article.revisions]]
-date = "2022-08-27"
-remark = "公開"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- 本日 <a href="https://phpcon.okinawa.jp/">PHP カンファレンス沖瞄 2022</a> が開催された (らしい)。
- </p>
- <p>
- カンファレンスには参加できなかったものの、懇芪䌚の LT で出題されたコヌドゎルフの問題が Twitter に流れおきたので、解いおみた。
- </p>
- <ul>
- <li>ツむヌト: https://twitter.com/m3m0r7/status/1563397620231712772</li>
- <li>スラむド: https://speakerdeck.com/memory1994/php-conference-okinawa-2022-extra?slide=3</li>
- </ul>
- </section>
- <section id="solution">
- <h>è§£</h>
- <p>
- 现かいレギュレヌションは䞍明だったので、勝手に定めた。
- </p>
- <ul>
- <li>コマンドラむン匕数の第1匕数で受けずる</li>
- <li>結果は暙準出力に出す</li>
- <li>コンマの盎埌にはスペヌスを1぀眮く</li>
- <li>末尟コンマは犁止</li>
- <li>数字でないものは入っおこないものずする</li>
- <li>負数は入っおこないものずする</li>
- </ul>
- <p>
- 曞いたものがこちら:
- </p>
- <codeblock language="php">
- <![CDATA[
- [<?php $n=$argv[1];foreach([1e4,5e3,2e3,1e3,500,100,50,10,5,1]as$x)for(;$n>=$x;$n-=$x)$r[]=$x;echo implode(', ',$r??[]);?>]
- ]]>
- </codeblock>
- <p>
- しめお 123 バむトずなった (末尟改行を含めずにカりント)。
- </p>
- <p>
- こちらは改行ずスペヌスを远加したバヌゞョン:
- </p>
- <codeblock language="php">
- <![CDATA[
- [<?php
-
- $n = $argv[1];
- foreach ([1e4, 5e3, 2e3, 1e3, 500, 100, 50, 10, 5, 1] as $x)
- for (; $n >= $x; $n -= $x)
- $r[] = $x;
- echo implode(', ', $r ?? []);
-
- ?>]
- ]]>
- </codeblock>
- </section>
- <section id="techniques">
- <h>䜿甚したテクニック</h>
- <section id="exponential-notation">
- <h>指数衚蚘</h>
- <p>
- 割ず倚くの蚀語のゎルフで䜿えるテクニック。
- <code>e</code> を甚いた指数衚蚘で、倧きな数を短く衚す。
- このコヌドでは <code>10000</code>、<code>5000</code>、<code>2000</code>、<code>1000</code> を指数衚蚘しおいる。
- </p>
- </section>
- <section id="shorten-loop">
- <h>foreach や for の䞭身を1぀の文に</h>
- <p>
- <code>foreach</code>、<code>for</code>、<code>if</code> などの埌ろには、
- 通垞 <code>{</code> を続けお耇数の文を連ねるが、䞭身の文を1぀にしおしたえば、<code>{</code> ず <code>}</code> を省略できる。
- C蚀語などでも䜿える。
- </p>
- </section>
- <section id="omit-initialization">
- <h>$r に初期倀を入れない</h>
- <p>
- PHP では、<code>$r[] = ......</code> のような配列の末尟に远加する匏を実行したずき、
- <code>$r</code> が未定矩だった堎合は <code>$r</code> を勝手に定矩しお空の配列で初期化しおくれる。
- これを利甚するず、<code>$r = [];</code> のような初期化が䞍芁になる。
- </p>
- <p>
- ただし、プログラムに 0 が枡されるずルヌプを䞀床も回らないので、<code>$r</code> が未定矩になっおしたい、
- <code>implode()</code> に枡すずころで゚ラヌになる。
- それを防ぐために <code>$r ?? []</code> を䜿っおいる。
- </p>
- <p>
- もし 0 が枡されたケヌスを無芖するなら、これが䞍芁になるので 4 バむト瞮む。
- </p>
- </section>
- <section id="put-text-outside-php-tag">
- <h>PHP タグの倖に文字列を眮く</h>
- <p>
- PHP では、<code>&lt;?php</code> <code>?&gt;</code> で囲われた郚分の倖偎にある文字列は、そのたた出力される。
- 今回のケヌスでは、先頭ず末尟に必ず <code>[</code> ず <code>]</code> を出力するので、そのたた曞いおやればよい。
- </p>
- </section>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- 最埌になりたしたが、<a href="https://twitter.com/m3m0r7">めもりヌ</a>さん、楜しい問題をありがずうございたした。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2022-08-31/support-for-communty-is-employee-benefits.dj b/vhosts/blog/content/posts/2022-08-31/support-for-communty-is-employee-benefits.dj
new file mode 100644
index 00000000..1ba5891b
--- /dev/null
+++ b/vhosts/blog/content/posts/2022-08-31/support-for-communty-is-employee-benefits.dj
@@ -0,0 +1,52 @@
+---
+[article]
+uuid = "cd16debe-8077-4edf-aec0-b1d45955a0e2"
+title = "匊瀟の PHP Foundation ぞの寄付に寄せお"
+description = "先日、私の勀めるデゞタルサヌカス株匏䌚瀟が、PHP Foundation ぞ寄付をおこないたした。本件を瀟内でし぀こく掚進した1人ずしお、掚進の理由等を曞き残しおおきたす。"
+tags = []
+
+[[article.revisions]]
+date = "2022-08-31"
+remark = "公開"
+---
+{#intro}
+# はじめに
+
+*泚: これは私個人の意芋であり、所属する組織を代衚するものではありたせん。*
+
+先日、私の勀める [デゞタルサヌカス株匏䌚瀟](https://www.dgcircus.com/) が
+[PHP Foundation](https://opencollective.com/phpfoundation) ぞ $2,000 の寄付をおこないたした。
+
+蚘事: https://www.dgcircus.com/news/581
+
+本件を瀟内でし぀こく掚進した1人ずしお、掚進の理由等を曞き残しおおきたす。
+
+{#why}
+# なぜ
+
+組織ずしおの寄付理由は前掲した蚘事に譲るずしお、ここでは、私が瀟内でこの件を掚進した理由に぀いお曞くこずにしたす。
+
+圓時の考えを端的にたずめた瀟内チャットの投皿があったので、それを匕甚したす:
+
+> 結局これを通したい (私の䞭での) 最倧の理由が、「自分の勀める䌚瀟が、これをやる䌚瀟であっおほしい」ずいうのがあり、
+> ↑にしおも、感情ベヌスの理由しか出せおいないずいうのが説埗力に欠けおいる理由なのだず思いたすが、
+> 寄付の報告が流れおきたり、OSS のフリヌラむドの話が流れおきたりするたびに、自尊心が毀損される、ずいうか
+> (これは倧袈裟すぎる衚珟で、実際にはそこたで明確に傷぀いおいるわけではありたせんが)。
+>
+> 远蚘: 「肩身が狭くなる」ずいうのがより適切でした。
+
+※文䞭の「↑にしおも」は、ここに茉せおいない別の投皿を指しおいたす。
+
+OSS を金銭的に支揎したり、技術カンファレンスぞ協賛したり
+(あるいは [CTO](https://twitter.com/tomzoh) がカンファレンスを幎2で䞻催したり:
+[iOSDC](https://iosdc.jp) [PHPerKaigi](https://phperkaigi.jp) )
+ずいった行為は、コミュニティぞの貢献であるず同時に、瀟員に察する粟神的犏利厚生でもあるず蚀えるでしょう (知らんけど)。
+これらは、技術や技術者を倧切にする組織である、ずいうこずの、察倖的にも察内的にも匷力なメッセヌゞなのです。
+
+以䞊が、私が瀟内で寄付の件を進めた (かなり私的な) 理由です。
+
+{#outro}
+# おわりに
+
+最終的に瀟ずしおの寄付たで挕ぎ着けられたのは、もちろん私の力ではなく圹員の方々の決定によるものです。
+この堎を借りお感謝申し䞊げたす。
diff --git a/vhosts/blog/content/posts/2022-08-31/support-for-communty-is-employee-benefits.ndoc b/vhosts/blog/content/posts/2022-08-31/support-for-communty-is-employee-benefits.ndoc
deleted file mode 100644
index cbc99969..00000000
--- a/vhosts/blog/content/posts/2022-08-31/support-for-communty-is-employee-benefits.ndoc
+++ /dev/null
@@ -1,69 +0,0 @@
----
-[article]
-uuid = "cd16debe-8077-4edf-aec0-b1d45955a0e2"
-title = "匊瀟の PHP Foundation ぞの寄付に寄せお"
-description = "先日、私の勀めるデゞタルサヌカス株匏䌚瀟が、PHP Foundation ぞ寄付をおこないたした。本件を瀟内でし぀こく掚進した1人ずしお、掚進の理由等を曞き残しおおきたす。"
-tags = []
-
-[[article.revisions]]
-date = "2022-08-31"
-remark = "公開"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- <strong>泚: これは私個人の意芋であり、所属する組織を代衚するものではありたせん。</strong>
- </p>
- <p>
- 先日、私の勀める <a href="https://www.dgcircus.com/">デゞタルサヌカス株匏䌚瀟</a> が
- <a href="https://opencollective.com/phpfoundation">PHP Foundation</a> ぞ $2,000 の寄付をおこないたした。
- </p>
- <p>
- 蚘事: https://www.dgcircus.com/news/581
- </p>
- <p>
- 本件を瀟内でし぀こく掚進した1人ずしお、掚進の理由等を曞き残しおおきたす。
- </p>
- </section>
- <section id="why">
- <h>なぜ</h>
- <p>
- 組織ずしおの寄付理由は前掲した蚘事に譲るずしお、ここでは、私が瀟内でこの件を掚進した理由に぀いお曞くこずにしたす。
- </p>
- <p>
- 圓時の考えを端的にたずめた瀟内チャットの投皿があったので、それを匕甚したす:
- </p>
- <blockquote>
- <p>
- 結局これを通したい (私の䞭での) 最倧の理由が、「自分の勀める䌚瀟が、これをやる䌚瀟であっおほしい」ずいうのがあり、
- ↑にしおも、感情ベヌスの理由しか出せおいないずいうのが説埗力に欠けおいる理由なのだず思いたすが、
- 寄付の報告が流れおきたり、OSS のフリヌラむドの話が流れおきたりするたびに、自尊心が毀損される、ずいうか
- (これは倧袈裟すぎる衚珟で、実際にはそこたで明確に傷぀いおいるわけではありたせんが)。
- </p>
- <p>
- 远蚘: 「肩身が狭くなる」ずいうのがより適切でした。
- </p>
- </blockquote>
- <p>
- ※文䞭の「↑にしおも」は、ここに茉せおいない別の投皿を指しおいたす。
- </p>
- <p>
- OSS を金銭的に支揎したり、技術カンファレンスぞ協賛したり
- (あるいは <a href="https://twitter.com/tomzoh">CTO</a> がカンファレンスを幎2で䞻催したり:
- <a href="https://iosdc.jp">iOSDC</a> <a href="https://phperkaigi.jp">PHPerKaigi</a>)
- ずいった行為は、コミュニティぞの貢献であるず同時に、瀟員に察する粟神的犏利厚生でもあるず蚀えるでしょう (知らんけど)。
- これらは、技術や技術者を倧切にする組織である、ずいうこずの、察倖的にも察内的にも匷力なメッセヌゞなのです。
- </p>
- <p>
- 以䞊が、私が瀟内で寄付の件を進めた (かなり私的な) 理由です。
- </p>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- 最終的に瀟ずしおの寄付たで挕ぎ着けられたのは、もちろん私の力ではなく圹員の方々の決定によるものです。
- この堎を借りお感謝申し䞊げたす。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line.dj b/vhosts/blog/content/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line.dj
new file mode 100644
index 00000000..c23341dc
--- /dev/null
+++ b/vhosts/blog/content/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line.dj
@@ -0,0 +1,617 @@
+---
+[article]
+uuid = "42f0b29b-1e44-4dbe-9864-69abe3bb1e6e"
+title = "【PHP】 fizzbuzz を曞く。1行あたり2文字で。"
+description = "PHP で fizzbuzz を曞いた。ただし、1行あたりに䜿える文字数は2文字たで。"
+tags = [
+ "php",
+]
+
+[[article.revisions]]
+date = "2022-09-28"
+remark = "公開"
+
+[[article.revisions]]
+date = "2022-09-29"
+remark = "小さな文蚀の修正・倉曎"
+---
+{#intro}
+# 蚘事の構成に぀いお
+
+この蚘事は、普通の fizzbuzz を埐々に倉圢しお最終圢にしおいく、ずいう構成で曞かれおいる。
+最終圢を芋おどのような仕組みで動いおいるのか解読しおから解説を読みたい、ずいうかたがいれば、
+[このペヌゞ](https://gist.github.com/nsfisis/04c227d5a419867472a0b23a83ad2919#file-fizzbuzz-php-2-letters-per-line-and-supports-php-8-x-without-warnings)
+に゜ヌスコヌドがあるので、そちらを先に芋おほしい。
+
+{#regulations}
+# レギュレヌション
+
+PHP で、次のような制玄の䞋に fizzbuzz を曞いた。
+
+* 1行あたりの文字数は2文字たでに収めるこず (ただし `&lt;?php` タグは陀く)
+
+ * 厳密な定矩: `&lt;?php` タグ以降の゜ヌスコヌドが、2 byte ごずにラむンフィヌド (LF) で区切られるこず
+
+* スペヌスやタブを䜿甚しないこず
+* ルヌプのアンロヌルをしないこず
+
+ * 100 回ルヌプの代わりに 100 回コヌドをコピペ、ずいうのは犁止
+
+* PHP 7.4〜8.1 で動䜜するこず
+* 実行時に Notice や Warning が出ないこず
+* 暙準的なむンストヌル構成の PHP で実珟できるこず (デフォルトで有効になっおいない拡匵等を䜿わないこず)
+
+備考: PHP には `short_open_tag` ずいうオプションがあり、
+これを有効にするずファむル冒頭の `&lt;?php` の代わりに `&lt;?`
+を䜿うこずができ、文字どおり1行2文字で曞ける。
+ただ、このオプションはデフォルト off になっおいる環境が倚いようなので、今回は䜿わないこずにした。
+
+{#problems}
+# 䞻な障害
+
+1行あたりの文字数など、適圓に改行を挟めばいいだけではないのか
+
+特に、C蚀語でこのような詊みをおこなったこずがあるかたならそう思うだろう。事実、Cでのこの制玄はほずんど無意味に等しい。
+
+```c
+#\
+i\
+n\
+c\
+l\
+u\
+d\
+e\
+<\
+s\
+t\
+d\
+i\
+o\
+.\
+h\
+>\
+/*
+*/
+i\
+n\
+t\
+/*
+*/
+m\
+a\
+i\
+n(
+){
+f\
+o\
+r(
+i\
+n\
+t\
+/*
+*/
+i=
+1;
+i<
+1\
+0\
+0;
+i\
++\
++)
+if
+(i
+%\
+15
+==
+0)
+p\
+r\
+i\
+n\
+t\
+f(
+"\
+F\
+i\
+z\
+z\
+B\
+u\
+z\
+z\
+%\
+c\
+",
+10
+);
+
+/* あずは同じように普通のプログラムを倉圢するだけなので省略 */
+```
+
+バックスラッシュを䜿った行継続がトヌクンを区切らない、ずいうのがポむントだ。
+
+さお、PHP ではそもそもバックスラッシュを行継続に䜿うこずができない。
+これにより、「3文字以䞊からなるトヌクンが䞀切䜿えない」ずいう制玄が課される。
+䟋えば、`echo` で出力するこずや、`for` でルヌプするこず、
+`new` でむンスタンスを生成するこずができない。
+特に、出力は fizzbuzz をどんなアルゎリズムで実装しようずおこなわなければならないので、できないのは臎呜的である。
+
+圓然、名前が3文字以䞊ある関数も䜿えない。なお、暙準 PHP の範囲内においお、名前が 2文字以䞋の関数は以䞋のずおりである:
+
+* `_`: `gettext` の゚むリアス
+* `dl`: 拡匵モゞュヌルをロヌドする
+* `pi`: 円呚率を返す
+
+(環境によっお倚少は倉わるかも)
+
+2文字の関数を定矩したくった拡匵モゞュヌルを甚意しおおいお `dl()` で読み蟌む行為は、レギュレヌションで定めた
+
+> * 暙準的なむンストヌル構成の PHP で実珟できるこず (デフォルトで有効になっおいない拡匵等を䜿わないこず)
+
+に反する (ずいうより、「それだずおもしろくもなんずもないので、このルヌルを足した」ずいうのが正しい)。
+
+たた、2文字だず文字列がたずもに曞けないのも蟛い。`''` だけで2文字䜿うので、
+「1文字の文字列リテラル」ずいうものを曞くこずができない。PHP では文字列リテラル䞭に生の改行が曞けるので
+
+```php
+$a
+='
+a'
+;;
+```
+
+ずするず `$a` は `"\na"` になるのだが、䜙蚈な改行が入っおしたう。
+
+これらの障害をどのように乗り越えるのか、次節から芋おいく。
+
+{#commentary}
+# 解説
+
+{#normal-fizzbuzz}
+## 普通の (?) fizzbuzz
+
+たずは普通に曞くずしよう。
+
+```php
+<?php
+
+for ($i = 1; $i < 100; $i++) {
+ echo (($i % 3 ? '' : 'Fizz') . ($i % 5 ? '' : 'Buzz') ?: $i) . "\n";
+}
+```
+
+玠盎に曞いた fizzbuzz ずは蚀い難いが、このくらいは普通だずいうこずにしおおかないず、この先がやっおいられないので蚱しおほしい。
+
+{#remove-keywords}
+## `for` の排陀
+
+`for` は、3文字もある長いキヌワヌドである。
+こんなものは䜿えない。`array_` 系の関数を䜿っお、適圓に眮き換えるずしよう。
+
+```php
+<?php
+
+$s = range(1, 100);
+array_walk(
+$s,
+fn($i) =>
+printf((($i % 3 ? '' : 'Fizz') . ($i % 5 ? '' : 'Buzz') ?: $i) . "\n"),
+);
+```
+
+`array_walk` や `range`、`printf` ずいった
+`for` よりも長いトヌクンが珟れおしたったが、これは次節で盎すこずにする。
+なお、`echo` は文 (statement) であり匏 (expression) ではないので、匏である `printf` に眮き換えた。
+
+{#shorten-function-invocation}
+## 関数呌び出しの短瞮
+
+`range`、`array_walk`、`printf` は長すぎるのでどうにかせねばならない。
+ここで、PHP の可倉関数を䜿う。可倉関数ずは、関数名が文字列ずしお入った倉数を経由しお、関数を呌び出す機胜である。
+
+```php
+<?php
+
+$r = 'range';
+$w = 'array_walk';
+$p = 'printf';
+
+$s = $r(1, 100);
+$w(
+$s,
+fn($i) =>
+$p((($i % 3 ? '' : 'Fizz') . ($i % 5 ? '' : 'Buzz') ?: $i) . "\n"),
+);
+```
+
+これで関数を呌び出しおいる所は短くなった。
+では、`$r` や `$w` や `$p`、
+たた `'Fizz'` や `'Buzz'` はどうやっお 1 行 2 文字に収めるのか。
+次のテクニックぞ移ろう。
+
+{#incompatible-solution}
+## 䜙談: PHP 8.x で動䜜しなくおもいいなら
+
+今回䜿ったテクニックを説明する前に、䜙談ずしお、文字列リテラルの短瞮法ずしお今回採甚しなかったものを玹介する。
+
+> * PHP 7.4〜8.1 で動䜜するこず
+
+ずいうルヌルがない堎合、「未定矩の定数が評䟡された堎合、その定数の名前が倀になる」ずいう PHP 7.x たでの仕様が利甚できる。
+䟋えば、 `Fizz` ずいう文字列が欲しければ、次のようにする。
+
+```php
+$f
+=F
+.i
+.z
+.z
+;;
+```
+
+こうしお簡単に文字列を䜜れる。
+なお、この仕様は 7.x 時点でも譊告を受けるので、`@` 挔算子を䜿っお抑制しおやるずよい。
+
+```php
+$f
+=@
+F.
+@i
+.#
+@z
+.#
+@z
+;;
+```
+
+むしろ、このこずがわかっおいたからこそ PHP 8.x での動䜜を芁件に課したずころがある。
+
+{#shorten-string-literals}
+## 文字列リテラルの短瞮
+
+実際に䜿った手法の説明に移る。
+
+ずばり、文字列同士のビット挔算を䜿う。
+PHP では、文字列同士でビット挔算 (`&amp;`、`|`、`^`) をした堎合、
+文字列の各バむトごずに指定したビット挔算がなされ、それを結合したものが挔算結果ずなる。
+
+```php
+$a = "12345";
+$b = "world";
+
+// $a ^ $b は次のコヌドず同じ
+$result = '';
+for ($i = 0; $i < min(strlen($a), strlen($b)); $i++) {
+$result .= $a[$i] ^ $b[$i];
+}
+
+echo $result;
+// => F]AXQ
+```
+
+これを螏たえ、次のコヌドを芋おみよう。
+
+```php
+$x = "x\nOm\n";
+$y = "\nk!\no";
+$r = $x ^ $y;
+echo "$r\n";
+```
+
+実行するず、`range` が衚瀺される。
+さお、PHP では文字列リテラル䞭に生の改行を盎接曞いおもよいのだった (「䞻な障害」の節を参照のこず)。
+曞きかえおみよう。
+
+```php
+$x
+='x
+Om
+';
+$y
+='
+k!
+o'
+;
+
+$r = $x ^ $y;
+echo "$r\n";
+```
+
+さらに `#` を䜿っお適圓に調敎するず、次のようになる。
+
+```php
+$x
+=#
+'x
+Om
+';
+$y
+='
+k!
+o'
+;#
+$r
+=#
+$x
+^#
+$y
+;#
+
+echo "$r\n";
+```
+
+1行あたり2文字で、`range` ずいう文字列を生成するこずに成功した。
+他の必芁な文字列にも、同様の凊理をほどこす。
+
+備考: `Buzz` 䞭にある小文字の `u` は、このロゞックだず non-printable な文字になっおしたう。
+ここたでのテクニックを駆䜿すれば回避するのはそう難しくないので、考えおみおほしい。
+
+{#stretched-fizzbuzz}
+# 完成系
+
+完成したものがこちら。
+
+```php
+<?php
+
+$x
+=#
+'i
+S'
+;;
+$y
+='
+b!
+';
+$c
+=#
+$x
+^#
+$y
+;#
+$x
+=#
+'x
+Om
+';
+$y
+='
+k!
+o'
+;#
+$r
+=#
+$x
+^#
+$y
+;#
+$x
+=#
+'k
+Sk
+~}
+Ma
+';
+$y
+='
+x!
+s!
+k!
+';
+$w
+=#
+$x
+^#
+$y
+;#
+$x
+=#
+'z
+Hd
+G'
+;#
+$y
+='
+x!
+~!
+';
+$p
+=#
+$x
+^#
+$y
+;#
+$x
+=#
+'L
+[p
+';
+$y
+='
+c!
+';
+$f
+=#
+$x
+^#
+$y
+;#
+$x
+=#
+'H
+[p
+';
+$y
+='
+_!
+';
+$b
+=#
+$x
+^#
+$y
+;#
+$b
+[1
+]=
+$c
+(#
+13
+*9
+);
+$s
+=#
+$r
+(1
+,(
+10
+**
+2)
+);
+$w
+(#
+$s
+,#
+fn
+(#
+$i
+)#
+=>
+$p
+((
+(#
+$i
+%3
+?#
+''
+:#
+$f
+).
+(#
+$i
+%5
+?#
+''
+:#
+$b
+)?
+:#
+$i
+)#
+.'
+')
+);
+```
+
+{#outro}
+# 感想など
+
+PHP は、スクリプト蚀語の䞭だずシンタックスシュガヌが少ない (䜓感)。
+この挑戊は䞍可胜に思われたが、PHP マニュアルずにらめっこしおいたらなんずかなった。
+
+みんなもプログラムを现長くしよう。
+
+{#alternative-solution}
+# 䜙談2: 別解
+
+PHP では、バッククォヌトを䜿っおシェルを呌び出せる。
+これは `shell_exec` 関数ず等䟡である。
+さお、PHP ではバックスラッシュによる行継続が䜿えないず曞いたが、シェルでは䜿える
+(圓然だが、呌び出されるシェルに䟝存する。Bash なら倧䞈倫だろう。知らんけど)。
+
+```php
+<?php
+
+printf(`
+e\
+c\
+h\
+o\
+\
+1\
+2\
+3\
+`);
+```
+
+なお、ここでは簡単のため出力に `printf` をそのたた䜿っおいるが、
+実際には `printf` ずいう文字列を合成しお可倉関数で呌び出す。
+
+ただし、これでは
+
+> * スペヌスやタブを䜿甚しないこず
+
+に違反しおしたう。スペヌスが䜿えないず匕数ずコマンドを区切れない。これは困った。
+
+もうこれ以䞊は䞍可胜だず思っおいたのだが、この蚘事の執筆䞭に解決する方法を思い぀いたので茉せおおく。
+
+```php
+<?php
+
+$c = 'chr';
+
+${
+'_
+'}
+=#
+$c
+(#
+32
+).
+$c
+(#
+92
+);
+
+printf(`
+e\
+c\
+h\
+o\
+${
+'_
+'}
+1\
+2\
+3\
+`);
+```
+
+先皋ず同じく、`chr` や `printf` を生成する郚分は長くなるので省いた。
+
+```
+${
+'_
+'}
+```
+
+は倉数で、䞭にはスペヌスず゚スケヌプが入っおいる (`chr(32) . chr(92)`)。
+シェルに枡されおいる文字列は次のようになる。
+
+```
+e\
+c\
+h\
+o\
+\
+1\
+2\
+3\
+```
+
+これは、前掲したコマンドず同じだ。
+かくしお、スペヌスを陜に曞かずにシェルをおおよそ自由に扱えるようになった。
+Fizzbuzz のワンラむナヌくらいすぐ曞けるだろうから、あずはなんずかなるだろう (詊しおないけど)。
+
+ずいうこずでこれは別解ずいうこずにしおおく。
+
+ちなみに、PHP 8.2 からは、この蚘法で Warning が出るようになるようだ。
+
+```
+${
+'_
+'}
+```
+
+最新版で譊告が出るずいうのも矎しくないので、私ずしおは本線の解法を掚す。
diff --git a/vhosts/blog/content/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line.ndoc b/vhosts/blog/content/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line.ndoc
deleted file mode 100644
index f8b0d62e..00000000
--- a/vhosts/blog/content/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line.ndoc
+++ /dev/null
@@ -1,705 +0,0 @@
----
-[article]
-uuid = "42f0b29b-1e44-4dbe-9864-69abe3bb1e6e"
-title = "【PHP】 fizzbuzz を曞く。1行あたり2文字で。"
-description = "PHP で fizzbuzz を曞いた。ただし、1行あたりに䜿える文字数は2文字たで。"
-tags = [
- "php",
-]
-
-[[article.revisions]]
-date = "2022-09-28"
-remark = "公開"
-
-[[article.revisions]]
-date = "2022-09-29"
-remark = "小さな文蚀の修正・倉曎"
----
-<article>
- <section id="intro">
- <h>蚘事の構成に぀いお</h>
- <p>
- この蚘事は、普通の fizzbuzz を埐々に倉圢しお最終圢にしおいく、ずいう構成で曞かれおいる。
- 最終圢を芋おどのような仕組みで動いおいるのか解読しおから解説を読みたい、ずいうかたがいれば、
- <a href="https://gist.github.com/nsfisis/04c227d5a419867472a0b23a83ad2919#file-fizzbuzz-php-2-letters-per-line-and-supports-php-8-x-without-warnings">このペヌゞ</a>
- に゜ヌスコヌドがあるので、そちらを先に芋おほしい。
- </p>
- </section>
- <section id="regulations">
- <h>レギュレヌション</h>
- <p>
- PHP で、次のような制玄の䞋に fizzbuzz を曞いた。
- </p>
- <ul>
- <li>
- 1行あたりの文字数は2文字たでに収めるこず (ただし <code>&lt;?php</code> タグは陀く)
- <ul>
- <li>
- 厳密な定矩: <code>&lt;?php</code> タグ以降の゜ヌスコヌドが、2 byte ごずにラむンフィヌド (LF) で区切られるこず
- </li>
- </ul>
- </li>
- <li>スペヌスやタブを䜿甚しないこず</li>
- <li>
- ルヌプのアンロヌルをしないこず
- <ul>
- <li>100 回ルヌプの代わりに 100 回コヌドをコピペ、ずいうのは犁止</li>
- </ul>
- </li>
- <li>PHP 7.4〜8.1 で動䜜するこず</li>
- <li>実行時に Notice や Warning が出ないこず</li>
- <li>暙準的なむンストヌル構成の PHP で実珟できるこず (デフォルトで有効になっおいない拡匵等を䜿わないこず)</li>
- </ul>
- <p>
- 備考: PHP には <code>short_open_tag</code> ずいうオプションがあり、
- これを有効にするずファむル冒頭の <code>&lt;?php</code> の代わりに <code>&lt;?</code>
- を䜿うこずができ、文字どおり1行2文字で曞ける。
- ただ、このオプションはデフォルト off になっおいる環境が倚いようなので、今回は䜿わないこずにした。
- </p>
- </section>
- <section id="problems">
- <h>䞻な障害</h>
- <p>
- 1行あたりの文字数など、適圓に改行を挟めばいいだけではないのか
- </p>
- <p>
- 特に、C蚀語でこのような詊みをおこなったこずがあるかたならそう思うだろう。事実、Cでのこの制玄はほずんど無意味に等しい。
- </p>
- <codeblock language="c">
- <![CDATA[
- #\
- i\
- n\
- c\
- l\
- u\
- d\
- e\
- <\
- s\
- t\
- d\
- i\
- o\
- .\
- h\
- >\
- /*
- */
- i\
- n\
- t\
- /*
- */
- m\
- a\
- i\
- n(
- ){
- f\
- o\
- r(
- i\
- n\
- t\
- /*
- */
- i=
- 1;
- i<
- 1\
- 0\
- 0;
- i\
- +\
- +)
- if
- (i
- %\
- 15
- ==
- 0)
- p\
- r\
- i\
- n\
- t\
- f(
- "\
- F\
- i\
- z\
- z\
- B\
- u\
- z\
- z\
- %\
- c\
- ",
- 10
- );
-
- /* あずは同じように普通のプログラムを倉圢するだけなので省略 */
- ]]>
- </codeblock>
- <p>
- バックスラッシュを䜿った行継続がトヌクンを区切らない、ずいうのがポむントだ。
- </p>
- <p>
- さお、PHP ではそもそもバックスラッシュを行継続に䜿うこずができない。
- これにより、「3文字以䞊からなるトヌクンが䞀切䜿えない」ずいう制玄が課される。
- 䟋えば、<code>echo</code> で出力するこずや、<code>for</code> でルヌプするこず、
- <code>new</code> でむンスタンスを生成するこずができない。
- 特に、出力は fizzbuzz をどんなアルゎリズムで実装しようずおこなわなければならないので、できないのは臎呜的である。
- </p>
- <p>
- 圓然、名前が3文字以䞊ある関数も䜿えない。なお、暙準 PHP の範囲内においお、名前が 2文字以䞋の関数は以䞋のずおりである:
- </p>
- <ul>
- <li>
- <code>_</code>: <code>gettext</code> の゚むリアス
- </li>
- <li>
- <code>dl</code>: 拡匵モゞュヌルをロヌドする
- </li>
- <li>
- <code>pi</code>: 円呚率を返す
- </li>
- </ul>
- <p>
- (環境によっお倚少は倉わるかも)
- </p>
- <p>
- 2文字の関数を定矩したくった拡匵モゞュヌルを甚意しおおいお <code>dl()</code> で読み蟌む行為は、レギュレヌションで定めた
- </p>
- <blockquote>
- <ul>
- <li>暙準的なむンストヌル構成の PHP で実珟できるこず (デフォルトで有効になっおいない拡匵等を䜿わないこず)</li>
- </ul>
- </blockquote>
- <p>
- に反する (ずいうより、「それだずおもしろくもなんずもないので、このルヌルを足した」ずいうのが正しい)。
- </p>
- <p>
- たた、2文字だず文字列がたずもに曞けないのも蟛い。<code>''</code> だけで2文字䜿うので、
- 「1文字の文字列リテラル」ずいうものを曞くこずができない。PHP では文字列リテラル䞭に生の改行が曞けるので
- </p>
- <codeblock language="php">
- <![CDATA[
- $a
- ='
- a'
- ;;
- ]]>
- </codeblock>
- <p>
- ずするず <code>$a</code> は <code>"\na"</code> になるのだが、䜙蚈な改行が入っおしたう。
- </p>
- <p>
- これらの障害をどのように乗り越えるのか、次節から芋おいく。
- </p>
- </section>
- <section id="commentary">
- <h>解説</h>
- <section id="normal-fizzbuzz">
- <h>普通の (?) fizzbuzz</h>
- <p>
- たずは普通に曞くずしよう。
- </p>
- <codeblock language="php">
- <![CDATA[
- <?php
-
- for ($i = 1; $i < 100; $i++) {
- echo (($i % 3 ? '' : 'Fizz') . ($i % 5 ? '' : 'Buzz') ?: $i) . "\n";
- }
- ]]>
- </codeblock>
- <p>
- 玠盎に曞いた fizzbuzz ずは蚀い難いが、このくらいは普通だずいうこずにしおおかないず、この先がやっおいられないので蚱しおほしい。
- </p>
- </section>
- <section id="remove-keywords">
- <h><code>for</code> の排陀</h>
- <p>
- <code>for</code> は、3文字もある長いキヌワヌドである。
- こんなものは䜿えない。<code>array_</code> 系の関数を䜿っお、適圓に眮き換えるずしよう。
- </p>
- <codeblock language="php">
- <![CDATA[
- <?php
-
- $s = range(1, 100);
- array_walk(
- $s,
- fn($i) =>
- printf((($i % 3 ? '' : 'Fizz') . ($i % 5 ? '' : 'Buzz') ?: $i) . "\n"),
- );
- ]]>
- </codeblock>
- <p>
- <code>array_walk</code> や <code>range</code>、<code>printf</code> ずいった
- <code>for</code> よりも長いトヌクンが珟れおしたったが、これは次節で盎すこずにする。
- なお、<code>echo</code> は文 (statement) であり匏 (expression) ではないので、匏である <code>printf</code> に眮き換えた。
- </p>
- </section>
- <section id="shorten-function-invocation">
- <h>関数呌び出しの短瞮</h>
- <p>
- <code>range</code>、<code>array_walk</code>、<code>printf</code> は長すぎるのでどうにかせねばならない。
- ここで、PHP の可倉関数を䜿う。可倉関数ずは、関数名が文字列ずしお入った倉数を経由しお、関数を呌び出す機胜である。
- </p>
- <codeblock language="php">
- <![CDATA[
- <?php
-
- $r = 'range';
- $w = 'array_walk';
- $p = 'printf';
-
- $s = $r(1, 100);
- $w(
- $s,
- fn($i) =>
- $p((($i % 3 ? '' : 'Fizz') . ($i % 5 ? '' : 'Buzz') ?: $i) . "\n"),
- );
- ]]>
- </codeblock>
- <p>
- これで関数を呌び出しおいる所は短くなった。
- では、<code>$r</code> や <code>$w</code> や <code>$p</code>、
- たた <code>'Fizz'</code> や <code>'Buzz'</code> はどうやっお 1 行 2 文字に収めるのか。
- 次のテクニックぞ移ろう。
- </p>
- </section>
- <section id="incompatible-solution">
- <h>䜙談: PHP 8.x で動䜜しなくおもいいなら</h>
- <p>
- 今回䜿ったテクニックを説明する前に、䜙談ずしお、文字列リテラルの短瞮法ずしお今回採甚しなかったものを玹介する。
- </p>
- <blockquote>
- <ul>
- <li>PHP 7.4〜8.1 で動䜜するこず</li>
- </ul>
- </blockquote>
- <p>
- ずいうルヌルがない堎合、「未定矩の定数が評䟡された堎合、その定数の名前が倀になる」ずいう PHP 7.x たでの仕様が利甚できる。
- 䟋えば、 <code>Fizz</code> ずいう文字列が欲しければ、次のようにする。
- </p>
- <codeblock language="php">
- <![CDATA[
- $f
- =F
- .i
- .z
- .z
- ;;
- ]]>
- </codeblock>
- <p>
- こうしお簡単に文字列を䜜れる。
- なお、この仕様は 7.x 時点でも譊告を受けるので、<code>@</code> 挔算子を䜿っお抑制しおやるずよい。
- </p>
- <codeblock language="php">
- <![CDATA[
- $f
- =@
- F.
- @i
- .#
- @z
- .#
- @z
- ;;
- ]]>
- </codeblock>
- <p>
- むしろ、このこずがわかっおいたからこそ PHP 8.x での動䜜を芁件に課したずころがある。
- </p>
- </section>
- <section id="shorten-string-literals">
- <h>文字列リテラルの短瞮</h>
- <p>
- 実際に䜿った手法の説明に移る。
- </p>
- <p>
- ずばり、文字列同士のビット挔算を䜿う。
- PHP では、文字列同士でビット挔算 (<code>&amp;</code>、<code>|</code>、<code>^</code>) をした堎合、
- 文字列の各バむトごずに指定したビット挔算がなされ、それを結合したものが挔算結果ずなる。
- </p>
- <codeblock language="php">
- <![CDATA[
- $a = "12345";
- $b = "world";
-
- // $a ^ $b は次のコヌドず同じ
- $result = '';
- for ($i = 0; $i < min(strlen($a), strlen($b)); $i++) {
- $result .= $a[$i] ^ $b[$i];
- }
-
- echo $result;
- // => F]AXQ
- ]]>
- </codeblock>
- <p>
- これを螏たえ、次のコヌドを芋おみよう。
- </p>
- <codeblock language="php">
- <![CDATA[
- $x = "x\nOm\n";
- $y = "\nk!\no";
- $r = $x ^ $y;
- echo "$r\n";
- ]]>
- </codeblock>
- <p>
- 実行するず、<code>range</code> が衚瀺される。
- さお、PHP では文字列リテラル䞭に生の改行を盎接曞いおもよいのだった (「䞻な障害」の節を参照のこず)。
- 曞きかえおみよう。
- </p>
- <codeblock language="php">
- <![CDATA[
- $x
- ='x
- Om
- ';
- $y
- ='
- k!
- o'
- ;
-
- $r = $x ^ $y;
- echo "$r\n";
- ]]>
- </codeblock>
- <p>
- さらに <code>#</code> を䜿っお適圓に調敎するず、次のようになる。
- </p>
- <codeblock language="php">
- <![CDATA[
- $x
- =#
- 'x
- Om
- ';
- $y
- ='
- k!
- o'
- ;#
- $r
- =#
- $x
- ^#
- $y
- ;#
-
- echo "$r\n";
- ]]>
- </codeblock>
- <p>
- 1行あたり2文字で、<code>range</code> ずいう文字列を生成するこずに成功した。
- 他の必芁な文字列にも、同様の凊理をほどこす。
- </p>
- <p>
- 備考: <code>Buzz</code> 䞭にある小文字の <code>u</code> は、このロゞックだず non-printable な文字になっおしたう。
- ここたでのテクニックを駆䜿すれば回避するのはそう難しくないので、考えおみおほしい。
- </p>
- </section>
- </section>
- <section id="stretched-fizzbuzz">
- <h>完成系</h>
- <p>
- 完成したものがこちら。
- </p>
- <codeblock language="php">
- <![CDATA[
- <?php
-
- $x
- =#
- 'i
- S'
- ;;
- $y
- ='
- b!
- ';
- $c
- =#
- $x
- ^#
- $y
- ;#
- $x
- =#
- 'x
- Om
- ';
- $y
- ='
- k!
- o'
- ;#
- $r
- =#
- $x
- ^#
- $y
- ;#
- $x
- =#
- 'k
- Sk
- ~}
- Ma
- ';
- $y
- ='
- x!
- s!
- k!
- ';
- $w
- =#
- $x
- ^#
- $y
- ;#
- $x
- =#
- 'z
- Hd
- G'
- ;#
- $y
- ='
- x!
- ~!
- ';
- $p
- =#
- $x
- ^#
- $y
- ;#
- $x
- =#
- 'L
- [p
- ';
- $y
- ='
- c!
- ';
- $f
- =#
- $x
- ^#
- $y
- ;#
- $x
- =#
- 'H
- [p
- ';
- $y
- ='
- _!
- ';
- $b
- =#
- $x
- ^#
- $y
- ;#
- $b
- [1
- ]=
- $c
- (#
- 13
- *9
- );
- $s
- =#
- $r
- (1
- ,(
- 10
- **
- 2)
- );
- $w
- (#
- $s
- ,#
- fn
- (#
- $i
- )#
- =>
- $p
- ((
- (#
- $i
- %3
- ?#
- ''
- :#
- $f
- ).
- (#
- $i
- %5
- ?#
- ''
- :#
- $b
- )?
- :#
- $i
- )#
- .'
- ')
- );
- ]]>
- </codeblock>
- </section>
- <section id="outro">
- <h>感想など</h>
- <p>
- PHP は、スクリプト蚀語の䞭だずシンタックスシュガヌが少ない (䜓感)。
- この挑戊は䞍可胜に思われたが、PHP マニュアルずにらめっこしおいたらなんずかなった。
- </p>
- <p>
- みんなもプログラムを现長くしよう。
- </p>
- </section>
- <section id="alternative-solution">
- <h>䜙談2: 別解</h>
- <p>
- PHP では、バッククォヌトを䜿っおシェルを呌び出せる。
- これは <code>shell_exec</code> 関数ず等䟡である。
- さお、PHP ではバックスラッシュによる行継続が䜿えないず曞いたが、シェルでは䜿える
- (圓然だが、呌び出されるシェルに䟝存する。Bash なら倧䞈倫だろう。知らんけど)。
- </p>
- <codeblock language="php">
- <![CDATA[
- <?php
-
- printf(`
- e\
- c\
- h\
- o\
- \
- 1\
- 2\
- 3\
- `);
- ]]>
- </codeblock>
- <p>
- なお、ここでは簡単のため出力に <code>printf</code> をそのたた䜿っおいるが、
- 実際には <code>printf</code> ずいう文字列を合成しお可倉関数で呌び出す。
- </p>
- <p>
- ただし、これでは
- </p>
- <blockquote>
- <ul>
- <li>スペヌスやタブを䜿甚しないこず</li>
- </ul>
- </blockquote>
- <p>
- に違反しおしたう。スペヌスが䜿えないず匕数ずコマンドを区切れない。これは困った。
- </p>
- <p>
- もうこれ以䞊は䞍可胜だず思っおいたのだが、この蚘事の執筆䞭に解決する方法を思い぀いたので茉せおおく。
- </p>
- <codeblock language="php">
- <![CDATA[
- <?php
-
- $c = 'chr';
-
- ${
- '_
- '}
- =#
- $c
- (#
- 32
- ).
- $c
- (#
- 92
- );
-
- printf(`
- e\
- c\
- h\
- o\
- ${
- '_
- '}
- 1\
- 2\
- 3\
- `);
- ]]>
- </codeblock>
- <p>
- 先皋ず同じく、<code>chr</code> や <code>printf</code> を生成する郚分は長くなるので省いた。
- </p>
- <codeblock>
- <![CDATA[
- ${
- '_
- '}
- ]]>
- </codeblock>
- <p>
- は倉数で、䞭にはスペヌスず゚スケヌプが入っおいる (<code>chr(32) . chr(92)</code>)。
- シェルに枡されおいる文字列は次のようになる。
- </p>
- <codeblock>
- <![CDATA[
- e\
- c\
- h\
- o\
- \
- 1\
- 2\
- 3\
- ]]>
- </codeblock>
- <p>
- これは、前掲したコマンドず同じだ。
- かくしお、スペヌスを陜に曞かずにシェルをおおよそ自由に扱えるようになった。
- Fizzbuzz のワンラむナヌくらいすぐ曞けるだろうから、あずはなんずかなるだろう (詊しおないけど)。
- </p>
- <p>
- ずいうこずでこれは別解ずいうこずにしおおく。
- </p>
- <p>
- ちなみに、PHP 8.2 からは、この蚘法で Warning が出るようになるようだ。
- </p>
- <codeblock>
- <![CDATA[
- ${
- '_
- '}
- ]]>
- </codeblock>
- <p>
- 最新版で譊告が出るずいうのも矎しくないので、私ずしおは本線の解法を掚す。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1.dj b/vhosts/blog/content/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1.dj
new file mode 100644
index 00000000..8567c711
--- /dev/null
+++ b/vhosts/blog/content/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1.dj
@@ -0,0 +1,154 @@
+---
+[article]
+uuid = "46e0d5db-b17e-464c-a723-8c3e01af7d1d"
+title = "PHPerKaigi 2023: ボツになったトヌクン問題 その 1"
+description = "来幎の PHPerKaigi 2023 でデゞタルサヌカス株匏䌚瀟から出題予定のトヌクン問題のうち、ボツになった問題を公開する (その 1)。"
+tags = [
+ "php",
+ "phperkaigi",
+]
+
+[[article.revisions]]
+date = "2022-10-23"
+remark = "公開"
+---
+{#intro}
+# はじめに
+
+2023 幎 3 月 23 日から 25 日にかけお開催予定 (蚘事執筆時点) の、
+[PHPerKaigi 2023](https://phperkaigi.jp/2023/) においお、
+昚幎ず同様に、匊瀟 [デゞタルサヌカス株匏䌚瀟](https://www.dgcircus.com/) から、
+トヌクン問題を出題予定である。
+
+昚幎のトヌクン問題の蚘事はこちら: [PHPerKaigi 2022 トヌクン問題の解説](/posts/2022-04-09/phperkaigi-2022-tokens)
+
+すでに 2023 幎甚の問題は䜜成枈みであるが、その制䜜過皋の䞭でいく぀かボツ問ができた。
+せっかくなので、PHPerKaigi 開催を埅぀間に玹介しようず思う。
+
+10 月から 2 月たで、毎月 1 蚘事ず぀公開しおいく予定 (忘れおいなければ)。
+
+{#quiz}
+# 問題
+
+泚意: これはボツ問なので、埗られたトヌクンを PHPerKaigi で入力しおもポむントにはならない。
+
+```php
+<?php
+
+$π = $argv[1] ?? null;
+if ($π === null) {
+ exit('No input.');
+}
+$π = trim($π);
+if (!is_numeric($π)) {
+ exit('Invalid input.');
+}
+
+$s = implode(array_map(chr(...), str_split($π, 2)));
+
+preg_match('/(\x23.+?) /', $s, $m);
+$t = $m[1] ?? '';
+
+if (md5($t) === '056e831a4146bf123e8ea16613303d2e') {
+ echo "Token: {$t}\n";
+} else {
+ echo "Failed.\n";
+}
+```
+
+{#how-to-obtain-token}
+# トヌクン入手方法
+
+゜ヌスを芋るずわかるずおり、`$argv[1]` を参照しおいる。
+それを `$π` なる倉数に代入しおいるので、円呚率を枡しおみる。
+
+```shell-session
+$ php Q.php 3.14
+Failed.
+```
+
+倱敗しおしたった。粟床を䞊げおみる。
+
+```shell-session
+$ php Q.php 3.1415
+Failed.
+```
+
+だめだった。これを成功するたで繰り返す。
+
+最初にトヌクンが埗られるのは、小数点以䞋 16 桁目たで入力したずきで、こうなる。
+
+```shell-session
+$ php Q.php 3.1415926535897932
+Token: #YO
+```
+
+めでたくトヌクン「`#YO`」が手に入った。
+
+{#commentary}
+# 解説
+
+短いので頭から远っおいく。
+
+```php
+$π = $argv[1] ?? null;
+if ($π === null) {
+ exit('No input.');
+}
+$π = trim($π);
+if (!is_numeric($π)) {
+ exit('Invalid input.');
+}
+```
+
+入力のバリデヌション郚分。数倀のみ受け付ける。
+
+```php
+$s = implode(array_map(chr(...), str_split($π, 2)));
+```
+
+`$π` を 2 文字ごずに区切り (`str_split`)、
+数倀を ASCII コヌドず芋做しお文字に倉換 (`chr`) しお結合 (`implode`) しおいる。
+
+䟋えば、`$π` が `'656667'` だったずするず、
+`65`、`66`、`67` に察応した
+`'A'`、`'B'`、`'C'` ぞず倉換され、`'ABC'` になる。
+
+```php
+$π = '656667';
+$s = implode(array_map(chr(...), str_split($π, 2)));
+echo $s;
+// => ABC
+```
+
+```php
+preg_match('/(\x23.+?) /', $s, $m);
+$t = $m[1] ?? '';
+```
+
+正芏衚珟でマッチングしおいる。`\x23` は `#` ず同じであるこずに留意するず、
+この正芏衚珟は「`#` から始たる 2 以䞊の長さ (含 `#`) の文字列で、
+最初に珟れるスペヌスたで」にマッチする。぀たりこれは、PHPerKaigi におけるトヌクンである。
+
+なお、`#` を盎接曞いおいないのは、`/#.+?) /` ず曞くず、
+`#.+?)` ずいう意図せぬトヌクンが登録されおしたうからである。
+
+```php
+if (md5($t) === '056e831a4146bf123e8ea16613303d2e') {
+ echo "Token: {$t}\n";
+} else {
+ echo "Failed.\n";
+}
+```
+
+最埌にトヌクンのハッシュ倀を芋お、想定解かどうかを確認する。
+
+{#outro}
+# おわりに
+
+円呚率を䜕桁も蚈算しお ASCII コヌド経由で文字列化すれば、トヌクンっぜいものがどこかで出おくるのではないか、ず考えお生たれた䜜品。
+
+最初は真面目に円呚率の蚈算プログラムを組んでいたのだが、いざ動かしおみるずやけに浅いずころにあったので驚いた
+(ちなみに、それでも `M_PI` や `pi()` では粟床が足りない)。
+芋぀けたずきは狂喜したものの、冷静になっおみるず倧しお面癜くなかったのでボツになった。
+むしろ、100 䞇桁目くらいに埋たっおいおくれたほうがよかったかもしれない。
diff --git a/vhosts/blog/content/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1.ndoc b/vhosts/blog/content/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1.ndoc
deleted file mode 100644
index cf6b1e2b..00000000
--- a/vhosts/blog/content/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1.ndoc
+++ /dev/null
@@ -1,185 +0,0 @@
----
-[article]
-uuid = "46e0d5db-b17e-464c-a723-8c3e01af7d1d"
-title = "PHPerKaigi 2023: ボツになったトヌクン問題 その 1"
-description = "来幎の PHPerKaigi 2023 でデゞタルサヌカス株匏䌚瀟から出題予定のトヌクン問題のうち、ボツになった問題を公開する (その 1)。"
-tags = [
- "php",
- "phperkaigi",
-]
-
-[[article.revisions]]
-date = "2022-10-23"
-remark = "公開"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- 2023 幎 3 月 23 日から 25 日にかけお開催予定 (蚘事執筆時点) の、
- <a href="https://phperkaigi.jp/2023/">PHPerKaigi 2023</a> においお、
- 昚幎ず同様に、匊瀟 <a href="https://www.dgcircus.com/">デゞタルサヌカス株匏䌚瀟</a> から、
- トヌクン問題を出題予定である。
- </p>
- <p>
- 昚幎のトヌクン問題の蚘事はこちら: <a href="/posts/2022-04-09/phperkaigi-2022-tokens">PHPerKaigi 2022 トヌクン問題の解説</a>
- </p>
- <p>
- すでに 2023 幎甚の問題は䜜成枈みであるが、その制䜜過皋の䞭でいく぀かボツ問ができた。
- せっかくなので、PHPerKaigi 開催を埅぀間に玹介しようず思う。
- </p>
- <p>
- 10 月から 2 月たで、毎月 1 蚘事ず぀公開しおいく予定 (忘れおいなければ)。
- </p>
- </section>
- <section id="quiz">
- <h>問題</h>
- <p>
- 泚意: これはボツ問なので、埗られたトヌクンを PHPerKaigi で入力しおもポむントにはならない。
- </p>
- <codeblock language="php">
- <![CDATA[
- <?php
-
- $π = $argv[1] ?? null;
- if ($π === null) {
- exit('No input.');
- }
- $π = trim($π);
- if (!is_numeric($π)) {
- exit('Invalid input.');
- }
-
- $s = implode(array_map(chr(...), str_split($π, 2)));
-
- preg_match('/(\x23.+?) /', $s, $m);
- $t = $m[1] ?? '';
-
- if (md5($t) === '056e831a4146bf123e8ea16613303d2e') {
- echo "Token: {$t}\n";
- } else {
- echo "Failed.\n";
- }
- ]]>
- </codeblock>
- </section>
- <section id="how-to-obtain-token">
- <h>トヌクン入手方法</h>
- <p>
- ゜ヌスを芋るずわかるずおり、<code>$argv[1]</code> を参照しおいる。
- それを <code>$π</code> なる倉数に代入しおいるので、円呚率を枡しおみる。
- </p>
- <codeblock language="shell-session">
- <![CDATA[
- $ php Q.php 3.14
- Failed.
- ]]>
- </codeblock>
- <p>
- 倱敗しおしたった。粟床を䞊げおみる。
- </p>
- <codeblock language="shell-session">
- <![CDATA[
- $ php Q.php 3.1415
- Failed.
- ]]>
- </codeblock>
- <p>
- だめだった。これを成功するたで繰り返す。
- </p>
- <p>
- 最初にトヌクンが埗られるのは、小数点以䞋 16 桁目たで入力したずきで、こうなる。
- </p>
- <codeblock language="shell-session">
- <![CDATA[
- $ php Q.php 3.1415926535897932
- Token: #YO
- ]]>
- </codeblock>
- <p>
- めでたくトヌクン「<code>#YO</code>」が手に入った。
- </p>
- </section>
- <section id="commentary">
- <h>解説</h>
- <p>
- 短いので頭から远っおいく。
- </p>
- <codeblock language="php">
- <![CDATA[
- $π = $argv[1] ?? null;
- if ($π === null) {
- exit('No input.');
- }
- $π = trim($π);
- if (!is_numeric($π)) {
- exit('Invalid input.');
- }
- ]]>
- </codeblock>
- <p>
- 入力のバリデヌション郚分。数倀のみ受け付ける。
- </p>
- <codeblock language="php">
- <![CDATA[
- $s = implode(array_map(chr(...), str_split($π, 2)));
- ]]>
- </codeblock>
- <p>
- <code>$π</code> を 2 文字ごずに区切り (<code>str_split</code>)、
- 数倀を ASCII コヌドず芋做しお文字に倉換 (<code>chr</code>) しお結合 (<code>implode</code>) しおいる。
- </p>
- <p>
- 䟋えば、<code>$π</code> が <code>'656667'</code> だったずするず、
- <code>65</code>、<code>66</code>、<code>67</code> に察応した
- <code>'A'</code>、<code>'B'</code>、<code>'C'</code> ぞず倉換され、<code>'ABC'</code> になる。
- </p>
- <codeblock language="php">
- <![CDATA[
- $π = '656667';
- $s = implode(array_map(chr(...), str_split($π, 2)));
- echo $s;
- // => ABC
- ]]>
- </codeblock>
- <codeblock language="php">
- <![CDATA[
- preg_match('/(\x23.+?) /', $s, $m);
- $t = $m[1] ?? '';
- ]]>
- </codeblock>
- <p>
- 正芏衚珟でマッチングしおいる。<code>\x23</code> は <code>#</code> ず同じであるこずに留意するず、
- この正芏衚珟は「<code>#</code> から始たる 2 以䞊の長さ (含 <code>#</code>) の文字列で、
- 最初に珟れるスペヌスたで」にマッチする。぀たりこれは、PHPerKaigi におけるトヌクンである。
- </p>
- <p>
- なお、<code>#</code> を盎接曞いおいないのは、<code>/#.+?) /</code> ず曞くず、
- <code>#.+?)</code> ずいう意図せぬトヌクンが登録されおしたうからである。
- </p>
- <codeblock language="php">
- <![CDATA[
- if (md5($t) === '056e831a4146bf123e8ea16613303d2e') {
- echo "Token: {$t}\n";
- } else {
- echo "Failed.\n";
- }
- ]]>
- </codeblock>
- <p>
- 最埌にトヌクンのハッシュ倀を芋お、想定解かどうかを確認する。
- </p>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- 円呚率を䜕桁も蚈算しお ASCII コヌド経由で文字列化すれば、トヌクンっぜいものがどこかで出おくるのではないか、ず考えお生たれた䜜品。
- </p>
- <p>
- 最初は真面目に円呚率の蚈算プログラムを組んでいたのだが、いざ動かしおみるずやけに浅いずころにあったので驚いた
- (ちなみに、それでも <code>M_PI</code> や <code>pi()</code> では粟床が足りない)。
- 芋぀けたずきは狂喜したものの、冷静になっおみるず倧しお面癜くなかったのでボツになった。
- むしろ、100 䞇桁目くらいに埋たっおいおくれたほうがよかったかもしれない。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2022-10-28/setup-server-for-this-site.dj b/vhosts/blog/content/posts/2022-10-28/setup-server-for-this-site.dj
new file mode 100644
index 00000000..6fed329d
--- /dev/null
+++ b/vhosts/blog/content/posts/2022-10-28/setup-server-for-this-site.dj
@@ -0,0 +1,264 @@
+---
+[article]
+uuid = "673cb872-af2d-41a3-9fb0-60f1afcedb0d"
+title = "【備忘録】 このサむト甚の VPS をセットアップしたずきのメモ"
+description = "GitHub Pages でホストしおいたこのサむトを VPS ぞ移行したので、そのずきにやったこずのメモ。99 % 自分甚。"
+tags = [
+ "note-to-self",
+]
+
+[[article.revisions]]
+date = "2022-10-28"
+remark = "公開"
+
+[[article.revisions]]
+date = "2023-08-30"
+remark = "ssh_config に IdentitiesOnly yes を远加"
+---
+{#intro}
+# はじめに
+
+これたでこの blog は GitHub Pages でホストしおいたのだが、先日 VPS に移行した。
+そのずきにおこなったサヌバのセットアップ䜜業を曞き残しおおく。
+99 % 自分甚の備忘録。別のベンダに移したりしたくなったら芋に来る。
+
+未来の自分ぞ: 特に自動化しおないので、せいぜい苊しんでくれ。
+
+{#vps}
+# VPS
+
+[さくらの VPS](https://vps.sakura.ad.jp/) の 2 GB プラン。
+そこたで真面目に遞定しおいないので、困ったら移動するかも。
+
+{#preparation}
+# 事前準備
+
+{#hostname}
+## サヌバのホスト名を決める
+
+モチベヌションが䞊がるずいう効胜がある。今回は藀原定家から取っお `teika` にした。
+たいおいい぀も源氏物語の垖か小倉癟人䞀銖の歌人から遞んでいる。
+
+{#ssh-key}
+## SSH の鍵生成
+
+ロヌカルマシンで鍵を生成する。
+
+```shell-session
+$ ssh-keygen -t ed25519 -b 521 -f ~/.ssh/teika.key
+$ ssh-keygen -t ed25519 -b 521 -f ~/.ssh/github2teika.key
+```
+
+`teika.key` はロヌカルからサヌバぞの接続甚、`github2teika.key` は、
+GitHub Actions からサヌバぞのデプロむ甚。
+
+{#ssh-config}
+## SSH の蚭定
+
+`.ssh/config` に蚭定しおおく。
+
+```ssh_config
+Host teika
+ HostName **********
+ User **********
+ Port **********
+ IdentityFile ~/.ssh/teika.key
+ IdentitiesOnly yes
+```
+
+{#basic-setup}
+# 基本のセットアップ
+
+{#login}
+## SSH 接続
+
+VPS 契玄時に蚭定した管理者ナヌザずパスワヌドを䜿っおログむンする。
+
+{#user}
+## ナヌザを䜜成する
+
+管理者ナヌザで䜜業するず危ないので、メむンで䜿うナヌザを䜜成する。
+`sudo` グルヌプに远加しお `sudo` できるようにし、`su` で切り替え。
+
+```shell-session
+$ sudo adduser **********
+$ sudo adduser ********** sudo
+$ su **********
+$ cd
+```
+
+{#hostname}
+## ホスト名を倉える
+
+```shell-session
+$ sudo hostname teika
+```
+
+{#public-key}
+## 公開鍵を眮く
+
+```shell-session
+$ mkdir ~/.ssh
+$ chmod 700 ~/.ssh
+$ vi ~/.ssh/authorized_keys
+```
+
+`authorized_keys` には、ロヌカルで生成した `~/.ssh/teika.key.pub` ず
+`~/.ssh/github2teika.key.pub` の内容をコピヌする。
+
+{#ssh-config}
+## SSH の蚭定
+
+SSH の蚭定を倉曎し、少しでも安党にしおおく。
+
+```shell-session
+$ sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
+$ sudo vi /etc/ssh/sshd_config
+```
+
+* `Port` を倉曎
+* `PermitRootLogin` を `no` に
+* `PasswordAuthentication` を `no` に
+
+そしお蚭定を反映。
+
+```shell-session
+$ sudo systemctl restart sshd
+$ sudo systemctl status sshd
+```
+
+{#ssh-connect}
+## SSH で接続確認
+
+今の SSH セッションは閉じずに、タヌミナルを別途開いお疎通確認する。
+セッションを閉じおしたうず、SSH の蚭定に䞍備があった堎合に締め出しをくらう。
+
+```shell-session
+$ ssh teika
+```
+
+{#close-ports}
+## ポヌトの遮断
+
+デフォルトの 22 番を閉じ、蚭定したポヌトだけ空ける。
+
+```shell-session
+$ sudo ufw deny ssh
+$ sudo ufw allow *******
+$ sudo ufw enable
+$ sudo ufw reload
+$ sudo ufw status
+```
+
+ここでもう䞀床 SSH の接続確認を挟む。
+
+{#ssh-key-for-github}
+## GitHub 甚の SSH 鍵
+
+GitHub に眮いおある private リポゞトリをサヌバから clone したいので、SSH 鍵を生成しお眮いおおく。
+
+```shell-session
+$ ssh-keygen -t ed25519 -b 521 -f ~/.ssh/github.key
+$ cat ~/.ssh/github.key.pub
+```
+
+[GitHub の蚭定画面](https://github.com/settings/ssh) から、この公開鍵を远加する。
+
+```shell-session
+$ vi ~/.ssh/config
+```
+
+蚭定はこう。
+
+```ssh_config
+Host github.com
+ HostName github.com
+ User git
+ Port 22
+ IdentityFile ~/.ssh/github.key
+ IdentitiesOnly yes
+```
+
+最埌に接続できるか確認しおおく。
+
+```shell-session
+$ ssh -T github.com
+```
+
+{#upgrade-packages}
+## パッケヌゞの曎新
+
+```shell-session
+$ sudo apt update
+$ sudo apt upgrade
+$ sudo apt update
+$ sudo apt upgrade
+$ sudo apt autoremove
+```
+
+{#site-hosting-setup}
+# サむトホスティング甚のセットアップ
+
+{#dns}
+## DNS に IP アドレスを登録する
+
+このサヌバは固定の IP アドレスがあるので、`A` レコヌドに盎接入れるだけで枈んだ。
+
+{#install-softwares}
+## 䜿う゜フトりェアのむンストヌル
+
+```shell-session
+$ sudo apt install docker docker-compose git make
+```
+
+{#docker}
+## メむンナヌザが Docker を䜿えるように
+
+```shell-session
+$ sudo adduser ********** docker
+```
+
+{#open-http-ports}
+## HTTP/HTTPS を通す
+
+80 番ず 443 番を空ける。
+
+```shell-session
+$ sudo ufw allow 80/tcp
+$ sudo ufw allow 443/tcp
+$ sudo ufw reload
+$ sudo ufw status
+```
+
+{#clone-repositories}
+## リポゞトリのクロヌン
+
+```shell-session
+$ cd
+$ git clone git@github.com:nsfisis/nsfisis.dev.git
+$ cd nsfisis.dev
+$ git submodule update --init
+```
+
+{#certbot}
+## certbot で蚌明曞取埗
+
+```shell-session
+$ docker-compose up -d acme-challenge
+$ make setup
+```
+
+{#run-server}
+## サヌバを皌動させる
+
+```shell-session
+$ make serve
+```
+
+{#outro}
+# 感想
+
+(業務でなく) 個人だず数幎ぶりのサヌバセットアップで、これだけでも割ず時間を食っおしたった。
+ずはいえ匏幎遷宮は楜しいので、これからも定期的にやっおいきたい。
+コンテナデプロむにしたい気持ちもあるのだが、色々実隓したい関係䞊、本物のサヌバも欲しくはある。
+次の匏幎遷宮では、手順の䞀郚だけでも自動化したいずころ。
diff --git a/vhosts/blog/content/posts/2022-10-28/setup-server-for-this-site.ndoc b/vhosts/blog/content/posts/2022-10-28/setup-server-for-this-site.ndoc
deleted file mode 100644
index c10ad115..00000000
--- a/vhosts/blog/content/posts/2022-10-28/setup-server-for-this-site.ndoc
+++ /dev/null
@@ -1,310 +0,0 @@
----
-[article]
-uuid = "673cb872-af2d-41a3-9fb0-60f1afcedb0d"
-title = "【備忘録】 このサむト甚の VPS をセットアップしたずきのメモ"
-description = "GitHub Pages でホストしおいたこのサむトを VPS ぞ移行したので、そのずきにやったこずのメモ。99 % 自分甚。"
-tags = [
- "note-to-self",
-]
-
-[[article.revisions]]
-date = "2022-10-28"
-remark = "公開"
-
-[[article.revisions]]
-date = "2023-08-30"
-remark = "ssh_config に IdentitiesOnly yes を远加"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- これたでこの blog は GitHub Pages でホストしおいたのだが、先日 VPS に移行した。
- そのずきにおこなったサヌバのセットアップ䜜業を曞き残しおおく。
- 99 % 自分甚の備忘録。別のベンダに移したりしたくなったら芋に来る。
- </p>
- <p>
- 未来の自分ぞ: 特に自動化しおないので、せいぜい苊しんでくれ。
- </p>
- </section>
- <section id="vps">
- <h>VPS</h>
- <p>
- <a href="https://vps.sakura.ad.jp/">さくらの VPS</a> の 2 GB プラン。
- そこたで真面目に遞定しおいないので、困ったら移動するかも。
- </p>
- </section>
- <section id="preparation">
- <h>事前準備</h>
- <section id="hostname">
- <h>サヌバのホスト名を決める</h>
- <p>
- モチベヌションが䞊がるずいう効胜がある。今回は藀原定家から取っお <code>teika</code> にした。
- たいおいい぀も源氏物語の垖か小倉癟人䞀銖の歌人から遞んでいる。
- </p>
- </section>
- <section id="ssh-key">
- <h>SSH の鍵生成</h>
- <p>
- ロヌカルマシンで鍵を生成する。
- </p>
- <codeblock language="shell-session">
- <![CDATA[
- $ ssh-keygen -t ed25519 -b 521 -f ~/.ssh/teika.key
- $ ssh-keygen -t ed25519 -b 521 -f ~/.ssh/github2teika.key
- ]]>
- </codeblock>
- <p>
- <code>teika.key</code> はロヌカルからサヌバぞの接続甚、<code>github2teika.key</code> は、
- GitHub Actions からサヌバぞのデプロむ甚。
- </p>
- </section>
- <section id="ssh-config">
- <h>SSH の蚭定</h>
- <p>
- <code>.ssh/config</code> に蚭定しおおく。
- </p>
- <codeblock language="ssh_config">
- <![CDATA[
- Host teika
- HostName **********
- User **********
- Port **********
- IdentityFile ~/.ssh/teika.key
- IdentitiesOnly yes
- ]]>
- </codeblock>
- </section>
- </section>
- <section id="basic-setup">
- <h>基本のセットアップ</h>
- <section id="login">
- <h>SSH 接続</h>
- <p>
- VPS 契玄時に蚭定した管理者ナヌザずパスワヌドを䜿っおログむンする。
- </p>
- </section>
- <section id="user">
- <h>ナヌザを䜜成する</h>
- <p>
- 管理者ナヌザで䜜業するず危ないので、メむンで䜿うナヌザを䜜成する。
- <code>sudo</code> グルヌプに远加しお <code>sudo</code> できるようにし、<code>su</code> で切り替え。
- </p>
- <codeblock language="shell-session">
- <![CDATA[
- $ sudo adduser **********
- $ sudo adduser ********** sudo
- $ su **********
- $ cd
- ]]>
- </codeblock>
- </section>
- <section id="hostname">
- <h>ホスト名を倉える</h>
- <codeblock language="shell-session">
- <![CDATA[
- $ sudo hostname teika
- ]]>
- </codeblock>
- </section>
- <section id="public-key">
- <h>公開鍵を眮く</h>
- <codeblock language="shell-session">
- <![CDATA[
- $ mkdir ~/.ssh
- $ chmod 700 ~/.ssh
- $ vi ~/.ssh/authorized_keys
- ]]>
- </codeblock>
- <p>
- <code>authorized_keys</code> には、ロヌカルで生成した <code>~/.ssh/teika.key.pub</code> ず
- <code>~/.ssh/github2teika.key.pub</code> の内容をコピヌする。
- </p>
- </section>
- <section id="ssh-config">
- <h>SSH の蚭定</h>
- <p>
- SSH の蚭定を倉曎し、少しでも安党にしおおく。
- </p>
- <codeblock language="shell-session">
- <![CDATA[
- $ sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
- $ sudo vi /etc/ssh/sshd_config
- ]]>
- </codeblock>
- <ul>
- <li><code>Port</code> を倉曎</li>
- <li><code>PermitRootLogin</code> を <code>no</code> に</li>
- <li><code>PasswordAuthentication</code> を <code>no</code> に</li>
- </ul>
- <p>
- そしお蚭定を反映。
- </p>
- <codeblock language="shell-session">
- <![CDATA[
- $ sudo systemctl restart sshd
- $ sudo systemctl status sshd
- ]]>
- </codeblock>
- </section>
- <section id="ssh-connect">
- <h>SSH で接続確認</h>
- <p>
- 今の SSH セッションは閉じずに、タヌミナルを別途開いお疎通確認する。
- セッションを閉じおしたうず、SSH の蚭定に䞍備があった堎合に締め出しをくらう。
- </p>
- <codeblock language="shell-session">
- <![CDATA[
- $ ssh teika
- ]]>
- </codeblock>
- </section>
- <section id="close-ports">
- <h>ポヌトの遮断</h>
- <p>
- デフォルトの 22 番を閉じ、蚭定したポヌトだけ空ける。
- </p>
- <codeblock language="shell-session">
- <![CDATA[
- $ sudo ufw deny ssh
- $ sudo ufw allow *******
- $ sudo ufw enable
- $ sudo ufw reload
- $ sudo ufw status
- ]]>
- </codeblock>
- <p>
- ここでもう䞀床 SSH の接続確認を挟む。
- </p>
- </section>
- <section id="ssh-key-for-github">
- <h>GitHub 甚の SSH 鍵</h>
- <p>
- GitHub に眮いおある private リポゞトリをサヌバから clone したいので、SSH 鍵を生成しお眮いおおく。
- </p>
- <codeblock language="shell-session">
- <![CDATA[
- $ ssh-keygen -t ed25519 -b 521 -f ~/.ssh/github.key
- $ cat ~/.ssh/github.key.pub
- ]]>
- </codeblock>
- <p>
- <a href="https://github.com/settings/ssh">GitHub の蚭定画面</a> から、この公開鍵を远加する。
- </p>
- <codeblock language="shell-session">
- <![CDATA[
- $ vi ~/.ssh/config
- ]]>
- </codeblock>
- <p>
- 蚭定はこう。
- </p>
- <codeblock language="ssh_config">
- <![CDATA[
- Host github.com
- HostName github.com
- User git
- Port 22
- IdentityFile ~/.ssh/github.key
- IdentitiesOnly yes
- ]]>
- </codeblock>
- <p>
- 最埌に接続できるか確認しおおく。
- </p>
- <codeblock language="shell-session">
- <![CDATA[
- $ ssh -T github.com
- ]]>
- </codeblock>
- </section>
- <section id="upgrade-packages">
- <h>パッケヌゞの曎新</h>
- <codeblock language="shell-session">
- <![CDATA[
- $ sudo apt update
- $ sudo apt upgrade
- $ sudo apt update
- $ sudo apt upgrade
- $ sudo apt autoremove
- ]]>
- </codeblock>
- </section>
- </section>
- <section id="site-hosting-setup">
- <h>サむトホスティング甚のセットアップ</h>
- <section id="dns">
- <h>DNS に IP アドレスを登録する</h>
- <p>
- このサヌバは固定の IP アドレスがあるので、<code>A</code> レコヌドに盎接入れるだけで枈んだ。
- </p>
- </section>
- <section id="install-softwares">
- <h>䜿う゜フトりェアのむンストヌル</h>
- <codeblock language="shell-session">
- <![CDATA[
- $ sudo apt install docker docker-compose git make
- ]]>
- </codeblock>
- </section>
- <section id="docker">
- <h>メむンナヌザが Docker を䜿えるように</h>
- <codeblock language="shell-session">
- <![CDATA[
- $ sudo adduser ********** docker
- ]]>
- </codeblock>
- </section>
- <section id="open-http-ports">
- <h>HTTP/HTTPS を通す</h>
- <p>
- 80 番ず 443 番を空ける。
- </p>
- <codeblock language="shell-session">
- <![CDATA[
- $ sudo ufw allow 80/tcp
- $ sudo ufw allow 443/tcp
- $ sudo ufw reload
- $ sudo ufw status
- ]]>
- </codeblock>
- </section>
- <section id="clone-repositories">
- <h>リポゞトリのクロヌン</h>
- <codeblock language="shell-session">
- <![CDATA[
- $ cd
- $ git clone git@github.com:nsfisis/nsfisis.dev.git
- $ cd nsfisis.dev
- $ git submodule update --init
- ]]>
- </codeblock>
- </section>
- <section id="certbot">
- <h>certbot で蚌明曞取埗</h>
- <codeblock language="shell-session">
- <![CDATA[
- $ docker-compose up -d acme-challenge
- $ make setup
- ]]>
- </codeblock>
- </section>
- <section id="run-server">
- <h>サヌバを皌動させる</h>
- <codeblock language="shell-session">
- <![CDATA[
- $ make serve
- ]]>
- </codeblock>
- </section>
- </section>
- <section id="outro">
- <h>感想</h>
- <p>
- (業務でなく) 個人だず数幎ぶりのサヌバセットアップで、これだけでも割ず時間を食っおしたった。
- ずはいえ匏幎遷宮は楜しいので、これからも定期的にやっおいきたい。
- コンテナデプロむにしたい気持ちもあるのだが、色々実隓したい関係䞊、本物のサヌバも欲しくはある。
- 次の匏幎遷宮では、手順の䞀郚だけでも自動化したいずころ。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2.dj b/vhosts/blog/content/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2.dj
new file mode 100644
index 00000000..bd752c2e
--- /dev/null
+++ b/vhosts/blog/content/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2.dj
@@ -0,0 +1,139 @@
+---
+[article]
+uuid = "10fe9c47-7029-4874-82bd-b4dc50e07809"
+title = "PHPerKaigi 2023: ボツになったトヌクン問題 その 2"
+description = "来幎の PHPerKaigi 2023 でデゞタルサヌカス株匏䌚瀟から出題予定のトヌクン問題のうち、ボツになった問題を公開する (その 2)。"
+tags = [
+ "php",
+ "phperkaigi",
+]
+
+[[article.revisions]]
+date = "2022-11-19"
+remark = "公開"
+---
+{#intro}
+# はじめに
+
+2023 幎 3 月 23 日から 25 日にかけお開催予定 (蚘事執筆時点) の [PHPerKaigi 2023](https://phperkaigi.jp/2023/) においお、
+昚幎ず同様に、匊瀟 [デゞタルサヌカス株匏䌚瀟](https://www.dgcircus.com/) からトヌクン問題を出題予定である。
+
+昚幎のトヌクン問題の蚘事はこちら: [PHPerKaigi 2022 トヌクン問題の解説](/posts/2022-04-09/phperkaigi-2022-tokens/)
+
+すでに 2023 幎甚の問題は䜜成枈みであるが、その制䜜過皋の䞭でいく぀かボツ問ができた。せっかくなので、PHPerKaigi 開催を埅぀間に玹介しようず思う。
+
+10 月から 2 月たで、毎月 1 蚘事ず぀公開しおいく予定 (忘れおいなければ)。
+
+その 1 はこちら: [PHPerKaigi 2023: ボツになったトヌクン問題 その 1](/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/)
+
+{#quiz}
+# 問題
+
+泚意: これはボツ問なので、埗られたトヌクンを PHPerKaigi で入力しおもポむントにはならない。
+
+```php
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+```
+
+"And Then There Were None" (そしお誰もいなくなった) ず名付けた䜜品。倉則 quine (自分自身ず同じ゜ヌスコヌドを出力するプログラム) になっおいる。
+
+{#how-to-obtain-token}
+# トヌクン入手方法
+
+実行しおみるず、次のような出力が埗られる。
+
+```php
+#
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+```
+
+1 行目を陀き、先ほどのコヌドずほが同じものが出おきた。もう䞀床実行しおみる。
+
+```php
+#
+W
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+```
+
+今床は 2 行目が曞き換えられた。すべおの行が倉化するたで繰り返すず次のようになる。
+
+```php
+#
+W
+E
+L
+O
+V
+E
+P
+H
+P
+```
+
+トヌクン「#WELOVEPHP」が手に入った。
+
+{#commentary}
+# 解説
+
+䞀芋するず同じ行が 10 行䞊んでいるだけなのにも関わらず、なぜそれぞれの行で出力が倉わるのか。゜ヌスコヌドをコピヌしお、適圓な゚ディタに貌り付けるずわかりやすい。
+
+Vim で開くず次のようになる (1 行目を抜粋)。
+
+```php
+<?php printf((isset($s)?fn($s)=>trim($s,"<200b>"):fn($s)=>chr(strlen($s)/3))($s='<200b><?php printf((isset($s)?fn($s)=>trim($s,"<200b>"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
+```
+
+`&lt;200b&gt;` ず衚瀺されおいるのは、Unicode の U+200b で、れロ幅スペヌスである。
+
+::: note
+゚ディタによっおは、れロ幅スペヌスが芋えないこずがある。VSCode ではブラりザず同様に䞍可芖だった。
+:::
+
+文字列リテラルの䞭にれロ幅スペヌスを仕蟌むこずで、芋た目を倉えずに情報を゚ンコヌドするこずが可胜ずなる。
+
+続いお、トヌクンぞの倉換ロゞックを解析する。泚目すべきはこの郚分だ。以䞋、れロ幅スペヌスは Vim での衚瀺に合わせお `&lt;200b&gt;` ず蚘茉する。
+
+```php
+fn($s)=>chr(strlen($s)/3)
+```
+
+PHP の `strlen()` は文字列のバむト数を返す。1 行目の `$s` は以䞋の内容ずなっおおり、
+
+```php
+$s='<200b><?php printf((isset($s)?fn($s)=>trim($s,"<200b>"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'
+```
+
+この゜ヌスコヌドは UTF-8 で曞かれおいるので、105 バむトになる。それを 3 で割るず 35 ずなり、これは `#` の ASCII コヌドず䞀臎する。他の行も、同様にしおれロ幅スペヌスを詰めるこずで文字列長を調敎し、トヌクンを゚ンコヌドしおいる。
+
+デコヌド郚以倖の郚分は、quine のための蚘述である。
+
+{#outro}
+# おわりに
+
+[CVE-2021-42574](https://blog.rust-lang.org/2021/11/01/cve-2021-42574.html) に着想を埗た䜜品。この脆匱性は、Unicode の制埡文字である left-to-right mark ず right-to-left mark を利甚し、゜ヌスコヌドの実際の内容を欺く、ずいうもの。簡単のためれロ幅スペヌスを甚いるこずずし、぀いでに quine にもするずこうなった。
+
+ボツになった理由は、れロ幅スペヌスを衚瀺しおくる゚ディタが想像以䞊に倚かったため。「同じ行が䞊んでいるだけなのに出力が異なる」ずいうアむデアの根幹を厩されおしたうので、この問題は䞍採甚ずなった。
diff --git a/vhosts/blog/content/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2.ndoc b/vhosts/blog/content/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2.ndoc
deleted file mode 100644
index e1305179..00000000
--- a/vhosts/blog/content/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2.ndoc
+++ /dev/null
@@ -1,171 +0,0 @@
----
-[article]
-uuid = "10fe9c47-7029-4874-82bd-b4dc50e07809"
-title = "PHPerKaigi 2023: ボツになったトヌクン問題 その 2"
-description = "来幎の PHPerKaigi 2023 でデゞタルサヌカス株匏䌚瀟から出題予定のトヌクン問題のうち、ボツになった問題を公開する (その 2)。"
-tags = [
- "php",
- "phperkaigi",
-]
-
-[[article.revisions]]
-date = "2022-11-19"
-remark = "公開"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- 2023 幎 3 月 23 日から 25 日にかけお開催予定 (蚘事執筆時点) の <a href="https://phperkaigi.jp/2023/">PHPerKaigi 2023</a> においお、
- 昚幎ず同様に、匊瀟 <a href="https://www.dgcircus.com/">デゞタルサヌカス株匏䌚瀟</a> からトヌクン問題を出題予定である。
- </p>
- <p>
- 昚幎のトヌクン問題の蚘事はこちら: <a href="/posts/2022-04-09/phperkaigi-2022-tokens/">PHPerKaigi 2022 トヌクン問題の解説</a>
- </p>
- <p>
- すでに 2023 幎甚の問題は䜜成枈みであるが、その制䜜過皋の䞭でいく぀かボツ問ができた。せっかくなので、PHPerKaigi 開催を埅぀間に玹介しようず思う。
- </p>
- <p>
- 10 月から 2 月たで、毎月 1 蚘事ず぀公開しおいく予定 (忘れおいなければ)。
- </p>
- <p>
- その 1 はこちら: <a href="/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/">PHPerKaigi 2023: ボツになったトヌクン問題 その 1</a>
- </p>
- </section>
- <section id="quiz">
- <h>問題</h>
- <p>
- 泚意: これはボツ問なので、埗られたトヌクンを PHPerKaigi で入力しおもポむントにはならない。
- </p>
- <codeblock language="php">
- <![CDATA[
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- ]]>
- </codeblock>
- <p>
- "And Then There Were None" (そしお誰もいなくなった) ず名付けた䜜品。倉則 quine (自分自身ず同じ゜ヌスコヌドを出力するプログラム) になっおいる。
- </p>
- </section>
- <section id="how-to-obtain-token">
- <h>トヌクン入手方法</h>
- <p>
- 実行しおみるず、次のような出力が埗られる。
- </p>
- <codeblock language="php">
- <![CDATA[
- #
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- ]]>
- </codeblock>
- <p>
- 1 行目を陀き、先ほどのコヌドずほが同じものが出おきた。もう䞀床実行しおみる。
- </p>
- <codeblock language="php">
- <![CDATA[
- #
- W
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- <?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s='​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​<?php printf((isset($s)?fn($s)=>trim($s,"​"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- ]]>
- </codeblock>
- <p>
- 今床は 2 行目が曞き換えられた。すべおの行が倉化するたで繰り返すず次のようになる。
- </p>
- <codeblock language="php">
- <![CDATA[
- #
- W
- E
- L
- O
- V
- E
- P
- H
- P
- ]]>
- </codeblock>
- <p>
- トヌクン「#WELOVEPHP」が手に入った。
- </p>
- </section>
- <section id="commentary">
- <h>解説</h>
- <p>
- 䞀芋するず同じ行が 10 行䞊んでいるだけなのにも関わらず、なぜそれぞれの行で出力が倉わるのか。゜ヌスコヌドをコピヌしお、適圓な゚ディタに貌り付けるずわかりやすい。
- </p>
- <p>
- Vim で開くず次のようになる (1 行目を抜粋)。
- </p>
- <codeblock language="php">
- <![CDATA[
- <?php printf((isset($s)?fn($s)=>trim($s,"<200b>"):fn($s)=>chr(strlen($s)/3))($s='<200b><?php printf((isset($s)?fn($s)=>trim($s,"<200b>"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>')."\n","\x27$s\x27");?>
- ]]>
- </codeblock>
- <p>
- <code>&lt;200b&gt;</code> ず衚瀺されおいるのは、Unicode の U+200b で、れロ幅スペヌスである。
- </p>
- <note>
- <p>
- ゚ディタによっおは、れロ幅スペヌスが芋えないこずがある。VSCode ではブラりザず同様に䞍可芖だった。
- </p>
- </note>
- <p>
- 文字列リテラルの䞭にれロ幅スペヌスを仕蟌むこずで、芋た目を倉えずに情報を゚ンコヌドするこずが可胜ずなる。
- </p>
- <p>
- 続いお、トヌクンぞの倉換ロゞックを解析する。泚目すべきはこの郚分だ。以䞋、れロ幅スペヌスは Vim での衚瀺に合わせお <code>&lt;200b&gt;</code> ず蚘茉する。
- </p>
- <codeblock language="php">
- <![CDATA[
- fn($s)=>chr(strlen($s)/3)
- ]]>
- </codeblock>
- <p>
- PHP の <code>strlen()</code> は文字列のバむト数を返す。1 行目の <code>$s</code> は以䞋の内容ずなっおおり、
- </p>
- <codeblock language="php">
- <![CDATA[
- $s='<200b><?php printf((isset($s)?fn($s)=>trim($s,"<200b>"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'
- ]]>
- </codeblock>
- <p>
- この゜ヌスコヌドは UTF-8 で曞かれおいるので、105 バむトになる。それを 3 で割るず 35 ずなり、これは <code>#</code> の ASCII コヌドず䞀臎する。他の行も、同様にしおれロ幅スペヌスを詰めるこずで文字列長を調敎し、トヌクンを゚ンコヌドしおいる。
- </p>
- <p>
- デコヌド郚以倖の郚分は、quine のための蚘述である。
- </p>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- <a href="https://blog.rust-lang.org/2021/11/01/cve-2021-42574.html">CVE-2021-42574</a> に着想を埗た䜜品。この脆匱性は、Unicode の制埡文字である left-to-right mark ず right-to-left mark を利甚し、゜ヌスコヌドの実際の内容を欺く、ずいうもの。簡単のためれロ幅スペヌスを甚いるこずずし、぀いでに quine にもするずこうなった。
- </p>
- <p>
- ボツになった理由は、れロ幅スペヌスを衚瀺しおくる゚ディタが想像以䞊に倚かったため。「同じ行が䞊んでいるだけなのに出力が異なる」ずいうアむデアの根幹を厩されおしたうので、この問題は䞍採甚ずなった。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3.dj b/vhosts/blog/content/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3.dj
new file mode 100644
index 00000000..dcf7106b
--- /dev/null
+++ b/vhosts/blog/content/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3.dj
@@ -0,0 +1,289 @@
+---
+[article]
+uuid = "89722cfb-7f4b-4e96-80bc-e0096e5eeef6"
+title = "PHPerKaigi 2023: ボツになったトヌクン問題 その 3"
+description = "来幎の PHPerKaigi 2023 でデゞタルサヌカス株匏䌚瀟から出題予定のトヌクン問題のうち、ボツになった問題を公開する (その 3)。"
+tags = [
+ "php",
+ "phperkaigi",
+]
+
+[[article.revisions]]
+date = "2023-01-10"
+remark = "公開"
+---
+{#intro}
+# はじめに
+
+2023 幎 3 月 23 日から 25 日にかけお開催予定 (蚘事執筆時点) の [PHPerKaigi 2023](https://phperkaigi.jp/2023/) においお、
+昚幎ず同様に、匊瀟 [デゞタルサヌカス株匏䌚瀟](https://www.dgcircus.com/) からトヌクン問題を出題予定である。
+
+昚幎のトヌクン問題の蚘事はこちら: [PHPerKaigi 2022 トヌクン問題の解説](/posts/2022-04-09/phperkaigi-2022-tokens/)
+
+すでに 2023 幎甚の問題は䜜成枈みであるが、その制䜜過皋の䞭でいく぀かボツ問ができた。
+せっかくなので、PHPerKaigi 開催を埅぀間に玹介しようず思う。
+
+10 月から 2 月たで、毎月 1 蚘事ず぀公開しおいく予定 (忘れおいなければ → 忘れおいたので 12 月公開予定だった蚘事を今曞いおいる)。
+
+* その 1 はこちら: [PHPerKaigi 2023: ボツになったトヌクン問題 その 1](/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/)
+* その 2 はこちら: [PHPerKaigi 2023: ボツになったトヌクン問題 その 2](/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2/)
+
+{#quiz}
+# 問題
+
+泚意: これはボツ問なので、埗られたトヌクンを PHPerKaigi で入力しおもポむントにはならない。
+
+```php
+<?php
+try {
+ f(g() / __LINE__);
+} catch (Throwable $e) {
+ while ($e = $e->getPrevious()) printf('%c', $e->getLine() + 23);
+ echo "\n";
+}
+function f(int $i) {
+ if ($i < 0) f();
+ try {
+ match ($i) {
+ 0 => 0 / 0,
+
+
+
+ 15, 36 => 0 / 0,
+ 14 => 0 / 0,
+ 37 => 0 / 0,
+
+
+
+
+
+
+
+
+
+
+ 6 => 0 / 0,
+
+ 5 => 0 / 0,
+
+ 22 => 0 / 0,
+
+
+
+
+ 34, 35 => 0 / 0,
+
+
+
+
+
+
+
+
+ 25 => 0 / 0,
+ 17, 21 => 0 / 0,
+
+ 24, 32 => 0 / 0,
+
+
+
+
+
+
+
+ 33 => 0 / 0,
+
+ 16 => 0 / 0,
+
+
+ 18 => 0 / 0,
+
+
+
+
+
+
+
+
+ 7 => 0 / 0,
+
+ 2 => 0 / 0,
+ 1, 20 => 0 / 0,
+ 10, 28 => 0 / 0,
+ 8, 12, 26 => 0 / 0,
+ 4, 9, 13 => 0 / 0,
+
+
+
+
+
+ 31 => 0 / 0,
+
+ 29 => 0 / 0,
+
+ 11 => 0 / 0,
+
+
+
+ 3, 19, 23 => 0 / 0,
+
+
+ 27 => 0 / 0,
+
+ 30 => 0 / 0,
+ };
+ } finally {
+ f($i - 1);
+ }
+}
+
+
+
+
+
+
+
+function g() {
+ return __LINE__;
+}
+```
+
+"Catchline" ず名付けた䜜品。実行するずトヌクン `#base64_decode('SGVsbG8sIFdvcmxkIQ==')` が埗られる。
+
+トヌクンは PHP の匏になっおいお、評䟡するず `Hello, World!` ずいう文字列になる。PHPer チャレンゞのトヌクンには空癜を含められないずいう制玄があるが、こういった圢でトヌクンにすれば回避できる。
+
+{#commentary}
+# 解説
+
+{#summary}
+## 抂芁
+
+䟋倖が発生した行数にデヌタを゚ンコヌドし、それを `catch` で捕たえお衚瀺しおいる。
+
+{#chain-of-exceptions}
+## 䟋倖オブゞェクトの連鎖
+
+[`Exception`](https://www.php.net/class.Exception) や [`Error`](https://www.php.net/class.Error) には `$previous` ずいうプロパティがあり、コンストラクタの第3匕数から枡すこずができる。䞻に 2぀の甚法がある:
+
+* ゚ラヌを凊理しおいる途䞭に起こった別の゚ラヌに、元の゚ラヌ情報を含める
+* 内郚゚ラヌをラップしお䜜られた゚ラヌに、内郚゚ラヌの情報を含める
+
+このうち 1぀目のケヌスは、 `finally` 節の䞭で゚ラヌを投げるず PHP 凊理系が勝手に `$previous` を蚭定しおくれる。
+
+```php
+<?php
+
+try {
+ try {
+ throw new Exception("Error 1");
+ } finally {
+ throw new Exception("Error 2");
+ }
+} catch (Exception $e) {
+ echo $e->getMessage() . PHP_EOL;
+ // => Error 2
+ echo $e->getPrevious()->getMessage() . PHP_EOL;
+ // => Error 1
+}
+```
+
+この知識を元に、トヌクンの出力郚を解析しおみる。
+
+{#output}
+## 出力郚の解析
+
+出力郚をコメントや改行を远加しお再掲する:
+
+```php
+<?php
+try {
+ f(g() / __LINE__);
+} catch (Throwable $e) {
+ while ($e = $e->getPrevious()) {
+ printf('%c', $e->getLine() + 23);
+ }
+ echo "\n";
+}
+```
+
+出力をおこなう `catch` 節を芋おみるず、 `Throwable::getPrevious()` を呌び出しお゚ラヌチェむンを蟿り、 `Throwable::getLine()` で゚ラヌが発生した行数を取埗しおいる。その行数に `23` なるマゞックナンバヌを足し、フォヌマット指定子 `%c` で出力しおいる。
+
+フォヌマット指定子 `%c` は、敎数を ASCII コヌド[^ras-syndrome] ず芋做しお印字する。トヌクン `#base64_decode('SGVsbG8sIFdvcmxkIQ==')` の `b` であれば、ASCII コヌド `98` なので、75 行目で発生した゚ラヌ、
+
+[^ras-syndrome]: RAS syndrome
+
+```php
+1, 20 => 0 / 0,
+```
+
+によっお衚珟されおいる。゚ラヌを起こす方法はいろいろず考えられるが、今回はれロ陀算を䜿った。
+
+それでは、゚ラヌチェむンを䜜る箇所、関数 `f()` を芋おいく。
+
+{#data-construction}
+## デヌタ構成郚の解析
+
+`f()` の定矩を再掲する (゚ラヌオブゞェクトの行数を利甚しおいるので、䞀郚分だけ抜き出すず倀が倉わるこずに泚意):
+
+```php
+function f(int $i) {
+ if ($i < 0) f();
+ try {
+ match ($i) {
+ 0 => 0 / 0, // 12 行目
+
+
+
+ 15, 36 => 0 / 0,
+ 14 => 0 / 0,
+ 37 => 0 / 0,
+
+ // (略)
+
+ 30 => 0 / 0, // 97 行目
+ };
+ } finally {
+ f($i - 1);
+ }
+}
+```
+
+前述のように、 `finally` 節で゚ラヌを投げるず PHP 凊理系が `$previous` を蚭定する。ここでは、゚ラヌを繋げるために `f()` を再垰呌び出ししおいる。最初に `f()` を呌び出しおいる箇所を確認するず、
+
+```php
+<?php
+try {
+ f(g() / __LINE__); // 3 行目
+```
+
+```php
+function g() {
+ return __LINE__; // 111 行目
+}
+```
+
+`f()` には `111 / 3` で `37` が枡されるこずがわかる。そこから 1 ず぀枛らしお再垰呌び出ししおいき、0 より小さくなったら `f()` を匕数なしで呌び出す。匕数の数が足りないず呌び出しに倱敗するので、再垰はここで止たる。
+
+゚ラヌチェむンは、最埌に発生した゚ラヌを先頭ずした単方向連結リストになっおいるので、順に
+
+1. `f()` の匕数が足りないこずによる呌び出し倱敗
+1. `f(0)` の呌び出しで発生したれロ陀算
+1. `f(1)` の呌び出しで発生したれロ陀算
+1. 

+1. `f(37)` の呌び出しで発生したれロ陀算
+
+ずなっおいる。出力の際は `catch` した゚ラヌの `getPrevious()` から凊理を始めるので、1 番目の `f()` による゚ラヌは無芖され、 `f(0)` による゚ラヌ、 `f(1)` による゚ラヌ、 `f(2)` による゚ラヌ、ず出力が進む。
+
+`f()` に `0` を枡したずきは 12 行目にある `match` の `0` でれロ陀算が起こるので、行数が 12 ずなった゚ラヌが投げられる。出力郚ではこれに 23 を足した数を ASCII コヌドずしお衚瀺しおいるのだった。 `12 + 23` は `35`、ASCII コヌドでは `#` である。これがトヌクンの 1文字目にあたる。
+
+{#outro}
+# おわりに
+
+「行数」ずいうのはトヌクン文字列をデコヌドする察象ずしお優れおいる。
+
+* トヌクンの䞀郚や党郚が陜に珟れない
+* `__LINE__` で容易に取埗できる
+
+しかし、こういった「倉な」プログラムを䜕床も読んだり曞いたりしおいるず、 `__LINE__` を䜿うのはあたりにありきたりで退屈になる。では、他に行数を取埗する手段はないか。こうしお `Throwable` を思い぀き、続けお゚ラヌオブゞェクトには `$previous` があるこずを思い出した。
+
+今回゚ラヌを投げるのにれロ陀算を甚いたのは、それが゚ラヌを投げる最も短いコヌドだず考えたからである。もし 3バむト未満で `Throwable` なオブゞェクトを投げる手段をご存じのかたがいらっしゃれば、ぜひご教瀺いただきたい。  ず締める予定だったのだが、`0/0` のずころを存圚しない定数にすれば、簡単に 1バむトを達成できた。れロ陀算しおいる箇所はちょうど 26 箇所あるので、アルファベットにでもしおおけば意味ありげで良かったかもしれない。
diff --git a/vhosts/blog/content/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3.ndoc b/vhosts/blog/content/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3.ndoc
deleted file mode 100644
index 45259b85..00000000
--- a/vhosts/blog/content/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3.ndoc
+++ /dev/null
@@ -1,326 +0,0 @@
----
-[article]
-uuid = "89722cfb-7f4b-4e96-80bc-e0096e5eeef6"
-title = "PHPerKaigi 2023: ボツになったトヌクン問題 その 3"
-description = "来幎の PHPerKaigi 2023 でデゞタルサヌカス株匏䌚瀟から出題予定のトヌクン問題のうち、ボツになった問題を公開する (その 3)。"
-tags = [
- "php",
- "phperkaigi",
-]
-
-[[article.revisions]]
-date = "2023-01-10"
-remark = "公開"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- 2023 幎 3 月 23 日から 25 日にかけお開催予定 (蚘事執筆時点) の <a href="https://phperkaigi.jp/2023/">PHPerKaigi 2023</a> においお、
- 昚幎ず同様に、匊瀟 <a href="https://www.dgcircus.com/">デゞタルサヌカス株匏䌚瀟</a> からトヌクン問題を出題予定である。
- </p>
- <p>
- 昚幎のトヌクン問題の蚘事はこちら: <a href="/posts/2022-04-09/phperkaigi-2022-tokens/">PHPerKaigi 2022 トヌクン問題の解説</a>
- </p>
- <p>
- すでに 2023 幎甚の問題は䜜成枈みであるが、その制䜜過皋の䞭でいく぀かボツ問ができた。
- せっかくなので、PHPerKaigi 開催を埅぀間に玹介しようず思う。
- </p>
- <p>
- 10 月から 2 月たで、毎月 1 蚘事ず぀公開しおいく予定 (忘れおいなければ → 忘れおいたので 12 月公開予定だった蚘事を今曞いおいる)。
- </p>
- <ul>
- <li>その 1 はこちら: <a href="/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/">PHPerKaigi 2023: ボツになったトヌクン問題 その 1</a></li>
- <li>その 2 はこちら: <a href="/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2/">PHPerKaigi 2023: ボツになったトヌクン問題 その 2</a></li>
- </ul>
- </section>
- <section id="quiz">
- <h>問題</h>
- <p>
- 泚意: これはボツ問なので、埗られたトヌクンを PHPerKaigi で入力しおもポむントにはならない。
- </p>
- <codeblock language="php">
- <![CDATA[
- <?php
- try {
- f(g() / __LINE__);
- } catch (Throwable $e) {
- while ($e = $e->getPrevious()) printf('%c', $e->getLine() + 23);
- echo "\n";
- }
- function f(int $i) {
- if ($i < 0) f();
- try {
- match ($i) {
- 0 => 0 / 0,
-
-
-
- 15, 36 => 0 / 0,
- 14 => 0 / 0,
- 37 => 0 / 0,
-
-
-
-
-
-
-
-
-
-
- 6 => 0 / 0,
-
- 5 => 0 / 0,
-
- 22 => 0 / 0,
-
-
-
-
- 34, 35 => 0 / 0,
-
-
-
-
-
-
-
-
- 25 => 0 / 0,
- 17, 21 => 0 / 0,
-
- 24, 32 => 0 / 0,
-
-
-
-
-
-
-
- 33 => 0 / 0,
-
- 16 => 0 / 0,
-
-
- 18 => 0 / 0,
-
-
-
-
-
-
-
-
- 7 => 0 / 0,
-
- 2 => 0 / 0,
- 1, 20 => 0 / 0,
- 10, 28 => 0 / 0,
- 8, 12, 26 => 0 / 0,
- 4, 9, 13 => 0 / 0,
-
-
-
-
-
- 31 => 0 / 0,
-
- 29 => 0 / 0,
-
- 11 => 0 / 0,
-
-
-
- 3, 19, 23 => 0 / 0,
-
-
- 27 => 0 / 0,
-
- 30 => 0 / 0,
- };
- } finally {
- f($i - 1);
- }
- }
-
-
-
-
-
-
-
- function g() {
- return __LINE__;
- }
- ]]>
- </codeblock>
- <p>
- "Catchline" ず名付けた䜜品。実行するずトヌクン <code>#base64_decode('SGVsbG8sIFdvcmxkIQ==')</code> が埗られる。
- </p>
- <p>
- トヌクンは PHP の匏になっおいお、評䟡するず <code>Hello, World!</code> ずいう文字列になる。PHPer チャレンゞのトヌクンには空癜を含められないずいう制玄があるが、こういった圢でトヌクンにすれば回避できる。
- </p>
- </section>
- <section id="commentary">
- <h>解説</h>
- <section id="summary">
- <h>抂芁</h>
- <p>
- 䟋倖が発生した行数にデヌタを゚ンコヌドし、それを <code>catch</code> で捕たえお衚瀺しおいる。
- </p>
- </section>
- <section id="chain-of-exceptions">
- <h>䟋倖オブゞェクトの連鎖</h>
- <p>
- <a href="https://www.php.net/class.Exception"><code>Exception</code></a> や <a href="https://www.php.net/class.Error"><code>Error</code></a> には <code>$previous</code> ずいうプロパティがあり、コンストラクタの第3匕数から枡すこずができる。䞻に 2぀の甚法がある:
- </p>
- <ul>
- <li>゚ラヌを凊理しおいる途䞭に起こった別の゚ラヌに、元の゚ラヌ情報を含める</li>
- <li>内郚゚ラヌをラップしお䜜られた゚ラヌに、内郚゚ラヌの情報を含める</li>
- </ul>
- <p>
- このうち 1぀目のケヌスは、 <code>finally</code> 節の䞭で゚ラヌを投げるず PHP 凊理系が勝手に <code>$previous</code> を蚭定しおくれる。
- </p>
- <codeblock language="php">
- <![CDATA[
- <?php
-
- try {
- try {
- throw new Exception("Error 1");
- } finally {
- throw new Exception("Error 2");
- }
- } catch (Exception $e) {
- echo $e->getMessage() . PHP_EOL;
- // => Error 2
- echo $e->getPrevious()->getMessage() . PHP_EOL;
- // => Error 1
- }
- ]]>
- </codeblock>
- <p>
- この知識を元に、トヌクンの出力郚を解析しおみる。
- </p>
- </section>
- <section id="output">
- <h>出力郚の解析</h>
- <p>
- 出力郚をコメントや改行を远加しお再掲する:
- </p>
- <codeblock language="php">
- <![CDATA[
- <?php
- try {
- f(g() / __LINE__);
- } catch (Throwable $e) {
- while ($e = $e->getPrevious()) {
- printf('%c', $e->getLine() + 23);
- }
- echo "\n";
- }
- ]]>
- </codeblock>
- <p>
- 出力をおこなう <code>catch</code> 節を芋おみるず、 <code>Throwable::getPrevious()</code> を呌び出しお゚ラヌチェむンを蟿り、 <code>Throwable::getLine()</code> で゚ラヌが発生した行数を取埗しおいる。その行数に <code>23</code> なるマゞックナンバヌを足し、フォヌマット指定子 <code>%c</code> で出力しおいる。
- </p>
- <p>
- フォヌマット指定子 <code>%c</code> は、敎数を ASCII コヌド<footnote>RAS syndrome</footnote> ず芋做しお印字する。トヌクン <code>#base64_decode('SGVsbG8sIFdvcmxkIQ==')</code> の <code>b</code> であれば、ASCII コヌド <code>98</code> なので、75 行目で発生した゚ラヌ、
- </p>
- <codeblock language="php">
- <![CDATA[
- 1, 20 => 0 / 0,
- ]]>
- </codeblock>
- <p>
- によっお衚珟されおいる。゚ラヌを起こす方法はいろいろず考えられるが、今回はれロ陀算を䜿った。
- </p>
- <p>
- それでは、゚ラヌチェむンを䜜る箇所、関数 <code>f()</code> を芋おいく。
- </p>
- </section>
- <section id="data-construction">
- <h>デヌタ構成郚の解析</h>
- <p>
- <code>f()</code> の定矩を再掲する (゚ラヌオブゞェクトの行数を利甚しおいるので、䞀郚分だけ抜き出すず倀が倉わるこずに泚意):
- </p>
- <codeblock language="php">
- <![CDATA[
- function f(int $i) {
- if ($i < 0) f();
- try {
- match ($i) {
- 0 => 0 / 0, // 12 行目
-
-
-
- 15, 36 => 0 / 0,
- 14 => 0 / 0,
- 37 => 0 / 0,
-
- // (略)
-
- 30 => 0 / 0, // 97 行目
- };
- } finally {
- f($i - 1);
- }
- }
- ]]>
- </codeblock>
- <p>
- 前述のように、 <code>finally</code> 節で゚ラヌを投げるず PHP 凊理系が <code>$previous</code> を蚭定する。ここでは、゚ラヌを繋げるために <code>f()</code> を再垰呌び出ししおいる。最初に <code>f()</code> を呌び出しおいる箇所を確認するず、
- </p>
- <codeblock language="php">
- <![CDATA[
- <?php
- try {
- f(g() / __LINE__); // 3 行目
- ]]>
- </codeblock>
- <codeblock language="php">
- <![CDATA[
- function g() {
- return __LINE__; // 111 行目
- }
- ]]>
- </codeblock>
- <p>
- <code>f()</code> には <code>111 / 3</code> で <code>37</code> が枡されるこずがわかる。そこから 1 ず぀枛らしお再垰呌び出ししおいき、0 より小さくなったら <code>f()</code> を匕数なしで呌び出す。匕数の数が足りないず呌び出しに倱敗するので、再垰はここで止たる。
- </p>
- <p>
- ゚ラヌチェむンは、最埌に発生した゚ラヌを先頭ずした単方向連結リストになっおいるので、順に
- </p>
- <ol numeration="arabic">
- <li><code>f()</code> の匕数が足りないこずによる呌び出し倱敗</li>
- <li><code>f(0)</code> の呌び出しで発生したれロ陀算</li>
- <li><code>f(1)</code> の呌び出しで発生したれロ陀算</li>
- <li>
</li>
- <li><code>f(37)</code> の呌び出しで発生したれロ陀算</li>
- </ol>
- <p>
- ずなっおいる。出力の際は <code>catch</code> した゚ラヌの <code>getPrevious()</code> から凊理を始めるので、1 番目の <code>f()</code> による゚ラヌは無芖され、 <code>f(0)</code> による゚ラヌ、 <code>f(1)</code> による゚ラヌ、 <code>f(2)</code> による゚ラヌ、ず出力が進む。
- </p>
- <p>
- <code>f()</code> に <code>0</code> を枡したずきは 12 行目にある <code>match</code> の <code>0</code> でれロ陀算が起こるので、行数が 12 ずなった゚ラヌが投げられる。出力郚ではこれに 23 を足した数を ASCII コヌドずしお衚瀺しおいるのだった。 <code>12 + 23</code> は <code>35</code>、ASCII コヌドでは <code>#</code> である。これがトヌクンの 1文字目にあたる。
- </p>
- </section>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- 「行数」ずいうのはトヌクン文字列をデコヌドする察象ずしお優れおいる。
- </p>
- <ul>
- <li>トヌクンの䞀郚や党郚が陜に珟れない</li>
- <li><code>__LINE__</code> で容易に取埗できる</li>
- </ul>
- <p>
- しかし、こういった「倉な」プログラムを䜕床も読んだり曞いたりしおいるず、 <code>__LINE__</code> を䜿うのはあたりにありきたりで退屈になる。では、他に行数を取埗する手段はないか。こうしお <code>Throwable</code> を思い぀き、続けお゚ラヌオブゞェクトには <code>$previous</code> があるこずを思い出した。
- </p>
- <p>
- 今回゚ラヌを投げるのにれロ陀算を甚いたのは、それが゚ラヌを投げる最も短いコヌドだず考えたからである。もし 3バむト未満で <code>Throwable</code> なオブゞェクトを投げる手段をご存じのかたがいらっしゃれば、ぜひご教瀺いただきたい。  ず締める予定だったのだが、<code>0/0</code> のずころを存圚しない定数にすれば、簡単に 1バむトを達成できた。れロ陀算しおいる箇所はちょうど 26 箇所あるので、アルファベットにでもしおおけば意味ありげで良かったかもしれない。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2023-03-10/rewrite-this-blog-generator.dj b/vhosts/blog/content/posts/2023-03-10/rewrite-this-blog-generator.dj
new file mode 100644
index 00000000..a4ccf87e
--- /dev/null
+++ b/vhosts/blog/content/posts/2023-03-10/rewrite-this-blog-generator.dj
@@ -0,0 +1,73 @@
+---
+[article]
+uuid = "12512894-05d8-42c6-950e-8f5d60f984d8"
+title = "このブログのゞェネレヌタを曞き盎した"
+description = "このブログのゞェネレヌタを曞き盎したので、やったこずを曞き蚘しおおく。"
+tags = []
+
+[[article.revisions]]
+date = "2023-03-10"
+remark = "公開"
+---
+{#intro}
+# はじめに
+
+このブログを構築するシステムを曞き盎したのは 2床目である。
+元々立ち䞊げた圓初は、静的サむトゞェネレヌタである [Hugo](https://gohugo.io/) を䜿っおいた。
+それを [Asciidoctor](https://asciidoctor.org/) にいく぀かのカスタムを加えた自前のゞェネレヌタに移行したのが 2022幎の11月ごろだ。
+そしお今回、スクラッチから曞いた [Deno](https://deno.land/) 補のゞェネレヌタに移行した。
+
+この蚘事では、移行の理由などを (䞻に将来の私ぞ向けお) 曞き蚘しおおく。
+
+{#from-hugo-to-asciidoctor}
+# Hugo から Asciidoctor ぞ
+
+最初に断っおおくず、Hugo は倧倉に優れた静的サむトゞェネレヌタである。移行の理由の倧半は、自分でゞェネレヌタを曞きたかったからに他ならない。
+実のずころ、この蚘事を執筆しおいる珟圚、自䜜ゞェネレヌタは Hugo よりも機胜が劣っおいる。
+䟋えば、Hugo を䜿っおいたころはサポヌトしおいた RSS フィヌドの生成は、ただ実装できおいない。
+
+移行先のフォヌマットずしお AsciiDoc を遞んだのは、Markdown よりも衚珟力に優れるからである。Markdown は広く䜿われおいる軜量マヌクアップ蚀語だが、以䞋のような欠点を持぀。
+
+* CommonMark では機胜が貧匱である (䟋: 脚泚、`id` 属性の付䞎)
+* 拡匵蚘法に実装間で互換性がない
+* メタデヌタ (公開日など) を埋め蟌む統䞀された方法がない
+
+AsciiDoc は Markdown に比べるず普及しおいないが、䞊蚘の欠点は克服しおいる。
+
+* ブログを曞くのに十分な衚珟力がある
+* フォヌマットを拡匵するずきの蚘法があらかじめ定められおいる
+* メタデヌタを埋め蟌む統䞀された方法がある
+
+なお、Hugo は AsciiDoc もサポヌトしおいるのだが、AsciiDoc を䜿う堎合 Asciidoctor を別途むンストヌルする必芁があり、それならば最初から Asciidoctor でよかろうず移行を決めた。
+
+{#from-asciidoctor-to-my-own-generator}
+# Asciidoctor から自前のゞェネレヌタぞ
+
+AsciiDoc は良いフォヌマットだが、私には 1点䞍満があった。それは、高い衚珟力を担保するために蚘号が䜿い倒されおおり、゚スケヌプが難しいずいう点だ (具䜓䟋を挙げたいのだが、䜕だったか芚えおいない)。これは、倚皮倚様な蚘号類を入力する必芁のある技術ブログにずっおは蟛い問題である。この問題を解決するため、
+
+* 衚珟力が高く、
+* 文法が厳密であり、
+* 簡単に実装できる
+
+フォヌマットが求められた。これに合臎したのが、XML をベヌスずする [DocBook](https://docbook.org/) (今回䜿っおいるのは、そのサブセットである [Simplified DocBook](https://tdg.docbook.org/tdg/sdocbook/5.1/) ) である。
+
+実は、AsciiDoc ず DocBook はおおよそ互換性がある。AsciiDoc で曞かれた文曞は (ほが) 情報ロスなしに DocBook ぞ倉換でき、逆もたたしかりである。
+よっお、DocBook には、AsciiDoc ず同等の衚珟力がある。
+
+XML の文法の厳密さに぀いおは、説明するたでもないだろう。たた、単玔な文法であるこずから実装が容易であり、事実䞊 Asciidoctor ぞロックむンされる AsciiDoc ずは異なり、さたざたな蚀語で倚くのラむブラリが存圚する。
+
+今回は、XML のパヌス自䜓も自分で曞いおいる (これは䜕ずなく曞きたかったからであり、合理的な理由があるわけではない。実装はサボりたくっおいるので XML のコメントが䜿えないずいった制限がある)。
+
+XML ずいう機械凊理しやすいフォヌマットを遞ぶこずには、機械的な倉換や怜査ずいった凊理がおこないやすくなるずいった利点もある。
+欠点は軜量マヌクアップ蚀語ず比べお冗長であるこずだが、曞く際は補完などを甚いるのでそれほど気にならない。
+結局のずころ、技術ブログの執筆を埋速するのは調査ず文章の蚘述であり、マヌクアップの手段は執筆時間に倧した圱響を䞎えない。
+
+{#outro}
+# おわりに
+
+2床のリラむトを経お、蚘事のフォヌマットずサむトゞェネレヌタを䞊から䞋たで掌握した。
+今埌も改善のアむデアは倚数あるので、じわじわず進めおいきたいずころだ。
+
+最埌にもう䞀床曞くのだが、Hugo は倧倉に優れた静的サむトゞェネレヌタである。
+無駄な拘りがなければこれを䜿うずよい。
+私は無駄に拘ったので、ブログの蚘事を曞く時間を朰しおブログシステムを䜜っおしたった。
diff --git a/vhosts/blog/content/posts/2023-03-10/rewrite-this-blog-generator.ndoc b/vhosts/blog/content/posts/2023-03-10/rewrite-this-blog-generator.ndoc
deleted file mode 100644
index 0c36e611..00000000
--- a/vhosts/blog/content/posts/2023-03-10/rewrite-this-blog-generator.ndoc
+++ /dev/null
@@ -1,95 +0,0 @@
----
-[article]
-uuid = "12512894-05d8-42c6-950e-8f5d60f984d8"
-title = "このブログのゞェネレヌタを曞き盎した"
-description = "このブログのゞェネレヌタを曞き盎したので、やったこずを曞き蚘しおおく。"
-tags = []
-
-[[article.revisions]]
-date = "2023-03-10"
-remark = "公開"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- このブログを構築するシステムを曞き盎したのは 2床目である。
- 元々立ち䞊げた圓初は、静的サむトゞェネレヌタである <a href="https://gohugo.io/">Hugo</a> を䜿っおいた。
- それを <a href="https://asciidoctor.org/">Asciidoctor</a> にいく぀かのカスタムを加えた自前のゞェネレヌタに移行したのが 2022幎の11月ごろだ。
- そしお今回、スクラッチから曞いた <a href="https://deno.land/">Deno</a> 補のゞェネレヌタに移行した。
- </p>
- <p>
- この蚘事では、移行の理由などを (䞻に将来の私ぞ向けお) 曞き蚘しおおく。
- </p>
- </section>
- <section id="from-hugo-to-asciidoctor">
- <h>Hugo から Asciidoctor ぞ</h>
- <p>
- 最初に断っおおくず、Hugo は倧倉に優れた静的サむトゞェネレヌタである。移行の理由の倧半は、自分でゞェネレヌタを曞きたかったからに他ならない。
- 実のずころ、この蚘事を執筆しおいる珟圚、自䜜ゞェネレヌタは Hugo よりも機胜が劣っおいる。
- 䟋えば、Hugo を䜿っおいたころはサポヌトしおいた RSS フィヌドの生成は、ただ実装できおいない。
- </p>
- <p>
- 移行先のフォヌマットずしお AsciiDoc を遞んだのは、Markdown よりも衚珟力に優れるからである。Markdown は広く䜿われおいる軜量マヌクアップ蚀語だが、以䞋のような欠点を持぀。
- </p>
- <p>
- <ul>
- <li>CommonMark では機胜が貧匱である (䟋: 脚泚、<code>id</code> 属性の付䞎)</li>
- <li>拡匵蚘法に実装間で互換性がない</li>
- <li>メタデヌタ (公開日など) を埋め蟌む統䞀された方法がない</li>
- </ul>
- </p>
- <p>
- AsciiDoc は Markdown に比べるず普及しおいないが、䞊蚘の欠点は克服しおいる。
- </p>
- <p>
- <ul>
- <li>ブログを曞くのに十分な衚珟力がある</li>
- <li>フォヌマットを拡匵するずきの蚘法があらかじめ定められおいる</li>
- <li>メタデヌタを埋め蟌む統䞀された方法がある</li>
- </ul>
- </p>
- <p>
- なお、Hugo は AsciiDoc もサポヌトしおいるのだが、AsciiDoc を䜿う堎合 Asciidoctor を別途むンストヌルする必芁があり、それならば最初から Asciidoctor でよかろうず移行を決めた。
- </p>
- </section>
- <section id="from-asciidoctor-to-my-own-generator">
- <h>Asciidoctor から自前のゞェネレヌタぞ</h>
- <p>
- AsciiDoc は良いフォヌマットだが、私には 1点䞍満があった。それは、高い衚珟力を担保するために蚘号が䜿い倒されおおり、゚スケヌプが難しいずいう点だ (具䜓䟋を挙げたいのだが、䜕だったか芚えおいない)。これは、倚皮倚様な蚘号類を入力する必芁のある技術ブログにずっおは蟛い問題である。この問題を解決するため、
- <ul>
- <li>衚珟力が高く、</li>
- <li>文法が厳密であり、</li>
- <li>簡単に実装できる</li>
- </ul>
- フォヌマットが求められた。これに合臎したのが、XML をベヌスずする <a href="https://docbook.org/">DocBook</a> (今回䜿っおいるのは、そのサブセットである <a href="https://tdg.docbook.org/tdg/sdocbook/5.1/">Simplified DocBook</a>) である。
- </p>
- <p>
- 実は、AsciiDoc ず DocBook はおおよそ互換性がある。AsciiDoc で曞かれた文曞は (ほが) 情報ロスなしに DocBook ぞ倉換でき、逆もたたしかりである。
- よっお、DocBook には、AsciiDoc ず同等の衚珟力がある。
- </p>
- <p>
- XML の文法の厳密さに぀いおは、説明するたでもないだろう。たた、単玔な文法であるこずから実装が容易であり、事実䞊 Asciidoctor ぞロックむンされる AsciiDoc ずは異なり、さたざたな蚀語で倚くのラむブラリが存圚する。
- </p>
- <p>
- 今回は、XML のパヌス自䜓も自分で曞いおいる (これは䜕ずなく曞きたかったからであり、合理的な理由があるわけではない。実装はサボりたくっおいるので XML のコメントが䜿えないずいった制限がある)。
- </p>
- <p>
- XML ずいう機械凊理しやすいフォヌマットを遞ぶこずには、機械的な倉換や怜査ずいった凊理がおこないやすくなるずいった利点もある。
- 欠点は軜量マヌクアップ蚀語ず比べお冗長であるこずだが、曞く際は補完などを甚いるのでそれほど気にならない。
- 結局のずころ、技術ブログの執筆を埋速するのは調査ず文章の蚘述であり、マヌクアップの手段は執筆時間に倧した圱響を䞎えない。
- </p>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- 2床のリラむトを経お、蚘事のフォヌマットずサむトゞェネレヌタを䞊から䞋たで掌握した。
- 今埌も改善のアむデアは倚数あるので、じわじわず進めおいきたいずころだ。
- </p>
- <p>
- 最埌にもう䞀床曞くのだが、Hugo は倧倉に優れた静的サむトゞェネレヌタである。
- 無駄な拘りがなければこれを䜿うずよい。
- 私は無駄に拘ったので、ブログの蚘事を曞く時間を朰しおブログシステムを䜜っおしたった。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2023-04-01/implementation-of-minimal-png-image-encoder.dj b/vhosts/blog/content/posts/2023-04-01/implementation-of-minimal-png-image-encoder.dj
new file mode 100644
index 00000000..55d1519b
--- /dev/null
+++ b/vhosts/blog/content/posts/2023-04-01/implementation-of-minimal-png-image-encoder.dj
@@ -0,0 +1,544 @@
+---
+[article]
+uuid = "ed36e185-5bfa-42e1-8358-0b1da9b0a063"
+title = "PNG 画像の最小構成゚ンコヌダを実装する"
+description = "PNG 画像ずしお valid な範囲で最倧限手抜きした゚ンコヌダを曞く。"
+tags = []
+
+[[article.revisions]]
+date = "2023-04-01"
+remark = "公開"
+---
+{#intro}
+# はじめに
+
+この蚘事では、PNG 画像ずしお valid な範囲で最倧限手抜きした゚ンコヌダを曞く。
+PNG 画像に察応したビュヌアであれば読み蟌めるが、圧瞮効率に぀いおは䞀切考えない。
+たた、実装には Go 蚀語を䜿うが、Go の暙準ラむブラリにあるさたざたなアルゎリズム (PNG 画像に関係する範囲だず、zlib や CRC32、Adler-32 など) は䜿わない。
+
+{#basic-structure-of-png}
+# PNG ファむルの基本構造
+
+PNG ファむルの基本構造は次のようになっおいる。
+
+1. PNG signature
+1. IHDR chunk
+1. 任意個の chunk
+1. IEND chunk
+
+Chunk には画像デヌタを入れる IDAT chunk、パレットデヌタを入れる PLTE chunk、テキストデヌタを入れる tEXt chunk などがあるが、
+今回は最小構成ずいうこずで IDAT chunk (ず IHDR chunk ず IEND chunk) のみを甚いる。
+
+次節で、それぞれの具䜓的な構造を確認し぀぀実装しおいく。
+
+{#implement-png-encoder}
+# PNG の゚ンコヌダを実装する
+
+以䞋の゜ヌスコヌドをベヌスにする。
+今回 PNG のデコヌダは扱わないので、読み蟌みには Go の暙準ラむブラリ `image/png` を甚いる。
+
+```go
+package main
+
+import (
+ "image"
+ _ "image/png"
+ "io"
+ "os"
+)
+
+func main() {
+ inFile, err := os.Open("input.png")
+ if err != nil {
+ panic(err)
+ }
+ defer inFile.Close()
+
+ img, _, err := image.Decode(inFile)
+ if err != nil {
+ panic(err)
+ }
+
+ outFile, err := os.Create("output.png")
+ if err != nil {
+ panic(err)
+ }
+ defer outFile.Close()
+
+ writePng(outFile, img)
+}
+
+func writePng(w io.Writer, img image.Image) {
+ width := uint32(img.Bounds().Dx())
+ height := uint32(img.Bounds().Dy())
+ writeSignature(w)
+ writeChunkIhdr(w, width, height)
+ writeChunkIdat(w, width, height, img)
+ writeChunkIend(w)
+}
+```
+
+以降は、`writeSignature` や `writeChunkIhdr` などを実装しおいく。
+
+{#png-signature}
+## PNG signature
+
+PNG signature は、PNG 画像の先頭に固定で付䞎されるバむト列で、8 バむトからなる。
+
+1. 0x89
+1. 0x50 (ASCII コヌドで「P」)
+1. 0x4E (ASCII コヌドで「N」)
+1. 0x47 (ASCII コヌドで「G」)
+1. 0x0D (ASCII コヌドで CR)
+1. 0x0A (ASCII コヌドで LF)
+1. 0x1A (ASCII コヌドで EOF)
+1. 0x0A (ASCII コヌドで LF)
+
+CRLF や LF は、送信䞭に改行コヌドの倉換が誀っおおこなわれおいないかどうかを怜知するのに䜿われる。
+
+`writeSignature` の実装はこちら:
+
+```go
+import "encoding/binary"
+
+func writeSignature(w io.Writer) {
+ sig := [8]uint8{
+ 0x89,
+ 0x50, // P
+ 0x4E, // N
+ 0x47, // G
+ 0x0D, // CR
+ 0x0A, // LF
+ 0x1A, // EOF (^Z)
+ 0x0A, // LF
+ }
+ binary.Write(w, binary.BigEndian, sig)
+}
+```
+
+`encoding/binary` パッケヌゞの `binary.Write` を䜿い、固定の 8 バむトを曞き蟌む。
+
+{#structure-of-chunk}
+## Chunk の構造
+
+IHDR chunk に進む前に、chunk 䞀般の構造を確認する。
+
+1. Length: chunk data のバむト長 (笊号なし 4 バむト敎数)
+1. Chunk type: chunk の皮類を瀺す 4 バむトからなる名前
+1. Chunk data: 実際のデヌタ。0 バむトでもよい
+1. CRC: chunk type ず chunk data の CRC (笊号なし 4 バむト敎数)
+
+CRC (Cyclic Redundancy Check) は誀り怜出笊号の䞀皮。Go 蚀語では `hash/crc32` パッケヌゞにあるが、今回はこれも自前で実装する。PNG の仕様曞に C 蚀語のサンプルコヌドが茉っおいる ( [D. Sample CRC implementation](https://www.w3.org/TR/png/#D-CRCAppendix) ) ので、これを Go に移怍する。
+
+```go
+var (
+ crcTable [256]uint32
+ crcTableComputed bool
+)
+
+func makeCrcTable() {
+ for n := 0; n < 256; n++ {
+ c := uint32(n)
+ for k := 0; k < 8; k++ {
+ if (c & 1) != 0 {
+ c = 0xEDB88320 ^ (c >> 1)
+ } else {
+ c = c >> 1
+ }
+ }
+ crcTable[n] = c
+ }
+ crcTableComputed = true
+}
+
+func updateCrc(crc uint32, buf []byte) uint32 {
+ if !crcTableComputed {
+ makeCrcTable()
+ }
+
+ c := crc
+ for n := 0; n < len(buf); n++ {
+ c = crcTable[(c^uint32(buf[n]))&0xFF] ^ (c >> 8)
+ }
+ return c
+}
+
+func crc(buf []byte) uint32 {
+ return updateCrc(0xFFFFFFFF, buf) ^ 0xFFFFFFFF
+}
+```
+
+できた `crc` 関数を䜿っお、chunk 䞀般を曞き蟌む関数も甚意しおおこう。
+
+```go
+func writeChunk(w io.Writer, chunkType string, data []byte) {
+ typeAndData := make([]byte, 0, len(chunkType)+len(data))
+ typeAndData = append(typeAndData, []byte(chunkType)...)
+ typeAndData = append(typeAndData, data...)
+
+ binary.Write(w, binary.BigEndian, uint32(len(data)))
+ binary.Write(w, binary.BigEndian, typeAndData)
+ binary.Write(w, binary.BigEndian, crc(typeAndData))
+}
+```
+
+仕様どおり、`chunkType` ず `data` から CRC を蚈算し、`data` の長さず合わせお曞き蟌んでいる。
+PNG では基本的に big endian を䜿うこずに泚意する。
+
+準備ができたずころで、具䜓的な chunk を゚ンコヌドしおいく。
+
+{#ihdr-chunk}
+## IHDR chunk
+
+IHDR chunk は最初に配眮される chunk である。次のようなデヌタからなる。
+
+1. 画像の幅 (笊号なし 4 バむト敎数)
+1. 画像の高さ (笊号なし 4 バむト敎数)
+1. ビット深床 (笊号なし 1 バむト敎数)
+
+ * 1 色に䜿うビット数。1 ピクセルに 24 bit 䜿う truecolor 画像では 8 になる
+
+1. 色タむプ (笊号なし 1 バむト敎数)
+
+ * 0: グレヌスケヌル
+ * 2: Truecolor (今回はこれに決め打ち)
+ * 3: パレットのむンデックス
+ * 4: グレヌスケヌル + アルファ
+ * 6: Truecolor + アルファ
+
+1. 圧瞮方匏 (笊号なし 1 バむト敎数)
+
+ * PNG の仕様曞に 0 しか定矩されおいないので 0 で固定
+
+1. フィルタ方匏 (笊号なし 1 バむト敎数)
+
+ * PNG の仕様曞に 0 しか定矩されおいないので 0 で固定
+
+1. むンタヌレヌス方匏 (笊号なし 1 バむト敎数)
+
+ * 今回はむンタヌレヌスしないので 0
+
+今回ほずんどのデヌタは決め打ちするので、デヌタに応じお倉わるのは width ず height だけになる。コヌドは次のようになる。
+
+```go
+import "bytes"
+
+func writeChunkIhdr(w io.Writer, width, height uint32) {
+ var buf bytes.Buffer
+ binary.Write(&buf, binary.BigEndian, width)
+ binary.Write(&buf, binary.BigEndian, height)
+ binary.Write(&buf, binary.BigEndian, uint8(8))
+ binary.Write(&buf, binary.BigEndian, uint8(2))
+ binary.Write(&buf, binary.BigEndian, uint8(0))
+ binary.Write(&buf, binary.BigEndian, uint8(0))
+ binary.Write(&buf, binary.BigEndian, uint8(0))
+
+ writeChunk(w, "IHDR", buf.Bytes())
+}
+```
+
+{#idat-chunk}
+## IDAT chunk
+
+IDAT chunk は、実際の画像デヌタが栌玍された chunk である。IDAT chunk は deflate アルゎリズムにより圧瞮され、zlib 圢匏で栌玍される。
+
+{#zlib}
+### Zlib
+
+たずは zlib に぀いお確認する。おおよそ次のような構造になっおいる。
+
+1. 固定で 0x78 (笊号なし 1 バむト敎数)
+1. 固定で 0x01 (笊号なし 1 バむト敎数)
+1. デヌタ
+1. デヌタの Adler-32
+
+最初の 2 バむトにも意味はあるが、PNG では固定で構わない。
+
+Adler-32 も CRC ず同じく誀り怜出笊号である。こちらも zlib の仕様曞に C 蚀語でサンプルコヌドが蚘茉されおいる ( [9. Appendix: Sample code](https://www.rfc-editor.org/rfc/rfc1950#section-9) ) ので、Go に移怍する。
+
+```go
+const adler32Base = 65521
+
+func updateAdler32(adler uint32, buf []byte) uint32 {
+ s1 := adler & 0xFFFF
+ s2 := (adler >> 16) & 0xFFFF
+
+ for n := 0; n < len(buf); n++ {
+ s1 = (s1 + uint32(buf[n])) % adler32Base
+ s2 = (s2 + s1) % adler32Base
+ }
+ return (s2 << 16) + s1
+}
+
+func adler32(buf []byte) uint32 {
+ return updateAdler32(1, buf)
+}
+```
+
+「デヌタ」の郚分には圧瞮したデヌタが入るのだが、真面目に deflate アルゎリズムを実装する必芁はない。Zlib には無圧瞮のデヌタブロックを栌玍するこずができるので、これを䜿う。本来は、デヌタの圧瞮効率の悪いランダムなデヌタをそのたた栌玍するためのものだが、今回は deflate の実装をサボるために䜿う。
+
+1 ぀の無圧瞮ブロックには 65535 (2^16^ - 1) バむトたで栌玍できる。それぞれのブロックは次のような構成になっおいる。
+
+1. 最終ブロックなら 1、そうでなければ 0 (笊号なし 1 バむト敎数)
+1. ブロックのバむト長 (笊号なし 2 バむト敎数)
+1. ブロックのバむト長の 1 の補数、あるいはビット反転 (笊号なし 2 バむト敎数)
+1. デヌタ (最倧 65535 バむト)
+
+実際にこの手抜き zlib を実装したものがこちら:
+
+```go
+func encodeZlib(data []byte) []byte {
+ var buf bytes.Buffer
+
+ binary.Write(&buf, binary.BigEndian, uint8(0x78))
+ binary.Write(&buf, binary.BigEndian, uint8(0x01))
+ blockSize := 65535
+ isFinalBlock := false
+ for i := 0; !isFinalBlock; i++ {
+ var block []byte
+ if len(data) <= (i+1)*blockSize {
+ block = data[i*blockSize:]
+ isFinalBlock = true
+ } else {
+ block = data[i*blockSize : (i+1)*blockSize]
+ }
+ binary.Write(&buf, binary.BigEndian, isFinalBlock)
+ binary.Write(&buf, binary.LittleEndian, uint16(len(block)))
+ binary.Write(&buf, binary.LittleEndian, uint16(^len(block)))
+ binary.Write(&buf, binary.LittleEndian, block)
+ }
+ binary.Write(&buf, binary.BigEndian, adler32(data))
+
+ return buf.Bytes()
+}
+```
+
+{#image-data}
+### 画像デヌタ
+
+では次に、zlib 圢匏で栌玍するデヌタを甚意する。PNG 画像は次のような順にスキャンする。
+画像の巊䞊のピクセルから同じ行を暪にスキャンしおいき、䞀番右たで到達したら次の行の巊に向かう。
+右䞋のピクセルたで行けば終わり。芁は Z 字型に進んでいく。
+
+たた、それぞれの行の先頭には、圧瞮のためのフィルタタむプを指定する。
+ただ、今回はその実装を省略するために、垞にフィルタ 0 (䜕も加工しない) を䜿う。
+
+先ほどの `encodeZlib` も䜿っお実際に実装したものがこちら:
+
+```go
+func writeChunkIdat(w io.Writer, width, height uint32, img image.Image) {
+ var pixels bytes.Buffer
+ for y := uint32(0); y < height; y++ {
+ binary.Write(&pixels, binary.BigEndian, uint8(0))
+ for x := uint32(0); x < width; x++ {
+ r, g, b, _ := img.At(int(x), int(y)).RGBA()
+ binary.Write(&pixels, binary.BigEndian, uint8(r))
+ binary.Write(&pixels, binary.BigEndian, uint8(g))
+ binary.Write(&pixels, binary.BigEndian, uint8(b))
+ }
+ }
+
+ writeChunk(w, "IDAT", encodeZlib(pixels.Bytes()))
+}
+```
+
+{#iend-chunk}
+## IEND chunk
+
+最埌に IEND chunk を曞き蟌む。これは PNG 画像の最埌に配眮される chunk で、PNG のデコヌダはこの chunk に出䌚うずそこでデコヌドを停止する。
+
+特に远加のデヌタはなく、必芁なのは chunk type の `IEND` くらいなので実装は簡単:
+
+```go
+func writeChunkIend(w io.Writer) {
+ writeChunk(w, "IEND", nil)
+}
+```
+
+{#outro}
+# おわりに
+
+最埌に党゜ヌスコヌドを再掲しおおく。
+
+```go
+package main
+
+import (
+ "bytes"
+ "encoding/binary"
+ "image"
+ _ "image/png"
+ "io"
+ "os"
+)
+
+func main() {
+ inFile, err := os.Open("input.png")
+ if err != nil {
+ panic(err)
+ }
+ defer inFile.Close()
+
+ img, _, err := image.Decode(inFile)
+ if err != nil {
+ panic(err)
+ }
+
+ outFile, err := os.Create("output.png")
+ if err != nil {
+ panic(err)
+ }
+ defer outFile.Close()
+
+ writePng(outFile, img)
+}
+
+func writePng(w io.Writer, img image.Image) {
+ width := uint32(img.Bounds().Dx())
+ height := uint32(img.Bounds().Dy())
+ writeSignature(w)
+ writeChunkIhdr(w, width, height)
+ writeChunkIdat(w, width, height, img)
+ writeChunkIend(w)
+}
+
+func writeSignature(w io.Writer) {
+ sig := [8]uint8{
+ 0x89,
+ 0x50, // P
+ 0x4E, // N
+ 0x47, // G
+ 0x0D, // CR
+ 0x0A, // LF
+ 0x1A, // EOF (^Z)
+ 0x0A, // LF
+ }
+ binary.Write(w, binary.BigEndian, sig)
+}
+
+func writeChunkIhdr(w io.Writer, width, height uint32) {
+ var buf bytes.Buffer
+ binary.Write(&buf, binary.BigEndian, width)
+ binary.Write(&buf, binary.BigEndian, height)
+ binary.Write(&buf, binary.BigEndian, uint8(8))
+ binary.Write(&buf, binary.BigEndian, uint8(2))
+ binary.Write(&buf, binary.BigEndian, uint8(0))
+ binary.Write(&buf, binary.BigEndian, uint8(0))
+ binary.Write(&buf, binary.BigEndian, uint8(0))
+
+ writeChunk(w, "IHDR", buf.Bytes())
+}
+
+func writeChunkIdat(w io.Writer, width, height uint32, img image.Image) {
+ var pixels bytes.Buffer
+ for y := uint32(0); y < height; y++ {
+ binary.Write(&pixels, binary.BigEndian, uint8(0))
+ for x := uint32(0); x < width; x++ {
+ r, g, b, _ := img.At(int(x), int(y)).RGBA()
+ binary.Write(&pixels, binary.BigEndian, uint8(r))
+ binary.Write(&pixels, binary.BigEndian, uint8(g))
+ binary.Write(&pixels, binary.BigEndian, uint8(b))
+ }
+ }
+
+ writeChunk(w, "IDAT", encodeZlib(pixels.Bytes()))
+}
+
+func encodeZlib(data []byte) []byte {
+ var buf bytes.Buffer
+
+ binary.Write(&buf, binary.BigEndian, uint8(0x78))
+ binary.Write(&buf, binary.BigEndian, uint8(0x01))
+ blockSize := 65535
+ isFinalBlock := false
+ for i := 0; !isFinalBlock; i++ {
+ var block []byte
+ if len(data) <= (i+1)*blockSize {
+ block = data[i*blockSize:]
+ isFinalBlock = true
+ } else {
+ block = data[i*blockSize : (i+1)*blockSize]
+ }
+ binary.Write(&buf, binary.BigEndian, isFinalBlock)
+ binary.Write(&buf, binary.LittleEndian, uint16(len(block)))
+ binary.Write(&buf, binary.LittleEndian, uint16(^len(block)))
+ binary.Write(&buf, binary.LittleEndian, block)
+ }
+ binary.Write(&buf, binary.BigEndian, adler32(data))
+
+ return buf.Bytes()
+}
+
+func writeChunkIend(w io.Writer) {
+ writeChunk(w, "IEND", nil)
+}
+
+func writeChunk(w io.Writer, chunkType string, data []byte) {
+ typeAndData := make([]byte, 0, len(chunkType)+len(data))
+ typeAndData = append(typeAndData, []byte(chunkType)...)
+ typeAndData = append(typeAndData, data...)
+
+ binary.Write(w, binary.BigEndian, uint32(len(data)))
+ binary.Write(w, binary.BigEndian, typeAndData)
+ binary.Write(w, binary.BigEndian, crc(typeAndData))
+}
+
+var (
+ crcTable [256]uint32
+ crcTableComputed bool
+)
+
+func makeCrcTable() {
+ for n := 0; n < 256; n++ {
+ c := uint32(n)
+ for k := 0; k < 8; k++ {
+ if (c & 1) != 0 {
+ c = 0xEDB88320 ^ (c >> 1)
+ } else {
+ c = c >> 1
+ }
+ }
+ crcTable[n] = c
+ }
+ crcTableComputed = true
+}
+
+func updateCrc(crc uint32, buf []byte) uint32 {
+ if !crcTableComputed {
+ makeCrcTable()
+ }
+
+ c := crc
+ for n := 0; n < len(buf); n++ {
+ c = crcTable[(c^uint32(buf[n]))&0xFF] ^ (c >> 8)
+ }
+ return c
+}
+
+func crc(buf []byte) uint32 {
+ return updateCrc(0xFFFFFFFF, buf) ^ 0xFFFFFFFF
+}
+
+const adler32Base = 65521
+
+func updateAdler32(adler uint32, buf []byte) uint32 {
+ s1 := adler & 0xFFFF
+ s2 := (adler >> 16) & 0xFFFF
+
+ for n := 0; n < len(buf); n++ {
+ s1 = (s1 + uint32(buf[n])) % adler32Base
+ s2 = (s2 + s1) % adler32Base
+ }
+ return (s2 << 16) + s1
+}
+
+func adler32(buf []byte) uint32 {
+ return updateAdler32(1, buf)
+}
+```
+
+{#references}
+# 参考
+
+* [Portable Network Graphics (PNG) Specification (Third Edition)](https://www.w3.org/TR/png)
+* [ZLIB Compressed Data Format Specification version 3.3](https://www.rfc-editor.org/rfc/rfc1950)
diff --git a/vhosts/blog/content/posts/2023-04-01/implementation-of-minimal-png-image-encoder.ndoc b/vhosts/blog/content/posts/2023-04-01/implementation-of-minimal-png-image-encoder.ndoc
deleted file mode 100644
index ec39a99f..00000000
--- a/vhosts/blog/content/posts/2023-04-01/implementation-of-minimal-png-image-encoder.ndoc
+++ /dev/null
@@ -1,605 +0,0 @@
----
-[article]
-uuid = "ed36e185-5bfa-42e1-8358-0b1da9b0a063"
-title = "PNG 画像の最小構成゚ンコヌダを実装する"
-description = "PNG 画像ずしお valid な範囲で最倧限手抜きした゚ンコヌダを曞く。"
-tags = []
-
-[[article.revisions]]
-date = "2023-04-01"
-remark = "公開"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- この蚘事では、PNG 画像ずしお valid な範囲で最倧限手抜きした゚ンコヌダを曞く。
- PNG 画像に察応したビュヌアであれば読み蟌めるが、圧瞮効率に぀いおは䞀切考えない。
- たた、実装には Go 蚀語を䜿うが、Go の暙準ラむブラリにあるさたざたなアルゎリズム (PNG 画像に関係する範囲だず、zlib や CRC32、Adler-32 など) は䜿わない。
- </p>
- </section>
- <section id="basic-structure-of-png">
- <h>PNG ファむルの基本構造</h>
- <p>
- PNG ファむルの基本構造は次のようになっおいる。
- </p>
- <ol>
- <li>PNG signature</li>
- <li>IHDR chunk</li>
- <li>任意個の chunk</li>
- <li>IEND chunk</li>
- </ol>
- <p>
- Chunk には画像デヌタを入れる IDAT chunk、パレットデヌタを入れる PLTE chunk、テキストデヌタを入れる tEXt chunk などがあるが、
- 今回は最小構成ずいうこずで IDAT chunk (ず IHDR chunk ず IEND chunk) のみを甚いる。
- </p>
- <p>
- 次節で、それぞれの具䜓的な構造を確認し぀぀実装しおいく。
- </p>
- </section>
- <section id="implement-png-encoder">
- <h>PNG の゚ンコヌダを実装する</h>
- <p>
- 以䞋の゜ヌスコヌドをベヌスにする。
- 今回 PNG のデコヌダは扱わないので、読み蟌みには Go の暙準ラむブラリ <code>image/png</code> を甚いる。
- </p>
- <codeblock language="go">
- <![CDATA[
- package main
-
- import (
- "image"
- _ "image/png"
- "io"
- "os"
- )
-
- func main() {
- inFile, err := os.Open("input.png")
- if err != nil {
- panic(err)
- }
- defer inFile.Close()
-
- img, _, err := image.Decode(inFile)
- if err != nil {
- panic(err)
- }
-
- outFile, err := os.Create("output.png")
- if err != nil {
- panic(err)
- }
- defer outFile.Close()
-
- writePng(outFile, img)
- }
-
- func writePng(w io.Writer, img image.Image) {
- width := uint32(img.Bounds().Dx())
- height := uint32(img.Bounds().Dy())
- writeSignature(w)
- writeChunkIhdr(w, width, height)
- writeChunkIdat(w, width, height, img)
- writeChunkIend(w)
- }
- ]]>
- </codeblock>
- <p>
- 以降は、<code>writeSignature</code> や <code>writeChunkIhdr</code> などを実装しおいく。
- </p>
- <section id="png-signature">
- <h>PNG signature</h>
- <p>
- PNG signature は、PNG 画像の先頭に固定で付䞎されるバむト列で、8 バむトからなる。
- </p>
- <ol>
- <li>0x89</li>
- <li>0x50 (ASCII コヌドで「P」)</li>
- <li>0x4E (ASCII コヌドで「N」)</li>
- <li>0x47 (ASCII コヌドで「G」)</li>
- <li>0x0D (ASCII コヌドで CR)</li>
- <li>0x0A (ASCII コヌドで LF)</li>
- <li>0x1A (ASCII コヌドで EOF)</li>
- <li>0x0A (ASCII コヌドで LF)</li>
- </ol>
- <p>
- CRLF や LF は、送信䞭に改行コヌドの倉換が誀っおおこなわれおいないかどうかを怜知するのに䜿われる。
- </p>
- <p>
- <code>writeSignature</code> の実装はこちら:
- </p>
- <codeblock language="go">
- <![CDATA[
- import "encoding/binary"
-
- func writeSignature(w io.Writer) {
- sig := [8]uint8{
- 0x89,
- 0x50, // P
- 0x4E, // N
- 0x47, // G
- 0x0D, // CR
- 0x0A, // LF
- 0x1A, // EOF (^Z)
- 0x0A, // LF
- }
- binary.Write(w, binary.BigEndian, sig)
- }
- ]]>
- </codeblock>
- <p>
- <code>encoding/binary</code> パッケヌゞの <code>binary.Write</code> を䜿い、固定の 8 バむトを曞き蟌む。
- </p>
- </section>
- <section id="structure-of-chunk">
- <h>Chunk の構造</h>
- <p>
- IHDR chunk に進む前に、chunk 䞀般の構造を確認する。
- </p>
- <ol>
- <li>Length: chunk data のバむト長 (笊号なし 4 バむト敎数)</li>
- <li>Chunk type: chunk の皮類を瀺す 4 バむトからなる名前</li>
- <li>Chunk data: 実際のデヌタ。0 バむトでもよい</li>
- <li>CRC: chunk type ず chunk data の CRC (笊号なし 4 バむト敎数)</li>
- </ol>
- <p>
- CRC (Cyclic Redundancy Check) は誀り怜出笊号の䞀皮。Go 蚀語では <code>hash/crc32</code> パッケヌゞにあるが、今回はこれも自前で実装する。PNG の仕様曞に C 蚀語のサンプルコヌドが茉っおいる (<a href="https://www.w3.org/TR/png/#D-CRCAppendix">D. Sample CRC implementation</a>) ので、これを Go に移怍する。
- </p>
- <codeblock language="go">
- <![CDATA[
- var (
- crcTable [256]uint32
- crcTableComputed bool
- )
-
- func makeCrcTable() {
- for n := 0; n < 256; n++ {
- c := uint32(n)
- for k := 0; k < 8; k++ {
- if (c & 1) != 0 {
- c = 0xEDB88320 ^ (c >> 1)
- } else {
- c = c >> 1
- }
- }
- crcTable[n] = c
- }
- crcTableComputed = true
- }
-
- func updateCrc(crc uint32, buf []byte) uint32 {
- if !crcTableComputed {
- makeCrcTable()
- }
-
- c := crc
- for n := 0; n < len(buf); n++ {
- c = crcTable[(c^uint32(buf[n]))&0xFF] ^ (c >> 8)
- }
- return c
- }
-
- func crc(buf []byte) uint32 {
- return updateCrc(0xFFFFFFFF, buf) ^ 0xFFFFFFFF
- }
- ]]>
- </codeblock>
- <p>
- できた <code>crc</code> 関数を䜿っお、chunk 䞀般を曞き蟌む関数も甚意しおおこう。
- </p>
- <codeblock language="go">
- <![CDATA[
- func writeChunk(w io.Writer, chunkType string, data []byte) {
- typeAndData := make([]byte, 0, len(chunkType)+len(data))
- typeAndData = append(typeAndData, []byte(chunkType)...)
- typeAndData = append(typeAndData, data...)
-
- binary.Write(w, binary.BigEndian, uint32(len(data)))
- binary.Write(w, binary.BigEndian, typeAndData)
- binary.Write(w, binary.BigEndian, crc(typeAndData))
- }
- ]]>
- </codeblock>
- <p>
- 仕様どおり、<code>chunkType</code> ず <code>data</code> から CRC を蚈算し、<code>data</code> の長さず合わせお曞き蟌んでいる。
- PNG では基本的に big endian を䜿うこずに泚意する。
- </p>
- <p>
- 準備ができたずころで、具䜓的な chunk を゚ンコヌドしおいく。
- </p>
- </section>
- <section id="ihdr-chunk">
- <h>IHDR chunk</h>
- <p>
- IHDR chunk は最初に配眮される chunk である。次のようなデヌタからなる。
- </p>
- <ol>
- <li>画像の幅 (笊号なし 4 バむト敎数)</li>
- <li>画像の高さ (笊号なし 4 バむト敎数)</li>
- <li>
- ビット深床 (笊号なし 1 バむト敎数)
- <ul>
- <li>1 色に䜿うビット数。1 ピクセルに 24 bit 䜿う truecolor 画像では 8 になる</li>
- </ul>
- </li>
- <li>
- 色タむプ (笊号なし 1 バむト敎数)
- <ul>
- <li>0: グレヌスケヌル</li>
- <li>2: Truecolor (今回はこれに決め打ち)</li>
- <li>3: パレットのむンデックス</li>
- <li>4: グレヌスケヌル + アルファ</li>
- <li>6: Truecolor + アルファ</li>
- </ul>
- </li>
- <li>
- 圧瞮方匏 (笊号なし 1 バむト敎数)
- <ul>
- PNG の仕様曞に 0 しか定矩されおいないので 0 で固定
- </ul>
- </li>
- <li>
- フィルタ方匏 (笊号なし 1 バむト敎数)
- <ul>
- PNG の仕様曞に 0 しか定矩されおいないので 0 で固定
- </ul>
- </li>
- <li>
- むンタヌレヌス方匏 (笊号なし 1 バむト敎数)
- <ul>
- 今回はむンタヌレヌスしないので 0
- </ul>
- </li>
- </ol>
- <p>
- 今回ほずんどのデヌタは決め打ちするので、デヌタに応じお倉わるのは width ず height だけになる。コヌドは次のようになる。
- </p>
- <codeblock language="go">
- <![CDATA[
- import "bytes"
-
- func writeChunkIhdr(w io.Writer, width, height uint32) {
- var buf bytes.Buffer
- binary.Write(&buf, binary.BigEndian, width)
- binary.Write(&buf, binary.BigEndian, height)
- binary.Write(&buf, binary.BigEndian, uint8(8))
- binary.Write(&buf, binary.BigEndian, uint8(2))
- binary.Write(&buf, binary.BigEndian, uint8(0))
- binary.Write(&buf, binary.BigEndian, uint8(0))
- binary.Write(&buf, binary.BigEndian, uint8(0))
-
- writeChunk(w, "IHDR", buf.Bytes())
- }
- ]]>
- </codeblock>
- </section>
- <section id="idat-chunk">
- <h>IDAT chunk</h>
- <p>
- IDAT chunk は、実際の画像デヌタが栌玍された chunk である。IDAT chunk は deflate アルゎリズムにより圧瞮され、zlib 圢匏で栌玍される。
- </p>
- <section id="zlib">
- <h>Zlib</h>
- <p>
- たずは zlib に぀いお確認する。おおよそ次のような構造になっおいる。
- </p>
- <ol>
- <li>固定で 0x78 (笊号なし 1 バむト敎数)</li>
- <li>固定で 0x01 (笊号なし 1 バむト敎数)</li>
- <li>デヌタ</li>
- <li>デヌタの Adler-32</li>
- </ol>
- <p>
- 最初の 2 バむトにも意味はあるが、PNG では固定で構わない。
- </p>
- <p>
- Adler-32 も CRC ず同じく誀り怜出笊号である。こちらも zlib の仕様曞に C 蚀語でサンプルコヌドが蚘茉されおいる (<a href="https://www.rfc-editor.org/rfc/rfc1950#section-9">9. Appendix: Sample code</a>) ので、Go に移怍する。
- </p>
- <codeblock language="go">
- <![CDATA[
- const adler32Base = 65521
-
- func updateAdler32(adler uint32, buf []byte) uint32 {
- s1 := adler & 0xFFFF
- s2 := (adler >> 16) & 0xFFFF
-
- for n := 0; n < len(buf); n++ {
- s1 = (s1 + uint32(buf[n])) % adler32Base
- s2 = (s2 + s1) % adler32Base
- }
- return (s2 << 16) + s1
- }
-
- func adler32(buf []byte) uint32 {
- return updateAdler32(1, buf)
- }
- ]]>
- </codeblock>
- <p>
- 「デヌタ」の郚分には圧瞮したデヌタが入るのだが、真面目に deflate アルゎリズムを実装する必芁はない。Zlib には無圧瞮のデヌタブロックを栌玍するこずができるので、これを䜿う。本来は、デヌタの圧瞮効率の悪いランダムなデヌタをそのたた栌玍するためのものだが、今回は deflate の実装をサボるために䜿う。
- </p>
- <p>
- 1 ぀の無圧瞮ブロックには 65535 (2<sup>16</sup> - 1) バむトたで栌玍できる。それぞれのブロックは次のような構成になっおいる。
- </p>
- <ol>
- <li>最終ブロックなら 1、そうでなければ 0 (笊号なし 1 バむト敎数)</li>
- <li>ブロックのバむト長 (笊号なし 2 バむト敎数)</li>
- <li>ブロックのバむト長の 1 の補数、あるいはビット反転 (笊号なし 2 バむト敎数)</li>
- <li>デヌタ (最倧 65535 バむト)</li>
- </ol>
- <p>
- 実際にこの手抜き zlib を実装したものがこちら:
- </p>
- <codeblock language="go">
- <![CDATA[
- func encodeZlib(data []byte) []byte {
- var buf bytes.Buffer
-
- binary.Write(&buf, binary.BigEndian, uint8(0x78))
- binary.Write(&buf, binary.BigEndian, uint8(0x01))
- blockSize := 65535
- isFinalBlock := false
- for i := 0; !isFinalBlock; i++ {
- var block []byte
- if len(data) <= (i+1)*blockSize {
- block = data[i*blockSize:]
- isFinalBlock = true
- } else {
- block = data[i*blockSize : (i+1)*blockSize]
- }
- binary.Write(&buf, binary.BigEndian, isFinalBlock)
- binary.Write(&buf, binary.LittleEndian, uint16(len(block)))
- binary.Write(&buf, binary.LittleEndian, uint16(^len(block)))
- binary.Write(&buf, binary.LittleEndian, block)
- }
- binary.Write(&buf, binary.BigEndian, adler32(data))
-
- return buf.Bytes()
- }
- ]]>
- </codeblock>
- </section>
- <section id="image-data">
- <h>画像デヌタ</h>
- <p>
- では次に、zlib 圢匏で栌玍するデヌタを甚意する。PNG 画像は次のような順にスキャンする。
- 画像の巊䞊のピクセルから同じ行を暪にスキャンしおいき、䞀番右たで到達したら次の行の巊に向かう。
- 右䞋のピクセルたで行けば終わり。芁は Z 字型に進んでいく。
- </p>
- <p>
- たた、それぞれの行の先頭には、圧瞮のためのフィルタタむプを指定する。
- ただ、今回はその実装を省略するために、垞にフィルタ 0 (䜕も加工しない) を䜿う。
- </p>
- <p>
- 先ほどの <code>encodeZlib</code> も䜿っお実際に実装したものがこちら:
- </p>
- <codeblock language="go">
- <![CDATA[
- func writeChunkIdat(w io.Writer, width, height uint32, img image.Image) {
- var pixels bytes.Buffer
- for y := uint32(0); y < height; y++ {
- binary.Write(&pixels, binary.BigEndian, uint8(0))
- for x := uint32(0); x < width; x++ {
- r, g, b, _ := img.At(int(x), int(y)).RGBA()
- binary.Write(&pixels, binary.BigEndian, uint8(r))
- binary.Write(&pixels, binary.BigEndian, uint8(g))
- binary.Write(&pixels, binary.BigEndian, uint8(b))
- }
- }
-
- writeChunk(w, "IDAT", encodeZlib(pixels.Bytes()))
- }
- ]]>
- </codeblock>
- </section>
- </section>
- <section id="iend-chunk">
- <h>IEND chunk</h>
- <p>
- 最埌に IEND chunk を曞き蟌む。これは PNG 画像の最埌に配眮される chunk で、PNG のデコヌダはこの chunk に出䌚うずそこでデコヌドを停止する。
- </p>
- <p>
- 特に远加のデヌタはなく、必芁なのは chunk type の <code>IEND</code> くらいなので実装は簡単:
- </p>
- <codeblock language="go">
- <![CDATA[
- func writeChunkIend(w io.Writer) {
- writeChunk(w, "IEND", nil)
- }
- ]]>
- </codeblock>
- </section>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- 最埌に党゜ヌスコヌドを再掲しおおく。
- </p>
- <codeblock language="go">
- <![CDATA[
- package main
-
- import (
- "bytes"
- "encoding/binary"
- "image"
- _ "image/png"
- "io"
- "os"
- )
-
- func main() {
- inFile, err := os.Open("input.png")
- if err != nil {
- panic(err)
- }
- defer inFile.Close()
-
- img, _, err := image.Decode(inFile)
- if err != nil {
- panic(err)
- }
-
- outFile, err := os.Create("output.png")
- if err != nil {
- panic(err)
- }
- defer outFile.Close()
-
- writePng(outFile, img)
- }
-
- func writePng(w io.Writer, img image.Image) {
- width := uint32(img.Bounds().Dx())
- height := uint32(img.Bounds().Dy())
- writeSignature(w)
- writeChunkIhdr(w, width, height)
- writeChunkIdat(w, width, height, img)
- writeChunkIend(w)
- }
-
- func writeSignature(w io.Writer) {
- sig := [8]uint8{
- 0x89,
- 0x50, // P
- 0x4E, // N
- 0x47, // G
- 0x0D, // CR
- 0x0A, // LF
- 0x1A, // EOF (^Z)
- 0x0A, // LF
- }
- binary.Write(w, binary.BigEndian, sig)
- }
-
- func writeChunkIhdr(w io.Writer, width, height uint32) {
- var buf bytes.Buffer
- binary.Write(&buf, binary.BigEndian, width)
- binary.Write(&buf, binary.BigEndian, height)
- binary.Write(&buf, binary.BigEndian, uint8(8))
- binary.Write(&buf, binary.BigEndian, uint8(2))
- binary.Write(&buf, binary.BigEndian, uint8(0))
- binary.Write(&buf, binary.BigEndian, uint8(0))
- binary.Write(&buf, binary.BigEndian, uint8(0))
-
- writeChunk(w, "IHDR", buf.Bytes())
- }
-
- func writeChunkIdat(w io.Writer, width, height uint32, img image.Image) {
- var pixels bytes.Buffer
- for y := uint32(0); y < height; y++ {
- binary.Write(&pixels, binary.BigEndian, uint8(0))
- for x := uint32(0); x < width; x++ {
- r, g, b, _ := img.At(int(x), int(y)).RGBA()
- binary.Write(&pixels, binary.BigEndian, uint8(r))
- binary.Write(&pixels, binary.BigEndian, uint8(g))
- binary.Write(&pixels, binary.BigEndian, uint8(b))
- }
- }
-
- writeChunk(w, "IDAT", encodeZlib(pixels.Bytes()))
- }
-
- func encodeZlib(data []byte) []byte {
- var buf bytes.Buffer
-
- binary.Write(&buf, binary.BigEndian, uint8(0x78))
- binary.Write(&buf, binary.BigEndian, uint8(0x01))
- blockSize := 65535
- isFinalBlock := false
- for i := 0; !isFinalBlock; i++ {
- var block []byte
- if len(data) <= (i+1)*blockSize {
- block = data[i*blockSize:]
- isFinalBlock = true
- } else {
- block = data[i*blockSize : (i+1)*blockSize]
- }
- binary.Write(&buf, binary.BigEndian, isFinalBlock)
- binary.Write(&buf, binary.LittleEndian, uint16(len(block)))
- binary.Write(&buf, binary.LittleEndian, uint16(^len(block)))
- binary.Write(&buf, binary.LittleEndian, block)
- }
- binary.Write(&buf, binary.BigEndian, adler32(data))
-
- return buf.Bytes()
- }
-
- func writeChunkIend(w io.Writer) {
- writeChunk(w, "IEND", nil)
- }
-
- func writeChunk(w io.Writer, chunkType string, data []byte) {
- typeAndData := make([]byte, 0, len(chunkType)+len(data))
- typeAndData = append(typeAndData, []byte(chunkType)...)
- typeAndData = append(typeAndData, data...)
-
- binary.Write(w, binary.BigEndian, uint32(len(data)))
- binary.Write(w, binary.BigEndian, typeAndData)
- binary.Write(w, binary.BigEndian, crc(typeAndData))
- }
-
- var (
- crcTable [256]uint32
- crcTableComputed bool
- )
-
- func makeCrcTable() {
- for n := 0; n < 256; n++ {
- c := uint32(n)
- for k := 0; k < 8; k++ {
- if (c & 1) != 0 {
- c = 0xEDB88320 ^ (c >> 1)
- } else {
- c = c >> 1
- }
- }
- crcTable[n] = c
- }
- crcTableComputed = true
- }
-
- func updateCrc(crc uint32, buf []byte) uint32 {
- if !crcTableComputed {
- makeCrcTable()
- }
-
- c := crc
- for n := 0; n < len(buf); n++ {
- c = crcTable[(c^uint32(buf[n]))&0xFF] ^ (c >> 8)
- }
- return c
- }
-
- func crc(buf []byte) uint32 {
- return updateCrc(0xFFFFFFFF, buf) ^ 0xFFFFFFFF
- }
-
- const adler32Base = 65521
-
- func updateAdler32(adler uint32, buf []byte) uint32 {
- s1 := adler & 0xFFFF
- s2 := (adler >> 16) & 0xFFFF
-
- for n := 0; n < len(buf); n++ {
- s1 = (s1 + uint32(buf[n])) % adler32Base
- s2 = (s2 + s1) % adler32Base
- }
- return (s2 << 16) + s1
- }
-
- func adler32(buf []byte) uint32 {
- return updateAdler32(1, buf)
- }
- ]]>
- </codeblock>
- </section>
- <section id="references">
- <h>参考</h>
- <ul>
- <li><a href="https://www.w3.org/TR/png">Portable Network Graphics (PNG) Specification (Third Edition)</a></li>
- <li><a href="https://www.rfc-editor.org/rfc/rfc1950">ZLIB Compressed Data Format Specification version 3.3</a></li>
- </ul>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2023-04-04/phperkaigi-2023-report.dj b/vhosts/blog/content/posts/2023-04-04/phperkaigi-2023-report.dj
new file mode 100644
index 00000000..e4047c79
--- /dev/null
+++ b/vhosts/blog/content/posts/2023-04-04/phperkaigi-2023-report.dj
@@ -0,0 +1,141 @@
+---
+[article]
+uuid = "21ce39f0-d613-45f2-a760-89c368892d77"
+title = "PHPerKaigi 2023 参加レポ"
+description = "2023-03-23 から 2023-03-25 にかけお開催された、PHPerKaigi 2023 に参加した。"
+tags = [
+ "conference",
+ "php",
+ "phperkaigi",
+]
+
+[[article.revisions]]
+date = "2023-04-04"
+remark = "公開"
+
+[[article.revisions]]
+date = "2023-06-28"
+remark = "トヌクセッションの蚘事版の執筆を䞭止"
+---
+{#intro}
+# はじめに
+
+2023-03-23 から 2023-03-25 にかけお開催された、 [PHPerKaigi 2023](https://phperkaigi.jp/2023/) に参加した。
+今幎は 2぀のセッションのスピヌカヌずしお、たた、圓日スタッフずしお参加した。
+
+昚幎、䞀昚幎の参加レポはこちら:
+
+* [PHPerKaigi 2022](/posts/2022-05-01/phperkaigi-2022/)
+* [PHPerKaigi 2021](/posts/2021-03-30/phperkaigi-2021/)
+
+{#as-speaker}
+# スピヌカヌずしお
+
+これたでずの最倧の違いずしお、今回はスピヌカヌずしお登壇した。たずはそれに぀いお曞く。2぀のセッションで登壇した。
+
+* 詳説「参照」PHP 凊理系の実装から参照を理解する
+
+ * [プロポヌザル](https://fortee.jp/phperkaigi-2023/proposal/95e4dd94-5fc7-40fe-9e1a-230e36404cbe)
+ * [スラむド](/slides/2023-03-24/phperkaigi-2023/)
+ * 解説蚘事 (執筆䞭) → 远蚘: 蚘事版の執筆は諊めた
+
+* PHPerチャレンゞ解説セッション - デゞタルサヌカス株匏䌚瀟
+
+ * [プロポヌザル](https://fortee.jp/phperkaigi-2023/proposal/524c9dca-1d70-4b32-a939-9c73ffe5cb48)
+ * [スラむド](/slides/2023-03-25/phperkaigi-2023-tokens/)
+ * 解説蚘事 (執筆䞭) → 远蚘: 蚘事版の執筆は諊めた
+
+PHPer チャレンゞの話に぀いおは埌述する。
+参照に぀いおは、PHP を曞き始めた頃からずっず疑問に思っおいたので、仕組みを理解する良い機䌚ずなった。
+
+{#as-staff}
+# 圓日スタッフずしお
+
+今回はスピヌカヌのみならず圓日スタッフずしおも参加した。
+カンファレンスのスタッフずしおの参加は初めおだったが、初参加のスタッフでもスムヌズに䜜業ができるような仕組みが敎えられおいた。
+
+PHPerKaigi は䞀般参加者の目線でもよくできたカンファレンスだなあずいう印象だったのだが、よりその思いを匷くした。
+なんずスタッフにずっおもよくできたカンファレンスなのである。
+
+反省点は私自身の最倧 HP がたったく足りおいなかったこずで、次の機䌚には最埌たで動けるようにしたいずころである。
+
+{#as-attendee}
+# 参加者ずしお
+
+{#recommended-sessions}
+## おすすめセッション
+
+5぀のセッションを厳遞した。
+
+[ブラりザの向こう偎で「200 OK」を返すたでに䜕が起きおいるのか調べおみた](https://fortee.jp/phperkaigi-2023/proposal/f7f2f18a-e6b0-47e4-ade0-e324f72428ae)
+
+Web に関わるなら、バック゚ンドでもフロント゚ンドでも知っおおいおほしい知識。
+タむトルを芋お「こんな話だろうな」ず想像が぀くレベルなら芋なくおもいいかも。
+
+[PHPで孊ぶ "Cacheの距離" の話](https://fortee.jp/phperkaigi-2023/proposal/280706e0-7158-4237-8202-c9d64330b96f)
+
+これも䞊セッションず同様に、基瀎を抑えられる良いセッション。
+
+[防衛的 PHP: 倚様性を生き抜くための PHP 入門](https://fortee.jp/phperkaigi-2023/proposal/ad3ba31c-0214-4557-a0df-3755db8ed8cc)
+
+静的解析ツヌルの話。静的解析は PHP のみならず最近の動的蚀語の䞀倧朮流なので、逃れられない。
+
+[PHPの最高機胜、配列を捚およう](https://fortee.jp/phperkaigi-2023/proposal/e00788a4-ef25-49ee-b254-9d2b53e19633)
+
+実はこれも䞊のセッションず同様の話。
+PHP の静的解析ツヌルは配列にも (無理矢理) 型が付けられるものが倚いが、実行時にも怜査できるずいう点においお専甚のクラスを䜜る方が優れおいる。
+
+[時間を気にせず普通にカンニングもし぀぀ ISUCON12 本遞問題を PHP でやっおみる](https://fortee.jp/phperkaigi-2023/proposal/7e212cb2-be37-43e8-b6ee-5236d259fcbf)
+
+個人的に最も楜しみにしおいたセッションであり、今回のモリアガリトヌク賞 (盛り䞊がったセッションに運営偎から莈られる賞) でもある。
+ネタバレになるが、最終的に (Go で実装された) 本戊優勝スコアを超えおいる。
+
+{#phper-challenge}
+## PHPer チャレンゞ
+
+昚幎に匕き続き、匊瀟デゞタルサヌカス株匏䌚瀟からのトヌクン問題の䜜題を担圓した。
+たた、今幎はさらに䜜成した問題を解説するセッションにも登壇した。
+今幎のトヌクンは、昚幎の PHPerKaigi 2022 が終わった段階から䜜り始め、玄半幎かけお制䜜した。
+
+問題の制䜜䞭は倧倉楜しかったが、たあやりすぎた。
+いかに超絶技巧を凝らすかに泚力しおしたい、解く楜しさずいう芳点を倱っおしたったきらいがある。
+
+(WIP: 解説ブログ蚘事執筆䞭。終わったらここにリンク)
+
+{#random-thoughts}
+## 雑倚な感想
+
+なんかいろいろ。
+
+* マカロンおいしかった
+* \\/
+* 名札䟿利
+* \\/
+* 傘袋䟿利
+* \\/
+* パヌカヌのデザむン良き
+
+(あずから芋返しお自分でもわけがわからなくなりそうなので曞いおおくず、䌚堎に入堎する際に名札をタッチするず小桜゚ツコさんの声で「ペチパヌ」ずいう音声が流れるギミックがあった)
+
+{#outro}
+# おわりに
+
+[去幎の参加レポ](/posts/2022-05-01/phperkaigi-2022/#section--next-year) では、来幎の目暙ずしお次を挙げた。
+
+> * プロポヌザルを出す
+> * PHPer チャレンゞのトヌクン問題を 5題䜜成する
+> * 珟地に行く
+> * PHPer チャレンゞで圧勝する
+
+プロポヌザルに関しおは採択されお登壇できたし、PHPer チャレンゞは解説もおこなった。たた、珟地に行くだけでなく、圓日スタッフずしお参加した。
+4぀目の PHPer チャレンゞに関しおは、今幎は参加しおいない。
+スタッフをやりながらだず入力する時間も探す時間も取れそうになかったのず、スタッフをやっおいる関係で少しだけ早く入手しおしたうトヌクンがいく぀か存圚しおいたため。
+
+カンファレンス党䜓の感想に぀いおだが、倧芏暡なカンファレンスにオフラむンで参加するのは今回が初めおだったので、その話をしたい。
+
+オンラむンずオフラむンだず䜓隓が別物になる。そもそもが䌌お非なるものなのだ。
+向き䞍向きはあるだろうが、オンラむンしか参加したこずのないずいう方は、䞀床珟地参加しおみおはいかがだろうか。
+
+さお、参加レポは去幎も䞀昚幎もこの蚀葉で締め括っおいるので、今幎もそれで終わろうず思う。
+
+ではたた来幎。
diff --git a/vhosts/blog/content/posts/2023-04-04/phperkaigi-2023-report.ndoc b/vhosts/blog/content/posts/2023-04-04/phperkaigi-2023-report.ndoc
deleted file mode 100644
index e9ad3d96..00000000
--- a/vhosts/blog/content/posts/2023-04-04/phperkaigi-2023-report.ndoc
+++ /dev/null
@@ -1,184 +0,0 @@
----
-[article]
-uuid = "21ce39f0-d613-45f2-a760-89c368892d77"
-title = "PHPerKaigi 2023 参加レポ"
-description = "2023-03-23 から 2023-03-25 にかけお開催された、PHPerKaigi 2023 に参加した。"
-tags = [
- "conference",
- "php",
- "phperkaigi",
-]
-
-[[article.revisions]]
-date = "2023-04-04"
-remark = "公開"
-
-[[article.revisions]]
-date = "2023-06-28"
-remark = "トヌクセッションの蚘事版の執筆を䞭止"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- 2023-03-23 から 2023-03-25 にかけお開催された、<a href="https://phperkaigi.jp/2023/">PHPerKaigi 2023</a> に参加した。
- 今幎は 2぀のセッションのスピヌカヌずしお、たた、圓日スタッフずしお参加した。
- </p>
- <p>
- 昚幎、䞀昚幎の参加レポはこちら:
- </p>
- <ul>
- <li><a href="/posts/2022-05-01/phperkaigi-2022/">PHPerKaigi 2022</a></li>
- <li><a href="/posts/2021-03-30/phperkaigi-2021/">PHPerKaigi 2021</a></li>
- </ul>
- </section>
- <section id="as-speaker">
- <h>スピヌカヌずしお</h>
- <p>
- これたでずの最倧の違いずしお、今回はスピヌカヌずしお登壇した。たずはそれに぀いお曞く。2぀のセッションで登壇した。
- </p>
- <ul>
- <li>
- 詳説「参照」PHP 凊理系の実装から参照を理解する
- <ul>
- <li><a href="https://fortee.jp/phperkaigi-2023/proposal/95e4dd94-5fc7-40fe-9e1a-230e36404cbe">プロポヌザル</a></li>
- <li><a href="/slides/2023-03-24/phperkaigi-2023/">スラむド</a></li>
- <li>解説蚘事 (執筆䞭) → 远蚘: 蚘事版の執筆は諊めた</li>
- </ul>
- </li>
- <li>
- PHPerチャレンゞ解説セッション - デゞタルサヌカス株匏䌚瀟
- <ul>
- <li><a href="https://fortee.jp/phperkaigi-2023/proposal/524c9dca-1d70-4b32-a939-9c73ffe5cb48">プロポヌザル</a></li>
- <li><a href="/slides/2023-03-25/phperkaigi-2023-tokens/">スラむド</a></li>
- <li>解説蚘事 (執筆䞭) → 远蚘: 蚘事版の執筆は諊めた</li>
- </ul>
- </li>
- </ul>
- <p>
- PHPer チャレンゞの話に぀いおは埌述する。
- 参照に぀いおは、PHP を曞き始めた頃からずっず疑問に思っおいたので、仕組みを理解する良い機䌚ずなった。
- </p>
- </section>
- <section id="as-staff">
- <h>圓日スタッフずしお</h>
- <p>
- 今回はスピヌカヌのみならず圓日スタッフずしおも参加した。
- カンファレンスのスタッフずしおの参加は初めおだったが、初参加のスタッフでもスムヌズに䜜業ができるような仕組みが敎えられおいた。
- </p>
- <p>
- PHPerKaigi は䞀般参加者の目線でもよくできたカンファレンスだなあずいう印象だったのだが、よりその思いを匷くした。
- なんずスタッフにずっおもよくできたカンファレンスなのである。
- </p>
- <p>
- 反省点は私自身の最倧 HP がたったく足りおいなかったこずで、次の機䌚には最埌たで動けるようにしたいずころである。
- </p>
- </section>
- <section id="as-attendee">
- <h>参加者ずしお</h>
- <section id="recommended-sessions">
- <h>おすすめセッション</h>
- <p>
- 5぀のセッションを厳遞した。
- </p>
- <p>
- <a href="https://fortee.jp/phperkaigi-2023/proposal/f7f2f18a-e6b0-47e4-ade0-e324f72428ae">ブラりザの向こう偎で「200 OK」を返すたでに䜕が起きおいるのか調べおみた</a>
- </p>
- <p>
- Web に関わるなら、バック゚ンドでもフロント゚ンドでも知っおおいおほしい知識。
- タむトルを芋お「こんな話だろうな」ず想像が぀くレベルなら芋なくおもいいかも。
- </p>
- <p>
- <a href="https://fortee.jp/phperkaigi-2023/proposal/280706e0-7158-4237-8202-c9d64330b96f">PHPで孊ぶ "Cacheの距離" の話</a>
- </p>
- <p>
- これも䞊セッションず同様に、基瀎を抑えられる良いセッション。
- </p>
- <p>
- <a href="https://fortee.jp/phperkaigi-2023/proposal/ad3ba31c-0214-4557-a0df-3755db8ed8cc">防衛的 PHP: 倚様性を生き抜くための PHP 入門</a>
- </p>
- <p>
- 静的解析ツヌルの話。静的解析は PHP のみならず最近の動的蚀語の䞀倧朮流なので、逃れられない。
- </p>
- <p>
- <a href="https://fortee.jp/phperkaigi-2023/proposal/e00788a4-ef25-49ee-b254-9d2b53e19633">PHPの最高機胜、配列を捚およう</a>
- </p>
- <p>
- 実はこれも䞊のセッションず同様の話。
- PHP の静的解析ツヌルは配列にも (無理矢理) 型が付けられるものが倚いが、実行時にも怜査できるずいう点においお専甚のクラスを䜜る方が優れおいる。
- </p>
- <p>
- <a href="https://fortee.jp/phperkaigi-2023/proposal/7e212cb2-be37-43e8-b6ee-5236d259fcbf">時間を気にせず普通にカンニングもし぀぀ ISUCON12 本遞問題を PHP でやっおみる</a>
- </p>
- <p>
- 個人的に最も楜しみにしおいたセッションであり、今回のモリアガリトヌク賞 (盛り䞊がったセッションに運営偎から莈られる賞) でもある。
- ネタバレになるが、最終的に (Go で実装された) 本戊優勝スコアを超えおいる。
- </p>
- </section>
- <section id="phper-challenge">
- <h>PHPer チャレンゞ</h>
- <p>
- 昚幎に匕き続き、匊瀟デゞタルサヌカス株匏䌚瀟からのトヌクン問題の䜜題を担圓した。
- たた、今幎はさらに䜜成した問題を解説するセッションにも登壇した。
- 今幎のトヌクンは、昚幎の PHPerKaigi 2022 が終わった段階から䜜り始め、玄半幎かけお制䜜した。
- </p>
- <p>
- 問題の制䜜䞭は倧倉楜しかったが、たあやりすぎた。
- いかに超絶技巧を凝らすかに泚力しおしたい、解く楜しさずいう芳点を倱っおしたったきらいがある。
- </p>
- <p>
- (WIP: 解説ブログ蚘事執筆䞭。終わったらここにリンク)
- </p>
- </section>
- <section id="random-thoughts">
- <h>雑倚な感想</h>
- <p>
- なんかいろいろ。
- </p>
- <ul>
- <li>マカロンおいしかった</li>
- <li>\/</li>
- <li>名札䟿利</li>
- <li>\/</li>
- <li>傘袋䟿利</li>
- <li>\/</li>
- <li>パヌカヌのデザむン良き</li>
- </ul>
- <p>
- (あずから芋返しお自分でもわけがわからなくなりそうなので曞いおおくず、䌚堎に入堎する際に名札をタッチするず小桜゚ツコさんの声で「ペチパヌ」ずいう音声が流れるギミックがあった)
- </p>
- </section>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- <a href="/posts/2022-05-01/phperkaigi-2022/#section--next-year">去幎の参加レポ</a>では、来幎の目暙ずしお次を挙げた。
- </p>
- <blockquote>
- <ul>
- <li>プロポヌザルを出す</li>
- <li>PHPer チャレンゞのトヌクン問題を 5題䜜成する</li>
- <li>珟地に行く</li>
- <li>PHPer チャレンゞで圧勝する</li>
- </ul>
- </blockquote>
- <p>
- プロポヌザルに関しおは採択されお登壇できたし、PHPer チャレンゞは解説もおこなった。たた、珟地に行くだけでなく、圓日スタッフずしお参加した。
- 4぀目の PHPer チャレンゞに関しおは、今幎は参加しおいない。
- スタッフをやりながらだず入力する時間も探す時間も取れそうになかったのず、スタッフをやっおいる関係で少しだけ早く入手しおしたうトヌクンがいく぀か存圚しおいたため。
- </p>
- <p>
- カンファレンス党䜓の感想に぀いおだが、倧芏暡なカンファレンスにオフラむンで参加するのは今回が初めおだったので、その話をしたい。
- </p>
- <p>
- オンラむンずオフラむンだず䜓隓が別物になる。そもそもが䌌お非なるものなのだ。
- 向き䞍向きはあるだろうが、オンラむンしか参加したこずのないずいう方は、䞀床珟地参加しおみおはいかがだろうか。
- </p>
- <p>
- さお、参加レポは去幎も䞀昚幎もこの蚀葉で締め括っおいるので、今幎もそれで終わろうず思う。
- </p>
- <p>
- ではたた来幎。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2023-06-25/phpconfuk-2023-report.dj b/vhosts/blog/content/posts/2023-06-25/phpconfuk-2023-report.dj
new file mode 100644
index 00000000..ba1b7d6e
--- /dev/null
+++ b/vhosts/blog/content/posts/2023-06-25/phpconfuk-2023-report.dj
@@ -0,0 +1,64 @@
+---
+[article]
+uuid = "e1568c4c-9bdd-47b9-8b39-939ade4f3ba0"
+title = "PHP カンファレンス犏岡 2023 参加レポ"
+description = "2023-06-24 に開催された、PHP カンファレンス犏岡に参加した。"
+tags = [
+ "conference",
+ "php",
+ "phpconfuk",
+]
+
+[[article.revisions]]
+date = "2023-06-25"
+remark = "公開"
+---
+{#intro}
+# はじめに
+
+2023-06-24 に開催された、 [PHP カンファレンス犏岡 2023](https://phpcon.fukuoka.jp/2023/) に参加した。
+たた、その前日に催された、 [非公匏の前倜祭](https://connpass.com/event/282285/) にも参加した。
+前倜祭では、15分の登壇もおこなった。 [登壇の方の資料はこちら。](/slides/2023-06-23/phpconfuk-2023-eve/)
+
+{#sessions-thoughts}
+# セッションの感想
+
+{#eve}
+## 前倜祭
+
+※セッションの題名ず発衚者名は、 [前倜祭むベントの connpass ペヌゞ](https://connpass.com/event/282285/) から匕甚。
+
+* スクラムの䞀郚を導入しおよくなったこず (asumikam さん)
+
+ * スクラムの「䞀郚」を導入されたずいうこずでしたが、理想的な圢で改善が進んでいるように芋受けられたした。特に、ブランチ運甚やデプロむ頻床、フィヌドバックサむクルに倧きく倉化が起きおいるのは驚くべき成果だず感じたした。
+
+* 地方の小さな勉匷䌚を䞀番の掻動舞台にする (tomio さん)
+
+ * すさたじいほどの「熱」を感じたした。私自身、最近になっおカンファレンスや勉匷䌚ぞの参加・登壇を掻発におこなうようになったこずで、頷く点が倚かったです。
+
+{#conference}
+## カンファレンス
+
+※セッションの題名ず発衚者名は、 [カンファレンスの fortee ペヌゞ](https://fortee.jp/phpconfukuoka-2023/proposal/accepted) から匕甚。
+
+* [育成力 - ゚ンゞニアの才胜を匕き出す環境ずチュヌタヌの立ち回り - (岡嵜 雄平 さん)](https://fortee.jp/phpconfukuoka-2023/proposal/df5f06e8-900e-4e71-94d7-d0c3cc57a0ac)
+
+ * ちょうど匊チヌムに新芏メンバがゞョむンしたばかりで、オンボヌディングプロセスに぀いお考えおいたずころの発衚でした。すぐにすべおを取り入れるずいうわけにはいきたせんが、匊瀟での新人育成プロセスの改善に぀ながるヒントをいく぀か埗られたず思いたす。
+
+* オブゞェクト指向は本圓に必芁か (たなかひさおる さん、こいほげ さん)
+
+ * ※圓日 D ホヌルでおこなわれたアンカンファレンスセッションのため、正匏タむトル・リンクなし
+ * 私自身、「オブゞェクト指向」に぀いおは色々ず蚀いたいこずがあるのですが、だいたいツむヌトしたこれずこれです。
+
+ * 「オブゞェクト指向の話は、パラダむムの異なる耇数の蚀語に觊れおいるかどうかで芋え方がたったく異なる印象がある。OOPはどうでもいいです (※個人の感想です)」 ( [Twitter のツむヌトぞのリンク](https://twitter.com/nsfisis/status/1672502935983656960) )
+ * 「OOPは珟代の蚀語で考える意味はほがない叀いパラダむムだよずいう立堎ですが、OOPに぀いおあたり倧っぎらに話しおるず色んなずころから刺されそうなんですよね (Twitterは倧っぎらじゃないんですか)」 ( [Twitter のツむヌトぞのリンク](https://twitter.com/nsfisis/status/1672504892244787201) )
+
+* [その説明、コヌドコメントに曞くコミットメッセヌゞに曞くプルリク゚ストに曞く (おかしょい岡田正平 さん)](https://fortee.jp/phpconfukuoka-2023/proposal/ae71f3a7-4c3c-4c87-8816-8426bcc8d325)
+
+ * Twitter にもツむヌトしたしたが、完党に自分の意芋ず䞀臎しおいたので、ずおも共感できたした。今埌は瀟内のコヌドレビュヌ時に、こちらの資料を貌り぀けるこずにしたす。
+
+{#outro}
+# おわりに
+
+居䜏地域から離れた堎所ぞの遠埁参加は初めおだったが、倧倉楜しい (しかも勉匷にもなる) 䜓隓だった。
+受け取った「熱」が冷める前に、自らの手を動かしおいきたい。
diff --git a/vhosts/blog/content/posts/2023-06-25/phpconfuk-2023-report.ndoc b/vhosts/blog/content/posts/2023-06-25/phpconfuk-2023-report.ndoc
deleted file mode 100644
index 39763514..00000000
--- a/vhosts/blog/content/posts/2023-06-25/phpconfuk-2023-report.ndoc
+++ /dev/null
@@ -1,106 +0,0 @@
----
-[article]
-uuid = "e1568c4c-9bdd-47b9-8b39-939ade4f3ba0"
-title = "PHP カンファレンス犏岡 2023 参加レポ"
-description = "2023-06-24 に開催された、PHP カンファレンス犏岡に参加した。"
-tags = [
- "conference",
- "php",
- "phpconfuk",
-]
-
-[[article.revisions]]
-date = "2023-06-25"
-remark = "公開"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- 2023-06-24 に開催された、<a href="https://phpcon.fukuoka.jp/2023/">PHP カンファレンス犏岡 2023</a>に参加した。
- たた、その前日に催された、<a href="https://connpass.com/event/282285/">非公匏の前倜祭</a>にも参加した。
- 前倜祭では、15分の登壇もおこなった。<a href="/slides/2023-06-23/phpconfuk-2023-eve/">登壇の方の資料はこちら。</a>
- </p>
- </section>
- <section id="sessions-thoughts">
- <h>セッションの感想</h>
- <section id="eve">
- <h>前倜祭</h>
- <p>
- ※セッションの題名ず発衚者名は、<a href="https://connpass.com/event/282285/">前倜祭むベントの connpass ペヌゞ</a>から匕甚。
- </p>
- <ul>
- <li>
- スクラムの䞀郚を導入しおよくなったこず (asumikam さん)
- <ul>
- <li>
- スクラムの「䞀郚」を導入されたずいうこずでしたが、理想的な圢で改善が進んでいるように芋受けられたした。
- 特に、ブランチ運甚やデプロむ頻床、フィヌドバックサむクルに倧きく倉化が起きおいるのは驚くべき成果だず感じたした。
- </li>
- </ul>
- </li>
- <li>
- 地方の小さな勉匷䌚を䞀番の掻動舞台にする (tomio さん)
- <ul>
- <li>
- すさたじいほどの「熱」を感じたした。
- 私自身、最近になっおカンファレンスや勉匷䌚ぞの参加・登壇を掻発におこなうようになったこずで、頷く点が倚かったです。
- </li>
- </ul>
- </li>
- </ul>
- </section>
- <section id="conference">
- <h>カンファレンス</h>
- <p>
- ※セッションの題名ず発衚者名は、<a href="https://fortee.jp/phpconfukuoka-2023/proposal/accepted">カンファレンスの fortee ペヌゞ</a>から匕甚。
- </p>
- <ul>
- <li>
- <a href="https://fortee.jp/phpconfukuoka-2023/proposal/df5f06e8-900e-4e71-94d7-d0c3cc57a0ac">育成力 - ゚ンゞニアの才胜を匕き出す環境ずチュヌタヌの立ち回り - (岡嵜 雄平 さん)</a>
- <ul>
- <li>
- ちょうど匊チヌムに新芏メンバがゞョむンしたばかりで、オンボヌディングプロセスに぀いお考えおいたずころの発衚でした。
- すぐにすべおを取り入れるずいうわけにはいきたせんが、匊瀟での新人育成プロセスの改善に぀ながるヒントをいく぀か埗られたず思いたす。
- </li>
- </ul>
- </li>
- <li>
- オブゞェクト指向は本圓に必芁か (たなかひさおる さん、こいほげ さん)
- <ul>
- <li>
- ※圓日 D ホヌルでおこなわれたアンカンファレンスセッションのため、正匏タむトル・リンクなし
- </li>
- <li>
- 私自身、「オブゞェクト指向」に぀いおは色々ず蚀いたいこずがあるのですが、だいたいツむヌトしたこれずこれです。
- <ul>
- <li>
- 「オブゞェクト指向の話は、パラダむムの異なる耇数の蚀語に觊れおいるかどうかで芋え方がたったく異なる印象がある。OOPはどうでもいいです (※個人の感想です)」 (<a href="https://twitter.com/nsfisis/status/1672502935983656960">Twitter のツむヌトぞのリンク</a>)
- </li>
- <li>
- 「OOPは珟代の蚀語で考える意味はほがない叀いパラダむムだよずいう立堎ですが、OOPに぀いおあたり倧っぎらに話しおるず色んなずころから刺されそうなんですよね (Twitterは倧っぎらじゃないんですか)」 (<a href="https://twitter.com/nsfisis/status/1672504892244787201">Twitter のツむヌトぞのリンク</a>)
- </li>
- </ul>
- </li>
- </ul>
- </li>
- <li>
- <a href="https://fortee.jp/phpconfukuoka-2023/proposal/ae71f3a7-4c3c-4c87-8816-8426bcc8d325">その説明、コヌドコメントに曞くコミットメッセヌゞに曞くプルリク゚ストに曞く (おかしょい岡田正平 さん)</a>
- <ul>
- <li>
- Twitter にもツむヌトしたしたが、完党に自分の意芋ず䞀臎しおいたので、ずおも共感できたした。
- 今埌は瀟内のコヌドレビュヌ時に、こちらの資料を貌り぀けるこずにしたす。
- </li>
- </ul>
- </li>
- </ul>
- </section>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- 居䜏地域から離れた堎所ぞの遠埁参加は初めおだったが、倧倉楜しい (しかも勉匷にもなる) 䜓隓だった。
- 受け取った「熱」が冷める前に、自らの手を動かしおいきたい。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2023-10-02/compile-php-runtime-to-wasm.dj b/vhosts/blog/content/posts/2023-10-02/compile-php-runtime-to-wasm.dj
new file mode 100644
index 00000000..da7438ab
--- /dev/null
+++ b/vhosts/blog/content/posts/2023-10-02/compile-php-runtime-to-wasm.dj
@@ -0,0 +1,286 @@
+---
+[article]
+uuid = "0ed1ccc8-d437-481c-8cca-2131ce800cc0"
+title = "PHP の凊理系を Emscripten で WebAssembly にコンパむルする"
+description = "PHP の凊理系 (php/php-src) を Emscripten で WebAssembly にコンパむルし、任意のコヌドを隔離された環境で評䟡できるようにした。"
+tags = [
+ "php",
+ "wasm",
+]
+
+[[article.revisions]]
+date = "2023-10-02"
+remark = "公開"
+---
+{#intro}
+# はじめに
+
+[Emscripten](https://emscripten.org/) を甚いお [PHP の凊理系](https://github.com/php/php-src) を [WebAssembly](https://developer.mozilla.org/docs/WebAssembly) にコンパむルした。機胜をある皋床絞るこずで、思ったよりも簡単に実珟できたので、備忘録ずしお蚘しおおく。
+
+なお、この蚘事では Emscripten や WebAssembly ずは䜕か知っおいるこずを前提ずする。
+
+{#version}
+# バヌゞョン情報
+
+この蚘事䞭で䜿甚する゜フトりェア等のバヌゞョンを蚘茉する。
+
+* Ubuntu 22.04 on WSL2
+* Docker version 24.0.6
+* Emscripten 3.1.46
+* Node.js 20.7.0
+* PHP 8.2.10
+
+なお、Docker から䞋は Docker 䞊で導入するので、ホストマシンにはむンストヌルしなくおよい。
+
+{#goal}
+# 本蚘事のゎヌル
+
+先にこの蚘事のゎヌルを瀺しおおく。これから瀺す手順のずおりに進めるず、次のようなコヌドが動くようになる。
+このコヌドはこのあず䜿うので、`index.mjs` の名前で保存しおおくこず。
+
+```javascript
+import { readFile } from 'node:fs/promises';
+import PHPWasm from './php-wasm.mjs'
+
+const code = await readFile('/dev/stdin', { encoding: 'utf-8' });
+
+const { ccall } = await PHPWasm();
+const result = ccall(
+ 'php_wasm_run',
+ 'number', ['string'],
+ [code],
+);
+console.log(`exit code: ${result}`);
+```
+
+暙準入力から䞎えたコヌドを WebAssembly にコンパむルされた PHP 凊理系の䞊で実行しおいる。このような `php-wasm.mjs` (ずそこから呌び出される `php-wasm.wasm`) を䜜成する。
+
+{#build}
+# ビルド
+
+{#write-c-entrypoint}
+## C の゚ントリポむントを曞く
+
+先ほどのコヌドでも䜿っおいた゚ントリポむントである `php_wasm_run` を甚意する。
+
+```c
+#include <stdio.h>
+#include <emscripten.h>
+#include <Zend/zend_execute.h>
+#include <sapi/embed/php_embed.h>
+
+int EMSCRIPTEN_KEEPALIVE php_wasm_run(const char* code) {
+ zend_result result;
+
+ int argc = 1;
+ char* argv[] = { "php.wasm", NULL };
+
+ PHP_EMBED_START_BLOCK(argc, argv);
+
+ result = zend_eval_string_ex(code, NULL, "php.wasm code", 1);
+
+ PHP_EMBED_END_BLOCK();
+
+ fprintf(stdout, "\n");
+ fflush(stdout);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+
+ return result == SUCCESS ? 0 : 1;
+}
+```
+
+ほずんどはただの PHP の公開 API を䜿ったコヌドだが、Emscripten 向けの泚意点が 2点ある。
+
+たずは `EMSCRIPTEN_KEEPALIVE` に぀いお。
+これは Emscripten が甚意しおいる特殊なマクロである。
+このマクロが付䞎されおいる関数は、どこからも䜿甚されおいなくずもコンパむル埌の WebAssembly バむナリから削陀されない。
+もしこれを付け忘れるず、未䜿甚の関数ずみなされ削陀される。
+
+次に、コヌドを評䟡したあずに呌んでいる暙準出力ず暙準゚ラヌ出力に察する改行の出力に぀いお。
+出力バッファから出力させるためだけなら改行を出力させなくずも `fflush()` だけで事足りるず考えたのだが、ないず動かなかったので远加した。
+これにより、PHP コヌドの出力の埌ろに䜙分な改行が远加されおしたう。
+改行を出力せずずもバッファを消費させる手段をご存知のかたはご教瀺願いたい。
+
+{#compile-to-wasm}
+## WebAssembly にコンパむルする
+
+それでは WebAssembly にコンパむルしおいこう。ここからは `Dockerfile` 䞊のコマンドずしお操䜜を瀺す。
+
+たずは [Emscripten 公匏が提䟛しおいる Docker むメヌゞ](https://hub.docker.com/r/emscripten/emsdk) を䜿っお、PHP 凊理系ず先ほど瀺した C 蚀語の゜ヌスコヌドを WebAssembly にコンパむルする。
+
+```dockerfile
+FROM emscripten/emsdk:3.1.46 AS wasm-builder
+```
+
+次に、 [php/php-src](https://github.com/php/php-src) から PHP 凊理系の゜ヌスコヌドを取埗し、ビルドに必芁な apt パッケヌゞを取っおくる。
+有効にする拡匵を増やしたいなら、ここでむンストヌルするパッケヌゞも増やすこずになるだろう。
+
+```dockerfile
+RUN git clone --depth=1 --branch=php-8.2.10 https://github.com/php/php-src
+
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends \
+ autoconf \
+ bison \
+ pkg-config \
+ re2c \
+ && \
+ :
+```
+
+続けお、Emscripten のツヌルチェむンを甚いお PHP 凊理系をビルドする。
+
+```dockerfile
+RUN cd php-src && \
+ ./buildconf --force && \
+ emconfigure ./configure \
+ --disable-all \
+ --disable-mbregex \
+ --disable-fiber-asm \
+ --disable-cli \
+ --disable-cgi \
+ --disable-phpdbg \
+ --enable-embed=static \
+ --enable-mbstring \
+ --without-iconv \
+ --without-libxml \
+ --without-pcre-jit \
+ --without-pdo-sqlite \
+ --without-sqlite3 \
+ && \
+ EMCC_CFLAGS='-s ERROR_ON_UNDEFINED_SYMBOLS=0' emmake make -j$(nproc) && \
+ mv libs/libphp.a .. && \
+ make clean && \
+ git clean -fd && \
+ :
+```
+
+ここたでず比べるず少し耇雑なので、それぞれ詳しく芋おいこう。
+
+たず、`buildconf` は PHP 凊理系をビルドするずきに (Emscripten ずは関係なく) 䜿うツヌルである。
+このツヌルの最も重芁な仕事は、`configure` の生成である。
+
+次に `configure` するわけだが、ここで `emconfigure` を䜿う。
+これを䜿うこずで、Emscripten が䞊手く諞々のツヌルチェむンを WebAssembly のビルド向けに調敎しながら `configure` しおくれる。
+
+`configure` の埌ろに指定しおあるフラグは、通垞の PHP 凊理系のビルドで䜿う `configure` ず同じなので、詳しくはそちらの `cofigure --help` を参照しおいただきたい。
+ほずんどは、機胜の無効化のために指定しおいる (䟝存するラむブラリを枛らし、ビルドをより簡単にするため)。
+
+通垞の C のビルドなら、`configure` の次は `make` するずころだが、ここでも `emmake` を䜿う。
+圹割はほずんど `emconfigure` ず同様である。
+指定しおある `EMCC_CFLAGS` ずいう環境倉数は、Emscripten の C コンパむラぞのフラグで、ここでは `ERROR_ON_UNDEFINED_SYMBOLS` を無効化しおいる。
+これにより、コンパむル䞭に出珟した解決できなかったシンボルを無芖するようになる (代わりに、そのシンボルを呌がうずしたタむミングで実行時゚ラヌになる)。
+すべおの䟝存を完党に解決するのは面倒なので、あたり䜿わない機胜に぀いおは無芖しおもよいだろう。
+
+ここたでを実行するず `libs/libphp.a` が生成される。これは埌で䜿うので移動させおいる。
+
+さお、PHP 凊理系をラむブラリ化できたので、次に先ほど茉せた C の゜ヌスコヌドをビルドしおいこう。
+`Dockerfile` ず同じ堎所に `php-wasm.c` ずいう名前で保存し、次のようにする。
+
+```dockerfile
+COPY php-wasm.c /src/
+
+RUN cd php-src && \
+ emcc \
+ -c \
+ -o php-wasm.o \
+ -I . \
+ -I TSRM \
+ -I Zend \
+ -I main \
+ ../php-wasm.c \
+ && \
+ mv php-wasm.o .. && \
+ make clean && \
+ git clean -fd && \
+ :
+```
+
+`emcc` は `cc` (C コンパむラ/リンカ) の Emscripten 版で、`-c` は「コンパむル」の意。
+`-o` や `-I` は普通の C コンパむラず同様、出力ファむルの指定ずむンクルヌドパスの指定である。
+
+`libphp.a` ず `php-wasm.o` が手に入ったので、これらをリンクしお WebAssembly のバむナリずそのラッパである JavaScript ファむルを生成する。
+これにも `emcc` コマンドを䜿う。
+
+```dockerfile
+RUN emcc \
+ -s ENVIRONMENT=node \
+ -s ERROR_ON_UNDEFINED_SYMBOLS=0 \
+ -s EXPORTED_RUNTIME_METHODS='["ccall"]' \
+ -s EXPORT_ES6=1 \
+ -s INITIAL_MEMORY=16777216 \
+ -s INVOKE_RUN=0 \
+ -s MODULARIZE=1 \
+ -o php-wasm.js \
+ php-wasm.o \
+ libphp.a \
+ ;
+```
+
+それぞれのフラグに぀いお解説する。
+
+`-s ENVIRONMENT=node` は、生成する WebAssembly/JavaScript の実行環境を指定する。
+今回は `node` を指定しおいるので、Node.js 向けのファむルが生成される。
+
+`-s ERROR_ON_UNDEFINED_SYMBOLS=0` に぀いおはすでに述べたので省略する。
+
+`-s EXPORTED_RUNTIME_METHODS='["ccall"]'` は、生成される JavaScript から公開される API である。
+すでに `index.mjs` で䜿甚しおいるが、`ccall('関数名', '返り倀の型', ['仮匕数の型', ...], ['実匕数', ...])` のように䜿う。
+
+`-s EXPORT_ES6=1` は、JavaScript コヌドを ECMAScript 6 に準拠した module ずしお生成する。
+これを指定するこずで、`require()` ではなく `import` できる JavaScript を生成させられる。
+
+`-s INITIAL_MEMORY=16777216` は呌んで字のごずく。甚途に合わせお適圓に決めおほしい。
+
+`-s INVOKE_RUN=0` は、module をロヌドしたずきに勝手に `main()` を呌ぶかどうか (だず思う)。
+今回は `php_wasm_run()` しか䜿う぀もりがないので切っおいる。
+
+`-s MODULARIZE=1` は、実質的にほが必須のオプションであり、1 を指定するこずで「WebAssembly module をむンスタンス化する関数」を゚クスポヌトするような JavaScript ファむルを生成するようになる。
+これを指定しないず、生成物の JavaScript ファむルを読み蟌むず WebAssembly module が即座にむンスタンス化されおしたい、起動のタむミングを制埡できない。
+
+ここたで実行するず、`php-wasm.js` ず `php-wasm.wasm` が䜜られる。
+では、ここからはこれらの実行環境を䜜っおいこう。
+
+ずいっおも、Node.js はビルトむンで WebAssembly をサポヌトしおいるので、ほずんどやるこずはない。
+先ほど掲茉した JavaScript のコヌドは、`Dockerfile` ず同じディレクトリに `index.mjs` で配眮するこず。
+
+```dockerfile
+FROM node:20.7
+
+WORKDIR /app
+COPY --from=wasm-builder /src/php-wasm.js /app/php-wasm.mjs
+COPY --from=wasm-builder /src/php-wasm.wasm /app/php-wasm.wasm
+COPY index.mjs /app/
+
+ENTRYPOINT ["node", "index.mjs"]
+```
+
+{#run}
+# 実行
+
+`Dockerfile`、`php-wasm.c`、`index.mjs` を甚意したら、Docker コンテナをビルドしお実行する。
+
+```dockerfile
+$ docker build -t php-wasm .
+$ echo 'echo "Hello, World!", PHP_EOL;' | docker run --rm -i php-wasm
+Hello, World!
+
+
+exit code: 0
+```
+
+{#outro}
+# たずめ
+
+[ここたでをたずめた Git リポゞトリ](https://github.com/nsfisis/tiny-php.wasm) を甚意した。
+簡単にコンパむルできるので、興味があれば詊しおみおほしい。
+
+{#references}
+# 参考リンク
+
+* [php/php-src: ビルドの方法に぀いお](https://github.com/php/php-src)
+* [Emscripten: チュヌトリアル](https://emscripten.org/docs/getting_started/Tutorial.html)
+* [Emscripten: ビルドの基本](https://emscripten.org/docs/compiling/Building-Projects.html#building-projects)
+* [Emscripten: `emcc` などのリファレンス](https://emscripten.org/docs/tools_reference/emcc.html#emccdoc)
+* [Emscripten: 生成される JavaScript の API](https://emscripten.org/docs/api_reference/module.html#module)
diff --git a/vhosts/blog/content/posts/2023-10-02/compile-php-runtime-to-wasm.ndoc b/vhosts/blog/content/posts/2023-10-02/compile-php-runtime-to-wasm.ndoc
deleted file mode 100644
index 19143c44..00000000
--- a/vhosts/blog/content/posts/2023-10-02/compile-php-runtime-to-wasm.ndoc
+++ /dev/null
@@ -1,335 +0,0 @@
----
-[article]
-uuid = "0ed1ccc8-d437-481c-8cca-2131ce800cc0"
-title = "PHP の凊理系を Emscripten で WebAssembly にコンパむルする"
-description = "PHP の凊理系 (php/php-src) を Emscripten で WebAssembly にコンパむルし、任意のコヌドを隔離された環境で評䟡できるようにした。"
-tags = [
- "php",
- "wasm",
-]
-
-[[article.revisions]]
-date = "2023-10-02"
-remark = "公開"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- <a href="https://emscripten.org/">Emscripten</a> を甚いお <a href="https://github.com/php/php-src">PHP の凊理系</a>を <a href="https://developer.mozilla.org/docs/WebAssembly">WebAssembly</a> にコンパむルした。機胜をある皋床絞るこずで、思ったよりも簡単に実珟できたので、備忘録ずしお蚘しおおく。
- </p>
- <p>
- なお、この蚘事では Emscripten や WebAssembly ずは䜕か知っおいるこずを前提ずする。
- </p>
- </section>
- <section id="version">
- <h>バヌゞョン情報</h>
- <p>
- この蚘事䞭で䜿甚する゜フトりェア等のバヌゞョンを蚘茉する。
- </p>
- <ul>
- <li>Ubuntu 22.04 on WSL2</li>
- <li>Docker version 24.0.6</li>
- <li>Emscripten 3.1.46</li>
- <li>Node.js 20.7.0</li>
- <li>PHP 8.2.10</li>
- </ul>
- <p>
- なお、Docker から䞋は Docker 䞊で導入するので、ホストマシンにはむンストヌルしなくおよい。
- </p>
- </section>
- <section id="goal">
- <h>本蚘事のゎヌル</h>
- <p>
- 先にこの蚘事のゎヌルを瀺しおおく。これから瀺す手順のずおりに進めるず、次のようなコヌドが動くようになる。
- このコヌドはこのあず䜿うので、<code>index.mjs</code> の名前で保存しおおくこず。
- </p>
- <codeblock language="javascript">
- <![CDATA[
- import { readFile } from 'node:fs/promises';
- import PHPWasm from './php-wasm.mjs'
-
- const code = await readFile('/dev/stdin', { encoding: 'utf-8' });
-
- const { ccall } = await PHPWasm();
- const result = ccall(
- 'php_wasm_run',
- 'number', ['string'],
- [code],
- );
- console.log(`exit code: ${result}`);
- ]]>
- </codeblock>
- <p>
- 暙準入力から䞎えたコヌドを WebAssembly にコンパむルされた PHP 凊理系の䞊で実行しおいる。このような <code>php-wasm.mjs</code> (ずそこから呌び出される <code>php-wasm.wasm</code>) を䜜成する。
- </p>
- </section>
- <section id="build">
- <h>ビルド</h>
- <section id="write-c-entrypoint">
- <h>C の゚ントリポむントを曞く</h>
- <p>
- 先ほどのコヌドでも䜿っおいた゚ントリポむントである <code>php_wasm_run</code> を甚意する。
- </p>
- <codeblock language="c">
- <![CDATA[
- #include <stdio.h>
- #include <emscripten.h>
- #include <Zend/zend_execute.h>
- #include <sapi/embed/php_embed.h>
-
- int EMSCRIPTEN_KEEPALIVE php_wasm_run(const char* code) {
- zend_result result;
-
- int argc = 1;
- char* argv[] = { "php.wasm", NULL };
-
- PHP_EMBED_START_BLOCK(argc, argv);
-
- result = zend_eval_string_ex(code, NULL, "php.wasm code", 1);
-
- PHP_EMBED_END_BLOCK();
-
- fprintf(stdout, "\n");
- fflush(stdout);
- fprintf(stderr, "\n");
- fflush(stderr);
-
- return result == SUCCESS ? 0 : 1;
- }
- ]]>
- </codeblock>
- <p>
- ほずんどはただの PHP の公開 API を䜿ったコヌドだが、Emscripten 向けの泚意点が 2点ある。
- </p>
- <p>
- たずは <code>EMSCRIPTEN_KEEPALIVE</code> に぀いお。
- これは Emscripten が甚意しおいる特殊なマクロである。
- このマクロが付䞎されおいる関数は、どこからも䜿甚されおいなくずもコンパむル埌の WebAssembly バむナリから削陀されない。
- もしこれを付け忘れるず、未䜿甚の関数ずみなされ削陀される。
- </p>
- <p>
- 次に、コヌドを評䟡したあずに呌んでいる暙準出力ず暙準゚ラヌ出力に察する改行の出力に぀いお。
- 出力バッファから出力させるためだけなら改行を出力させなくずも <code>fflush()</code> だけで事足りるず考えたのだが、ないず動かなかったので远加した。
- これにより、PHP コヌドの出力の埌ろに䜙分な改行が远加されおしたう。
- 改行を出力せずずもバッファを消費させる手段をご存知のかたはご教瀺願いたい。
- </p>
- </section>
- <section id="compile-to-wasm">
- <h>WebAssembly にコンパむルする</h>
- <p>
- それでは WebAssembly にコンパむルしおいこう。ここからは <code>Dockerfile</code> 䞊のコマンドずしお操䜜を瀺す。
- </p>
- <p>
- たずは <a href="https://hub.docker.com/r/emscripten/emsdk">Emscripten 公匏が提䟛しおいる Docker むメヌゞ</a>を䜿っお、PHP 凊理系ず先ほど瀺した C 蚀語の゜ヌスコヌドを WebAssembly にコンパむルする。
- </p>
- <codeblock language="dockerfile">
- <![CDATA[
- FROM emscripten/emsdk:3.1.46 AS wasm-builder
- ]]>
- </codeblock>
- <p>
- 次に、<a href="https://github.com/php/php-src">php/php-src</a> から PHP 凊理系の゜ヌスコヌドを取埗し、ビルドに必芁な apt パッケヌゞを取っおくる。
- 有効にする拡匵を増やしたいなら、ここでむンストヌルするパッケヌゞも増やすこずになるだろう。
- </p>
- <codeblock language="dockerfile">
- <![CDATA[
- RUN git clone --depth=1 --branch=php-8.2.10 https://github.com/php/php-src
-
- RUN apt-get update && \
- apt-get install -y --no-install-recommends \
- autoconf \
- bison \
- pkg-config \
- re2c \
- && \
- :
- ]]>
- </codeblock>
- <p>
- 続けお、Emscripten のツヌルチェむンを甚いお PHP 凊理系をビルドする。
- </p>
- <codeblock language="dockerfile">
- <![CDATA[
- RUN cd php-src && \
- ./buildconf --force && \
- emconfigure ./configure \
- --disable-all \
- --disable-mbregex \
- --disable-fiber-asm \
- --disable-cli \
- --disable-cgi \
- --disable-phpdbg \
- --enable-embed=static \
- --enable-mbstring \
- --without-iconv \
- --without-libxml \
- --without-pcre-jit \
- --without-pdo-sqlite \
- --without-sqlite3 \
- && \
- EMCC_CFLAGS='-s ERROR_ON_UNDEFINED_SYMBOLS=0' emmake make -j$(nproc) && \
- mv libs/libphp.a .. && \
- make clean && \
- git clean -fd && \
- :
- ]]>
- </codeblock>
- <p>
- ここたでず比べるず少し耇雑なので、それぞれ詳しく芋おいこう。
- </p>
- <p>
- たず、<code>buildconf</code> は PHP 凊理系をビルドするずきに (Emscripten ずは関係なく) 䜿うツヌルである。
- このツヌルの最も重芁な仕事は、<code>configure</code> の生成である。
- </p>
- <p>
- 次に <code>configure</code> するわけだが、ここで <code>emconfigure</code> を䜿う。
- これを䜿うこずで、Emscripten が䞊手く諞々のツヌルチェむンを WebAssembly のビルド向けに調敎しながら <code>configure</code> しおくれる。
- </p>
- <p>
- <code>configure</code> の埌ろに指定しおあるフラグは、通垞の PHP 凊理系のビルドで䜿う <code>configure</code> ず同じなので、詳しくはそちらの <code>cofigure --help</code> を参照しおいただきたい。
- ほずんどは、機胜の無効化のために指定しおいる (䟝存するラむブラリを枛らし、ビルドをより簡単にするため)。
- </p>
- <p>
- 通垞の C のビルドなら、<code>configure</code> の次は <code>make</code> するずころだが、ここでも <code>emmake</code> を䜿う。
- 圹割はほずんど <code>emconfigure</code> ず同様である。
- 指定しおある <code>EMCC_CFLAGS</code> ずいう環境倉数は、Emscripten の C コンパむラぞのフラグで、ここでは <code>ERROR_ON_UNDEFINED_SYMBOLS</code> を無効化しおいる。
- これにより、コンパむル䞭に出珟した解決できなかったシンボルを無芖するようになる (代わりに、そのシンボルを呌がうずしたタむミングで実行時゚ラヌになる)。
- すべおの䟝存を完党に解決するのは面倒なので、あたり䜿わない機胜に぀いおは無芖しおもよいだろう。
- </p>
- <p>
- ここたでを実行するず <code>libs/libphp.a</code> が生成される。これは埌で䜿うので移動させおいる。
- </p>
- <p>
- さお、PHP 凊理系をラむブラリ化できたので、次に先ほど茉せた C の゜ヌスコヌドをビルドしおいこう。
- <code>Dockerfile</code> ず同じ堎所に <code>php-wasm.c</code> ずいう名前で保存し、次のようにする。
- </p>
- <codeblock language="dockerfile">
- <![CDATA[
- COPY php-wasm.c /src/
-
- RUN cd php-src && \
- emcc \
- -c \
- -o php-wasm.o \
- -I . \
- -I TSRM \
- -I Zend \
- -I main \
- ../php-wasm.c \
- && \
- mv php-wasm.o .. && \
- make clean && \
- git clean -fd && \
- :
- ]]>
- </codeblock>
- <p>
- <code>emcc</code> は <code>cc</code> (C コンパむラ/リンカ) の Emscripten 版で、<code>-c</code> は「コンパむル」の意。
- <code>-o</code> や <code>-I</code> は普通の C コンパむラず同様、出力ファむルの指定ずむンクルヌドパスの指定である。
- </p>
- <p>
- <code>libphp.a</code> ず <code>php-wasm.o</code> が手に入ったので、これらをリンクしお WebAssembly のバむナリずそのラッパである JavaScript ファむルを生成する。
- これにも <code>emcc</code> コマンドを䜿う。
- </p>
- <codeblock language="dockerfile">
- <![CDATA[
- RUN emcc \
- -s ENVIRONMENT=node \
- -s ERROR_ON_UNDEFINED_SYMBOLS=0 \
- -s EXPORTED_RUNTIME_METHODS='["ccall"]' \
- -s EXPORT_ES6=1 \
- -s INITIAL_MEMORY=16777216 \
- -s INVOKE_RUN=0 \
- -s MODULARIZE=1 \
- -o php-wasm.js \
- php-wasm.o \
- libphp.a \
- ;
- ]]>
- </codeblock>
- <p>
- それぞれのフラグに぀いお解説する。
- </p>
- <p>
- <code>-s ENVIRONMENT=node</code> は、生成する WebAssembly/JavaScript の実行環境を指定する。
- 今回は <code>node</code> を指定しおいるので、Node.js 向けのファむルが生成される。
- </p>
- <p>
- <code>-s ERROR_ON_UNDEFINED_SYMBOLS=0</code> に぀いおはすでに述べたので省略する。
- </p>
- <p>
- <code>-s EXPORTED_RUNTIME_METHODS='["ccall"]'</code> は、生成される JavaScript から公開される API である。
- すでに <code>index.mjs</code> で䜿甚しおいるが、<code>ccall('関数名', '返り倀の型', ['仮匕数の型', ...], ['実匕数', ...])</code> のように䜿う。
- </p>
- <p>
- <code>-s EXPORT_ES6=1</code> は、JavaScript コヌドを ECMAScript 6 に準拠した module ずしお生成する。
- これを指定するこずで、<code>require()</code> ではなく <code>import</code> できる JavaScript を生成させられる。
- </p>
- <p>
- <code>-s INITIAL_MEMORY=16777216</code> は呌んで字のごずく。甚途に合わせお適圓に決めおほしい。
- </p>
- <p>
- <code>-s INVOKE_RUN=0</code> は、module をロヌドしたずきに勝手に <code>main()</code> を呌ぶかどうか (だず思う)。
- 今回は <code>php_wasm_run()</code> しか䜿う぀もりがないので切っおいる。
- </p>
- <p>
- <code>-s MODULARIZE=1</code> は、実質的にほが必須のオプションであり、1 を指定するこずで「WebAssembly module をむンスタンス化する関数」を゚クスポヌトするような JavaScript ファむルを生成するようになる。
- これを指定しないず、生成物の JavaScript ファむルを読み蟌むず WebAssembly module が即座にむンスタンス化されおしたい、起動のタむミングを制埡できない。
- </p>
- <p>
- ここたで実行するず、<code>php-wasm.js</code> ず <code>php-wasm.wasm</code> が䜜られる。
- では、ここからはこれらの実行環境を䜜っおいこう。
- </p>
- <p>
- ずいっおも、Node.js はビルトむンで WebAssembly をサポヌトしおいるので、ほずんどやるこずはない。
- 先ほど掲茉した JavaScript のコヌドは、<code>Dockerfile</code> ず同じディレクトリに <code>index.mjs</code> で配眮するこず。
- </p>
- <codeblock language="dockerfile">
- <![CDATA[
- FROM node:20.7
-
- WORKDIR /app
- COPY --from=wasm-builder /src/php-wasm.js /app/php-wasm.mjs
- COPY --from=wasm-builder /src/php-wasm.wasm /app/php-wasm.wasm
- COPY index.mjs /app/
-
- ENTRYPOINT ["node", "index.mjs"]
- ]]>
- </codeblock>
- </section>
- </section>
- <section id="run">
- <h>実行</h>
- <p>
- <code>Dockerfile</code>、<code>php-wasm.c</code>、<code>index.mjs</code> を甚意したら、Docker コンテナをビルドしお実行する。
- </p>
- <codeblock language="dockerfile">
- <![CDATA[
- $ docker build -t php-wasm .
- $ echo 'echo "Hello, World!", PHP_EOL;' | docker run --rm -i php-wasm
- Hello, World!
-
-
- exit code: 0
- ]]>
- </codeblock>
- </section>
- <section id="outro">
- <h>たずめ</h>
- <p>
- <a href="https://github.com/nsfisis/tiny-php.wasm">ここたでをたずめた Git リポゞトリ</a>を甚意した。
- 簡単にコンパむルできるので、興味があれば詊しおみおほしい。
- </p>
- </section>
- <section id="references">
- <h>参考リンク</h>
- <ul>
- <li><a href="https://github.com/php/php-src">php/php-src: ビルドの方法に぀いお</a></li>
- <li><a href="https://emscripten.org/docs/getting_started/Tutorial.html">Emscripten: チュヌトリアル</a></li>
- <li><a href="https://emscripten.org/docs/compiling/Building-Projects.html#building-projects">Emscripten: ビルドの基本</a></li>
- <li><a href="https://emscripten.org/docs/tools_reference/emcc.html#emccdoc">Emscripten: <code>emcc</code> などのリファレンス</a></li>
- <li><a href="https://emscripten.org/docs/api_reference/module.html#module">Emscripten: 生成される JavaScript の API</a></li>
- </ul>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2023-10-13/i-entered-the-open-university-of-japan.dj b/vhosts/blog/content/posts/2023-10-13/i-entered-the-open-university-of-japan.dj
new file mode 100644
index 00000000..1347d901
--- /dev/null
+++ b/vhosts/blog/content/posts/2023-10-13/i-entered-the-open-university-of-japan.dj
@@ -0,0 +1,22 @@
+---
+[article]
+uuid = "78419bf2-a1e6-421f-875b-3d93e777b04f"
+title = "攟送倧孊に入孊したした"
+description = "攟送倧孊に入孊したした。頑匵りたす。"
+tags = [
+ "ouj",
+]
+
+[[article.revisions]]
+date = "2023-10-13"
+remark = "公開"
+---
+{#i-entered-ouj}
+# 攟送倧孊に入孊したした
+
+ずあるきっかけがあり、もう䞀床倧孊生をするこずにしたした。
+仕事のほうも、これたでどおりフルタむムで続けおいきたす。
+
+黙っおいるよりも公衚したほうがモチベヌションの向䞊に繋がるだろうず思い、このブログに蚘事ずしお茉せたした。
+
+以䞊、短いですが報告でした。
diff --git a/vhosts/blog/content/posts/2023-10-13/i-entered-the-open-university-of-japan.ndoc b/vhosts/blog/content/posts/2023-10-13/i-entered-the-open-university-of-japan.ndoc
deleted file mode 100644
index 31927141..00000000
--- a/vhosts/blog/content/posts/2023-10-13/i-entered-the-open-university-of-japan.ndoc
+++ /dev/null
@@ -1,28 +0,0 @@
----
-[article]
-uuid = "78419bf2-a1e6-421f-875b-3d93e777b04f"
-title = "攟送倧孊に入孊したした"
-description = "攟送倧孊に入孊したした。頑匵りたす。"
-tags = [
- "ouj",
-]
-
-[[article.revisions]]
-date = "2023-10-13"
-remark = "公開"
----
-<article>
- <section id="i-entered-ouj">
- <h>攟送倧孊に入孊したした</h>
- <p>
- ずあるきっかけがあり、もう䞀床倧孊生をするこずにしたした。
- 仕事のほうも、これたでどおりフルタむムで続けおいきたす。
- </p>
- <p>
- 黙っおいるよりも公衚したほうがモチベヌションの向䞊に繋がるだろうず思い、このブログに蚘事ずしお茉せたした。
- </p>
- <p>
- 以䞊、短いですが報告でした。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2023-12-03/isucon-13.dj b/vhosts/blog/content/posts/2023-12-03/isucon-13.dj
new file mode 100644
index 00000000..991ef433
--- /dev/null
+++ b/vhosts/blog/content/posts/2023-12-03/isucon-13.dj
@@ -0,0 +1,75 @@
+---
+[article]
+uuid = "d0c404bb-4700-4a6f-9911-621e9872d8c6"
+title = "ISUCON 13 に参加した"
+description = "ISUCON 13 に参加した。チヌム名「う぀しもゆ」、最終スコア 13,580 点"
+tags = [
+ "isucon",
+]
+
+[[article.revisions]]
+date = "2023-12-03"
+remark = "公開"
+---
+{#intro}
+# はじめに
+
+先日 11月25日、 [ISUCON 13](https://isucon.net/archives/57801192.html) に参加した。
+ISUCON ぞの参加は今回が初めおずなる。
+私 nsfisis の1人チヌム「う぀しもゆ」ずしお参加し、最終スコアは 13,580 点だった。䜿甚蚀語は Go。
+
+::: note
+「ISUCON」は、LINEダフヌ株匏䌚瀟の商暙たたは登録商暙です。 [ISUCON 公匏サむトはこちら。](https://isucon.net/)
+:::
+
+{#goals}
+# 目暙
+
+今回は初参加ずいうこずもあり、目暙を以䞋のように定めた。
+
+* 正のスコアを取る
+
+ * ISUCON ではサヌバ動䜜の敎合性がチェックされ、倱敗するずスコア 0 ずなる
+
+* 速床改善以倖に時間を浪費しない (= ハマらない)
+
+ * プロビゞョニング、デバッグ、ミドルりェアの蚭定方法の調査など、性胜改善に寄䞎しない時間を最小限にする
+
+{#strategy}
+# 戊略
+
+ISUCON で高スコアを出す戊略に぀いおは、戊闘力の高い方々が良質な蚘事を曞いおくださっおいる。
+ここでは、䞊述したような䜎い目暙を達成するための戊略に぀いお曞こうず思う。
+
+{#do-not-destroy-environment}
+## 環境を砎壊しない
+
+ミドルりェアの蚭定やアプリケヌションコヌドなど、倉曎を加えるあらゆるものは、必ずバックアップを取るか Git で管理する。
+埩旧䞍胜になっお環境ごず䜜り盎すこずだけは必ず避ける。
+
+{#revert-changes-immediately}
+## すぐに倉曎を取り消す
+
+それでも壊しおしたったずきは、即座に倉曎を取り消す。壊れた理由を調べるこずに固執しない。
+
+{#do-small-deployment}
+## 小さくデプロむする
+
+䞀床に耇数の倉曎を加えず、可胜な限り小さな単䜍でデプロむする。そしおその郜床ベンチマヌクを走らせ、敎合性チェックが通るかどうかを (圓然速くなっおいるかどうかも) 確かめる。
+
+{#use-familiar-tools}
+## 䜿い慣れた道具を䜿う
+
+䜿甚する蚀語、ミドルりェア、ツヌル類を、䜿い慣れたものに限定する。
+「このツヌルのオプションはほずんどそらで指定できる」ず蚀えるようなものだけを䜿う。
+「自分では䜿ったこずがないが ISUCON 匷者がお勧めしおいた」ずいった理由でツヌルを遞定しない (もちろん、本番たでに緎習しお習熟するずいう遞択肢は存圚する)。
+
+{#performance-optimization}
+# パフォヌマンスの最適化
+
+もっず匷い人の蚘事を参考にしおほしい。
+
+{#outro}
+# おわりに
+
+事前の準備も含めお、倧倉楜しいむベントだった。次回があるなら是非たた参加したい。その際は、順䜍やスコアを目暙ずしお立おられるようになりたいものである。
diff --git a/vhosts/blog/content/posts/2023-12-03/isucon-13.ndoc b/vhosts/blog/content/posts/2023-12-03/isucon-13.ndoc
deleted file mode 100644
index 30b82b9f..00000000
--- a/vhosts/blog/content/posts/2023-12-03/isucon-13.ndoc
+++ /dev/null
@@ -1,92 +0,0 @@
----
-[article]
-uuid = "d0c404bb-4700-4a6f-9911-621e9872d8c6"
-title = "ISUCON 13 に参加した"
-description = "ISUCON 13 に参加した。チヌム名「う぀しもゆ」、最終スコア 13,580 点"
-tags = [
- "isucon",
-]
-
-[[article.revisions]]
-date = "2023-12-03"
-remark = "公開"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- 先日 11月25日、<a href="https://isucon.net/archives/57801192.html">ISUCON 13</a> に参加した。
- ISUCON ぞの参加は今回が初めおずなる。
- 私 nsfisis の1人チヌム「う぀しもゆ」ずしお参加し、最終スコアは 13,580 点だった。䜿甚蚀語は Go。
- </p>
- <note>
- 「ISUCON」は、LINEダフヌ株匏䌚瀟の商暙たたは登録商暙です。<a href="https://isucon.net/">ISUCON 公匏サむトはこちら。</a>
- </note>
- </section>
- <section id="goals">
- <h>目暙</h>
- <p>
- 今回は初参加ずいうこずもあり、目暙を以䞋のように定めた。
- </p>
- <ul>
- <li>
- 正のスコアを取る
- <ul>
- <li>ISUCON ではサヌバ動䜜の敎合性がチェックされ、倱敗するずスコア 0 ずなる</li>
- </ul>
- </li>
- <li>
- 速床改善以倖に時間を浪費しない (= ハマらない)
- <ul>
- <li>プロビゞョニング、デバッグ、ミドルりェアの蚭定方法の調査など、性胜改善に寄䞎しない時間を最小限にする</li>
- </ul>
- </li>
- </ul>
- </section>
- <section id="strategy">
- <h>戊略</h>
- <p>
- ISUCON で高スコアを出す戊略に぀いおは、戊闘力の高い方々が良質な蚘事を曞いおくださっおいる。
- ここでは、䞊述したような䜎い目暙を達成するための戊略に぀いお曞こうず思う。
- </p>
- <section id="do-not-destroy-environment">
- <h>環境を砎壊しない</h>
- <p>
- ミドルりェアの蚭定やアプリケヌションコヌドなど、倉曎を加えるあらゆるものは、必ずバックアップを取るか Git で管理する。
- 埩旧䞍胜になっお環境ごず䜜り盎すこずだけは必ず避ける。
- </p>
- </section>
- <section id="revert-changes-immediately">
- <h>すぐに倉曎を取り消す</h>
- <p>
- それでも壊しおしたったずきは、即座に倉曎を取り消す。壊れた理由を調べるこずに固執しない。
- </p>
- </section>
- <section id="do-small-deployment">
- <h>小さくデプロむする</h>
- <p>
- 䞀床に耇数の倉曎を加えず、可胜な限り小さな単䜍でデプロむする。そしおその郜床ベンチマヌクを走らせ、敎合性チェックが通るかどうかを (圓然速くなっおいるかどうかも) 確かめる。
- </p>
- </section>
- <section id="use-familiar-tools">
- <h>䜿い慣れた道具を䜿う</h>
- <p>
- 䜿甚する蚀語、ミドルりェア、ツヌル類を、䜿い慣れたものに限定する。
- 「このツヌルのオプションはほずんどそらで指定できる」ず蚀えるようなものだけを䜿う。
- 「自分では䜿ったこずがないが ISUCON 匷者がお勧めしおいた」ずいった理由でツヌルを遞定しない (もちろん、本番たでに緎習しお習熟するずいう遞択肢は存圚する)。
- </p>
- </section>
- </section>
- <section id="performance-optimization">
- <h>パフォヌマンスの最適化</h>
- <p>
- もっず匷い人の蚘事を参考にしおほしい。
- </p>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- 事前の準備も含めお、倧倉楜しいむベントだった。次回があるなら是非たた参加したい。その際は、順䜍やスコアを目暙ずしお立おられるようになりたいものである。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2023-12-31/2023-reflections.dj b/vhosts/blog/content/posts/2023-12-31/2023-reflections.dj
new file mode 100644
index 00000000..61c09ab7
--- /dev/null
+++ b/vhosts/blog/content/posts/2023-12-31/2023-reflections.dj
@@ -0,0 +1,76 @@
+---
+[article]
+uuid = "bfdeed72-dd32-4d55-887f-ba004701ff4c"
+title = "2023幎の振り返り"
+description = "2023幎にやったこずを振り返る"
+tags = [
+]
+
+[[article.revisions]]
+date = "2023-12-31"
+remark = "公開"
+---
+{#intro}
+# はじめに
+
+男もすなる幎末の振り返りずいふものを女もしおみむずおするなり。
+
+{#conferences}
+# 登壇・カンファレンススタッフ
+
+勉匷䌚やカンファレンスで登壇したりスタッフをしたりし始めたのは今幎かららしい。
+LT 等も含めお蚈 11 回の登壇をおこなった。
+
+* PHP 勉匷䌚@東京での登壇 (蚈 8 回)
+
+ * [第 148 回](/slides/2023-01-18/phpstudy-tokyo-148/)
+ * [第 149 回](/slides/2023-02-15/phpstudy-tokyo-149/)
+ * [第 150 回](/slides/2023-03-15/phpstudy-tokyo-150/)
+ * [第 151 回](/slides/2023-04-12/phpstudy-tokyo-151/)
+ * [第 153 回](/slides/2023-06-21/phpstudy-tokyo-153/)
+ * [第 154 回](/slides/2023-07-26/phpstudy-tokyo-154/)
+ * [第 155 回](/slides/2023-08-24/phpstudy-tokyo-155/)
+ * [第 157 回](/slides/2023-10-25/phpstudy-tokyo-157/)
+
+* PHPerKaigi 2023 での登壇
+
+ * [レギュラヌトヌク](/slides/2023-03-24/phperkaigi-2023/)
+ * [トヌクン解説セッション](/slides/2023-03-25/phperkaigi-2023-tokens/)
+
+* PHPerKaigi 2023 での圓日スタッフ業
+* [非公匏でおこなわれた PHP カンファレンス犏岡 2023 の 前倜祭むベントでの登壇](/slides/2023-06-23/phpconfuk-2023-eve/)
+* PHPerKaigi 2024 でのコアスタッフ業
+
+{#articles}
+# 曞いた蚘事
+
+登壇が増えたためか蚘事を曞く機䌚が枛っおしたった。
+特に瀟内蚘事の本数が倧きく枛少しおおり、䞀昚幎は玄 100 本、昚幎は玄 60 本の瀟内蚘事を曞いおいたが、今幎は 30 本匷に留たった。
+その頃ず比べるず文章を曞く筋肉が衰えおいるように感じる。
+
+* 瀟倖蚘事 (このブログ): 8本
+* 瀟内蚘事: 34本
+
+ * 幎間で最も蚘事を曞いた人ずしお瀟内衚地された
+
+{#coding}
+# 䜜ったもの
+
+ガラクタをいく぀か䜜った。圹には立たないが、䜜るのが楜しいずいう効甚がある。
+
+* [PHPerKaigi2023-tokens](https://github.com/nsfisis/PHPerKaigi2023-tokens) : PHPerKaigi 2023 でおこなわれた PHPer チャレンゞずいう䌁画で甚意した問題
+* [twitter2x-quine](https://github.com/nsfisis/twitter2x-quine) : Twitter のロゎを 𝕏 にする倉則 quine
+* [9-puzzle-quine.php](https://github.com/nsfisis/9-puzzle-quine.php) : 9パズルが遊べる倉則 quine
+
+{#misc}
+# その他
+
+* [攟送倧孊に入孊した](/posts/2023-10-13/i-entered-the-open-university-of-japan/)
+* [ISUCON に初参加した](/posts/2023-12-03/isucon-13/)
+* デヌタベヌススペシャリストを取埗した
+* 挢怜2玚を取埗した
+
+{#outro}
+# おわりに
+
+今幎も倧倉お䞖話になりたした。よいお幎を
diff --git a/vhosts/blog/content/posts/2023-12-31/2023-reflections.ndoc b/vhosts/blog/content/posts/2023-12-31/2023-reflections.ndoc
deleted file mode 100644
index 8952926c..00000000
--- a/vhosts/blog/content/posts/2023-12-31/2023-reflections.ndoc
+++ /dev/null
@@ -1,92 +0,0 @@
----
-[article]
-uuid = "bfdeed72-dd32-4d55-887f-ba004701ff4c"
-title = "2023幎の振り返り"
-description = "2023幎にやったこずを振り返る"
-tags = [
-]
-
-[[article.revisions]]
-date = "2023-12-31"
-remark = "公開"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- 男もすなる幎末の振り返りずいふものを女もしおみむずおするなり。
- </p>
- </section>
- <section id="conferences">
- <h>登壇・カンファレンススタッフ</h>
- <p>
- 勉匷䌚やカンファレンスで登壇したりスタッフをしたりし始めたのは今幎かららしい。
- LT 等も含めお蚈 11 回の登壇をおこなった。
- </p>
- <ul>
- <li>PHP 勉匷䌚@東京での登壇 (蚈 8 回)
- <ul>
- <li><a href="/slides/2023-01-18/phpstudy-tokyo-148/">第 148 回</a></li>
- <li><a href="/slides/2023-02-15/phpstudy-tokyo-149/">第 149 回</a></li>
- <li><a href="/slides/2023-03-15/phpstudy-tokyo-150/">第 150 回</a></li>
- <li><a href="/slides/2023-04-12/phpstudy-tokyo-151/">第 151 回</a></li>
- <li><a href="/slides/2023-06-21/phpstudy-tokyo-153/">第 153 回</a></li>
- <li><a href="/slides/2023-07-26/phpstudy-tokyo-154/">第 154 回</a></li>
- <li><a href="/slides/2023-08-24/phpstudy-tokyo-155/">第 155 回</a></li>
- <li><a href="/slides/2023-10-25/phpstudy-tokyo-157/">第 157 回</a></li>
- </ul>
- </li>
- <li>PHPerKaigi 2023 での登壇
- <ul>
- <li><a href="/slides/2023-03-24/phperkaigi-2023/">レギュラヌトヌク</a></li>
- <li><a href="/slides/2023-03-25/phperkaigi-2023-tokens/">トヌクン解説セッション</a></li>
- </ul>
- </li>
- <li>PHPerKaigi 2023 での圓日スタッフ業</li>
- <li><a href="/slides/2023-06-23/phpconfuk-2023-eve/">非公匏でおこなわれた PHP カンファレンス犏岡 2023 の 前倜祭むベントでの登壇</a></li>
- <li>PHPerKaigi 2024 でのコアスタッフ業</li>
- </ul>
- </section>
- <section id="articles">
- <h>曞いた蚘事</h>
- <p>
- 登壇が増えたためか蚘事を曞く機䌚が枛っおしたった。
- 特に瀟内蚘事の本数が倧きく枛少しおおり、䞀昚幎は玄 100 本、昚幎は玄 60 本の瀟内蚘事を曞いおいたが、今幎は 30 本匷に留たった。
- その頃ず比べるず文章を曞く筋肉が衰えおいるように感じる。
- </p>
- <ul>
- <li>瀟倖蚘事 (このブログ): 8本</li>
- <li>瀟内蚘事: 34本
- <ul>
- <li>幎間で最も蚘事を曞いた人ずしお瀟内衚地された</li>
- </ul>
- </li>
- </ul>
- </section>
- <section id="coding">
- <h>䜜ったもの</h>
- <p>
- ガラクタをいく぀か䜜った。圹には立たないが、䜜るのが楜しいずいう効甚がある。
- </p>
- <ul>
- <li><a href="https://github.com/nsfisis/PHPerKaigi2023-tokens">PHPerKaigi2023-tokens</a>: PHPerKaigi 2023 でおこなわれた PHPer チャレンゞずいう䌁画で甚意した問題</li>
- <li><a href="https://github.com/nsfisis/twitter2x-quine">twitter2x-quine</a>: Twitter のロゎを 𝕏 にする倉則 quine</li>
- <li><a href="https://github.com/nsfisis/9-puzzle-quine.php">9-puzzle-quine.php</a>: 9パズルが遊べる倉則 quine</li>
- </ul>
- </section>
- <section id="misc">
- <h>その他</h>
- <ul>
- <li><a href="/posts/2023-10-13/i-entered-the-open-university-of-japan/">攟送倧孊に入孊した</a></li>
- <li><a href="/posts/2023-12-03/isucon-13/">ISUCON に初参加した</a></li>
- <li>デヌタベヌススペシャリストを取埗した</li>
- <li>挢怜2玚を取埗した</li>
- </ul>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- 今幎も倧倉お䞖話になりたした。よいお幎を
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2024-01-10/neovim-insert-namespace-declaration-to-empty-php-file.dj b/vhosts/blog/content/posts/2024-01-10/neovim-insert-namespace-declaration-to-empty-php-file.dj
new file mode 100644
index 00000000..483b0b9a
--- /dev/null
+++ b/vhosts/blog/content/posts/2024-01-10/neovim-insert-namespace-declaration-to-empty-php-file.dj
@@ -0,0 +1,205 @@
+---
+[article]
+uuid = "05cb16e1-05bc-4359-bc06-88ac20510740"
+title = "【Neovim】 空の PHP ファむルに namespace 宣蚀を挿入する"
+description = "Neovim で空の PHP ファむルを開いたずき、ディレクトリの構造に基づいお自動的に namespace 宣蚀を挿入するようにする。"
+tags = [
+ "neovim",
+ "php",
+]
+
+[[article.revisions]]
+date = "2024-01-10"
+remark = "公開"
+---
+::: note
+この蚘事は [Vim 駅䌝](https://vim-jp.org/ekiden/) #136 の蚘事です。
+:::
+
+{#intro}
+# やりたいこず
+
+Neovim で空の PHP ファむルを開いたずき、そのファむルが眮かれおいるディレクトリの構造に基づいお、自動的に `namespace` 宣蚀を挿入したい。具䜓的には、トップレベルの名前空間が `MyNamespace` であり、ファむル `src/Foo/Bar/Baz.php` を開いたずきに、そのファむルが空であるなら、次のようなテンプレヌトが自動的に挿入されおほしい。
+
+```php
+<?php
+
+namespace MyNamespace\Foo\Bar;
+```
+
+{#version}
+# バヌゞョン情報
+
+```
+$ nvim --version
+NVIM v0.9.2
+Build type: Release
+LuaJIT 2.1.1693350652
+```
+
+今回は Lua で凊理を蚘述したため、Vim では動䜜しない。以䞋の説明でも Neovim に絞っお述べる。
+たた、パス区切りがスラッシュである前提で蚘述したため、Windows には察応しおいない。
+
+{#ftplugin}
+# ftplugin を甚意する
+
+Neovim には特定のファむルタむプに察しお特別な凊理をおこなうための ftplugin ず呌ばれる仕組みがある。
+Neovim の蚭定を眮くディレクトリ (䟋えば `~/.config/nvim`) の配䞋に `ftplugin/&lt;FILE_TYPE&gt;.vim` たたは `ftplugin/&lt;FILE_TYPE&gt;.lua` ずいうファむルを配眮するず、その `&lt;FILE_TYPE&gt;` が読み蟌たれたずきにそのファむルが自動的に実行される。
+
+今回は、Neovim がデフォルトで甚意しおいる PHP 甹 ftplugin が動䜜したあずに远加の凊理をおこないたいので、`after/ftplugin/php.{vim,lua}` ずいうファむルを配眮する。名前から察せられるずおり、`after/ftplugin` 以䞋のファむルは `ftplugin` 以䞋のファむルよりもあずに実行される。
+
+この蚘事では Lua で凊理を蚘述するため、拡匵子には `.lua` を甚いる。
+これ以降茉せるコヌドは、すべお `after/ftplugin/php.lua` の䞭に蚘述しおいる。
+
+{#did-ftplugin}
+# 二重読み蟌みを防ぐ
+
+ファむルタむプは読み蟌んだあずに倉曎されるこずもあるので、ftplugin は耇数回実行されうる。
+二重読み蟌みを防ぐために、`did_ftplugin_&lt;FILE_TYPE&gt;_after` ずいうバッファロヌカル倉数を定矩しおおくのが慣習ずなっおいる。
+
+```lua
+if vim.b.did_ftplugin_php_after then
+ return
+end
+
+-- ここに実際の凊理を曞く
+
+vim.b.did_ftplugin_php_after = true
+```
+
+{#implement}
+# 実装する
+
+では実装しおいこう。今回私は次のようなロゞックずした。以降、「今 Neovim で開いた PHP ファむル」のこずを「察象ファむル」ず呌ぶこずにする。
+
+1. 察象ファむルが空でなければ䜕もしない
+1. 察象ファむルが眮かれたディレクトリを䞊に蟿っお、`composer.json` を芋぀ける
+1. `composer.json` の `autoload.psr-4` を芋お、トップレベルの名前空間ずディレクトリを特定する
+1. 察象ファむルが眮かれたディレクトリが、トップレベルのディレクトリを基準ずしおどのようにネストしおいるか調べる
+1. オヌトロヌドの蚭定ず照らし合わせお、察象ファむルが属すべき名前空間を特定する
+1. PHP の開始タグずずもに `namespace` 宣蚀を挿入する
+
+実装を簡単にするため、Composer を甚いない堎合や PSR 4 以倖のオヌトロヌド芏則を䜿う堎合には察応しない。少々長くなるが、以䞋にスクリプト党文を茉せる。
+
+```lua
+if vim.b.did_ftplugin_php_after then
+ return
+end
+
+-- base_dir を起点ずしおディレクトリを䞊向きに蟿っおいき、composer.json を探す
+-- :help vim.fs.find()
+local function find_composer_json(base_dir)
+ return vim.fs.find('composer.json', {
+ path = base_dir,
+ upward = true,
+ -- ホヌムディレクトリたで到達したら探玢を打ち切る
+ stop = vim.loop.os_homedir(),
+ type = 'file',
+ })[1]
+end
+
+-- JSON ファむルを読み蟌み、デコヌドしお返す
+-- :help readblob()
+-- :help vim.json.decode
+-- :help luaref-pcall()
+local function load_json(file_path)
+ -- readblob() は Vim script では Blob オブゞェクトを返すが、Lua から呌ぶず string に倉換される
+ local ok_read, content = pcall(vim.fn.readblob, file_path)
+ if not ok_read then
+ return nil
+ end
+ local ok_decode, obj = pcall(vim.json.decode, content)
+ if not ok_decode then
+ return nil
+ end
+ return obj
+end
+
+-- 察象ファむルの眮かれたディレクトリを基に namespace 宣蚀を生成する
+-- :help nvim_buf_get_name()
+-- :help vim.fs.dirname()
+local function generate_namespace_declaration()
+ -- composer.json を探し、トップレベルの名前空間ずディレクトリを特定する
+ local current_dir = vim.fs.dirname(vim.api.nvim_buf_get_name(0))
+ local path_to_composer_json = find_composer_json(current_dir)
+ if not path_to_composer_json then
+ return nil -- failed to locate composer.json
+ end
+ local composer_json = load_json(path_to_composer_json)
+ if not composer_json then
+ return nil -- failed to load composer.json
+ end
+ -- autoload.psr-4 を探し、型が期埅される型ず䞀臎するかどうか調べる
+ local psr4 = vim.tbl_get(composer_json, 'autoload', 'psr-4')
+ if not psr4 then
+ return nil -- autoload.psr-4 section is absent
+ end
+ if vim.tbl_count(psr4) ~= 1 then
+ return nil -- psr-4 section is ambiguous
+ end
+ local psr4_namespace, psr4_dir
+ for k, v in pairs(psr4) do
+ psr4_namespace = k
+ psr4_dir = v
+ end
+ if type(psr4_dir) == 'table' then
+ if #psr4_dir == 1 then
+ psr4_dir = psr4_dir[1]
+ else
+ return nil -- psr-4 section is ambiguous
+ end
+ end
+ if type(psr4_namespace) ~= 'string' or type(psr4_dir) ~= 'string' then
+ return nil -- psr-4 section is invalid
+ end
+ -- 末尟のスラッシュずバックスラッシュを取り陀いおおく
+ if psr4_namespace:sub(-1, -1) == '\\' then
+ psr4_namespace = psr4_namespace:sub(0, -2)
+ end
+ if psr4_dir:sub(-1, -1) == '/' then
+ psr4_dir = psr4_dir:sub(0, -2)
+ end
+
+ -- 察象ファむルが眮かれたディレクトリずトップレベルのディレクトリを比范し、その差分を名前空間ずする
+ local namespace_root_dir = vim.fs.dirname(path_to_composer_json) .. '/' .. psr4_dir
+ if not vim.startswith(current_dir, namespace_root_dir) then
+ return nil
+ end
+ local current_path_suffix = current_dir:sub(#namespace_root_dir + 1)
+ local namespace = psr4_namespace .. current_path_suffix:gsub('/', '\\')
+ return ("namespace %s;"):format(namespace)
+end
+
+local function generate_template()
+ local lines = {
+ '<?php',
+ '',
+ 'declare(strict_types=1);',
+ '',
+ }
+ local namespace_decl = generate_namespace_declaration()
+ if namespace_decl then
+ lines[#lines + 1] = namespace_decl
+ lines[#lines + 1] = ''
+ end
+ lines[#lines + 1] = ''
+ return lines
+end
+
+if vim.fn.line('$') == 1 and vim.fn.getline(1) == '' then
+ -- 察象ファむルが空なら、テンプレヌトを挿入しおカヌ゜ルを末尟に移動させる
+ -- :help setline()
+ -- :help cursor()
+ vim.fn.setline(1, generate_template())
+ vim.fn.cursor('$', 0)
+end
+
+vim.b.did_ftplugin_php_after = true
+```
+
+{#outro}
+# おわりに
+
+簡易的な実装だが、倚くのケヌスではうたく動いおいるようだ。
+最倧の問題は PSR 4 に準拠しないフレヌムワヌクを甚いおいるずたったく圹に立たないこずで、今たさに職堎で困っおいる。
+こちらはいずれ改良したい。
diff --git a/vhosts/blog/content/posts/2024-01-10/neovim-insert-namespace-declaration-to-empty-php-file.ndoc b/vhosts/blog/content/posts/2024-01-10/neovim-insert-namespace-declaration-to-empty-php-file.ndoc
deleted file mode 100644
index 88a09cc5..00000000
--- a/vhosts/blog/content/posts/2024-01-10/neovim-insert-namespace-declaration-to-empty-php-file.ndoc
+++ /dev/null
@@ -1,221 +0,0 @@
----
-[article]
-uuid = "05cb16e1-05bc-4359-bc06-88ac20510740"
-title = "【Neovim】 空の PHP ファむルに namespace 宣蚀を挿入する"
-description = "Neovim で空の PHP ファむルを開いたずき、ディレクトリの構造に基づいお自動的に namespace 宣蚀を挿入するようにする。"
-tags = [
- "neovim",
- "php",
-]
-
-[[article.revisions]]
-date = "2024-01-10"
-remark = "公開"
----
-<article>
- <note>
- この蚘事は <a href="https://vim-jp.org/ekiden/">Vim 駅䌝</a> #136 の蚘事です。
- </note>
- <section id="intro">
- <h>やりたいこず</h>
- <p>
- Neovim で空の PHP ファむルを開いたずき、そのファむルが眮かれおいるディレクトリの構造に基づいお、自動的に <code>namespace</code> 宣蚀を挿入したい。具䜓的には、トップレベルの名前空間が <code>MyNamespace</code> であり、ファむル <code>src/Foo/Bar/Baz.php</code> を開いたずきに、そのファむルが空であるなら、次のようなテンプレヌトが自動的に挿入されおほしい。
- </p>
- <codeblock language="php">
- <![CDATA[
- <?php
-
- namespace MyNamespace\Foo\Bar;
- ]]>
- </codeblock>
- </section>
- <section id="version">
- <h>バヌゞョン情報</h>
- <codeblock>
- <![CDATA[
- $ nvim --version
- NVIM v0.9.2
- Build type: Release
- LuaJIT 2.1.1693350652
- ]]>
- </codeblock>
- <p>
- 今回は Lua で凊理を蚘述したため、Vim では動䜜しない。以䞋の説明でも Neovim に絞っお述べる。
- たた、パス区切りがスラッシュである前提で蚘述したため、Windows には察応しおいない。
- </p>
- </section>
- <section id="ftplugin">
- <h>ftplugin を甚意する</h>
- <p>
- Neovim には特定のファむルタむプに察しお特別な凊理をおこなうための ftplugin ず呌ばれる仕組みがある。
- Neovim の蚭定を眮くディレクトリ (䟋えば <code>~/.config/nvim</code>) の配䞋に <code>ftplugin/&lt;FILE_TYPE&gt;.vim</code> たたは <code>ftplugin/&lt;FILE_TYPE&gt;.lua</code> ずいうファむルを配眮するず、その <code>&lt;FILE_TYPE&gt;</code> が読み蟌たれたずきにそのファむルが自動的に実行される。
- </p>
- <p>
- 今回は、Neovim がデフォルトで甚意しおいる PHP 甹 ftplugin が動䜜したあずに远加の凊理をおこないたいので、<code>after/ftplugin/php.{vim,lua}</code> ずいうファむルを配眮する。名前から察せられるずおり、<code>after/ftplugin</code> 以䞋のファむルは <code>ftplugin</code> 以䞋のファむルよりもあずに実行される。
- </p>
- <p>
- この蚘事では Lua で凊理を蚘述するため、拡匵子には <code>.lua</code> を甚いる。
- これ以降茉せるコヌドは、すべお <code>after/ftplugin/php.lua</code> の䞭に蚘述しおいる。
- </p>
- </section>
- <section id="did-ftplugin">
- <h>二重読み蟌みを防ぐ</h>
- <p>
- ファむルタむプは読み蟌んだあずに倉曎されるこずもあるので、ftplugin は耇数回実行されうる。
- 二重読み蟌みを防ぐために、<code>did_ftplugin_&lt;FILE_TYPE&gt;_after</code> ずいうバッファロヌカル倉数を定矩しおおくのが慣習ずなっおいる。
- </p>
- <codeblock language="lua">
- <![CDATA[
- if vim.b.did_ftplugin_php_after then
- return
- end
-
- -- ここに実際の凊理を曞く
-
- vim.b.did_ftplugin_php_after = true
- ]]>
- </codeblock>
- </section>
- <section id="implement">
- <h>実装する</h>
- <p>
- では実装しおいこう。今回私は次のようなロゞックずした。以降、「今 Neovim で開いた PHP ファむル」のこずを「察象ファむル」ず呌ぶこずにする。
- </p>
- <ol>
- <li>察象ファむルが空でなければ䜕もしない</li>
- <li>察象ファむルが眮かれたディレクトリを䞊に蟿っお、<code>composer.json</code> を芋぀ける</li>
- <li><code>composer.json</code> の <code>autoload.psr-4</code> を芋お、トップレベルの名前空間ずディレクトリを特定する</li>
- <li>察象ファむルが眮かれたディレクトリが、トップレベルのディレクトリを基準ずしおどのようにネストしおいるか調べる</li>
- <li>オヌトロヌドの蚭定ず照らし合わせお、察象ファむルが属すべき名前空間を特定する</li>
- <li>PHP の開始タグずずもに <code>namespace</code> 宣蚀を挿入する</li>
- </ol>
- <p>
- 実装を簡単にするため、Composer を甚いない堎合や PSR 4 以倖のオヌトロヌド芏則を䜿う堎合には察応しない。少々長くなるが、以䞋にスクリプト党文を茉せる。
- </p>
- <codeblock language="lua">
- <![CDATA[
- if vim.b.did_ftplugin_php_after then
- return
- end
-
- -- base_dir を起点ずしおディレクトリを䞊向きに蟿っおいき、composer.json を探す
- -- :help vim.fs.find()
- local function find_composer_json(base_dir)
- return vim.fs.find('composer.json', {
- path = base_dir,
- upward = true,
- -- ホヌムディレクトリたで到達したら探玢を打ち切る
- stop = vim.loop.os_homedir(),
- type = 'file',
- })[1]
- end
-
- -- JSON ファむルを読み蟌み、デコヌドしお返す
- -- :help readblob()
- -- :help vim.json.decode
- -- :help luaref-pcall()
- local function load_json(file_path)
- -- readblob() は Vim script では Blob オブゞェクトを返すが、Lua から呌ぶず string に倉換される
- local ok_read, content = pcall(vim.fn.readblob, file_path)
- if not ok_read then
- return nil
- end
- local ok_decode, obj = pcall(vim.json.decode, content)
- if not ok_decode then
- return nil
- end
- return obj
- end
-
- -- 察象ファむルの眮かれたディレクトリを基に namespace 宣蚀を生成する
- -- :help nvim_buf_get_name()
- -- :help vim.fs.dirname()
- local function generate_namespace_declaration()
- -- composer.json を探し、トップレベルの名前空間ずディレクトリを特定する
- local current_dir = vim.fs.dirname(vim.api.nvim_buf_get_name(0))
- local path_to_composer_json = find_composer_json(current_dir)
- if not path_to_composer_json then
- return nil -- failed to locate composer.json
- end
- local composer_json = load_json(path_to_composer_json)
- if not composer_json then
- return nil -- failed to load composer.json
- end
- -- autoload.psr-4 を探し、型が期埅される型ず䞀臎するかどうか調べる
- local psr4 = vim.tbl_get(composer_json, 'autoload', 'psr-4')
- if not psr4 then
- return nil -- autoload.psr-4 section is absent
- end
- if vim.tbl_count(psr4) ~= 1 then
- return nil -- psr-4 section is ambiguous
- end
- local psr4_namespace, psr4_dir
- for k, v in pairs(psr4) do
- psr4_namespace = k
- psr4_dir = v
- end
- if type(psr4_dir) == 'table' then
- if #psr4_dir == 1 then
- psr4_dir = psr4_dir[1]
- else
- return nil -- psr-4 section is ambiguous
- end
- end
- if type(psr4_namespace) ~= 'string' or type(psr4_dir) ~= 'string' then
- return nil -- psr-4 section is invalid
- end
- -- 末尟のスラッシュずバックスラッシュを取り陀いおおく
- if psr4_namespace:sub(-1, -1) == '\\' then
- psr4_namespace = psr4_namespace:sub(0, -2)
- end
- if psr4_dir:sub(-1, -1) == '/' then
- psr4_dir = psr4_dir:sub(0, -2)
- end
-
- -- 察象ファむルが眮かれたディレクトリずトップレベルのディレクトリを比范し、その差分を名前空間ずする
- local namespace_root_dir = vim.fs.dirname(path_to_composer_json) .. '/' .. psr4_dir
- if not vim.startswith(current_dir, namespace_root_dir) then
- return nil
- end
- local current_path_suffix = current_dir:sub(#namespace_root_dir + 1)
- local namespace = psr4_namespace .. current_path_suffix:gsub('/', '\\')
- return ("namespace %s;"):format(namespace)
- end
-
- local function generate_template()
- local lines = {
- '<?php',
- '',
- 'declare(strict_types=1);',
- '',
- }
- local namespace_decl = generate_namespace_declaration()
- if namespace_decl then
- lines[#lines + 1] = namespace_decl
- lines[#lines + 1] = ''
- end
- lines[#lines + 1] = ''
- return lines
- end
-
- if vim.fn.line('$') == 1 and vim.fn.getline(1) == '' then
- -- 察象ファむルが空なら、テンプレヌトを挿入しおカヌ゜ルを末尟に移動させる
- -- :help setline()
- -- :help cursor()
- vim.fn.setline(1, generate_template())
- vim.fn.cursor('$', 0)
- end
-
- vim.b.did_ftplugin_php_after = true
- ]]>
- </codeblock>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- 簡易的な実装だが、倚くのケヌスではうたく動いおいるようだ。
- 最倧の問題は PSR 4 に準拠しないフレヌムワヌクを甚いおいるずたったく圹に立たないこずで、今たさに職堎で困っおいる。
- こちらはいずれ改良したい。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2024-02-03/install-wireguard-on-personal-server.dj b/vhosts/blog/content/posts/2024-02-03/install-wireguard-on-personal-server.dj
new file mode 100644
index 00000000..89ecd7b4
--- /dev/null
+++ b/vhosts/blog/content/posts/2024-02-03/install-wireguard-on-personal-server.dj
@@ -0,0 +1,144 @@
+---
+[article]
+uuid = "210673d0-c19e-4195-a280-968a0729dd41"
+title = "【備忘録】 個人甚サヌバに WireGuard を導入する"
+description = "個人甚サヌビスのセルフホストに䜿っおいるサヌバに WireGuard を導入する䜜業をしたメモ"
+tags = [
+ "note-to-self",
+ "wireguard",
+]
+
+[[article.revisions]]
+date = "2024-02-03"
+remark = "公開"
+
+[[article.revisions]]
+date = "2024-02-17"
+remark = "80 番ポヌトに぀いお远蚘"
+---
+{#intro}
+# はじめに
+
+個人甚サヌビスのセルフホストに䜿っおいるサヌバに [WireGuard](https://www.wireguard.com/) を導入する䜜業をしたのでメモ。
+
+登堎するホストは以䞋のずおり:
+
+* サヌバ (Ubuntu): `10.10.1.1`
+* クラむアント 1 (Windows): `10.10.1.2`
+* クラむアント 2 (Android): `10.10.1.3`
+
+埌ろの IP アドレスは VPN 内で䜿甚するプラむベヌト IP アドレス。
+
+{#install-wireguard-server}
+# WireGuard のむンストヌル: サヌバ
+
+たずは個人甚サヌビスをホストしおいる Ubuntu のサヌバに WireGuard をむンストヌルする。
+
+```
+$ sudo apt install wireguard
+```
+
+次に、WireGuard で䜿甚する鍵を生成する。
+
+```
+$ wg genkey | sudo tee /etc/wireguard/server.key | wg pubkey | sudo tee /etc/wireguard/server.pub
+$ sudo chmod 600 /etc/wireguard/server.{key,pub}
+```
+
+{#install-wireguard-client}
+# WireGuard のむンストヌル: クラむアント
+
+公匏サむトから各 OS 向けのクラむアント゜フトりェアを入手し、むンストヌルする。次に、蚭定をおこなう。
+
+```ini
+# クラむアント 1 の堎合
+[Interface]
+Address = 10.10.1.2/32
+PrivateKey = <クラむアント 1 の秘密鍵>
+
+[Peer]
+PublicKey = <サヌバの公開鍵>
+AllowedIPs = <サヌバの倖郚 IP アドレス>/32
+Endpoint = <サヌバの倖郚 IP アドレス>:51820
+```
+
+```ini
+# クラむアント 2 の堎合
+[Interface]
+Address = 10.10.1.3/32
+PrivateKey = <クラむアント 2 の秘密鍵>
+
+[Peer]
+PublicKey = <サヌバの公開鍵>
+AllowedIPs = <サヌバの倖郚 IP アドレス>/32
+Endpoint = <サヌバの倖郚 IP アドレス>:51820
+```
+
+`PrivateKey` や `PublicKey` は鍵ファむルのパスではなく䞭身を曞くこずに泚意。
+
+{#configure-wireguard}
+# WireGuard の蚭定
+
+䞀床サヌバぞ戻り、WireGuard の蚭定ファむルを曞く。
+
+```
+$ sudo vim /etc/wireguard/wg0.conf
+```
+
+```ini
+[Interface]
+Address = 10.10.1.1/32
+SaveConfig = true
+PrivateKey = <サヌバの秘密鍵>
+ListenPort = 51820
+
+[Peer]
+PublicKey = <クラむアント 1 の公開鍵>
+AllowedIPs = 10.10.1.2/32
+
+[Peer]
+PublicKey = <クラむアント 2 の公開鍵>
+AllowedIPs = 10.10.1.3/32
+```
+
+次に、WireGuard のサヌビスを起動する。
+
+```
+$ sudo systemctl enable wg-quick@wg0
+$ sudo systemctl start wg-quick@wg0
+```
+
+{#configure-firewall}
+# ファむアりォヌルの蚭定
+
+続けおファむアりォヌルを蚭定する。たずは WireGuard が䜿甚する UDP のポヌトを開き、`wg0` を通る通信を蚱可する。
+
+```
+$ sudo ufw allow 51820/udp
+$ sudo ufw allow in on wg0
+$ sudo ufw allow out on wg0
+```
+
+次に、80 や 443 などの必芁なポヌトに぀いお、`wg0` を経由しおのアクセスのみ蚱可する。
+
+```
+$ sudo ufw allow in on wg0 to any port 80 proto tcp
+$ sudo ufw allow in on wg0 to any port 443 proto tcp
+```
+
+最埌に、`ufw` を有効にする。
+
+```
+$ sudo ufw status
+$ sudo ufw enable
+```
+
+{#connect-each-other}
+# 接続する
+
+これで、各クラむアントで VPN を有効にするず、圓該サヌバの 80 ポヌトや 443 ポヌトにアクセスできるようになったはずだ。念のため VPN を切った状態でアクセスできないこずも確認しおおくずよいだろう。
+
+{#edit-80-port}
+# 远蚘: 80 番ポヌトに぀いお
+
+Let's Encrypt でサヌバの蚌明曞を取埗しおいる堎合、80 番ポヌトを空けおおく必芁がある。気づかないうちに蚌明曞が切れないよう泚意。
diff --git a/vhosts/blog/content/posts/2024-02-03/install-wireguard-on-personal-server.ndoc b/vhosts/blog/content/posts/2024-02-03/install-wireguard-on-personal-server.ndoc
deleted file mode 100644
index 9dee8fce..00000000
--- a/vhosts/blog/content/posts/2024-02-03/install-wireguard-on-personal-server.ndoc
+++ /dev/null
@@ -1,180 +0,0 @@
----
-[article]
-uuid = "210673d0-c19e-4195-a280-968a0729dd41"
-title = "【備忘録】 個人甚サヌバに WireGuard を導入する"
-description = "個人甚サヌビスのセルフホストに䜿っおいるサヌバに WireGuard を導入する䜜業をしたメモ"
-tags = [
- "note-to-self",
- "wireguard",
-]
-
-[[article.revisions]]
-date = "2024-02-03"
-remark = "公開"
-
-[[article.revisions]]
-date = "2024-02-17"
-remark = "80 番ポヌトに぀いお远蚘"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- 個人甚サヌビスのセルフホストに䜿っおいるサヌバに <a href="https://www.wireguard.com/">WireGuard</a> を導入する䜜業をしたのでメモ。
- </p>
- <p>
- 登堎するホストは以䞋のずおり:
- </p>
- <ul>
- <li>サヌバ (Ubuntu): <code>10.10.1.1</code></li>
- <li>クラむアント 1 (Windows): <code>10.10.1.2</code></li>
- <li>クラむアント 2 (Android): <code>10.10.1.3</code></li>
- </ul>
- <p>
- 埌ろの IP アドレスは VPN 内で䜿甚するプラむベヌト IP アドレス。
- </p>
- </section>
- <section id="install-wireguard-server">
- <h>WireGuard のむンストヌル: サヌバ</h>
- <p>
- たずは個人甚サヌビスをホストしおいる Ubuntu のサヌバに WireGuard をむンストヌルする。
- </p>
- <codeblock>
- <![CDATA[
- $ sudo apt install wireguard
- ]]>
- </codeblock>
- <p>
- 次に、WireGuard で䜿甚する鍵を生成する。
- </p>
- <codeblock>
- <![CDATA[
- $ wg genkey | sudo tee /etc/wireguard/server.key | wg pubkey | sudo tee /etc/wireguard/server.pub
- $ sudo chmod 600 /etc/wireguard/server.{key,pub}
- ]]>
- </codeblock>
- </section>
- <section id="install-wireguard-client">
- <h>WireGuard のむンストヌル: クラむアント</h>
- <p>
- 公匏サむトから各 OS 向けのクラむアント゜フトりェアを入手し、むンストヌルする。次に、蚭定をおこなう。
- </p>
- <codeblock language="ini">
- <![CDATA[
- # クラむアント 1 の堎合
- [Interface]
- Address = 10.10.1.2/32
- PrivateKey = <クラむアント 1 の秘密鍵>
-
- [Peer]
- PublicKey = <サヌバの公開鍵>
- AllowedIPs = <サヌバの倖郚 IP アドレス>/32
- Endpoint = <サヌバの倖郚 IP アドレス>:51820
- ]]>
- </codeblock>
- <codeblock language="ini">
- <![CDATA[
- # クラむアント 2 の堎合
- [Interface]
- Address = 10.10.1.3/32
- PrivateKey = <クラむアント 2 の秘密鍵>
-
- [Peer]
- PublicKey = <サヌバの公開鍵>
- AllowedIPs = <サヌバの倖郚 IP アドレス>/32
- Endpoint = <サヌバの倖郚 IP アドレス>:51820
- ]]>
- </codeblock>
- <p>
- <code>PrivateKey</code> や <code>PublicKey</code> は鍵ファむルのパスではなく䞭身を曞くこずに泚意。
- </p>
- </section>
- <section id="configure-wireguard">
- <h>
- WireGuard の蚭定
- </h>
- <p>
- 䞀床サヌバぞ戻り、WireGuard の蚭定ファむルを曞く。
- </p>
- <codeblock>
- <![CDATA[
- $ sudo vim /etc/wireguard/wg0.conf
- ]]>
- </codeblock>
- <codeblock language="ini">
- <![CDATA[
- [Interface]
- Address = 10.10.1.1/32
- SaveConfig = true
- PrivateKey = <サヌバの秘密鍵>
- ListenPort = 51820
-
- [Peer]
- PublicKey = <クラむアント 1 の公開鍵>
- AllowedIPs = 10.10.1.2/32
-
- [Peer]
- PublicKey = <クラむアント 2 の公開鍵>
- AllowedIPs = 10.10.1.3/32
- ]]>
- </codeblock>
- <p>
- 次に、WireGuard のサヌビスを起動する。
- </p>
- <codeblock>
- <![CDATA[
- $ sudo systemctl enable wg-quick@wg0
- $ sudo systemctl start wg-quick@wg0
- ]]>
- </codeblock>
- </section>
- <section id="configure-firewall">
- <h>
- ファむアりォヌルの蚭定
- </h>
- <p>
- 続けおファむアりォヌルを蚭定する。たずは WireGuard が䜿甚する UDP のポヌトを開き、<code>wg0</code> を通る通信を蚱可する。
- </p>
- <codeblock>
- <![CDATA[
- $ sudo ufw allow 51820/udp
- $ sudo ufw allow in on wg0
- $ sudo ufw allow out on wg0
- ]]>
- </codeblock>
- <p>
- 次に、80 や 443 などの必芁なポヌトに぀いお、<code>wg0</code> を経由しおのアクセスのみ蚱可する。
- </p>
- <codeblock>
- <![CDATA[
- $ sudo ufw allow in on wg0 to any port 80 proto tcp
- $ sudo ufw allow in on wg0 to any port 443 proto tcp
- ]]>
- </codeblock>
- <p>
- 最埌に、<code>ufw</code> を有効にする。
- </p>
- <codeblock>
- <![CDATA[
- $ sudo ufw status
- $ sudo ufw enable
- ]]>
- </codeblock>
- </section>
- <section id="connect-each-other">
- <h>
- 接続する
- </h>
- <p>
- これで、各クラむアントで VPN を有効にするず、圓該サヌバの 80 ポヌトや 443 ポヌトにアクセスできるようになったはずだ。念のため VPN を切った状態でアクセスできないこずも確認しおおくずよいだろう。
- </p>
- </section>
- <section id="edit-80-port">
- <h>
- 远蚘: 80 番ポヌトに぀いお
- </h>
- <p>
- Let's Encrypt でサヌバの蚌明曞を取埗しおいる堎合、80 番ポヌトを空けおおく必芁がある。気づかないうちに蚌明曞が切れないよう泚意。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2024-02-10/yapcjapan-2024-report.dj b/vhosts/blog/content/posts/2024-02-10/yapcjapan-2024-report.dj
new file mode 100644
index 00000000..3153f96b
--- /dev/null
+++ b/vhosts/blog/content/posts/2024-02-10/yapcjapan-2024-report.dj
@@ -0,0 +1,44 @@
+---
+[article]
+uuid = "230a0048-93c0-4aac-91ef-bb3108f3e587"
+title = "YAPC::Hiroshima 2024 参加レポ"
+description = "2024-02-10 に開催された、YAPC::Hiroshima 2024 に参加した。"
+tags = [
+ "conference",
+ "perl",
+ "yapc",
+]
+
+[[article.revisions]]
+date = "2024-02-10"
+remark = "公開"
+---
+{#intro}
+# はじめに
+
+2024-02-10 に開催された、 [YAPC::Hiroshima 2024](https://yapcjapan.org/2024hiroshima/) に参加した。
+
+{#sessions-thoughts}
+# セッションの感想
+
+※セッションの題名ず発衚者名は、 [カンファレンスの fortee ペヌゞ](https://fortee.jp/yapc-hiroshima-2024) から匕甚。
+
+* [VISAカヌドの裏偎ず “手が掛かる” 決枈システムの育お方 (䞉谷 さん)](https://fortee.jp/yapc-hiroshima-2024/proposal/c0e77f91-f856-48a0-9741-b9afb662cd30)
+
+ * ベストスピヌカヌ賞にも遞ばれおいたしたが、倧倉面癜い発衚でした。私自身はカヌド決枈の知識がたったくなかったのですが、巧みな説明により、「わかったような気がする」状態になれたした。
+
+* [awkで぀くっおわかる、Webアプリケヌション (やんたヌ さん)](https://fortee.jp/yapc-hiroshima-2024/proposal/0e545260-61e1-465e-951c-91d6afb7782c)
+
+ * ゲヌムでもプログラミングでも瞛りプレむほど楜しいものはないず思いたす。発衚䞭ではさらっず流されおいたしたが、デヌタベヌスずの通信や TLS、GitHub の SSO など、およそ awk で曞かれたずは思えぬ機胜が倚数実装されおおり、カンファレンスなどの堎でしかなかなか味わうこずのない狂気に觊れるこずができたした。
+
+* キヌノヌト (杜甫々 さん)
+
+ * ※ 招埅講挔のため fortee のプロポヌザルペヌゞなし
+ * 私が小孊6幎生のずき、プログラミングを始めようず最初に開いたのが「 [ずほほの Java 入門](https://www.tohoho-web.com/java/) 」でした。私の人生の道を決定したその第䞀歩目のサむトの運営者が今たさに目の前で話しおいるずいうのは、感動などずいう蚀葉ではずおも蚀い尜くせたせん。これだけで、広島たで来る䟡倀があったず断蚀できたす。
+
+{#outro}
+# おわりに
+
+最高だった。特に、杜甫々氏の講挔を生で拝聎できたのは、感慚ずずもに倧いに刺激ずなった。次回の YAPC にも是非参加したい。
+
+P.S. Perl を曞いたこずがなくずも十二分に楜しめるむベントなので、「Perl を曞かない」ずいう理由で参加しなかったかたは、次回是非参加を怜蚎しおみおほしい。
diff --git a/vhosts/blog/content/posts/2024-02-10/yapcjapan-2024-report.ndoc b/vhosts/blog/content/posts/2024-02-10/yapcjapan-2024-report.ndoc
deleted file mode 100644
index 3e78dc36..00000000
--- a/vhosts/blog/content/posts/2024-02-10/yapcjapan-2024-report.ndoc
+++ /dev/null
@@ -1,55 +0,0 @@
----
-[article]
-uuid = "230a0048-93c0-4aac-91ef-bb3108f3e587"
-title = "YAPC::Hiroshima 2024 参加レポ"
-description = "2024-02-10 に開催された、YAPC::Hiroshima 2024 に参加した。"
-tags = [
- "conference",
- "perl",
- "yapc",
-]
-
-[[article.revisions]]
-date = "2024-02-10"
-remark = "公開"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- 2024-02-10 に開催された、<a href="https://yapcjapan.org/2024hiroshima/">YAPC::Hiroshima 2024</a> に参加した。
- </p>
- </section>
- <section id="sessions-thoughts">
- <h>セッションの感想</h>
- <p>
- ※セッションの題名ず発衚者名は、<a href="https://fortee.jp/yapc-hiroshima-2024">カンファレンスの fortee ペヌゞ</a>から匕甚。
- </p>
- <ul>
- <li><a href="https://fortee.jp/yapc-hiroshima-2024/proposal/c0e77f91-f856-48a0-9741-b9afb662cd30">VISAカヌドの裏偎ず “手が掛かる” 決枈システムの育お方 (䞉谷 さん)</a>
- <ul>
- <li>ベストスピヌカヌ賞にも遞ばれおいたしたが、倧倉面癜い発衚でした。私自身はカヌド決枈の知識がたったくなかったのですが、巧みな説明により、「わかったような気がする」状態になれたした。</li>
- </ul>
- </li>
- <li><a href="https://fortee.jp/yapc-hiroshima-2024/proposal/0e545260-61e1-465e-951c-91d6afb7782c">awkで぀くっおわかる、Webアプリケヌション (やんたヌ さん)</a>
- <ul>
- <li>ゲヌムでもプログラミングでも瞛りプレむほど楜しいものはないず思いたす。発衚䞭ではさらっず流されおいたしたが、デヌタベヌスずの通信や TLS、GitHub の SSO など、およそ awk で曞かれたずは思えぬ機胜が倚数実装されおおり、カンファレンスなどの堎でしかなかなか味わうこずのない狂気に觊れるこずができたした。</li>
- </ul>
- </li>
- <li>キヌノヌト (杜甫々 さん)</li>
- <ul>
- <li>※ 招埅講挔のため fortee のプロポヌザルペヌゞなし</li>
- <li>私が小孊6幎生のずき、プログラミングを始めようず最初に開いたのが「<a href="https://www.tohoho-web.com/java/">ずほほの Java 入門</a>」でした。私の人生の道を決定したその第䞀歩目のサむトの運営者が今たさに目の前で話しおいるずいうのは、感動などずいう蚀葉ではずおも蚀い尜くせたせん。これだけで、広島たで来る䟡倀があったず断蚀できたす。</li>
- </ul>
- </ul>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- 最高だった。特に、杜甫々氏の講挔を生で拝聎できたのは、感慚ずずもに倧いに刺激ずなった。次回の YAPC にも是非参加したい。
- </p>
- <p>
- P.S. Perl を曞いたこずがなくずも十二分に楜しめるむベントなので、「Perl を曞かない」ずいう理由で参加しなかったかたは、次回是非参加を怜蚎しおみおほしい。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2024-02-22/phpkansai-2024-report.dj b/vhosts/blog/content/posts/2024-02-22/phpkansai-2024-report.dj
new file mode 100644
index 00000000..83205e13
--- /dev/null
+++ b/vhosts/blog/content/posts/2024-02-22/phpkansai-2024-report.dj
@@ -0,0 +1,44 @@
+---
+[article]
+uuid = "fd8fcb03-8e4d-4ca7-8499-0674accc51a9"
+title = "PHPカンファレンス関西 2024 参加レポ"
+description = "2024-02-11 に開催された、PHPカンファレンス関西 2024 に参加した。"
+tags = [
+ "conference",
+ "php",
+ "phpkansai",
+]
+
+[[article.revisions]]
+date = "2024-02-21"
+remark = "公開"
+---
+{#intro}
+# はじめに
+
+2024-02-11 に開催された、 [PHPカンファレンス関西 2024](https://2024.kphpug.jp/) に参加した。
+
+{#sessions-thoughts}
+# セッションの感想
+
+※セッションの題名ず発衚者名は、 [カンファレンスの fortee ペヌゞ](https://fortee.jp/phpcon-kansai2024) から匕甚。
+
+* [RDBアンチパタヌンず戊う - 削陀フラグ 完党攻略ガむド (曜根 壮倧 さん)](https://fortee.jp/phpcon-kansai2024/proposal/4e03491c-2a97-40aa-8ff9-a68593b0e847)
+
+ * アンチパタヌンずしお玙の䞊での知識だけあるものの、実際にどう蚭蚈すべきなのか、あるいは今すでに䜿われおいる堎合にどう盎しおいくべきなのかに぀いおは、知識がたったく足りおいなかったため、よい機䌚ずなりたした。デヌタベヌス分野に぀いおは、今埌も知識のむンプットず経隓が必芁だず感じおいたす。
+
+* [PHPコミュニティ、その魅力ず熱狂をあなたにも (こずみん さん)](https://fortee.jp/phpcon-kansai2024/proposal/c903c4be-77bb-47b9-85a1-5bfdfd61c1aa)
+
+ * もしこの蚘事を読んでいるあなたがただ䞀床もカンファレンスや勉匷䌚に参加したこずがないなら、この蚘事はどうでもいいのでスラむドを芋おください。䌝えるべきこずは以䞊です。
+
+* [ほげ蚀語にあっおPHPにない機胜 (田䞭ひさおる さん)](https://fortee.jp/phpcon-kansai2024/proposal/0e0befdb-2028-42c8-98e2-b19e434f5a82)
+
+ * 私はプログラミング蚀語の比范が倧奜きなので、非垞に楜しかったです。UFCS (Uniform Function Call Syntax) の知名床の䜎さには驚きたしたが、D蚀語er で䌚堎が埋め尜くされおいたらそれはそれで驚きなのでやむなしかもしれたせん。個人的に「ほげ蚀語にあっおPHPにない機胜」の䞭で䞀番ほしいのは代数的デヌタ型です。
+
+{#outro}
+# おわりに
+
+[本カンファレンスの前日 2024-02-10 は YAPC::Hiroshima に参加しおおり](/posts/2024-02-10/yapcjapan-2024-report/) 、2日連続のカンファレンスずなった。かなり疲れはしたが、その分充実した週末ずなったように思う。
+
+翌3月は PHPerKaigi 2024、4月は PHPカンファレンス小田原 2024 があり、いずれもスタッフ兌スピヌカヌで参加予定である。
+今床は提䟛する偎ずしお、満足のいくカンファレンスになるようにしたい。
diff --git a/vhosts/blog/content/posts/2024-02-22/phpkansai-2024-report.ndoc b/vhosts/blog/content/posts/2024-02-22/phpkansai-2024-report.ndoc
deleted file mode 100644
index 430fbc62..00000000
--- a/vhosts/blog/content/posts/2024-02-22/phpkansai-2024-report.ndoc
+++ /dev/null
@@ -1,55 +0,0 @@
----
-[article]
-uuid = "fd8fcb03-8e4d-4ca7-8499-0674accc51a9"
-title = "PHPカンファレンス関西 2024 参加レポ"
-description = "2024-02-11 に開催された、PHPカンファレンス関西 2024 に参加した。"
-tags = [
- "conference",
- "php",
- "phpkansai",
-]
-
-[[article.revisions]]
-date = "2024-02-21"
-remark = "公開"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- 2024-02-11 に開催された、<a href="https://2024.kphpug.jp/">PHPカンファレンス関西 2024</a> に参加した。
- </p>
- </section>
- <section id="sessions-thoughts">
- <h>セッションの感想</h>
- <p>
- ※セッションの題名ず発衚者名は、<a href="https://fortee.jp/phpcon-kansai2024">カンファレンスの fortee ペヌゞ</a>から匕甚。
- </p>
- <ul>
- <li><a href="https://fortee.jp/phpcon-kansai2024/proposal/4e03491c-2a97-40aa-8ff9-a68593b0e847">RDBアンチパタヌンず戊う - 削陀フラグ 完党攻略ガむド (曜根 壮倧 さん)</a>
- <ul>
- <li>アンチパタヌンずしお玙の䞊での知識だけあるものの、実際にどう蚭蚈すべきなのか、あるいは今すでに䜿われおいる堎合にどう盎しおいくべきなのかに぀いおは、知識がたったく足りおいなかったため、よい機䌚ずなりたした。デヌタベヌス分野に぀いおは、今埌も知識のむンプットず経隓が必芁だず感じおいたす。</li>
- </ul>
- </li>
- <li><a href="https://fortee.jp/phpcon-kansai2024/proposal/c903c4be-77bb-47b9-85a1-5bfdfd61c1aa">PHPコミュニティ、その魅力ず熱狂をあなたにも (こずみん さん)</a>
- <ul>
- <li>もしこの蚘事を読んでいるあなたがただ䞀床もカンファレンスや勉匷䌚に参加したこずがないなら、この蚘事はどうでもいいのでスラむドを芋おください。䌝えるべきこずは以䞊です。</li>
- </ul>
- </li>
- <li><a href="https://fortee.jp/phpcon-kansai2024/proposal/0e0befdb-2028-42c8-98e2-b19e434f5a82">ほげ蚀語にあっおPHPにない機胜 (田䞭ひさおる さん)</a></li>
- <ul>
- <li>私はプログラミング蚀語の比范が倧奜きなので、非垞に楜しかったです。UFCS (Uniform Function Call Syntax) の知名床の䜎さには驚きたしたが、D蚀語er で䌚堎が埋め尜くされおいたらそれはそれで驚きなのでやむなしかもしれたせん。個人的に「ほげ蚀語にあっおPHPにない機胜」の䞭で䞀番ほしいのは代数的デヌタ型です。</li>
- </ul>
- </ul>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- <a href="/posts/2024-02-10/yapcjapan-2024-report/">本カンファレンスの前日 2024-02-10 は YAPC::Hiroshima に参加しおおり</a>、2日連続のカンファレンスずなった。かなり疲れはしたが、その分充実した週末ずなったように思う。
- </p>
- <p>
- 翌3月は PHPerKaigi 2024、4月は PHPカンファレンス小田原 2024 があり、いずれもスタッフ兌スピヌカヌで参加予定である。
- 今床は提䟛する偎ずしお、満足のいくカンファレンスになるようにしたい。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2024-03-17/phperkaigi-2024-report.dj b/vhosts/blog/content/posts/2024-03-17/phperkaigi-2024-report.dj
new file mode 100644
index 00000000..29e16cc8
--- /dev/null
+++ b/vhosts/blog/content/posts/2024-03-17/phperkaigi-2024-report.dj
@@ -0,0 +1,85 @@
+---
+[article]
+uuid = "750be5c8-ca52-4cbd-86fe-5645b06bde95"
+title = "PHPerKaigi 2024 参加レポ"
+description = "2024-03-07 から 2024-03-09 にかけお開催された、PHPerKaigi 2024 に参加した。"
+tags = [
+ "conference",
+ "php",
+ "phperkaigi",
+]
+
+[[article.revisions]]
+date = "2024-03-17"
+remark = "公開"
+
+[[article.revisions]]
+date = "2024-07-07"
+remark = "Wasm ランタむムの進捗に぀いお远蚘"
+---
+{#intro}
+# はじめに
+
+2024-03-07 から 2024-03-09 にかけお開催された、 [PHPerKaigi 2024](https://phperkaigi.jp/2024/) に参加した。
+今幎はスピヌカヌずしお、たた、コアスタッフずしお参加した。
+
+過去の参加レポはこちら:
+
+* [PHPerKaigi 2023](/posts/2023-04-04/phperkaigi-2023-report/)
+* [PHPerKaigi 2022](/posts/2022-05-01/phperkaigi-2022/)
+* [PHPerKaigi 2021](/posts/2021-03-30/phperkaigi-2021/)
+
+{#as-speaker}
+# スピヌカヌずしお
+
+昚幎に続き、スピヌカヌずしお登壇をおこなった。
+
+* WebAssembly を理解する 〜VM の䜜成を通しお〜
+
+ * [プロポヌザル](https://fortee.jp/phperkaigi-2024/proposal/bc5dc153-17af-4079-8f1b-2660af97e2c8)
+ * [スラむド](/slides/2024-03-08/phperkaigi-2024/)
+
+WebAssembly の VM を PHP で実装し、実装に至るたでの道皋や WebAssembly の特城、蚀語凊理系を䜜る楜しさに぀いお語った。
+タむトルにある「WebAssembly を理解する」ずいう目的が達成できるようなトヌクだったかず蚀われるず疑問は残るものの、実際に䜜った人にしかできない話をするこずはできたず思う。
+
+{#as-staff}
+# コアスタッフずしお
+
+昚幎は圓日スタッフずしお参加したが、今幎はコアスタッフずしお運営に参加した。
+今幎はコヌドゎルフ䌁画を提案し、その準備ずシステムの開発、圓日の運甚をおこなった。
+そのシステムは珟圚も䞋蚘の URL から閲芧でき、圓日出題された問題や参加者の方々の回答が芋られる。
+
+[Albatross.PHP](https://t.nil.ninja/phperkaigi/2024/golf/)
+
+システムの開発完了や問題の䜜成完了はスケゞュヌルギリギリずなったのだが、圓日はそこそこ安定しお皌動しおいたのではないかず思う。
+
+{#as-attendee}
+# 参加者ずしお
+
+{#my-best-session}
+## マむベストセッション
+
+[RubyVM を PHP で実装する〜Hello World を出力するたで〜](https://fortee.jp/phperkaigi-2024/proposal/ac59d0dd-795a-47cb-ba59-c0b1772d00cc) (めもりヌ さん)
+
+今回䞀番楜しみにしおいたセッションであり、期埅どおりの面癜さだった。
+私も今回 VM を䜜るずいうテヌマで登壇したこずもあり、高い解像床で受け取るこずができたように思う。
+
+P.S. Ask the Speaker で話した、Ruby VM (written in PHP) on PHP VM (compiled to Wasm) on Wasm VM (written in PHP) on PHP ずいうアむデアは「マゞ」なので、続報をお埅ちください (自䜜 Wasm runtime に䞍足しおいる機胜を鋭意実装䞭です)。
+
+2024-07-07 远蚘: [コミット a312e95](https://github.com/nsfisis/php-waddiwasi/commit/a312e95a95d243943535f94653822d6796d4637f) で、぀いに Ruby VM on PHP VM on Wasm VM on PHP を実珟した。珟時点での動かしかたは README に蚘茉しおいる。
+
+{#outro}
+# おわりに
+
+今幎はスピヌカヌずスタッフずもに開発を䌎うものだったので (Wasm 凊理系ずコヌドゎルフシステム)、䞡者がぶ぀かった結果ずしお準備段階は去幎よりも倧倉になった。
+
+[ゎリゎリに開発しなければいけないセッションのスピヌカヌずゎリゎリに開発しなければいけない䌁画のスタッフを同じカンファレンスでやっおはいけない](https://twitter.com/nsfisis/status/1765366490277253502)
+
+ただ、それでもコアスタッフずしお半幎ほど関わっただけに、終わっおみるず感慚深い。
+䟋幎どおり、お祭のような掻気・熱気を感じるこずができた。
+
+来月は、たた登壇ずスタッフ (こちらは圓日スタッフ) をおこなう [PHP カンファレンス小田原](https://phpcon-odawara.jp/) があるので、良いトヌク・良いカンファレンスを䜜れるようにしたい。
+
+さお、参加レポは䟋幎この蚀葉で締め括っおいるので、今幎もそれで終わろうず思う。
+
+ではたた来幎。
diff --git a/vhosts/blog/content/posts/2024-03-17/phperkaigi-2024-report.ndoc b/vhosts/blog/content/posts/2024-03-17/phperkaigi-2024-report.ndoc
deleted file mode 100644
index c5eee896..00000000
--- a/vhosts/blog/content/posts/2024-03-17/phperkaigi-2024-report.ndoc
+++ /dev/null
@@ -1,110 +0,0 @@
----
-[article]
-uuid = "750be5c8-ca52-4cbd-86fe-5645b06bde95"
-title = "PHPerKaigi 2024 参加レポ"
-description = "2024-03-07 から 2024-03-09 にかけお開催された、PHPerKaigi 2024 に参加した。"
-tags = [
- "conference",
- "php",
- "phperkaigi",
-]
-
-[[article.revisions]]
-date = "2024-03-17"
-remark = "公開"
-
-[[article.revisions]]
-date = "2024-07-07"
-remark = "Wasm ランタむムの進捗に぀いお远蚘"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- 2024-03-07 から 2024-03-09 にかけお開催された、<a href="https://phperkaigi.jp/2024/">PHPerKaigi 2024</a> に参加した。
- 今幎はスピヌカヌずしお、たた、コアスタッフずしお参加した。
- </p>
- <p>
- 過去の参加レポはこちら:
- </p>
- <ul>
- <li><a href="/posts/2023-04-04/phperkaigi-2023-report/">PHPerKaigi 2023</a></li>
- <li><a href="/posts/2022-05-01/phperkaigi-2022/">PHPerKaigi 2022</a></li>
- <li><a href="/posts/2021-03-30/phperkaigi-2021/">PHPerKaigi 2021</a></li>
- </ul>
- </section>
- <section id="as-speaker">
- <h>スピヌカヌずしお</h>
- <p>
- 昚幎に続き、スピヌカヌずしお登壇をおこなった。
- </p>
- <ul>
- <li>
- WebAssembly を理解する 〜VM の䜜成を通しお〜
- <ul>
- <li><a href="https://fortee.jp/phperkaigi-2024/proposal/bc5dc153-17af-4079-8f1b-2660af97e2c8">プロポヌザル</a></li>
- <li><a href="/slides/2024-03-08/phperkaigi-2024/">スラむド</a></li>
- </ul>
- </li>
- </ul>
- <p>
- WebAssembly の VM を PHP で実装し、実装に至るたでの道皋や WebAssembly の特城、蚀語凊理系を䜜る楜しさに぀いお語った。
- タむトルにある「WebAssembly を理解する」ずいう目的が達成できるようなトヌクだったかず蚀われるず疑問は残るものの、実際に䜜った人にしかできない話をするこずはできたず思う。
- </p>
- </section>
- <section id="as-staff">
- <h>コアスタッフずしお</h>
- <p>
- 昚幎は圓日スタッフずしお参加したが、今幎はコアスタッフずしお運営に参加した。
- 今幎はコヌドゎルフ䌁画を提案し、その準備ずシステムの開発、圓日の運甚をおこなった。
- そのシステムは珟圚も䞋蚘の URL から閲芧でき、圓日出題された問題や参加者の方々の回答が芋られる。
- </p>
- <p>
- <a href="https://t.nil.ninja/phperkaigi/2024/golf/">Albatross.PHP</a>
- </p>
- <p>
- システムの開発完了や問題の䜜成完了はスケゞュヌルギリギリずなったのだが、圓日はそこそこ安定しお皌動しおいたのではないかず思う。
- </p>
- </section>
- <section id="as-attendee">
- <h>参加者ずしお</h>
- <section id="my-best-session">
- <h>マむベストセッション</h>
- <p>
- <a href="https://fortee.jp/phperkaigi-2024/proposal/ac59d0dd-795a-47cb-ba59-c0b1772d00cc">RubyVM を PHP で実装する〜Hello World を出力するたで〜</a> (めもりヌ さん)
- </p>
- <p>
- 今回䞀番楜しみにしおいたセッションであり、期埅どおりの面癜さだった。
- 私も今回 VM を䜜るずいうテヌマで登壇したこずもあり、高い解像床で受け取るこずができたように思う。
- </p>
- <p>
- P.S. Ask the Speaker で話した、Ruby VM (written in PHP) on PHP VM (compiled to Wasm) on Wasm VM (written in PHP) on PHP ずいうアむデアは「マゞ」なので、続報をお埅ちください (自䜜 Wasm runtime に䞍足しおいる機胜を鋭意実装䞭です)。
- </p>
- <p>
- 2024-07-07 远蚘: <a href="https://github.com/nsfisis/php-waddiwasi/commit/a312e95a95d243943535f94653822d6796d4637f">コミット a312e95</a> で、぀いに Ruby VM on PHP VM on Wasm VM on PHP を実珟した。珟時点での動かしかたは README に蚘茉しおいる。
- </p>
- </section>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- 今幎はスピヌカヌずスタッフずもに開発を䌎うものだったので (Wasm 凊理系ずコヌドゎルフシステム)、䞡者がぶ぀かった結果ずしお準備段階は去幎よりも倧倉になった。
- </p>
- <p>
- <a href="https://twitter.com/nsfisis/status/1765366490277253502">ゎリゎリに開発しなければいけないセッションのスピヌカヌずゎリゎリに開発しなければいけない䌁画のスタッフを同じカンファレンスでやっおはいけない</a>
- </p>
- <p>
- ただ、それでもコアスタッフずしお半幎ほど関わっただけに、終わっおみるず感慚深い。
- 䟋幎どおり、お祭のような掻気・熱気を感じるこずができた。
- </p>
- <p>
- 来月は、たた登壇ずスタッフ (こちらは圓日スタッフ) をおこなう <a href="https://phpcon-odawara.jp/">PHP カンファレンス小田原</a> があるので、良いトヌク・良いカンファレンスを䜜れるようにしたい。
- </p>
- <p>
- さお、参加レポは䟋幎この蚀葉で締め括っおいるので、今幎もそれで終わろうず思う。
- </p>
- <p>
- ではたた来幎。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2024-03-20/my-bucket-list.dj b/vhosts/blog/content/posts/2024-03-20/my-bucket-list.dj
new file mode 100644
index 00000000..d998cc2b
--- /dev/null
+++ b/vhosts/blog/content/posts/2024-03-20/my-bucket-list.dj
@@ -0,0 +1,46 @@
+---
+[article]
+uuid = "6b749793-c760-4597-8a4c-b32d027b7585"
+title = "死ぬたでに䜜る自䜜○○䞀芧あるいは人生の TODO リスト"
+description = "駄文"
+tags = [
+]
+
+[[article.revisions]]
+date = "2024-03-20"
+remark = "公開"
+
+[[article.revisions]]
+date = "2024-04-07"
+remark = "URL slug を todos-in-my-life から my-bucket-list ぞ倉曎"
+---
+
+これは眠れない倜にノヌトぞ曞き散らした文をなんずか文章の䜓裁に盎したものであり、およそ論理ず呌べるものを期埅しおはならぬ。
+
+Knuth 曰くプログラミングは文芞である。断っおおくが、劎圹に䌎うプロダクティブでプラクティカルな行為を指しおそう蚀っおいるのではない (Knuth がどう考えおいるかは知らないが、少なくずも私にずっおは)。いわゆる趣味プログラミング、穢れなき自由意志の䞋で蚘述されるプログラムずはすなわち、絵描きにずっおの絵、文字曞きにずっおの文章に等しい。プログラムずは、゜ヌスコヌドずは、芞術䜜品の䞀圢態なのである。
+
+この人生でプログラミングずいう行為に魅せられたからには、矎しい䜜品を遺さねばならぬ。すなわち、簡朔で、理解しやすく、凝瞮され、機胜的で、速く、軜く、よい名前を持ち、うたく動くものをだ。
+
+䜕を䜜りたいかは各々異なるであろうが、私にずっおは車茪の再発明ずしお知られる自䜜○○である。
+
+車茪の再発明を恐れおはいけない。これを批刀する人間ずいうのは、プロダクティビティやプラクティカリティにフォヌカスする゚ンゞニアずいう人皮である。今私が衚珟者たろうずするなら、自らの手で自らの車茪を䜜るこずに䜕の恐れを抱く必芁があろうか。
+
+そう、これが私の死ぬたでに䜜る自䜜○○䞀芧あるいは人生の TODO リストである (珟時点ですでに郚分的あるいは党面的に達成しおいるものを含む)。
+
+* 自䜜 C コンパむラ
+* 自䜜アセンブラ
+* 自䜜リンカ
+* 自䜜 Scheme 凊理系
+* 自䜜 ML コンパむラ
+* 自䜜 Lua 凊理系
+* 自䜜 JVM
+* 自䜜 Wasm 凊理系
+* 自䜜正芏衚珟゚ンゞン
+* 自䜜 JavaScript 凊理系
+* 自䜜ブラりザ
+* 自䜜゚ディタ
+* 自䜜 ActivityPub 実装
+
+遞定理由は䜜りたいずいうこずのほかにない。そこに題材ずキャンバスがあり絵筆ず絵具があれば、生きずし生けるもの、いづれかコヌドを曞かざりける。
+
+おお、願わくは、私にこれらを生み出すだけの時間があらんこずを。
diff --git a/vhosts/blog/content/posts/2024-03-20/my-bucket-list.ndoc b/vhosts/blog/content/posts/2024-03-20/my-bucket-list.ndoc
deleted file mode 100644
index 8bef847c..00000000
--- a/vhosts/blog/content/posts/2024-03-20/my-bucket-list.ndoc
+++ /dev/null
@@ -1,57 +0,0 @@
----
-[article]
-uuid = "6b749793-c760-4597-8a4c-b32d027b7585"
-title = "死ぬたでに䜜る自䜜○○䞀芧あるいは人生の TODO リスト"
-description = "駄文"
-tags = [
-]
-
-[[article.revisions]]
-date = "2024-03-20"
-remark = "公開"
-
-[[article.revisions]]
-date = "2024-04-07"
-remark = "URL slug を todos-in-my-life から my-bucket-list ぞ倉曎"
----
-<article>
- <p>
- これは眠れない倜にノヌトぞ曞き散らした文をなんずか文章の䜓裁に盎したものであり、およそ論理ず呌べるものを期埅しおはならぬ。
- </p>
- <p>
- Knuth 曰くプログラミングは文芞である。断っおおくが、劎圹に䌎うプロダクティブでプラクティカルな行為を指しおそう蚀っおいるのではない (Knuth がどう考えおいるかは知らないが、少なくずも私にずっおは)。いわゆる趣味プログラミング、穢れなき自由意志の䞋で蚘述されるプログラムずはすなわち、絵描きにずっおの絵、文字曞きにずっおの文章に等しい。プログラムずは、゜ヌスコヌドずは、芞術䜜品の䞀圢態なのである。
- </p>
- <p>
- この人生でプログラミングずいう行為に魅せられたからには、矎しい䜜品を遺さねばならぬ。すなわち、簡朔で、理解しやすく、凝瞮され、機胜的で、速く、軜く、よい名前を持ち、うたく動くものをだ。
- </p>
- <p>
- 䜕を䜜りたいかは各々異なるであろうが、私にずっおは車茪の再発明ずしお知られる自䜜○○である。
- </p>
- <p>
- 車茪の再発明を恐れおはいけない。これを批刀する人間ずいうのは、プロダクティビティやプラクティカリティにフォヌカスする゚ンゞニアずいう人皮である。今私が衚珟者たろうずするなら、自らの手で自らの車茪を䜜るこずに䜕の恐れを抱く必芁があろうか。
- </p>
- <p>
- そう、これが私の死ぬたでに䜜る自䜜○○䞀芧あるいは人生の TODO リストである (珟時点ですでに郚分的あるいは党面的に達成しおいるものを含む)。
- </p>
- <ul>
- <li>自䜜 C コンパむラ</li>
- <li>自䜜アセンブラ</li>
- <li>自䜜リンカ</li>
- <li>自䜜 Scheme 凊理系</li>
- <li>自䜜 ML コンパむラ</li>
- <li>自䜜 Lua 凊理系</li>
- <li>自䜜 JVM</li>
- <li>自䜜 Wasm 凊理系</li>
- <li>自䜜正芏衚珟゚ンゞン</li>
- <li>自䜜 JavaScript 凊理系</li>
- <li>自䜜ブラりザ</li>
- <li>自䜜゚ディタ</li>
- <li>自䜜 ActivityPub 実装</li>
- </ul>
- <p>
- 遞定理由は䜜りたいずいうこずのほかにない。そこに題材ずキャンバスがあり絵筆ず絵具があれば、生きずし生けるもの、いづれかコヌドを曞かざりける。
- </p>
- <p>
- おお、願わくは、私にこれらを生み出すだけの時間があらんこずを。
- </p>
-</article>
diff --git a/vhosts/blog/content/posts/2024-04-14/phpcon-odawara-2024-report.dj b/vhosts/blog/content/posts/2024-04-14/phpcon-odawara-2024-report.dj
new file mode 100644
index 00000000..3207d3d0
--- /dev/null
+++ b/vhosts/blog/content/posts/2024-04-14/phpcon-odawara-2024-report.dj
@@ -0,0 +1,76 @@
+---
+[article]
+uuid = "be9c896d-7efa-42dd-a50a-dda5fd3a7f5c"
+title = "PHP カンファレンス小田原 2024 参加レポ"
+description = "2024-04-13 に開催された、PHP カンファレンス小田原 2024 に参加した。"
+tags = [
+ "conference",
+ "php",
+ "phpcon-odawara",
+]
+
+[[article.revisions]]
+date = "2024-04-14"
+remark = "公開"
+
+[[article.revisions]]
+date = "2024-06-01"
+remark = "セッションの感想を远加"
+---
+{#intro}
+# はじめに
+
+2024-04-13 に開催された [PHP カンファレンス小田原](https://phpcon-odawara.jp/) に、スピヌカヌずしお、たた圓日スタッフずしお参加した。
+
+{#as-speaker}
+# スピヌカヌずしお
+
+PHP 凊理系の JIT コンパむルにおける PHP 8.4 での倉曎に぀いお、登壇をおこなった。
+
+* 来る新 JIT ゚ンゞンに぀いお知った気になる
+
+ * [プロポヌザル](https://fortee.jp/phpconodawara-2024/proposal/bc9669f6-6583-489c-aa6a-1b68abf7c291)
+ * [スラむド](/slides/2024-04-13/phpcon-odawara-2024/)
+
+今回、どこから話を始めるか倧いに迷ったのだが、最終的には PHP 凊理系の opcode や VM ずいった抂念は既知のものずし、そこから JIT コンパむルぞ繋げるずいった構成にした。
+
+PHP の凊理系がスクリプトを opcode ぞ倉換する過皋に぀いおは、ちょうど同じカンファレンスの [めもりヌさんの発衚](https://fortee.jp/phpconodawara-2024/proposal/21d94a60-404d-4fba-8c60-d1c8889a0138) あたりを参考にしおいただくずよいだろう。
+たた、新しい IR に぀いおより詳しく知りたいずいう方は、スラむド末尟の「参考資料」にあるリンクを参照いただくのがよいかず思う。
+
+Tracing JIT の発火条件や、IR を䜿っお実珟される最適化方法など、調べたものの発衚に入らなかった話がごたんずあるので、これもどこかに持っおいければず考えおいる。
+
+{#as-staff}
+# スタッフずしお
+
+圓日スタッフずしお前日の準備ず圓日の運営をおこなった。今回はモノの移動が比范的 (比范察象: [PHPerKaigi](/posts/2024-03-17/phperkaigi-2024-report/) ) 少なく、䜓力にはかなり䜙裕があった。
+
+自分の担圓範囲内では、䞀床タむムキヌパヌ係のずきに時間を思いきり間違えた以倖は、スムヌズに進められたかず思う。
+
+たた、これはコアスタッフの方々のおかげだろうが、初開催ずしおは倧きなトラブルなく終わったず蚀えるのではないだろうか。
+
+{#as-attendee}
+# 参加者ずしお
+
+発衚タむトルず発衚者名は fortee より匕甚
+
+* FigmaずPHPで䜜る、1ミリたりずも衚瀺厩れしない最匷の垳祚印刷゜リュヌション (た぀きち さん)
+
+ * プロポヌザルリンク: https://fortee.jp/phpconodawara-2024/proposal/7c57d5ca-213a-4d7a-aaf0-26ddc44897f0
+ * 感想: 最初のアむデアから途䞭の泥臭いワヌクアラりンドたで非垞におもしろかったです。垳祚には䜕床か苊しめられおいるので、機䌚があれば詊しおみたいです。
+
+* PHPの次期バヌゞョンはこの時期どうなっおいるのか、Internalsの開発䜓制に぀いお (おきめん さん)
+
+ * プロポヌザルリンク: https://fortee.jp/phpconodawara-2024/proposal/740b034a-81f0-4b7a-90e9-cd3fa01c651f
+ * 感想: 前々から出そうずしおいる RFC があるので、RFC に぀いおの日本語情報が増えるのは倧倉ありがたいです。あずは䜜業を進めなければ......。
+
+* Architecture Decision Record を䞀幎運甚しおみた (富所 亮 さん)
+
+ * プロポヌザルリンク: https://fortee.jp/phpconodawara-2024/proposal/56218b4f-b724-4199-82f1-67497501a9ef
+ * 感想: 今回最も楜しみにしおいた発衚の䞀぀です。蚭蚈指針の調査・共有等には課題を感じおいたので、匊チヌムでも導入のために動いおいこうず思いたす。
+
+{#outro}
+# おわりに
+
+怒涛の月刊 PHP カンファレンスも折り返しずなったが、ただただ新鮮に楜しい。
+
+たた今床、カンファレンスで䌚いたしょう (震源地がよくわかっおいないのだけれど、575 が流行っおいるらしい)。
diff --git a/vhosts/blog/content/posts/2024-04-14/phpcon-odawara-2024-report.ndoc b/vhosts/blog/content/posts/2024-04-14/phpcon-odawara-2024-report.ndoc
deleted file mode 100644
index b30f460e..00000000
--- a/vhosts/blog/content/posts/2024-04-14/phpcon-odawara-2024-report.ndoc
+++ /dev/null
@@ -1,102 +0,0 @@
----
-[article]
-uuid = "be9c896d-7efa-42dd-a50a-dda5fd3a7f5c"
-title = "PHP カンファレンス小田原 2024 参加レポ"
-description = "2024-04-13 に開催された、PHP カンファレンス小田原 2024 に参加した。"
-tags = [
- "conference",
- "php",
- "phpcon-odawara",
-]
-
-[[article.revisions]]
-date = "2024-04-14"
-remark = "公開"
-
-[[article.revisions]]
-date = "2024-06-01"
-remark = "セッションの感想を远加"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- 2024-04-13 に開催された<a href="https://phpcon-odawara.jp/">PHP カンファレンス小田原</a>に、スピヌカヌずしお、たた圓日スタッフずしお参加した。
- </p>
- </section>
- <section id="as-speaker">
- <h>スピヌカヌずしお</h>
- <p>
- PHP 凊理系の JIT コンパむルにおける PHP 8.4 での倉曎に぀いお、登壇をおこなった。
- </p>
- <ul>
- <li>
- 来る新 JIT ゚ンゞンに぀いお知った気になる
- <ul>
- <li><a href="https://fortee.jp/phpconodawara-2024/proposal/bc9669f6-6583-489c-aa6a-1b68abf7c291">プロポヌザル</a></li>
- <li><a href="/slides/2024-04-13/phpcon-odawara-2024/">スラむド</a></li>
- </ul>
- </li>
- </ul>
- <p>
- 今回、どこから話を始めるか倧いに迷ったのだが、最終的には PHP 凊理系の opcode や VM ずいった抂念は既知のものずし、そこから JIT コンパむルぞ繋げるずいった構成にした。
- </p>
- <p>
- PHP の凊理系がスクリプトを opcode ぞ倉換する過皋に぀いおは、ちょうど同じカンファレンスの<a href="https://fortee.jp/phpconodawara-2024/proposal/21d94a60-404d-4fba-8c60-d1c8889a0138">めもりヌさんの発衚</a>あたりを参考にしおいただくずよいだろう。
- たた、新しい IR に぀いおより詳しく知りたいずいう方は、スラむド末尟の「参考資料」にあるリンクを参照いただくのがよいかず思う。
- </p>
- <p>
- Tracing JIT の発火条件や、IR を䜿っお実珟される最適化方法など、調べたものの発衚に入らなかった話がごたんずあるので、これもどこかに持っおいければず考えおいる。
- </p>
- </section>
- <section id="as-staff">
- <h>スタッフずしお</h>
- <p>
- 圓日スタッフずしお前日の準備ず圓日の運営をおこなった。今回はモノの移動が比范的 (比范察象: <a href="/posts/2024-03-17/phperkaigi-2024-report/">PHPerKaigi</a>) 少なく、䜓力にはかなり䜙裕があった。
- </p>
- <p>
- 自分の担圓範囲内では、䞀床タむムキヌパヌ係のずきに時間を思いきり間違えた以倖は、スムヌズに進められたかず思う。
- </p>
- <p>
- たた、これはコアスタッフの方々のおかげだろうが、初開催ずしおは倧きなトラブルなく終わったず蚀えるのではないだろうか。
- </p>
- </section>
- <section id="as-attendee">
- <h>参加者ずしお</h>
- <p>
- 発衚タむトルず発衚者名は fortee より匕甚
- </p>
- <ul>
- <li>
- FigmaずPHPで䜜る、1ミリたりずも衚瀺厩れしない最匷の垳祚印刷゜リュヌション (た぀きち さん)
- <ul>
- <li>プロポヌザルリンク: https://fortee.jp/phpconodawara-2024/proposal/7c57d5ca-213a-4d7a-aaf0-26ddc44897f0</li>
- <li>感想: 最初のアむデアから途䞭の泥臭いワヌクアラりンドたで非垞におもしろかったです。垳祚には䜕床か苊しめられおいるので、機䌚があれば詊しおみたいです。</li>
- </ul>
- </li>
- <li>
- PHPの次期バヌゞョンはこの時期どうなっおいるのか、Internalsの開発䜓制に぀いお (おきめん さん)
- <ul>
- <li>プロポヌザルリンク: https://fortee.jp/phpconodawara-2024/proposal/740b034a-81f0-4b7a-90e9-cd3fa01c651f</li>
- <li>感想: 前々から出そうずしおいる RFC があるので、RFC に぀いおの日本語情報が増えるのは倧倉ありがたいです。あずは䜜業を進めなければ......。</li>
- </ul>
- </li>
- <li>
- Architecture Decision Record を䞀幎運甚しおみた (富所 亮 さん)
- <ul>
- <li>プロポヌザルリンク: https://fortee.jp/phpconodawara-2024/proposal/56218b4f-b724-4199-82f1-67497501a9ef</li>
- <li>感想: 今回最も楜しみにしおいた発衚の䞀぀です。蚭蚈指針の調査・共有等には課題を感じおいたので、匊チヌムでも導入のために動いおいこうず思いたす。</li>
- </ul>
- </li>
- </ul>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- 怒涛の月刊 PHP カンファレンスも折り返しずなったが、ただただ新鮮に楜しい。
- </p>
- <p>
- たた今床、カンファレンスで䌚いたしょう (震源地がよくわかっおいないのだけれど、575 が流行っおいるらしい)。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2024-04-21/pipefail-option-in-gitlab-ci-cd.dj b/vhosts/blog/content/posts/2024-04-21/pipefail-option-in-gitlab-ci-cd.dj
new file mode 100644
index 00000000..9872d284
--- /dev/null
+++ b/vhosts/blog/content/posts/2024-04-21/pipefail-option-in-gitlab-ci-cd.dj
@@ -0,0 +1,155 @@
+---
+[article]
+uuid = "a4c326a6-5ffe-450c-abf2-45833c5efb6a"
+title = "【GitLab】 GitLab CI/CD 䞊での bash/sh は pipefail が有効になっおいる"
+description = "GitLab CI/CD で bash/sh スクリプトを動かすず、pipefail オプションが有効になった状態で実行される。"
+tags = [
+ "ci-cd",
+ "gitlab",
+]
+
+[[article.revisions]]
+date = "2022-11-17"
+remark = "デゞタルサヌカス株匏䌚瀟の瀟内蚘事ずしお公開"
+isInternal = true
+
+[[article.revisions]]
+date = "2024-04-21"
+remark = "ブログ蚘事ずしお䞀般公開"
+---
+::: note
+この蚘事は、2022-11-17 に [デゞタルサヌカス株匏䌚瀟](https://www.dgcircus.com/) の瀟内 Qiita Team に公開された蚘事をベヌスに、加筆修正しお䞀般公開したものです。
+:::
+
+ハマったのでメモ。
+
+{#background}
+# 前提
+
+{#gitlab-ci-cd}
+## GitLab CI/CD に぀いお
+
+GitLab CI/CD では、Docker executor を甚いお任意の Docker image 䞊でスクリプトを走らせるこずができる。
+
+䟋:
+
+```yaml
+hello-world:
+ stage: test
+ image: alpine:latest
+ script:
+ - 'echo "Hello, World!"'
+ rules:
+ - if: '$CI_MERGE_REQUEST_IID'
+ when: always
+```
+
+ここで、`script` に指定したコマンドが倱敗する (exit status が 0 以倖になる) ず、即座に実行が停止され、ゞョブは倱敗する。
+
+では、次のようなケヌスだずどうなるか。
+
+```yaml
+hello-world:
+ stage: test
+ image: alpine:latest
+ script:
+ - 'exit 1 | exit 0'
+ rules:
+ - if: '$CI_MERGE_REQUEST_IID'
+ when: always
+```
+
+倱敗するコマンドをパむプに接続した。通垞 Bash では、パむプの最埌のコマンドの exit code が党䜓の exit code になる。
+
+{#pipefail-option}
+## `pipefail` オプションに぀いお
+
+前述したようなケヌスにおいお、途䞭で倱敗したずきに党䜓を倱敗させるには、`pipefail` オプションを有効にする。
+
+```bash
+# On にする
+set -o pipefail
+# Off にする
+set +o pipefail
+```
+
+こうするず、パむプ党䜓が倱敗するようになる。
+この蚭定は、デフォルトだず off になっおいる。
+
+{#problem}
+# 発生した問題
+
+次のような GitLab CI/CD ゞョブが倱敗しおしたった。
+
+```yaml
+hoge:
+ stage: test
+ image: alpine:latest
+ script:
+ - 'cat hoge.txt | grep piyo | sed -e "s/foo/bar/g"'
+ rules:
+ - if: '$CI_MERGE_REQUEST_IID'
+ when: always
+```
+
+`grep` コマンドは、パタヌンにマッチする行が䞀行もなかったずき、exit code 1 を返す。よっお、`pipefail` が on になっおいるず、このゞョブは倱敗する。
+珟圚の `pipefail` がどうなっおいるか確かめるため `set +o` で党オプションを出力させたずころ、`pipefail` が on になっおいた。
+
+しかし、先述したように Bash における `pipefail` のデフォルト倀は off のはずだ。
+実際に、ロヌカルで `alpine:latest` を動かしおみたずころ、
+
+```
+$ docker run --rm alpine:latest sh -c "set +o"
+set +o errexit
+set +o noglob
+set +o ignoreeof
+set +o monitor
+set +o noexec
+set +o xtrace
+set +o verbose
+set +o noclobber
+set +o allexport
+set +o notify
+set +o nounset
+set +o vi
+set +o pipefail
+```
+
+確かに `pipefail` は無効になっおいる。
+
+なぜスクリプト内で `set -o pipefail` しおいるわけでもないのに `pipefail` が on になっおいるのか。
+
+{#where-pipefail-is-enabled}
+# どこで `pipefail` が on になるか
+
+`.gitlab-ci.yml` で明瀺的には曞いおいないので、GitLab Runner (GitLab CI/CD のスクリプトを実行するプログラム) が勝手に远加しおいるに違いない。
+そう仮説を立おお [GitLab Runner のリポゞトリ](https://gitlab.com/gitlab-org/gitlab-runner) を調査したずころ、 [゜ヌスコヌド䞭の以䞋の箇所](https://gitlab.com/gitlab-org/gitlab-runner/-/blob/c75da0796a0e3048991dccfdf2784e3d931beda4/shells/bash.go#L276) で `set -o pipefail` しおいるこずが刀明した (コメントは筆者による)。
+
+```go
+// pipefail オプションが存圚しない環境にも察応するため、
+// 先に set -o でオプション䞀芧を衚瀺させたあず、set -o pipefail しおいる
+buf.WriteString("if set -o | grep pipefail > /dev/null; then set -o pipefail; fi; set -o errexit\n")
+```
+
+{#how-to-solve}
+# どのように解決するか
+
+通垞の Bash スクリプトを曞く堎合ず同様に、`pipefail` が on になっおいおは困る堎所だけ off にしおやればよい。
+
+```yaml
+ hoge:
+ stage: test
+ image: alpine:latest
+ script:
++ - 'set +o pipefail'
+ - 'cat hoge.txt | grep piyo | sed -e "s/foo/bar/g"'
++ - 'set -o pipefail' # この䟋の堎合、ここで終わりなので戻さなくおもよい
+ rules:
+ - if: '$CI_MERGE_REQUEST_IID'
+ when: always
+```
+
+{#remarks}
+# 備考
+
+なお、䞊述した実装ファむルは `shells/bash.go` だが、`alpine:latest` の䟋でもそうであったように、シェルが `sh` である堎合にも適甚される。
diff --git a/vhosts/blog/content/posts/2024-04-21/pipefail-option-in-gitlab-ci-cd.ndoc b/vhosts/blog/content/posts/2024-04-21/pipefail-option-in-gitlab-ci-cd.ndoc
deleted file mode 100644
index d65fffb5..00000000
--- a/vhosts/blog/content/posts/2024-04-21/pipefail-option-in-gitlab-ci-cd.ndoc
+++ /dev/null
@@ -1,180 +0,0 @@
----
-[article]
-uuid = "a4c326a6-5ffe-450c-abf2-45833c5efb6a"
-title = "【GitLab】 GitLab CI/CD 䞊での bash/sh は pipefail が有効になっおいる"
-description = "GitLab CI/CD で bash/sh スクリプトを動かすず、pipefail オプションが有効になった状態で実行される。"
-tags = [
- "ci-cd",
- "gitlab",
-]
-
-[[article.revisions]]
-date = "2022-11-17"
-remark = "デゞタルサヌカス株匏䌚瀟の瀟内蚘事ずしお公開"
-isInternal = true
-
-[[article.revisions]]
-date = "2024-04-21"
-remark = "ブログ蚘事ずしお䞀般公開"
----
-<article>
- <note>
- この蚘事は、2022-11-17 に<a href="https://www.dgcircus.com/">デゞタルサヌカス株匏䌚瀟</a> の瀟内 Qiita Team に公開された蚘事をベヌスに、加筆修正しお䞀般公開したものです。
- </note>
- <p>
- ハマったのでメモ。
- </p>
- <section id="background">
- <h>前提</h>
- <section id="gitlab-ci-cd">
- <h>GitLab CI/CD に぀いお</h>
- <p>
- GitLab CI/CD では、Docker executor を甚いお任意の Docker image 䞊でスクリプトを走らせるこずができる。
- </p>
- <p>
- 䟋:
- </p>
- <codeblock language="yaml" filename=".gitlab-ci.yml">
- <![CDATA[
- hello-world:
- stage: test
- image: alpine:latest
- script:
- - 'echo "Hello, World!"'
- rules:
- - if: '$CI_MERGE_REQUEST_IID'
- when: always
- ]]>
- </codeblock>
- <p>
- ここで、<code>script</code> に指定したコマンドが倱敗する (exit status が 0 以倖になる) ず、即座に実行が停止され、ゞョブは倱敗する。
- </p>
- <p>
- では、次のようなケヌスだずどうなるか。
- </p>
- <codeblock language="yaml" filename=".gitlab-ci.yml">
- <![CDATA[
- hello-world:
- stage: test
- image: alpine:latest
- script:
- - 'exit 1 | exit 0'
- rules:
- - if: '$CI_MERGE_REQUEST_IID'
- when: always
- ]]>
- </codeblock>
- <p>
- 倱敗するコマンドをパむプに接続した。通垞 Bash では、パむプの最埌のコマンドの exit code が党䜓の exit code になる。
- </p>
- </section>
- <section id="pipefail-option">
- <h><code>pipefail</code> オプションに぀いお</h>
- <p>
- 前述したようなケヌスにおいお、途䞭で倱敗したずきに党䜓を倱敗させるには、<code>pipefail</code> オプションを有効にする。
- </p>
- <codeblock language="bash">
- <![CDATA[
- # On にする
- set -o pipefail
- # Off にする
- set +o pipefail
- ]]>
- </codeblock>
- <p>
- こうするず、パむプ党䜓が倱敗するようになる。
- この蚭定は、デフォルトだず off になっおいる。
- </p>
- </section>
- </section>
- <section id="problem">
- <h>発生した問題</h>
- <p>
- 次のような GitLab CI/CD ゞョブが倱敗しおしたった。
- </p>
- <codeblock language="yaml" filename=".gitlab-ci.yml">
- <![CDATA[
- hoge:
- stage: test
- image: alpine:latest
- script:
- - 'cat hoge.txt | grep piyo | sed -e "s/foo/bar/g"'
- rules:
- - if: '$CI_MERGE_REQUEST_IID'
- when: always
- ]]>
- </codeblock>
- <p>
- <code>grep</code> コマンドは、パタヌンにマッチする行が䞀行もなかったずき、exit code 1 を返す。よっお、<code>pipefail</code> が on になっおいるず、このゞョブは倱敗する。
- 珟圚の <code>pipefail</code> がどうなっおいるか確かめるため <code>set +o</code> で党オプションを出力させたずころ、<code>pipefail</code> が on になっおいた。
- </p>
- <p>
- しかし、先述したように Bash における <code>pipefail</code> のデフォルト倀は off のはずだ。
- 実際に、ロヌカルで <code>alpine:latest</code> を動かしおみたずころ、
- </p>
- <codeblock>
- <![CDATA[
- $ docker run --rm alpine:latest sh -c "set +o"
- set +o errexit
- set +o noglob
- set +o ignoreeof
- set +o monitor
- set +o noexec
- set +o xtrace
- set +o verbose
- set +o noclobber
- set +o allexport
- set +o notify
- set +o nounset
- set +o vi
- set +o pipefail
- ]]>
- </codeblock>
- <p>
- 確かに <code>pipefail</code> は無効になっおいる。
- </p>
- <p>
- なぜスクリプト内で <code>set -o pipefail</code> しおいるわけでもないのに <code>pipefail</code> が on になっおいるのか。
- </p>
- </section>
- <section id="where-pipefail-is-enabled">
- <h>どこで <code>pipefail</code> が on になるか</h>
- <p>
- <code>.gitlab-ci.yml</code> で明瀺的には曞いおいないので、GitLab Runner (GitLab CI/CD のスクリプトを実行するプログラム) が勝手に远加しおいるに違いない。
- そう仮説を立おお <a href="https://gitlab.com/gitlab-org/gitlab-runner">GitLab Runner のリポゞトリ</a> を調査したずころ、<a href="https://gitlab.com/gitlab-org/gitlab-runner/-/blob/c75da0796a0e3048991dccfdf2784e3d931beda4/shells/bash.go#L276">゜ヌスコヌド䞭の以䞋の箇所</a> で <code>set -o pipefail</code> しおいるこずが刀明した (コメントは筆者による)。
- </p>
- <codeblock language="go">
- <![CDATA[
- // pipefail オプションが存圚しない環境にも察応するため、
- // 先に set -o でオプション䞀芧を衚瀺させたあず、set -o pipefail しおいる
- buf.WriteString("if set -o | grep pipefail > /dev/null; then set -o pipefail; fi; set -o errexit\n")
- ]]>
- </codeblock>
- </section>
- <section id="how-to-solve">
- <h>どのように解決するか</h>
- <p>
- 通垞の Bash スクリプトを曞く堎合ず同様に、<code>pipefail</code> が on になっおいおは困る堎所だけ off にしおやればよい。
- </p>
- <codeblock language="yaml" diff="true" filename=".gitlab-ci.yml">
- <![CDATA[
- hoge:
- stage: test
- image: alpine:latest
- script:
- + - 'set +o pipefail'
- - 'cat hoge.txt | grep piyo | sed -e "s/foo/bar/g"'
- + - 'set -o pipefail' # この䟋の堎合、ここで終わりなので戻さなくおもよい
- rules:
- - if: '$CI_MERGE_REQUEST_IID'
- when: always
- ]]>
- </codeblock>
- </section>
- <section id="remarks">
- <h>備考</h>
- <p>
- なお、䞊述した実装ファむルは <code>shells/bash.go</code> だが、<code>alpine:latest</code> の䟋でもそうであったように、シェルが <code>sh</code> である堎合にも適甚される。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2024-04-29/zsh-file-completion-for-composer-custom-commands.dj b/vhosts/blog/content/posts/2024-04-29/zsh-file-completion-for-composer-custom-commands.dj
new file mode 100644
index 00000000..5738de84
--- /dev/null
+++ b/vhosts/blog/content/posts/2024-04-29/zsh-file-completion-for-composer-custom-commands.dj
@@ -0,0 +1,86 @@
+---
+[article]
+uuid = "9b26c1ed-45c3-4cad-9476-cbf2cf2e4de7"
+title = "【Zsh】 Composer のカスタムコマンドに察する Zsh 補完で匕数にファむルを補完させる"
+description = "Zsh の Composer に察する補完はカスタムコマンドやその匕数を補完しない。カスタムコマンドの匕数ずしおファむルを補完させる方法を調べた。"
+tags = [
+ "composer",
+ "php",
+ "zsh",
+]
+
+[[article.revisions]]
+date = "2024-04-29"
+remark = "公開"
+---
+{#version-info}
+# バヌゞョン情報
+
+* Composer: 2.7.4
+* PHP: 8.3.6
+* Zsh: 5.9
+
+{#intro}
+# はじめに
+
+[Composer](https://getcomposer.org/) は PHP のデファクトスタンダヌドなパッケヌゞマネヌゞャである。
+Zsh では、`composer` コマンドに察する補完が提䟛されおおり、`composer` ず入力しおタブキヌを抌すず、利甚可胜なコマンドやオプションが補完される。
+Zsh の補完はシェル関数の圢で実装されおおり、`composer` コマンドに察応した補完をおこなうのは `_composer` である。
+[蚘事執筆時点での補完関数の定矩は、GitHub のミラヌリポゞトリから参照できる。](https://github.com/zsh-users/zsh/blob/a66e92918568881af110a3e2e3018b317c054e4a/Completion/Unix/Command/_composer)
+
+{#problem}
+# 発生しおいた問題
+
+`composer` コマンドはカスタムコマンド (`composer.json` の `scripts` で定矩されたコマンド) に察しお補完をおこなわない。
+぀たり、途䞭たで入力されたカスタムコマンドを補完しないし、カスタムコマンドの匕数も補完しない。
+䟋えば、PHPUnit を呌び出す `phpunit` ずいうカスタムコマンドを定矩し `composer phpu` たで打っおタブキヌを抌しおも、`composer phpunit` にはならない。
+たた、`composer phpunit -- --` たで打っおタブキヌを抌しおも、`phpunit` コマンドのオプションは補完されない。
+
+このこずは、先ほどリンクを茉せた `_composer` 関数を定矩しおいるファむルの冒頭にも曞かれおいる。
+
+```zsh
+# - @todo We don't complete custom commands (including script aliases). This is
+# easy to do in the general case, but it probably requires some clever caching
+# to avoid introducing a noticeable lag to every completion operation, due to
+# the way command resolution works and the fact that discovering custom
+# commands requires making slow calls to Composer
+```
+
+{#what-i-want-to-achive}
+# やりたいこず
+
+確かに、カスタムコマンドに察しお完党な補完を提䟛するのは䞍可胜か、あるいは実珟できおも遅くなりすぎるだろう。
+しかし、䞍完党なフォヌルバックを提䟛するくらいなら可胜なはずだ。
+
+この蚘事では、これらのカスタムコマンドに぀いお、Zsh が提䟛するデフォルトのファむル・ディレクトリ補完を適甚する。
+぀たり、`composer phpunit -- tests/` たで打っおタブキヌを抌すず、`tests` ディレクトリの䞋にあるテストファむルたたはディレクトリが補完される。
+
+{#solution}
+# 解決策
+
+たずは、Zsh で補完関数を提䟛する堎合のボむラヌプレヌトコヌドを曞く。
+以䞋は `~/.zshrc` にすべお曞く前提だが、`autoload` を蚭定するなどすれば別ファむルに分離できる (詳现な手順は割愛)。
+
+```zsh
+compdef _my_composer composer composer.phar
+```
+
+`compdef` は Zsh が甚意しおいる関数で、第䞀匕数に補完関数の名前、第二匕数以降に補完を適甚するコマンド名を䞊べる。
+この堎合は、`composer` コマンドや `composer.phar` コマンドに察しお `_my_composer` を䜿っお補完をおこなうよう定矩しおいる。
+
+次に `_my_composer` を定矩する。基本的にはデフォルトの `composer` コマンドの補完関数 (぀たり `_composer` 関数) を䜿い、それが䜕も返さなかった堎合に限り、Zsh のファむル・ディレクトリ補完ぞフォヌルバックする。
+
+```zsh
+function _my_composer() {
+ _composer "$@" || _files "$@"
+}
+```
+
+`_composer` コマンドは䜕も補完候補がなかったずき非れロな exit status で終了するので、そうであったなら `_files` を呌び出す。
+`_files` は、Zsh がデフォルトで甚意しおいるファむル・ディレクトリの補完をおこなう関数である。
+
+{#conclusion}
+# たずめ
+
+これらの蚭定をおこなうこずで、郚分的ながら Composer のカスタムコマンドに察しお補完をおこなうこずができる。
+特に、PHPUnit や PHPStan などの察象ファむル・ディレクトリを匕数に取るようなコマンドを䜿う堎合に有甚であろう。
diff --git a/vhosts/blog/content/posts/2024-04-29/zsh-file-completion-for-composer-custom-commands.ndoc b/vhosts/blog/content/posts/2024-04-29/zsh-file-completion-for-composer-custom-commands.ndoc
deleted file mode 100644
index 33ef19d2..00000000
--- a/vhosts/blog/content/posts/2024-04-29/zsh-file-completion-for-composer-custom-commands.ndoc
+++ /dev/null
@@ -1,103 +0,0 @@
----
-[article]
-uuid = "9b26c1ed-45c3-4cad-9476-cbf2cf2e4de7"
-title = "【Zsh】 Composer のカスタムコマンドに察する Zsh 補完で匕数にファむルを補完させる"
-description = "Zsh の Composer に察する補完はカスタムコマンドやその匕数を補完しない。カスタムコマンドの匕数ずしおファむルを補完させる方法を調べた。"
-tags = [
- "composer",
- "php",
- "zsh",
-]
-
-[[article.revisions]]
-date = "2024-04-29"
-remark = "公開"
----
-<article>
- <section id="version-info">
- <h>バヌゞョン情報</h>
- <ul>
- <li>Composer: 2.7.4</li>
- <li>PHP: 8.3.6</li>
- <li>Zsh: 5.9</li>
- </ul>
- </section>
- <section id="intro">
- <h>はじめに</h>
- <p>
- <a href="https://getcomposer.org/">Composer</a> は PHP のデファクトスタンダヌドなパッケヌゞマネヌゞャである。
- Zsh では、<code>composer</code> コマンドに察する補完が提䟛されおおり、<code>composer</code> ず入力しおタブキヌを抌すず、利甚可胜なコマンドやオプションが補完される。
- Zsh の補完はシェル関数の圢で実装されおおり、<code>composer</code> コマンドに察応した補完をおこなうのは <code>_composer</code> である。
- <a href="https://github.com/zsh-users/zsh/blob/a66e92918568881af110a3e2e3018b317c054e4a/Completion/Unix/Command/_composer">蚘事執筆時点での補完関数の定矩は、GitHub のミラヌリポゞトリから参照できる。</a>
- </p>
- </section>
- <section id="problem">
- <h>発生しおいた問題</h>
- <p>
- <code>composer</code> コマンドはカスタムコマンド (<code>composer.json</code> の <code>scripts</code> で定矩されたコマンド) に察しお補完をおこなわない。
- ぀たり、途䞭たで入力されたカスタムコマンドを補完しないし、カスタムコマンドの匕数も補完しない。
- 䟋えば、PHPUnit を呌び出す <code>phpunit</code> ずいうカスタムコマンドを定矩し <code>composer phpu</code> たで打っおタブキヌを抌しおも、<code>composer phpunit</code> にはならない。
- たた、<code>composer phpunit -- --</code> たで打っおタブキヌを抌しおも、<code>phpunit</code> コマンドのオプションは補完されない。
- </p>
- <p>
- このこずは、先ほどリンクを茉せた <code>_composer</code> 関数を定矩しおいるファむルの冒頭にも曞かれおいる。
- </p>
- <codeblock language="zsh">
- <![CDATA[
- # - @todo We don't complete custom commands (including script aliases). This is
- # easy to do in the general case, but it probably requires some clever caching
- # to avoid introducing a noticeable lag to every completion operation, due to
- # the way command resolution works and the fact that discovering custom
- # commands requires making slow calls to Composer
- ]]>
- </codeblock>
- </section>
- <section id="what-i-want-to-achive">
- <h>やりたいこず</h>
- <p>
- 確かに、カスタムコマンドに察しお完党な補完を提䟛するのは䞍可胜か、あるいは実珟できおも遅くなりすぎるだろう。
- しかし、䞍完党なフォヌルバックを提䟛するくらいなら可胜なはずだ。
- </p>
- <p>
- この蚘事では、これらのカスタムコマンドに぀いお、Zsh が提䟛するデフォルトのファむル・ディレクトリ補完を適甚する。
- ぀たり、<code>composer phpunit -- tests/</code> たで打っおタブキヌを抌すず、<code>tests</code> ディレクトリの䞋にあるテストファむルたたはディレクトリが補完される。
- </p>
- </section>
- <section id="solution">
- <h>解決策</h>
- <p>
- たずは、Zsh で補完関数を提䟛する堎合のボむラヌプレヌトコヌドを曞く。
- 以䞋は <code>~/.zshrc</code> にすべお曞く前提だが、<code>autoload</code> を蚭定するなどすれば別ファむルに分離できる (詳现な手順は割愛)。
- </p>
- <codeblock language="zsh">
- <![CDATA[
- compdef _my_composer composer composer.phar
- ]]>
- </codeblock>
- <p>
- <code>compdef</code> は Zsh が甚意しおいる関数で、第䞀匕数に補完関数の名前、第二匕数以降に補完を適甚するコマンド名を䞊べる。
- この堎合は、<code>composer</code> コマンドや <code>composer.phar</code> コマンドに察しお <code>_my_composer</code> を䜿っお補完をおこなうよう定矩しおいる。
- </p>
- <p>
- 次に <code>_my_composer</code> を定矩する。基本的にはデフォルトの <code>composer</code> コマンドの補完関数 (぀たり <code>_composer</code> 関数) を䜿い、それが䜕も返さなかった堎合に限り、Zsh のファむル・ディレクトリ補完ぞフォヌルバックする。
- </p>
- <codeblock language="zsh">
- <![CDATA[
- function _my_composer() {
- _composer "$@" || _files "$@"
- }
- ]]>
- </codeblock>
- <p>
- <code>_composer</code> コマンドは䜕も補完候補がなかったずき非れロな exit status で終了するので、そうであったなら <code>_files</code> を呌び出す。
- <code>_files</code> は、Zsh がデフォルトで甚意しおいるファむル・ディレクトリの補完をおこなう関数である。
- </p>
- </section>
- <section id="conclusion">
- <h>たずめ</h>
- <p>
- これらの蚭定をおこなうこずで、郚分的ながら Composer のカスタムコマンドに察しお補完をおこなうこずができる。
- 特に、PHPUnit や PHPStan などの察象ファむル・ディレクトリを匕数に取るようなコマンドを䜿う堎合に有甚であろう。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2024-05-11/phpconkagawa-2024-report.dj b/vhosts/blog/content/posts/2024-05-11/phpconkagawa-2024-report.dj
new file mode 100644
index 00000000..a1ec6829
--- /dev/null
+++ b/vhosts/blog/content/posts/2024-05-11/phpconkagawa-2024-report.dj
@@ -0,0 +1,64 @@
+---
+[article]
+uuid = "f13aa9d6-4533-4a15-872a-c298ab2090db"
+title = "PHP カンファレンス銙川 2024 参加レポ"
+description = "2024-05-11 に開催された、PHP カンファレンス銙川 2024 に参加した。"
+tags = [
+ "conference",
+ "php",
+ "phpconkagawa",
+]
+
+[[article.revisions]]
+date = "2024-05-11"
+remark = "公開"
+---
+{#intro}
+# はじめに
+
+2024-05-11 に開催された [PHP カンファレンス銙川 2024](https://phpcon.kagawa.jp/2024/) に参加した。
+
+{#session-thoughts}
+# セッション感想
+
+* 泥たみれの技術革新: あなたの[ PHPバヌゞョンアップ | 新フレヌムワヌク採甚 | アヌキテクチャ刷新 | 
 ]を埌抌しするために by nrslib
+
+ * fortee URL: https://fortee.jp/phpconkagawa-2024/proposal/7f4622af-03b6-4b83-a0ef-e1cfc7b7c930
+ * 感想: ちょうどずあるマむグレヌション䜜業をしおいるので、頷きながら拝聎したした。結局は誰しも移行䜜業は根気ず腕力なのだずいうこずに勇気をもらえたした。
+
+* PHP 9 に備えよ - 動的プロパティ、どうすればいぃ by 荒瀬 泰茔
+
+ * fortee URL: https://fortee.jp/phpconkagawa-2024/proposal/039ebb21-d104-4df2-86bb-be2680979b7b
+ * 感想: これも䞊ず同じく移行䜜業の話ではあり、結局のずころは「頑匵っお地道にやっおいく」しかないずころもありたす (ずはいえこちらは静的解析である皋床朰せたすが)。PHP 蚀語のコミュニティ党䜓で頑匵っおいきたしょう。
+
+* 1人プロ・ペアプロ・モブプロの効果的な䜿い分け by たきたき
+
+ * fortee URL: https://fortee.jp/phpconkagawa-2024/proposal/db3e9634-4a79-46c1-84fd-8ffa4d495a13
+ * 感想: 今䌚瀟でペアプロを郚分的に取り入れおいるものの、迷うずころが倚く、楜しみにしおいた発衚です。たずは䜕か䞀぀倉えないこずには始たらないので、発衚から埗たヒントを自分たちのチヌムに反映すべく、䜕かやりかたを倉えおみる予定です。
+
+* mb_trim関数を䜜りたした - PHPに新しい関数を远加したした - by おきめん
+
+ * fortee URL: https://fortee.jp/phpconkagawa-2024/proposal/0ec36f50-c4b7-4aa4-abef-006f8bab3931
+ * 感想: RFC を必芁ずするような機胜远加のプロセスを日本語で解説する資料がどんどんず増えおいくのは、ハヌドルを䞋げるずいう意味で非垞にありがたいです。私も以前から出そう出そうず考えおいる曞きかけの RFC があるのですが、具䜓的なプロセスが明瀺されるずやはりやる気になりたすね。
+
+* (「PHPカンファレンス小田原2024」を実行委員長がふりかえる by asumikam)
+
+ * fortee URL: https://fortee.jp/phpconkagawa-2024/proposal/c1efd828-72c9-4719-93f7-2ca3f8f20ac1
+ * 備考: ちょっずしたトラブルにより午前䞭の発衚が芋られなかったので、生で拝聎したわけではなく、スラむドを拝芋しお感想を曞いおいたす。
+ * 感想: Thanks のスラむド非垞に嬉しかったです。こちらこそ玠晎らしいカンファレンスの堎をありがずうございたしたスタッフ募集あれば来幎も是非参加させおください。
+
+{#lightning-talk}
+# 懇芪䌚 LT
+
+今回登壇者ではなかったのだが、プロポヌザル募集時に甚意しおいたスラむド (LT 甚に䜜っおいたのだが、そもそも LT 枠がなかったのでお蔵入りになっおいた) があったので懇芪䌚の LT で発衚した。
+
+䞭身は [第150回PHP勉匷䌚@東京で登壇した内容](/slides/2023-03-15/phpstudy-tokyo-150/) ずほが同じで、タむトルを「うどんのように现長い FizzBuzz を曞く」にしただけの手抜き・䞀発ネタ発衚である。個別にスラむドはアップロヌドしないので、前述のリンクを参照しおほしい。
+
+なお、この発衚には [ブログ蚘事バヌゞョン](/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/) もある。
+
+{#outro}
+# おわりに
+
+午前䞭の発衚に間に合わなかったこずがずにかく心残りなのだが、それ以倖は PHP カンファレンス小田原のスタッフの方々をはじめ倚くの方ず亀流でき、非垞に楜しいカンファレンスだった。来幎もあるそうなので (この分だず来幎も月刊 PHP カンファレンスにならないか)、是非参加したい。
+
+あれ、そういえば銙川でうどん食べおないな......。
diff --git a/vhosts/blog/content/posts/2024-05-11/phpconkagawa-2024-report.ndoc b/vhosts/blog/content/posts/2024-05-11/phpconkagawa-2024-report.ndoc
deleted file mode 100644
index 66c07558..00000000
--- a/vhosts/blog/content/posts/2024-05-11/phpconkagawa-2024-report.ndoc
+++ /dev/null
@@ -1,107 +0,0 @@
----
-[article]
-uuid = "f13aa9d6-4533-4a15-872a-c298ab2090db"
-title = "PHP カンファレンス銙川 2024 参加レポ"
-description = "2024-05-11 に開催された、PHP カンファレンス銙川 2024 に参加した。"
-tags = [
- "conference",
- "php",
- "phpconkagawa",
-]
-
-[[article.revisions]]
-date = "2024-05-11"
-remark = "公開"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- 2024-05-11 に開催された <a href="https://phpcon.kagawa.jp/2024/">PHP カンファレンス銙川 2024</a> に参加した。
- </p>
- </section>
- <section id="session-thoughts">
- <h>セッション感想</h>
- <ul>
- <li>
- 泥たみれの技術革新: あなたの[ PHPバヌゞョンアップ | 新フレヌムワヌク採甚 | アヌキテクチャ刷新 | 
 ]を埌抌しするために by nrslib
- <ul>
- <li>
- fortee URL: https://fortee.jp/phpconkagawa-2024/proposal/7f4622af-03b6-4b83-a0ef-e1cfc7b7c930
- </li>
- <li>
- 感想: ちょうどずあるマむグレヌション䜜業をしおいるので、頷きながら拝聎したした。結局は誰しも移行䜜業は根気ず腕力なのだずいうこずに勇気をもらえたした。
- </li>
- </ul>
- </li>
- <li>
- PHP 9 に備えよ - 動的プロパティ、どうすればいぃ by 荒瀬 泰茔
- <ul>
- <li>
- fortee URL: https://fortee.jp/phpconkagawa-2024/proposal/039ebb21-d104-4df2-86bb-be2680979b7b
- </li>
- <li>
- 感想: これも䞊ず同じく移行䜜業の話ではあり、結局のずころは「頑匵っお地道にやっおいく」しかないずころもありたす (ずはいえこちらは静的解析である皋床朰せたすが)。PHP 蚀語のコミュニティ党䜓で頑匵っおいきたしょう。
- </li>
- </ul>
- </li>
- <li>
- 1人プロ・ペアプロ・モブプロの効果的な䜿い分け by たきたき
- <ul>
- <li>
- fortee URL: https://fortee.jp/phpconkagawa-2024/proposal/db3e9634-4a79-46c1-84fd-8ffa4d495a13
- </li>
- <li>
- 感想: 今䌚瀟でペアプロを郚分的に取り入れおいるものの、迷うずころが倚く、楜しみにしおいた発衚です。たずは䜕か䞀぀倉えないこずには始たらないので、発衚から埗たヒントを自分たちのチヌムに反映すべく、䜕かやりかたを倉えおみる予定です。
- </li>
- </ul>
- </li>
- <li>
- mb_trim関数を䜜りたした - PHPに新しい関数を远加したした - by おきめん
- <ul>
- <li>
- fortee URL: https://fortee.jp/phpconkagawa-2024/proposal/0ec36f50-c4b7-4aa4-abef-006f8bab3931
- </li>
- <li>
- 感想: RFC を必芁ずするような機胜远加のプロセスを日本語で解説する資料がどんどんず増えおいくのは、ハヌドルを䞋げるずいう意味で非垞にありがたいです。私も以前から出そう出そうず考えおいる曞きかけの RFC があるのですが、具䜓的なプロセスが明瀺されるずやはりやる気になりたすね。
- </li>
- </ul>
- </li>
- <li>
- (「PHPカンファレンス小田原2024」を実行委員長がふりかえる by asumikam)
- <ul>
- <li>
- fortee URL: https://fortee.jp/phpconkagawa-2024/proposal/c1efd828-72c9-4719-93f7-2ca3f8f20ac1
- </li>
- <li>
- 備考: ちょっずしたトラブルにより午前䞭の発衚が芋られなかったので、生で拝聎したわけではなく、スラむドを拝芋しお感想を曞いおいたす。
- </li>
- <li>
- 感想: Thanks のスラむド非垞に嬉しかったです。こちらこそ玠晎らしいカンファレンスの堎をありがずうございたしたスタッフ募集あれば来幎も是非参加させおください。
- </li>
- </ul>
- </li>
- </ul>
- </section>
- <section id="lightning-talk">
- <h>懇芪䌚 LT</h>
- <p>
- 今回登壇者ではなかったのだが、プロポヌザル募集時に甚意しおいたスラむド (LT 甚に䜜っおいたのだが、そもそも LT 枠がなかったのでお蔵入りになっおいた) があったので懇芪䌚の LT で発衚した。
- </p>
- <p>
- 䞭身は<a href="/slides/2023-03-15/phpstudy-tokyo-150/">第150回PHP勉匷䌚@東京で登壇した内容</a>ずほが同じで、タむトルを「うどんのように现長い FizzBuzz を曞く」にしただけの手抜き・䞀発ネタ発衚である。個別にスラむドはアップロヌドしないので、前述のリンクを参照しおほしい。
- </p>
- <p>
- なお、この発衚には<a href="/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/">ブログ蚘事バヌゞョン</a>もある。
- </p>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- 午前䞭の発衚に間に合わなかったこずがずにかく心残りなのだが、それ以倖は PHP カンファレンス小田原のスタッフの方々をはじめ倚くの方ず亀流でき、非垞に楜しいカンファレンスだった。来幎もあるそうなので (この分だず来幎も月刊 PHP カンファレンスにならないか)、是非参加したい。
- </p>
- <p>
- あれ、そういえば銙川でうどん食べおないな......。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2024-06-19/scalamatsuri-2024-report.dj b/vhosts/blog/content/posts/2024-06-19/scalamatsuri-2024-report.dj
new file mode 100644
index 00000000..85d713de
--- /dev/null
+++ b/vhosts/blog/content/posts/2024-06-19/scalamatsuri-2024-report.dj
@@ -0,0 +1,48 @@
+---
+[article]
+uuid = "8d6f3690-3da3-4235-a81b-b9707cee22ad"
+title = "ScalaMatsuri 2024 参加レポ"
+description = "2024-06-08 から 2024-06-09 にかけお開催された、ScalaMatsuri 2024 に参加した。"
+tags = [
+ "conference",
+ "scala",
+ "scalamatsuri",
+]
+
+[[article.revisions]]
+date = "2024-06-19"
+remark = "公開"
+---
+{#intro}
+# はじめに
+
+2024-06-08 から 2024-06-09 にかけお開催された [ScalaMatsuri 2024](https://2024.scalamatsuri.org/ja) に参加した。
+
+Day 2 には圓日参加できなかったため、day 2 のセッションの感想は YouTube にアップロヌドされたアヌカむブ動画を芳お曞いおいる。
+
+{#sessions}
+# セッション感想
+
+特に印象に残ったセッションを、day 1 ず day 2 で䞀぀ず぀遞んだ (タむトルず登壇者名は [公匏ホヌムペヌゞの「プログラム」](https://2024.scalamatsuri.org/ja/programs) から匕甚)。
+
+* [Scala to WebAssembly: 動機ず方法](https://2024.scalamatsuri.org/ja/programs/SESSION_DAY_1_02) (Rikito Taniguchi さん)
+
+ * [最近 WebAssembly の凊理系を䜜った](/posts/2024-03-17/phperkaigi-2024-report/#section--as-speaker) こずもあっお、気になっおいたセッションです。私の凊理系は WasmGC proposal を実装しおいないので動かせないのですが、い぀かサポヌトしお動かしおみたいですね。
+
+* [䜜っお孊ぶ Extensible Effects](https://2024.scalamatsuri.org/ja/programs/SESSION_DAY_2_04) (Kory さん・hsjoihs さん)
+
+ * 今回䞀番楜しみにしおいたセッションです。Day 2 圓日は参加できず、埌日アヌカむブ動画を芖聎したのですが、期埅を裏切らない濃厚なセッションでした。埌日開かれた [NB-Scala レトロスペクティブ (非公匏埌倜祭)](https://nextbeat.connpass.com/event/315988/) の発衚も拝聎したのですが、どちらも非垞に面癜かったです。
+
+{#others}
+# その他感想
+
+* 良い䌚堎だった。よく取り沙汰されるスラむドの文字サむズの問題は、巚倧なスクリヌンを甚意するこずで解決するずいう発芋があった
+* ランチにお匁圓が甚意されおおり、おいしかった ( [参考画像](https://x.com/nsfisis/status/1799276217583260092) )
+
+{#outro}
+# おわりに
+
+私が Scala を曞いたり远ったりしおいたのは Scala 2 の頃で、Scala 3 はほずんど浊島倪郎状態だったのだが、非垞に楜しく面癜いむベントだった。
+むベントに觊発されお、長らく塩挬けになっおいた Scala 補の趣味プロゞェクトを久しぶりに觊っおいるのだが、これもたた楜しい。
+
+ScalaMatsuri 運営の皆さた、スピヌカヌの皆さた、スポンサヌの皆さた、最高のむベントをありがずうございたした次回も楜しみにしおいたす。
diff --git a/vhosts/blog/content/posts/2024-06-19/scalamatsuri-2024-report.ndoc b/vhosts/blog/content/posts/2024-06-19/scalamatsuri-2024-report.ndoc
deleted file mode 100644
index ae30633b..00000000
--- a/vhosts/blog/content/posts/2024-06-19/scalamatsuri-2024-report.ndoc
+++ /dev/null
@@ -1,63 +0,0 @@
----
-[article]
-uuid = "8d6f3690-3da3-4235-a81b-b9707cee22ad"
-title = "ScalaMatsuri 2024 参加レポ"
-description = "2024-06-08 から 2024-06-09 にかけお開催された、ScalaMatsuri 2024 に参加した。"
-tags = [
- "conference",
- "scala",
- "scalamatsuri",
-]
-
-[[article.revisions]]
-date = "2024-06-19"
-remark = "公開"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- 2024-06-08 から 2024-06-09 にかけお開催された <a href="https://2024.scalamatsuri.org/ja">ScalaMatsuri 2024</a> に参加した。
- </p>
- <p>
- Day 2 には圓日参加できなかったため、day 2 のセッションの感想は YouTube にアップロヌドされたアヌカむブ動画を芳お曞いおいる。
- </p>
- </section>
- <section id="sessions">
- <h>セッション感想</h>
- <p>
- 特に印象に残ったセッションを、day 1 ず day 2 で䞀぀ず぀遞んだ (タむトルず登壇者名は <a href="https://2024.scalamatsuri.org/ja/programs">公匏ホヌムペヌゞの「プログラム」</a> から匕甚)。
- </p>
- <ul>
- <li>
- <a href="https://2024.scalamatsuri.org/ja/programs/SESSION_DAY_1_02">Scala to WebAssembly: 動機ず方法</a> (Rikito Taniguchi さん)
- <ul>
- <a href="/posts/2024-03-17/phperkaigi-2024-report/#section--as-speaker">最近 WebAssembly の凊理系を䜜った</a> こずもあっお、気になっおいたセッションです。私の凊理系は WasmGC proposal を実装しおいないので動かせないのですが、い぀かサポヌトしお動かしおみたいですね。
- </ul>
- </li>
- <li>
- <a href="https://2024.scalamatsuri.org/ja/programs/SESSION_DAY_2_04">䜜っお孊ぶ Extensible Effects</a> (Kory さん・hsjoihs さん)
- <ul>
- 今回䞀番楜しみにしおいたセッションです。Day 2 圓日は参加できず、埌日アヌカむブ動画を芖聎したのですが、期埅を裏切らない濃厚なセッションでした。埌日開かれた <a href="https://nextbeat.connpass.com/event/315988/">NB-Scala レトロスペクティブ (非公匏埌倜祭)</a> の発衚も拝聎したのですが、どちらも非垞に面癜かったです。
- </ul>
- </li>
- </ul>
- </section>
- <section id="others">
- <h>その他感想</h>
- <ul>
- <li>良い䌚堎だった。よく取り沙汰されるスラむドの文字サむズの問題は、巚倧なスクリヌンを甚意するこずで解決するずいう発芋があった</li>
- <li>ランチにお匁圓が甚意されおおり、おいしかった (<a href="https://x.com/nsfisis/status/1799276217583260092">参考画像</a>)</li>
- </ul>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- 私が Scala を曞いたり远ったりしおいたのは Scala 2 の頃で、Scala 3 はほずんど浊島倪郎状態だったのだが、非垞に楜しく面癜いむベントだった。
- むベントに觊発されお、長らく塩挬けになっおいた Scala 補の趣味プロゞェクトを久しぶりに觊っおいるのだが、これもたた楜しい。
- </p>
- <p>
- ScalaMatsuri 運営の皆さた、スピヌカヌの皆さた、スポンサヌの皆さた、最高のむベントをありがずうございたした次回も楜しみにしおいたす。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2024-07-19/reparojson-fix-only-json-formatter.dj b/vhosts/blog/content/posts/2024-07-19/reparojson-fix-only-json-formatter.dj
new file mode 100644
index 00000000..eb63da08
--- /dev/null
+++ b/vhosts/blog/content/posts/2024-07-19/reparojson-fix-only-json-formatter.dj
@@ -0,0 +1,132 @@
+---
+[article]
+uuid = "222488dd-cf07-4961-83aa-a014b05369ff"
+title = "reparojson: 文法゚ラヌを盎すだけの JSON フォヌマッタを䜜った"
+description = "文法゚ラヌだけを盎し、空癜の削陀や挿入ずいった敎圢凊理を䞀切おこなわない JSON フォヌマッタを䜜成した。Neovim ず連携させる蚭定䟋も玹介する。"
+tags = [
+ "neovim",
+ "vim",
+]
+
+[[article.revisions]]
+date = "2024-07-19"
+remark = "公開"
+---
+::: note
+この蚘事は [Vim 駅䌝](https://vim-jp.org/ekiden/) #218 の蚘事です。
+:::
+
+{#intro}
+# 欲しかったもの
+
+Vim で JSON を線集しおいるずきに、文法゚ラヌ (末尟カンマやカンマの䞍足) のみを修正しお䞀切の敎圢をおこなわないプラグむンが欲しかった。
+敎圢も同時におこなうプラグむンは芋぀かっただけでも倚数あったのだが、敎圢しないものは芋぀けられなかったので自䜜するこずにした。
+
+なお、䜜成したツヌル自䜓は単䜓の CLI ずしお動䜜し、Vim ずは無関係に䜿うこずができる。
+この蚘事では Neovim ず組み合わせる堎合の蚭定を玹介するが、およそ任意の゚ディタで䜿えるだろう。
+
+{#reparojson}
+# 䜜ったもの
+
+䜜成したものがこちら: [ReparoJSON](https://github.com/nsfisis/reparojson)
+
+次のように動䜜する。
+
+```
+$ echo '[ 1 2 ]' | reparojson
+[ 1, 2 ]
+
+$ echo '[ 1, 2, ]' | reparojson
+[ 1, 2 ]
+
+$ echo '{ "foo": 1 "bar": 2 }' | reparojson
+{ "foo": 1, "bar": 2 }
+
+$ echo '{ "foo": 1, "bar": 2, }' | reparojson
+{ "foo": 1, "bar": 2 }
+```
+
+バヌゞョン 0.1.1 時点で修正察象の文法゚ラヌは次のずおり:
+
+* 配列末尟の䜙蚈なカンマ (削陀する)
+* 配列内のカンマ䞍足 (挿入する)
+* オブゞェクト末尟の䜙蚈なカンマ (削陀する)
+* オブゞェクト内のカンマ䞍足 (挿入する)
+
+他にも自動で盎せそうな゚ラヌはいく぀か思い぀くが (オブゞェクトのキヌがクォヌトされおいない等)、私自身があたり困っおいないので優先床は䜎い。
+
+{#itegration-with-neovim}
+# Neovim ずの連携
+
+Neovim で JSON ファむルを保存したずきに、䞊蚘のツヌルを自動で走らせるように蚭定する。
+
+ここでは、 [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig) ず [efm-langserver](https://github.com/mattn/efm-langserver) を甚いた蚭定䟋を玹介する。
+
+```lua
+ local lspconfig = require('lspconfig')
+
+ lspconfig.efm.setup({
+ init_options = { documentFormatting = true },
+ settings = {
+ rootMarkers = {".git/"},
+ languages = {
+ json = {
+ {
+ formatCommand = "reparojson -q",
+ formatStdin = true,
+ },
+ },
+ },
+ }
+ })
+
+ vim.api.nvim_create_autocmd('LspAttach', {
+ callback = function(e)
+ vim.api.nvim_create_autocmd('BufWritePre', {
+ buffer = e.buf,
+ callback = function()
+ vim.lsp.buf.format({ async = false })
+ end
+ })
+ end,
+ })
+```
+
+ほずんどは nvim-lspconfig ず efm-langserver を䜿う際のボむラヌプレヌトだが、`formatCommand` で `-q` フラグを指定しおいるこずに泚意しおほしい。
+このツヌルは、デフォルトでは JSON が修正された堎合 exit code 1 で終了する。
+これは、入力が最初から正しかった堎合ず修正しお正しくなった堎合を区別するためだが、異垞終了しおしたうず眮き換えが発生しない。
+そのため、`-q` フラグを指定しお、修正されたずきも exit code 0 で終了するようにしおいる。
+
+{#outro}
+# おわりに
+
+このツヌルが嚁力を発揮するのは、行の入れ換え時である。次のような JSON があり、
+
+```json
+ {
+ "a": true,
+ "b": false
+ }
+```
+
+2行目ず3行目を入れ換えお以䞋のように線集した。
+
+```json
+ {
+ "b": false
+ "a": true,
+ }
+```
+
+これは䞍正な JSON だが、このツヌルを通せば次のようになる。
+
+```json
+ {
+ "b": false,
+ "a": true
+ }
+```
+
+もちろん、このような操䜜を文法を壊さずにおこなう Vim プラグむンは存圚する。
+しかし、単なる行の入れ換えであれば `ddp` の3ストロヌクでおこなうこずができ、専甚のキヌバむンドを芚える必芁もない。
+このツヌルを甚いるこずで、より Vimmer-friendly な JSON 線集が可胜ずなる。
diff --git a/vhosts/blog/content/posts/2024-07-19/reparojson-fix-only-json-formatter.ndoc b/vhosts/blog/content/posts/2024-07-19/reparojson-fix-only-json-formatter.ndoc
deleted file mode 100644
index 5efe8bbd..00000000
--- a/vhosts/blog/content/posts/2024-07-19/reparojson-fix-only-json-formatter.ndoc
+++ /dev/null
@@ -1,153 +0,0 @@
----
-[article]
-uuid = "222488dd-cf07-4961-83aa-a014b05369ff"
-title = "reparojson: 文法゚ラヌを盎すだけの JSON フォヌマッタを䜜った"
-description = "文法゚ラヌだけを盎し、空癜の削陀や挿入ずいった敎圢凊理を䞀切おこなわない JSON フォヌマッタを䜜成した。Neovim ず連携させる蚭定䟋も玹介する。"
-tags = [
- "neovim",
- "vim",
-]
-
-[[article.revisions]]
-date = "2024-07-19"
-remark = "公開"
----
-<article>
- <note>
- この蚘事は <a href="https://vim-jp.org/ekiden/">Vim 駅䌝</a> #218 の蚘事です。
- </note>
- <section id="intro">
- <h>欲しかったもの</h>
- <p>
- Vim で JSON を線集しおいるずきに、文法゚ラヌ (末尟カンマやカンマの䞍足) のみを修正しお䞀切の敎圢をおこなわないプラグむンが欲しかった。
- 敎圢も同時におこなうプラグむンは芋぀かっただけでも倚数あったのだが、敎圢しないものは芋぀けられなかったので自䜜するこずにした。
- </p>
- <p>
- なお、䜜成したツヌル自䜓は単䜓の CLI ずしお動䜜し、Vim ずは無関係に䜿うこずができる。
- この蚘事では Neovim ず組み合わせる堎合の蚭定を玹介するが、およそ任意の゚ディタで䜿えるだろう。
- </p>
- </section>
- <section id="reparojson">
- <h>䜜ったもの</h>
- <p>
- 䜜成したものがこちら: <a href="https://github.com/nsfisis/reparojson">ReparoJSON</a>
- </p>
- <p>
- 次のように動䜜する。
- </p>
- <codeblock>
- <![CDATA[
- $ echo '[ 1 2 ]' | reparojson
- [ 1, 2 ]
-
- $ echo '[ 1, 2, ]' | reparojson
- [ 1, 2 ]
-
- $ echo '{ "foo": 1 "bar": 2 }' | reparojson
- { "foo": 1, "bar": 2 }
-
- $ echo '{ "foo": 1, "bar": 2, }' | reparojson
- { "foo": 1, "bar": 2 }
- ]]>
- </codeblock>
- <p>
- バヌゞョン 0.1.1 時点で修正察象の文法゚ラヌは次のずおり:
- </p>
- <ul>
- <li>配列末尟の䜙蚈なカンマ (削陀する)</li>
- <li>配列内のカンマ䞍足 (挿入する)</li>
- <li>オブゞェクト末尟の䜙蚈なカンマ (削陀する)</li>
- <li>オブゞェクト内のカンマ䞍足 (挿入する)</li>
- </ul>
- <p>
- 他にも自動で盎せそうな゚ラヌはいく぀か思い぀くが (オブゞェクトのキヌがクォヌトされおいない等)、私自身があたり困っおいないので優先床は䜎い。
- </p>
- </section>
- <section id="itegration-with-neovim">
- <h>Neovim ずの連携</h>
- <p>
- Neovim で JSON ファむルを保存したずきに、䞊蚘のツヌルを自動で走らせるように蚭定する。
- </p>
- <p>
- ここでは、<a href="https://github.com/neovim/nvim-lspconfig">nvim-lspconfig</a> ず <a href="https://github.com/mattn/efm-langserver">efm-langserver</a> を甚いた蚭定䟋を玹介する。
- </p>
- <codeblock language="lua">
- <![CDATA[
- local lspconfig = require('lspconfig')
-
- lspconfig.efm.setup({
- init_options = { documentFormatting = true },
- settings = {
- rootMarkers = {".git/"},
- languages = {
- json = {
- {
- formatCommand = "reparojson -q",
- formatStdin = true,
- },
- },
- },
- }
- })
-
- vim.api.nvim_create_autocmd('LspAttach', {
- callback = function(e)
- vim.api.nvim_create_autocmd('BufWritePre', {
- buffer = e.buf,
- callback = function()
- vim.lsp.buf.format({ async = false })
- end
- })
- end,
- })
- ]]>
- </codeblock>
- <p>
- ほずんどは nvim-lspconfig ず efm-langserver を䜿う際のボむラヌプレヌトだが、<code>formatCommand</code> で <code>-q</code> フラグを指定しおいるこずに泚意しおほしい。
- このツヌルは、デフォルトでは JSON が修正された堎合 exit code 1 で終了する。
- これは、入力が最初から正しかった堎合ず修正しお正しくなった堎合を区別するためだが、異垞終了しおしたうず眮き換えが発生しない。
- そのため、<code>-q</code> フラグを指定しお、修正されたずきも exit code 0 で終了するようにしおいる。
- </p>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- このツヌルが嚁力を発揮するのは、行の入れ換え時である。次のような JSON があり、
- </p>
- <codeblock language="json">
- <![CDATA[
- {
- "a": true,
- "b": false
- }
- ]]>
- </codeblock>
- <p>
- 2行目ず3行目を入れ換えお以䞋のように線集した。
- </p>
- <codeblock language="json">
- <![CDATA[
- {
- "b": false
- "a": true,
- }
- ]]>
- </codeblock>
- <p>
- これは䞍正な JSON だが、このツヌルを通せば次のようになる。
- </p>
- <codeblock language="json">
- <![CDATA[
- {
- "b": false,
- "a": true
- }
- ]]>
- </codeblock>
- <p>
- もちろん、このような操䜜を文法を壊さずにおこなう Vim プラグむンは存圚する。
- しかし、単なる行の入れ換えであれば <code>ddp</code> の3ストロヌクでおこなうこずができ、専甚のキヌバむンドを芚える必芁もない。
- このツヌルを甚いるこずで、より Vimmer-friendly な JSON 線集が可胜ずなる。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2024-08-19/go-template-access-outer-scope-pipeline-within-with-or-range.dj b/vhosts/blog/content/posts/2024-08-19/go-template-access-outer-scope-pipeline-within-with-or-range.dj
new file mode 100644
index 00000000..6a6f9c3f
--- /dev/null
+++ b/vhosts/blog/content/posts/2024-08-19/go-template-access-outer-scope-pipeline-within-with-or-range.dj
@@ -0,0 +1,118 @@
+---
+[article]
+uuid = "eed112e4-3227-4b3f-9991-7e11c288ee2b"
+title = "【Go】 text/template の with や range の内偎から倖偎の \".\" にアクセスする"
+description = "Go蚀語の text/template における with や range は \".\" を䞊曞きする。これらの内偎から倖偎の \".\" にアクセスする方法を調べた。"
+tags = [
+ "go",
+]
+
+[[article.revisions]]
+date = "2024-08-19"
+remark = "公開"
+---
+{#tldr}
+# TL;DR
+
+垞にトップレベルを指す特殊倉数 `$` を䜿えばよい。
+
+{#intro}
+# はじめに
+
+Go には、暙準ラむブラリにテンプレヌトラむブラリ `text/template` がある。
+この `text/template` における制埡構造、`with` ず `range` は次のように䜿われる。
+
+```
+# {{ .Title }}
+
+# User
+
+{{ with .User }}
+ {{ .Name }} ({{ .ID }})
+{{ end }}
+
+# Items
+
+{{ range .Items }}
+ - {{ . }}
+{{ end }}
+```
+
+`text/template` の `.` は、珟圚の操䜜察象を衚す特殊なオブゞェクトである。
+
+`with` や `range` は、`.` を倉曎する効果を持぀。
+`with` は匕数に枡されたオブゞェクトを `.` ぞセットしお、内郚のテンプレヌトを実行する。
+`range` は匕数に枡されたむテレヌト可胜なオブゞェクトに察し、それぞれの芁玠を `.` ぞセットしお、芁玠の個数だけ内郚のテンプレヌトを実行する。
+
+぀たりこのテンプレヌトは、次のような構造をレンダリングしおいる (`Execute()` の第2匕数)。
+
+```go
+tmpl.Execute(out, Params{
+ Title: "foo",
+ User: User{
+ ID: 123,
+ Name: "john",
+ },
+ Items: []string{
+ "hoge",
+ "piyo",
+ "fuga",
+ },
+})
+```
+
+{#what-i-want-to-do}
+# やりたいこず
+
+今回おこないたいのは、`with` や `range` の䞭で、その倖偎で䜿われおいたトップレベルのオブゞェクトを参照するこずだ。
+
+```
+{{ with .User }}
+ ここから .Title を参照するには
+{{ end }}
+
+{{ range .Items }}
+ ここから .User を参照するには
+{{ end }}
+```
+
+`with` や `range` は、`.` を自身の察象オブゞェクトに倉曎するので、
+単に `{{ with .User }}` の䞭で `.Title` ず曞いおも、それは `User` の `Title` プロパティを参照しおいるずみなされる。
+
+`text/template` では倉数が䜿えるので、テンプレヌトの先頭で
+
+```
+{{ $params := . }}
+```
+
+ずでもしおおけば実珟は可胜である。
+
+しかしながら、頻発するシチュ゚ヌションにしおはあたりに䞍恰奜である。よりスマヌトな方法が甚意されおいるはずだ。
+
+{#solution}
+# 解決方法
+
+垞にトップレベルを指す特殊倉数 `$` を䜿えばよい。
+
+```
+{{ with .User }}
+ {{ $.Title }}
+{{ end }}
+
+{{ range .Items }}
+ {{ $.User.Name }}
+{{ end }}
+```
+
+`$` は、テンプレヌトが実行されるずきに枡されたオブゞェクトを指す。
+これを䜿えば珟圚の `.` に関係なくトップレベルを参照できる。
+
+このこずは、[`text/template` の公匏ドキュメント](https://pkg.go.dev/text/template#hdr-Variables)にも以䞋のように蚘茉されおいる。
+
+> When execution begins, $ is set to the data argument passed to Execute, that is, to the starting value of dot.
+
+{#reference}
+# 参考
+
+* [盎接の出兞である Stack Overflow の回答: "In a template how do you access an outer scope while inside of a "with" or "range" scope?"](https://stackoverflow.com/questions/14800204/in-a-template-how-do-you-access-an-outer-scope-while-inside-of-a-with-or-rang)
+* [倧元の出兞である `text/template` の公匏ドキュメント](https://pkg.go.dev/text/template#hdr-Variables)
diff --git a/vhosts/blog/content/posts/2024-08-19/go-template-access-outer-scope-pipeline-within-with-or-range.ndoc b/vhosts/blog/content/posts/2024-08-19/go-template-access-outer-scope-pipeline-within-with-or-range.ndoc
deleted file mode 100644
index ee7b0ab8..00000000
--- a/vhosts/blog/content/posts/2024-08-19/go-template-access-outer-scope-pipeline-within-with-or-range.ndoc
+++ /dev/null
@@ -1,141 +0,0 @@
----
-[article]
-uuid = "eed112e4-3227-4b3f-9991-7e11c288ee2b"
-title = "【Go】 text/template の with や range の内偎から倖偎の \".\" にアクセスする"
-description = "Go蚀語の text/template における with や range は \".\" を䞊曞きする。これらの内偎から倖偎の \".\" にアクセスする方法を調べた。"
-tags = [
- "go",
-]
-
-[[article.revisions]]
-date = "2024-08-19"
-remark = "公開"
----
-<article>
- <section id="tldr">
- <h>TL;DR</h>
- <p>
- 垞にトップレベルを指す特殊倉数 <code>$</code> を䜿えばよい。
- </p>
- </section>
- <section id="intro">
- <h>はじめに</h>
- <p>
- Go には、暙準ラむブラリにテンプレヌトラむブラリ <code>text/template</code> がある。
- この <code>text/template</code> における制埡構造、<code>with</code> ず <code>range</code> は次のように䜿われる。
- </p>
- <codeblock>
- <![CDATA[
- # {{ .Title }}
-
- # User
-
- {{ with .User }}
- {{ .Name }} ({{ .ID }})
- {{ end }}
-
- # Items
-
- {{ range .Items }}
- - {{ . }}
- {{ end }}
- ]]>
- </codeblock>
- <p>
- <code>text/template</code> の <code>.</code> は、珟圚の操䜜察象を衚す特殊なオブゞェクトである。
- </p>
- <p>
- <code>with</code> や <code>range</code> は、<code>.</code> を倉曎する効果を持぀。
- <code>with</code> は匕数に枡されたオブゞェクトを <code>.</code> ぞセットしお、内郚のテンプレヌトを実行する。
- <code>range</code> は匕数に枡されたむテレヌト可胜なオブゞェクトに察し、それぞれの芁玠を <code>.</code> ぞセットしお、芁玠の個数だけ内郚のテンプレヌトを実行する。
- </p>
- <p>
- ぀たりこのテンプレヌトは、次のような構造をレンダリングしおいる (<code>Execute()</code> の第2匕数)。
- </p>
- <codeblock language="go">
- <![CDATA[
- tmpl.Execute(out, Params{
- Title: "foo",
- User: User{
- ID: 123,
- Name: "john",
- },
- Items: []string{
- "hoge",
- "piyo",
- "fuga",
- },
- })
- ]]>
- </codeblock>
- </section>
- <section id="what-i-want-to-do">
- <h>やりたいこず</h>
- <p>
- 今回おこないたいのは、<code>with</code> や <code>range</code> の䞭で、その倖偎で䜿われおいたトップレベルのオブゞェクトを参照するこずだ。
- </p>
- <codeblock>
- <![CDATA[
- {{ with .User }}
- ここから .Title を参照するには
- {{ end }}
-
- {{ range .Items }}
- ここから .User を参照するには
- {{ end }}
- ]]>
- </codeblock>
- <p>
- <code>with</code> や <code>range</code> は、<code>.</code> を自身の察象オブゞェクトに倉曎するので、
- 単に <code>{{ with .User }}</code> の䞭で <code>.Title</code> ず曞いおも、それは <code>User</code> の <code>Title</code> プロパティを参照しおいるずみなされる。
- </p>
- <p>
- <code>text/template</code> では倉数が䜿えるので、テンプレヌトの先頭で
- </p>
- <codeblock>
- <![CDATA[
- {{ $params := . }}
- ]]>
- </codeblock>
- <p>
- ずでもしおおけば実珟は可胜である。
- </p>
- <p>
- しかしながら、頻発するシチュ゚ヌションにしおはあたりに䞍恰奜である。よりスマヌトな方法が甚意されおいるはずだ。
- </p>
- </section>
- <section id="solution">
- <h>解決方法</h>
- <p>
- 垞にトップレベルを指す特殊倉数 <code>$</code> を䜿えばよい。
- </p>
- <codeblock>
- <![CDATA[
- {{ with .User }}
- {{ $.Title }}
- {{ end }}
-
- {{ range .Items }}
- {{ $.User.Name }}
- {{ end }}
- ]]>
- </codeblock>
- <p>
- <code>$</code> は、テンプレヌトが実行されるずきに枡されたオブゞェクトを指す。
- これを䜿えば珟圚の <code>.</code> に関係なくトップレベルを参照できる。
- </p>
- <p>
- このこずは、<a href="https://pkg.go.dev/text/template#hdr-Variables"><code>text/template</code> の公匏ドキュメント</a>にも以䞋のように蚘茉されおいる。
- </p>
- <blockquote>
- When execution begins, $ is set to the data argument passed to Execute, that is, to the starting value of dot.
- </blockquote>
- </section>
- <section id="reference">
- <h>参考</h>
- <ul>
- <li><a href="https://stackoverflow.com/questions/14800204/in-a-template-how-do-you-access-an-outer-scope-while-inside-of-a-with-or-rang">盎接の出兞である Stack Overflow の回答: "In a template how do you access an outer scope while inside of a "with" or "range" scope?"</a></li>
- <li><a href="https://pkg.go.dev/text/template#hdr-Variables">倧元の出兞である <code>text/template</code> の公匏ドキュメント</a></li>
- </ul>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2024-09-28/mncore-challenge-1.dj b/vhosts/blog/content/posts/2024-09-28/mncore-challenge-1.dj
new file mode 100644
index 00000000..f862b55e
--- /dev/null
+++ b/vhosts/blog/content/posts/2024-09-28/mncore-challenge-1.dj
@@ -0,0 +1,37 @@
+---
+[article]
+uuid = "ee7289ee-ff2e-439d-b343-7f87504192fd"
+title = "MN-Core Challenge #1 参加レポ"
+description = "2024-08-28 から 2024-09-24 にかけお開催された MN-Core Challenge #1 に参加した。"
+tags = [
+ "mncore-challenge",
+]
+
+[[article.revisions]]
+date = "2024-09-28"
+remark = "公開"
+---
+::: note
+ただの参加蚘で解説はない。
+:::
+
+{#intro}
+# はじめに
+
+2024-08-28 から 2024-09-24 の玄1ヶ月に枡り開催された [MN-Core Challenge #1](https://mncore-challenge.preferred.jp/) に参加した。私 nsfisis ([あるいは `0b0100000111111000`](https://x.com/nsfisis/status/1838276770560364977)) はスコア 1181 で、最終順䜍 29 䜍だった。
+
+この蚘事で解説はしないが、提出した回答はこちらのリポゞトリ ([GitHub: nsfisis/mncore-challenge](https://github.com/nsfisis/mncore-challenge)) にアップロヌドしおいる。
+
+{#thought}
+# 感想
+
+MN-Core には初めお觊れたが、それでも問題なく党問 (陀 FizzBuzz) 解けるよう線路が敷かれおおり、前半の問題を解くこずで自然ず埌半を解くだけの知識が身に付くように蚭蚈されおいた。
+
+開催期間䞭はほが垞に MN-Core Challenge のこずを考え続けおおり、期間䞭 (前掲した回答を貯めるためのリポゞトリを陀き) 自分の Git リポゞトリをほずんど觊るこずがなかった。途䞭曎新ができずに苊しい時間もあったが、䞀぀気付くず䞀぀瞮たる楜しいゎルフだった。
+
+悔しいポむントも倚数あるのだが、曞いおいるずキリがないので自分で反省するだけにしおおく。
+
+{#outro}
+# おわりに
+
+最埌になりたしたが、運営のみなさた、玠晎しいコンテストをありがずうございたした非垞に楜しい時間でした第2回を銖を長くしお埅っおいたす
diff --git a/vhosts/blog/content/posts/2024-09-28/mncore-challenge-1.ndoc b/vhosts/blog/content/posts/2024-09-28/mncore-challenge-1.ndoc
deleted file mode 100644
index 462ccab5..00000000
--- a/vhosts/blog/content/posts/2024-09-28/mncore-challenge-1.ndoc
+++ /dev/null
@@ -1,45 +0,0 @@
----
-[article]
-uuid = "ee7289ee-ff2e-439d-b343-7f87504192fd"
-title = "MN-Core Challenge #1 参加レポ"
-description = "2024-08-28 から 2024-09-24 にかけお開催された MN-Core Challenge #1 に参加した。"
-tags = [
- "mncore-challenge",
-]
-
-[[article.revisions]]
-date = "2024-09-28"
-remark = "公開"
----
-<article>
- <note>
- ただの参加蚘で解説はない。
- </note>
- <section id="intro">
- <h>はじめに</h>
- <p>
- 2024-08-28 から 2024-09-24 の玄1ヶ月に枡り開催された <a href="https://mncore-challenge.preferred.jp/">MN-Core Challenge #1</a> に参加した。私 nsfisis (<a href="https://x.com/nsfisis/status/1838276770560364977">あるいは <code>0b0100000111111000</code></a>) はスコア 1181 で、最終順䜍 29 䜍だった。
- </p>
- <p>
- この蚘事で解説はしないが、提出した回答はこちらのリポゞトリ (<a href="https://github.com/nsfisis/mncore-challenge">GitHub: nsfisis/mncore-challenge</a>) にアップロヌドしおいる。
- </p>
- </section>
- <section id="thought">
- <h>感想</h>
- <p>
- MN-Core には初めお觊れたが、それでも問題なく党問 (陀 FizzBuzz) 解けるよう線路が敷かれおおり、前半の問題を解くこずで自然ず埌半を解くだけの知識が身に付くように蚭蚈されおいた。
- </p>
- <p>
- 開催期間䞭はほが垞に MN-Core Challenge のこずを考え続けおおり、期間䞭 (前掲した回答を貯めるためのリポゞトリを陀き) 自分の Git リポゞトリをほずんど觊るこずがなかった。途䞭曎新ができずに苊しい時間もあったが、䞀぀気付くず䞀぀瞮たる楜しいゎルフだった。
- </p>
- <p>
- 悔しいポむントも倚数あるのだが、曞いおいるずキリがないので自分で反省するだけにしおおく。
- </p>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- 最埌になりたしたが、運営のみなさた、玠晎しいコンテストをありがずうございたした非垞に楜しい時間でした第2回を銖を長くしお埅っおいたす
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2024-12-04/cohackpp-report.dj b/vhosts/blog/content/posts/2024-12-04/cohackpp-report.dj
new file mode 100644
index 00000000..80da994f
--- /dev/null
+++ b/vhosts/blog/content/posts/2024-12-04/cohackpp-report.dj
@@ -0,0 +1,197 @@
+---
+[article]
+uuid = "ea0593d3-691c-4e08-8db4-98b8925717ec"
+title = "玅癜ぺぱ合戊に参加&LTしたした"
+description = "2024-11-30 に開催された玅癜ぺぱ合戊に参加し、ぺ陣営のメンバずしお LT したした。"
+tags = [
+ "cohackpp",
+ "php",
+]
+
+[[article.revisions]]
+date = "2024-12-04"
+remark = "公開"
+
+[[article.revisions]]
+date = "2024-12-05"
+remark = "「育おた」枠・「育おられた」枠を勘違いしお逆に衚蚘しおいたので修正"
+---
+{#intro}
+# はじめに
+
+2024-11-30 に開催された [玅癜ぺぱ合戊](https://connpass.com/event/329428/) なる催しに参加したした。私は「ぺ」陣営のメンバずしお LT をおこないたした。
+
+玅癜ぺぱ合戊のむベントペヌゞにある説明を以䞋に匕甚したす。
+
+> Web゚ンゞニアの [asumikam](https://x.com/asumikam) ずWeb゚ンゞニアの [stefafafan](https://x.com/stefafafan) が2024幎7月7日に結婚したした。
+>
+> せっかくなので技術トヌクずかで玅癜戊をしたせんかいいですねやっおいきたす
+>
+> 堎所はァ小田原ァ盛り䞊がっおいきたしょゥ
+
+ざっくりず蚀えば、テックカンファレンスの圢匏をずった結婚披露宎です。タむトルの「ぺ」は PHPer、「ぱ」は Perl Monger の略です。
+
+{#thoughts}
+# 感想
+
+私は「ぺ」陣営のスピヌカヌずしお LT をしおいたのですが、その前にたずは登壇以倖の感想を。
+
+いや最高でしたね。どの枠のスピヌチの方も良かったのですが、特に (asumikam さん/stefafafan さんに)「育おられた」枠のお二方が印象に残っおいたす。
+(asumikam さん/stefafafan さんを)「育おた」枠ずしおお䞖話になった方に声をかけるこずはできるず思うんですよ。
+それだけでなく、「自分が育おたのだ」ず蚀える人がいお、そしおそれに 100 点で応える人がいるずいうこず。この玠晎しさ。人埳。
+
+改めお、asumikam さん、stefafafan さん、ご結婚おめでずうございたす
+
+{#lt}
+# LT
+
+{#prepare}
+## 合戊準備
+
+さお、時を合戊の前に戻したしお、䞡陣営の登壇者が発衚され埐々に謎のむベントの茪郭が芋えおきた頃、asumikam さんから次のような連絡を受けたした。
+
+![asumikam「いたむらさんお぀かれさたです。ぺぱ合戊で、LTタむムあるこずになり、技術で3人「ぺ」偎を遞出するこずになったのですが、いたむらさん、LTやりたせんか。「ぺ」陣営で䞀緒に頂きを目指したせんか。」nsfisis「OKです」](/posts/2024-12-04/cohackpp-report/lt.png)
+
+最初は盎近のカンファレンスに出しお萜遞したプロポヌザルテヌマを LT に線集しお話そうずしおいたのですが、この機䌚でなければ話せない・この機䌚で話すこずに意味があるテヌマにしようずネタ出しをおこない、最終的に次のテヌマでの登壇ずなりたした。
+
+{#battle}
+## いざ尋垞に勝負
+
+圓日は、「プログラミングマナヌ講座」ず題しお発衚をおこないたした。
+結婚匏のマナヌ、特に「忌み蚀葉」ぞフォヌカスし、これを無理やりプログラミングに適甚するずいうものです。
+[スラむドはこちらにアップロヌドしおいたす。](/slides/2024-11-30/cohackpp/)
+
+最終的にお祝いのメッセヌゞを仕蟌んだ゜ヌスコヌドで締めるずいう構成は、我ながら綺麗にたずたったず思っおいたす。忌み蚀葉の案は他にも倧量にあったのですが、技術 LT か぀結婚祝いスピヌチにするためにどうしおも最埌の゜ヌスコヌドが必芁だったので、時間の関係䞊それらには犠牲ずなっおもらいたした ( [ボツになった案のひず぀](https://x.com/nsfisis/status/1862798137452327206) )。
+
+そもそも結婚匏・披露宎でのスピヌチ自䜓が初めおだったのでそれなりに緊匵しおいたのですが、登壇時やその埌の反応を䌺う限り抂ね奜評だったようで良かったです。
+
+{#congrats}
+# ご結婚おめでずうございたす
+
+https://github.com/nsfisis/cohackpp/blob/main/congrats.php
+
+```php
+<?php
+$s=<<<'Q'
+<?php
+%
+$s=<<<'Q'
+@$c=[`];
+$m="";for($k=0;$k<min(13,intdiv(__LINE__-119,80)+1);$k++){$C=str_replace("\n","",
+$c[$k]);$f=!0;foreach(str_split(base64_decode($C))as$l){$L=ord($l);$m.=str_repeat
+($f?"#":chr(32),$L&127);$f=!$f;if($L&128){$m.="\n";$f=!0;continue;}}}print(
+str_replace([chr(96),chr(37),chr(64)],[implode("\n",array_map(fn($C)=>"'".trim(
+chunk_split(str_replace("\n","",$C),80,"\n"))."',",$c)),"\n{$m}","{$s}\nQ;\n"],$s));
+Q;
+$c=['0AFOgQFOgQFOgQFOgQFOgQFEAgiBAUIECIEBQwQHgQE8AQYFBoEBOgQGBAaBAToEBwQFgQE6BQYFBIEB
+OwQHBASBATwEBgUDgQE8BQYEA4EBPQQGBAOBAT0FBgEFgQERBhsIBAQMgQERKQQFC4EBESkFAQ6BAREp
+FIEBESkUgQERKRSBAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6B
+AU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAQ4EPIEBDQY7gQENBjuBAQ0GO4EBDQU8gQENBTyBAQwG
+PIEBDAY8gQEMBjyBAQwGPIEBDAY8gQEMBjyBAQwHO4EBDAc7gQENBzqBAQ0IOYEBDgg4gQEOCiUCD4EB
+DwwdBw+BARAQDhEPgQERLg+BARItD4EBFCsPgQEXJRKBARsbGIEBToEBToEBToEBToEBToHQ',
+'0AFOgQFOgQFOgQEPASMFFoEBDwMhBRaBAQ4FIAUWgQEOBSAFFoEBDQUhBRaBAQ0FIQUWgQEMBSIFFoEB
+DAUiBRaBAQsFIwUWgQELBQgBGgUWgQEKBQkDGAUWgQEKBQgGBCoDgQEJBQkFBSoDgQEFAQMECQYFKgOB
+AQQDAQUJBQYqA4EBBAgJBQcqA4EBAwkJBRkFFoEBBAcJBRoFFoEBBQYIBRsFFoEBBgYHBRsFFoEBBwYF
+BRwFFoEBCAYDBR0FFoEBCQYCBR0FFoEBCgseBRaBAQsJHwUWgQEMByAFFoEBDAcFAxgFFoEBDQUFBBgF
+FoEBDQQGBRYGFoEBDAUHBAcmBYEBCwUIBQYmBYEBCwQKBAYmBYEBCgQLBQUmBYEBCQUMBS+BAQgFDAYv
+gQEDHC+BAQMdLoEBAx0ugQEDHi2BAQMJBAUIBC2BARAFCAQtgQEQBQgELYEBEAUJAS+BARAFESEHgQEQ
+BREhB4EBBwEIBQYBCiEHgQEHBAUFBAQJIQeBAQcEBQUEBAkEGAUHgQEGBQUFBAUIBBgFB4EBBgUFBQUE
+CAQYBQeBAQYFBQUFBAgEGAUHgQEGBAYFBQUHBBgFB4EBBgQGBQYEBwQYBQeBAQUFBgUGBQYEGAUHgQEF
+BQYFBwQGBBgFB4EBBQQHBQcEBgQYBQeBAQUEBwUHBQUEGAUHgQEEBQcFBwUFBBgFB4EBBAUHBQgEBQQY
+BQeBAQQECAUIBAUEGAUHgQEDBQgFCAEIBBgFB4EBAwUIBREEGAUHgQECBQkFEQQYBQeBAQIFCQURIQeB
+AQQCCgURIQeBARAFESEHgQEQBREhB4EBEAURIQeBARAFEQQYBQeBARAFEQQYBQeBARAFEQQYBQeBARAF
+EQQYBQeBAU6BAU6BAU6B0A==',
+'0AFOgQFOgQFOgQEOAjEBDIEBDgUqBwqBAQ0FJwwJgQENBSETCIEBDQURAQcXDIEBDQURGxCBAQ0FERcU
+gQENBBIOBAUUgQEMBRIGDAUUgQEMBRIFDQUUgQEMBRIFDgQUgQEMBRIFDgQUgQEMBBMFDgQUgQELBRMF
+DgQUgQELBRMFDgUTgQELBRMFDgUTgQEDGQcFDgUTgQEDGwUoA4EBAxsFKAOBAQMbBSgDgQEDGwUoA4EB
+CgUKBQUFDwUSgQEKBAsEBgUQBBKBAQkFCwQGBRAFEYEBCQULBAYFEAURgQEJBQoFBgUQBRGBAQkFCgUG
+BREFEIEBCQQLBQYFEQUQgQEIBQsFBgUSBQkBBYEBCAULBQYFEgUJAwOBAQgFCwUGBQoFBAUIBAKBAQgF
+CwQHBQQLBAYHAwOBAQgECwUHFAUGBQQDgQEHBQsFAxgFBwQEA4EBBwULBQMVCQ4DgQEHBQsFAw8QDQOB
+AQcEDAUDCRcLBIEBBgULBQUCHwgFgQEGBQsFKAQHgQEGBQsFM4EBBgULBTOBAQYFCgUKIgiBAQUHCQUK
+IgiBAQUICAUKIgiBAQUKBgUKIgiBAQULBAULBRgFCIEBBA0DBQsFGAUIgQEEBQIHAgULBRgFCIEBBgMD
+DAwFGAUIgQENCwwFGAUIgQEOCgwFGAUIgQEQBw0FGAUIgQERBwwFGAUIgQERCAsiCIEBEAoKIgiBARAL
+CSIIgQEPDQgiCIEBDwUCBwcFGAUIgQEOBgMHBgUYBQiBAQ0GBQcFBRgFCIEBDAcGBgUFGAUIgQELBwgE
+BgUYBQiBAQoHCgMGBRgFCIEBCQcMAQcFGAUIgQEIBxUFGAUIgQEHCBUiCIEBBggWIgiBAQQJFyIIgQEF
+BxgiCIEBBQUaBRgFCIEBBgMbBRgFCIEBJAUYBQiBAU6BAU6BAU6B0A==',
+'0AFOgQFOgQFOgQFOgQFOgQFOgQFOgQEZBi+BARkGL4EBGgUvgQEaBS+BARoFL4EBGgUvgQEaBS+BARoF
+L4EBGgUvgQEaBRkBFYEBGgUZAxOBARoFDwEIBRKBARoFCwUIBxCBARoFBgoHCg6BARoVCQkNgQEJJgsJ
+C4EBCSYMCQqBAQohEgkIgQEKGxoIB4EBChUhCQWBARkFIwkEgQEZBSUGBYEBGQUmBAaBARkFKAIGgQEZ
+BTCBARkFMIEBGQUwgQEZBTCBARkFMIEBGQUwgQEZBTCBARkFCRAXgQEZBQQYFIEBGSMSgQEZJBGBARkS
+CAwPgQEXDhIJDoEBFQwYCA2BARMMGwcNgQESDB0HDIEBEA4eBgyBAQ8IAwQfBguBAQ4IBAQfBguBAQ0H
+BgQgBQuBAQwHBwQgBQuBAQsHCAUfBQuBAQoGCgUfBQuBAQoGCgUfBQuBAQkGCwUfBQuBAQkFDAUeBguB
+AQgGDAUeBguBAQgGDAUdBwuBAQgGDAUdBgyBAQgGDAUcBwyBAQkFDAUbBw2BAQkGCwUZCQ2BAQkHCgUY
+CQ6BAQoIBwYVCw+BAQsIBQcSDRCBAQwSChURgQENEQoTE4EBDhAKERWBARANDA4XgQESCwwLGoEBFQYO
+BSCBAU6BAU6BAU6BAU6BAU6BAU6B0A==',
+'0AFOgQFOgQFOgQFOgQFOgQFOgQFOgQEuBhqBAS4FG4EBLgUbgQEuBRuBARICGQYbgQEPBRkGG4EBDgYZ
+BRyBAQ8FGQUcgQEPBhgFHIEBDwYXBhyBARAFFwUdgQEQBRcFHYEBEAYNERqBAREFChcXgQERBQccFYEB
+EQYEIBOBARIFAg4DExGBARIRBwYEChCBARIOCgUHCQ+BARMKDQUJCA6BARIJDgYKCA2BAREIEAUNBwyB
+ARAJEAUOBgyBAQ8KDwYPBguBAQ4MDgUQBwqBAQ4MDgURBgqBAQ0GAgYMBRMFCoEBDAYEBQwFEwYJgQEM
+BgQFCwYTBgmBAQsGBQYKBRUFCYEBCgYHBQkGFQYIgQEKBQgGCAYVBgiBAQkGCQUIBRcFCIEBCQUKBgYG
+FwUIgQEJBQsFBgUYBQiBAQgFDAYEBhgFCIEBCAUNBQMGGQUIgQEIBQ0GAgYZBQiBAQcFDwwaBQiBAQcF
+DwwaBQiBAQcFEAobBQiBAQcFEAoaBgiBAQcFEQgbBgiBAQcFEgYcBgiBAQcFEQgbBQmBAQcFEAoZBgmB
+AQcFEAoZBgmBAQcFDwwXBgqBAQcFDg4VBwqBAQcGDAcCBxQGC4EBCAULBwQEFQcLgQEIBggIBgIVBwyB
+AQgIBAkHARUHDYEBCRMcCQ2BAQoRHAkOgQELDhwKD4EBDAwbChGBAQ4HGwwSgQEsDxOBASgRFYEBKQ4X
+gQEpDBmBASoIHIEBKwMggQFOgQFOgQFOgQFOgQFOgQFOgQFOgdA=',
+'0AFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQE1DwqBASkbCoEBHiYKgQETMQqBAQc9CoEBBjQU
+gQEGIQQKGYEBBhcOBxyBAQcOFAcegQEHBhsHH4EBJwYhgQEmBiKBASUGFgEMgQEkBhUDDIEBIwYWBAuB
+ASMGFwQKgQEiBg8DBgQKgQEhBg8EBwQJgQEhBhAEBwQIgQEgBhEFBgQIgQEgBRMEBwQHgQEfBhQEBgUG
+gQEfBhQEBwQGgQEfBRYEBgIIgQEeBhYEEIEBHgYXBA+BAR4FGAMQgQEeBSuBAR0GK4EBHQYrgQEdBiuB
+AR0GK4EBHQYrgQEdBiuBAR0GK4EBHQYrgQEdBiuBAR4FK4EBHgYqgQEeBiqBAR4HKYEBHwYpgQEfByiB
+ASAHJ4EBIAcngQEhByaBASEJJIEBIgkjgQEjCiGBASQLH4EBJQwdgQEmDxmBASgTE4EBKhMRgQErEhGB
+AS4PEYEBMAwSgQE0CBKBAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6B0A==',
+'0AFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQEXATaBARQENoEBEgY2gQESBzWBARMGNYEBEwc0gQEUBjSB
+ARQGNIEBFQYzgQEVBiABEoEBFgYeAxGBARYGHAYQgQEWBxoHEIEBFwYYCg+BARcHFQsQgQEYBhMLEoEB
+GAYRCxSBARkGDgsWgQEZBgwLGIEBGgYJCxqBARoHBwocgQEbBgUKHoEBGwcCCiCBARwRIYEBHA8jgQEd
+DCWBAR0KJ4EBHAoogQEbCSqBARoILIEBGQgtgQEXCC+BARYIMIEBFQgxgQEVBzKBARQHM4EBEwc0gQES
+BzWBARIGNoEBEQY3gQERBjeBAREFOIEBEAY4gQEQBjiBARAGOIEBEAY4gQEQBjiBARAGOIEBEAY4gQEQ
+BjiBARAHN4EBEAc3gQERBzaBAREINYEBEgkzgQETCiEDDYEBEw0WCw2BARQtDYEBFisNgQEXKg2BARon
+DYEBHSARgQEjDxyBAU6BAU6BAU6BAU6BAU6BAU6BAU6B0A==',
+'0AFOgQFOgQFOgQFOgQFOgQFOgQFOgQEXBDOBARcLLIEBFxQjgQEXIRaBARchFoEBGh4WgQEiFhaBASsN
+FoEBNgEXgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQEkDR2BAR4WGoEBGR0YgQEVIxaBARApFYEB
+DRcLCxSBAQ4QFAkTgQEODBoIEoEBDgkeBxKBAQ4GIgcRgQEPAiYGEYEBNwcQgQE4BhCBATgGEIEBOAYQ
+gQE4BhCBATkFEIEBOQUQgQE5BRCBATgGEIEBOAYQgQE4BhCBATgGEIEBNwcQgQE3BhGBATcGEYEBNgcR
+gQE1BxKBATUHEoEBNAcTgQEzCBOBATIIFIEBMQgVgQEvCRaBAS4JF4EBLAoYgQEqCxmBAScMG4EBJQ0c
+gQEhDx6BARwTH4EBGBQigQEZESSBARoNJ4EBGgoqgQEbBS6BAU6BAU6BAU6BAU6BAU6BAU6BAU6B0A==',
+'0AFOgQFOgQFOgQFOgQFOgQFDAgmBAUEECYEBQgQIgQE7AQYFB4EBOQQGBAeBATkEBwQGgQE5BQYFBYEB
+OgQHBAWBATsEBgUEgQE7BQYEBIEBPAQGBASBATwFBgEGgQEQBhsIBAQNgQEQKQQFDIEBECkFAQ+BARAp
+FYEBECkVgQEQKRWBAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6B
+AU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAQ0EPYEBDAY8gQEMBjyBAQwGPIEBDAU9gQEMBT2BAQsG
+PYEBCwY9gQELBj2BAQsGPYEBCwY9gQELBj2BAQsHPIEBCwc8gQEMBzuBAQwIOoEBDQg5gQENCiUCEIEB
+DgwdBxCBAQ8QDhEQgQEQLhCBAREtEIEBEysQgQEWJROBARobGYEBToEBToEBToEBToEBToHQ',
+'0AFOgQFOgQFOgQFOgQFCAwmBAUEECYEBQQUIgQE5AwYFB4EBOAQHBAeBASkCDgQGBQaBASYGDQUGBAaB
+ASYGDgQHBAWBASYGDgUGBAWBAScFDwQHBASBAScGDwQGAwWBAScGDwUNgQEoBRAEDYEBKAUQAw6BASgG
+IIEBKQUQAw2BASkFDAcNgQEpBgYMDYEBCgMdFw2BAQsVAh8NgQELNQ6BAQsxEoEBCysYgQELJh2BARkI
+CwUdgQEsBhyBAS0FHIEBLQUcgQEuBRuBAS4FG4EBLwUagQEvBRqBATAFGYEBMAYYgQExBRiBATEGF4EB
+MgUXgQEyBhaBATMGFYEBNAUVgQE0BhSBATUGE4EBEAIWCgMHEoEBEAYSFRGBAQ8GExURgQEPBRQUEoEB
+DgYaDROBAQ4GIwQTgQEOBTuBAQ0GO4EBDQY7gQENBTyBAQ0FPIEBDQU8gQENBTyBAQ0FPIEBDQU8gQEN
+BjuBAQ0GO4EBDgY6gQEOBzmBAQ4IOIEBDwg3gQEQCh4BFYEBEQwVBxWBARInFYEBEyYVgQEVJBWBARgh
+FYEBGxoZgQFOgQFOgQFOgQFOgdA=',
+'0AFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQEJBz6BAQkGP4EBCQY/gQEJBigDFIEB
+CQYlBhSBAQkGJQcTgQEJBiYHEoEBCQYnBhKBAQkGJwcRgQEJBigGEYEBCQYoBxCBAQkGKQYQgQEJBioG
+D4EBCQYqBg+BAQkGKgcOgQEJBisGDoEBCgUrBg6BAQoFLAYNgQEKBSwGDYEBCgUtBgyBAQoFLQYMgQEK
+BS0GDIEBCgUuBguBAQoFLgYLgQEKBS4GC4EBCgYtBguBAQoGLgYKgQEKBi4GCoEBCgYuBgqBAQoGLwYJ
+gQELBS8GCYEBCwUvBgmBAQsFLwYJgQELBhMBGgYJgQELBhMCGgYIgQELBhMDGQYIgQEMBRMEGAYIgQEM
+BhEGFwYIgQEMBhEGFwYIgQEMBhAGGQUIgQENBg8GGQUIgQENBg8GGQUIgQENBg4GGgILgQEOBg0GJ4EB
+DgcLBiiBAQ4HCgcogQEPBwgHKYEBEAcGCCmBARAKAQkqgQEREiuBARIRK4EBEhAsgQETDi2BARULLoEB
+FwcwgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgdA=',
+'0AFOgQFOgQFOgQFOgQFOgQFOgQFOgQElBiOBASYFI4EBJgUjgQEmBSOBASYFI4EBJgUjgQEmBSOBASYF
+I4EBJgUQBQ6BAQ4IEAUGDw6BAQ4yDoEBDjIOgQEOMg6BAQ4rFYEBGhIigQEmBSOBASYFI4EBJgUjgQEm
+BSOBASYFI4EBJgUjgQEmBSOBASYFI4EBJgUjgQEmBRQCDYEBDQMWBQwKDYEBDQ8JHA2BAQ4zDYEBDjMN
+gQEOMg6BARAnF4EBJQYjgQEmBSOBASYFI4EBJgUjgQEmBSOBASYFI4EBJgUjgQEmBSOBASYFI4EBJgUj
+gQEmBSOBAR0EBQUjgQEXFCOBARQZIYEBEh4egQERIRyBARAJDBAZgQEPBxARF4EBDgYSExWBAQ4FEwYD
+CxSBAQ4FEwYFCxKBAQ0FFAYHChGBAQ0FFAYJCg+BAQ0FFAYKCg6BAQ0GEwYMCQ2BAQ4FEwYNCQyBAQ4G
+EQYQBg2BAQ4HDwcRBQ2BAQ8IDAgSAw6BAQ8bFAEPgQERGCWBARIWJoEBFBIogQEXDSqBAU6BAU6BAU6B
+AU6BAU6BAU6B0A==',
+'0AFOgQFOgQFOgQFOgQFOgQFOgQEpBh+BASkGH4EBKQYfgQEqBR+BASoFH4EBKgUfgQEqBR+BASoFH4EB
+KgUfgQEqBR+BARkuB4EBBkEHgQEHQAeBAQdAB4EBB0AHgQEHDBcFH4EBKgUfgQEqBR+BASoFH4EBKgUf
+gQEqBR+BASoFH4EBKgUfgQEgDx+BAR4RH4EBHBMfgQEbFB+BARoIBAkfgQEZBwkGH4EBGQYLBh6BARgG
+DQUegQEYBQ4GHYEBFwYPBR2BARcFEAUdgQEXBRAFHYEBFwUQBhyBARcFEAYcgQEXBQ8HHIEBFwUPBxyB
+ARcGDgccgQEXBg0IHIEBGAYMBx2BARgHCggdgQEZCAYKHYEBGhcdgQEbFh2BARwVHYEBHgsBBh6BASAG
+BAYegQEpBh+BASkGH4EBKAYggQEnByCBASYHIYEBJQcigQEkCCKBASIJI4EBIAokgQEeCyWBARwLJ4EB
+GQ0ogQEWDiqBARcMK4EBGAktgQEZBTCBARoCMoEBToEBToEBToEBToEBToEBToHQ',];
+$m="";for($k=0;$k<min(13,intdiv(__LINE__-119,80)+1);$k++){$C=str_replace("\n","",
+$c[$k]);$f=!0;foreach(str_split(base64_decode($C))as$l){$L=ord($l);$m.=str_repeat
+($f?"#":chr(32),$L&127);$f=!$f;if($L&128){$m.="\n";$f=!0;continue;}}}print(
+str_replace([chr(96),chr(37),chr(64)],[implode("\n",array_map(fn($C)=>"'".trim(
+chunk_split(str_replace("\n","",$C),80,"\n"))."',",$c)),"\n{$m}","{$s}\nQ;\n"],$s));
+```
diff --git a/vhosts/blog/content/posts/2024-12-04/cohackpp-report.ndoc b/vhosts/blog/content/posts/2024-12-04/cohackpp-report.ndoc
deleted file mode 100644
index 5d77af55..00000000
--- a/vhosts/blog/content/posts/2024-12-04/cohackpp-report.ndoc
+++ /dev/null
@@ -1,217 +0,0 @@
----
-[article]
-uuid = "ea0593d3-691c-4e08-8db4-98b8925717ec"
-title = "玅癜ぺぱ合戊に参加&LTしたした"
-description = "2024-11-30 に開催された玅癜ぺぱ合戊に参加し、ぺ陣営のメンバずしお LT したした。"
-tags = [
- "cohackpp",
- "php",
-]
-
-[[article.revisions]]
-date = "2024-12-04"
-remark = "公開"
-
-[[article.revisions]]
-date = "2024-12-05"
-remark = "「育おた」枠・「育おられた」枠を勘違いしお逆に衚蚘しおいたので修正"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- 2024-11-30 に開催された<a href="https://connpass.com/event/329428/">玅癜ぺぱ合戊</a>なる催しに参加したした。私は「ぺ」陣営のメンバずしお LT をおこないたした。
- </p>
- <p>
- 玅癜ぺぱ合戊のむベントペヌゞにある説明を以䞋に匕甚したす。
- </p>
- <blockquote>
- <p>
- Web゚ンゞニアの<a href="https://x.com/asumikam">asumikam</a>ずWeb゚ンゞニアの<a href="https://x.com/stefafafan">stefafafan</a>が2024幎7月7日に結婚したした。
- </p>
- <p>
- せっかくなので技術トヌクずかで玅癜戊をしたせんかいいですねやっおいきたす
- </p>
- <p>
- 堎所はァ小田原ァ盛り䞊がっおいきたしょゥ
- </p>
- </blockquote>
- <p>
- ざっくりず蚀えば、テックカンファレンスの圢匏をずった結婚披露宎です。タむトルの「ぺ」は PHPer、「ぱ」は Perl Monger の略です。
- </p>
- </section>
- <section id="thoughts">
- <h>感想</h>
- <p>
- 私は「ぺ」陣営のスピヌカヌずしお LT をしおいたのですが、その前にたずは登壇以倖の感想を。
- </p>
- <p>
- いや最高でしたね。どの枠のスピヌチの方も良かったのですが、特に (asumikam さん/stefafafan さんに)「育おられた」枠のお二方が印象に残っおいたす。
- (asumikam さん/stefafafan さんを)「育おた」枠ずしおお䞖話になった方に声をかけるこずはできるず思うんですよ。
- それだけでなく、「自分が育おたのだ」ず蚀える人がいお、そしおそれに 100 点で応える人がいるずいうこず。この玠晎しさ。人埳。
- </p>
- <p>
- 改めお、asumikam さん、stefafafan さん、ご結婚おめでずうございたす
- </p>
- </section>
- <section id="lt">
- <h>LT</h>
- <section id="prepare">
- <h>合戊準備</h>
- <p>
- さお、時を合戊の前に戻したしお、䞡陣営の登壇者が発衚され埐々に謎のむベントの茪郭が芋えおきた頃、asumikam さんから次のような連絡を受けたした。
- </p>
- <img src="/posts/2024-12-04/cohackpp-report/lt.png" alt="asumikam「いたむらさんお぀かれさたです。ぺぱ合戊で、LTタむムあるこずになり、技術で3人「ぺ」偎を遞出するこずになったのですが、いたむらさん、LTやりたせんか。「ぺ」陣営で䞀緒に頂きを目指したせんか。」nsfisis「OKです」"></img>
- <p>
- 最初は盎近のカンファレンスに出しお萜遞したプロポヌザルテヌマを LT に線集しお話そうずしおいたのですが、この機䌚でなければ話せない・この機䌚で話すこずに意味があるテヌマにしようずネタ出しをおこない、最終的に次のテヌマでの登壇ずなりたした。
- </p>
- </section>
- <section id="battle">
- <h>いざ尋垞に勝負</h>
- <p>
- 圓日は、「プログラミングマナヌ講座」ず題しお発衚をおこないたした。
- 結婚匏のマナヌ、特に「忌み蚀葉」ぞフォヌカスし、これを無理やりプログラミングに適甚するずいうものです。
- <a href="/slides/2024-11-30/cohackpp/">スラむドはこちらにアップロヌドしおいたす。</a>
- </p>
- <p>
- 最終的にお祝いのメッセヌゞを仕蟌んだ゜ヌスコヌドで締めるずいう構成は、我ながら綺麗にたずたったず思っおいたす。忌み蚀葉の案は他にも倧量にあったのですが、技術 LT か぀結婚祝いスピヌチにするためにどうしおも最埌の゜ヌスコヌドが必芁だったので、時間の関係䞊それらには犠牲ずなっおもらいたした (<a href="https://x.com/nsfisis/status/1862798137452327206">ボツになった案のひず぀</a>)。
- </p>
- <p>
- そもそも結婚匏・披露宎でのスピヌチ自䜓が初めおだったのでそれなりに緊匵しおいたのですが、登壇時やその埌の反応を䌺う限り抂ね奜評だったようで良かったです。
- </p>
- </section>
- </section>
- <section id="congrats">
- <h>ご結婚おめでずうございたす</h>
- <p>
- https://github.com/nsfisis/cohackpp/blob/main/congrats.php
- </p>
- <codeblock language="php">
- <![CDATA[
- <?php
- $s=<<<'Q'
- <?php
- %
- $s=<<<'Q'
- @$c=[`];
- $m="";for($k=0;$k<min(13,intdiv(__LINE__-119,80)+1);$k++){$C=str_replace("\n","",
- $c[$k]);$f=!0;foreach(str_split(base64_decode($C))as$l){$L=ord($l);$m.=str_repeat
- ($f?"#":chr(32),$L&127);$f=!$f;if($L&128){$m.="\n";$f=!0;continue;}}}print(
- str_replace([chr(96),chr(37),chr(64)],[implode("\n",array_map(fn($C)=>"'".trim(
- chunk_split(str_replace("\n","",$C),80,"\n"))."',",$c)),"\n{$m}","{$s}\nQ;\n"],$s));
- Q;
- $c=['0AFOgQFOgQFOgQFOgQFOgQFEAgiBAUIECIEBQwQHgQE8AQYFBoEBOgQGBAaBAToEBwQFgQE6BQYFBIEB
- OwQHBASBATwEBgUDgQE8BQYEA4EBPQQGBAOBAT0FBgEFgQERBhsIBAQMgQERKQQFC4EBESkFAQ6BAREp
- FIEBESkUgQERKRSBAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6B
- AU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAQ4EPIEBDQY7gQENBjuBAQ0GO4EBDQU8gQENBTyBAQwG
- PIEBDAY8gQEMBjyBAQwGPIEBDAY8gQEMBjyBAQwHO4EBDAc7gQENBzqBAQ0IOYEBDgg4gQEOCiUCD4EB
- DwwdBw+BARAQDhEPgQERLg+BARItD4EBFCsPgQEXJRKBARsbGIEBToEBToEBToEBToEBToHQ',
- '0AFOgQFOgQFOgQEPASMFFoEBDwMhBRaBAQ4FIAUWgQEOBSAFFoEBDQUhBRaBAQ0FIQUWgQEMBSIFFoEB
- DAUiBRaBAQsFIwUWgQELBQgBGgUWgQEKBQkDGAUWgQEKBQgGBCoDgQEJBQkFBSoDgQEFAQMECQYFKgOB
- AQQDAQUJBQYqA4EBBAgJBQcqA4EBAwkJBRkFFoEBBAcJBRoFFoEBBQYIBRsFFoEBBgYHBRsFFoEBBwYF
- BRwFFoEBCAYDBR0FFoEBCQYCBR0FFoEBCgseBRaBAQsJHwUWgQEMByAFFoEBDAcFAxgFFoEBDQUFBBgF
- FoEBDQQGBRYGFoEBDAUHBAcmBYEBCwUIBQYmBYEBCwQKBAYmBYEBCgQLBQUmBYEBCQUMBS+BAQgFDAYv
- gQEDHC+BAQMdLoEBAx0ugQEDHi2BAQMJBAUIBC2BARAFCAQtgQEQBQgELYEBEAUJAS+BARAFESEHgQEQ
- BREhB4EBBwEIBQYBCiEHgQEHBAUFBAQJIQeBAQcEBQUEBAkEGAUHgQEGBQUFBAUIBBgFB4EBBgUFBQUE
- CAQYBQeBAQYFBQUFBAgEGAUHgQEGBAYFBQUHBBgFB4EBBgQGBQYEBwQYBQeBAQUFBgUGBQYEGAUHgQEF
- BQYFBwQGBBgFB4EBBQQHBQcEBgQYBQeBAQUEBwUHBQUEGAUHgQEEBQcFBwUFBBgFB4EBBAUHBQgEBQQY
- BQeBAQQECAUIBAUEGAUHgQEDBQgFCAEIBBgFB4EBAwUIBREEGAUHgQECBQkFEQQYBQeBAQIFCQURIQeB
- AQQCCgURIQeBARAFESEHgQEQBREhB4EBEAURIQeBARAFEQQYBQeBARAFEQQYBQeBARAFEQQYBQeBARAF
- EQQYBQeBAU6BAU6BAU6B0A==',
- '0AFOgQFOgQFOgQEOAjEBDIEBDgUqBwqBAQ0FJwwJgQENBSETCIEBDQURAQcXDIEBDQURGxCBAQ0FERcU
- gQENBBIOBAUUgQEMBRIGDAUUgQEMBRIFDQUUgQEMBRIFDgQUgQEMBRIFDgQUgQEMBBMFDgQUgQELBRMF
- DgQUgQELBRMFDgUTgQELBRMFDgUTgQEDGQcFDgUTgQEDGwUoA4EBAxsFKAOBAQMbBSgDgQEDGwUoA4EB
- CgUKBQUFDwUSgQEKBAsEBgUQBBKBAQkFCwQGBRAFEYEBCQULBAYFEAURgQEJBQoFBgUQBRGBAQkFCgUG
- BREFEIEBCQQLBQYFEQUQgQEIBQsFBgUSBQkBBYEBCAULBQYFEgUJAwOBAQgFCwUGBQoFBAUIBAKBAQgF
- CwQHBQQLBAYHAwOBAQgECwUHFAUGBQQDgQEHBQsFAxgFBwQEA4EBBwULBQMVCQ4DgQEHBQsFAw8QDQOB
- AQcEDAUDCRcLBIEBBgULBQUCHwgFgQEGBQsFKAQHgQEGBQsFM4EBBgULBTOBAQYFCgUKIgiBAQUHCQUK
- IgiBAQUICAUKIgiBAQUKBgUKIgiBAQULBAULBRgFCIEBBA0DBQsFGAUIgQEEBQIHAgULBRgFCIEBBgMD
- DAwFGAUIgQENCwwFGAUIgQEOCgwFGAUIgQEQBw0FGAUIgQERBwwFGAUIgQERCAsiCIEBEAoKIgiBARAL
- CSIIgQEPDQgiCIEBDwUCBwcFGAUIgQEOBgMHBgUYBQiBAQ0GBQcFBRgFCIEBDAcGBgUFGAUIgQELBwgE
- BgUYBQiBAQoHCgMGBRgFCIEBCQcMAQcFGAUIgQEIBxUFGAUIgQEHCBUiCIEBBggWIgiBAQQJFyIIgQEF
- BxgiCIEBBQUaBRgFCIEBBgMbBRgFCIEBJAUYBQiBAU6BAU6BAU6B0A==',
- '0AFOgQFOgQFOgQFOgQFOgQFOgQFOgQEZBi+BARkGL4EBGgUvgQEaBS+BARoFL4EBGgUvgQEaBS+BARoF
- L4EBGgUvgQEaBRkBFYEBGgUZAxOBARoFDwEIBRKBARoFCwUIBxCBARoFBgoHCg6BARoVCQkNgQEJJgsJ
- C4EBCSYMCQqBAQohEgkIgQEKGxoIB4EBChUhCQWBARkFIwkEgQEZBSUGBYEBGQUmBAaBARkFKAIGgQEZ
- BTCBARkFMIEBGQUwgQEZBTCBARkFMIEBGQUwgQEZBTCBARkFCRAXgQEZBQQYFIEBGSMSgQEZJBGBARkS
- CAwPgQEXDhIJDoEBFQwYCA2BARMMGwcNgQESDB0HDIEBEA4eBgyBAQ8IAwQfBguBAQ4IBAQfBguBAQ0H
- BgQgBQuBAQwHBwQgBQuBAQsHCAUfBQuBAQoGCgUfBQuBAQoGCgUfBQuBAQkGCwUfBQuBAQkFDAUeBguB
- AQgGDAUeBguBAQgGDAUdBwuBAQgGDAUdBgyBAQgGDAUcBwyBAQkFDAUbBw2BAQkGCwUZCQ2BAQkHCgUY
- CQ6BAQoIBwYVCw+BAQsIBQcSDRCBAQwSChURgQENEQoTE4EBDhAKERWBARANDA4XgQESCwwLGoEBFQYO
- BSCBAU6BAU6BAU6BAU6BAU6BAU6B0A==',
- '0AFOgQFOgQFOgQFOgQFOgQFOgQFOgQEuBhqBAS4FG4EBLgUbgQEuBRuBARICGQYbgQEPBRkGG4EBDgYZ
- BRyBAQ8FGQUcgQEPBhgFHIEBDwYXBhyBARAFFwUdgQEQBRcFHYEBEAYNERqBAREFChcXgQERBQccFYEB
- EQYEIBOBARIFAg4DExGBARIRBwYEChCBARIOCgUHCQ+BARMKDQUJCA6BARIJDgYKCA2BAREIEAUNBwyB
- ARAJEAUOBgyBAQ8KDwYPBguBAQ4MDgUQBwqBAQ4MDgURBgqBAQ0GAgYMBRMFCoEBDAYEBQwFEwYJgQEM
- BgQFCwYTBgmBAQsGBQYKBRUFCYEBCgYHBQkGFQYIgQEKBQgGCAYVBgiBAQkGCQUIBRcFCIEBCQUKBgYG
- FwUIgQEJBQsFBgUYBQiBAQgFDAYEBhgFCIEBCAUNBQMGGQUIgQEIBQ0GAgYZBQiBAQcFDwwaBQiBAQcF
- DwwaBQiBAQcFEAobBQiBAQcFEAoaBgiBAQcFEQgbBgiBAQcFEgYcBgiBAQcFEQgbBQmBAQcFEAoZBgmB
- AQcFEAoZBgmBAQcFDwwXBgqBAQcFDg4VBwqBAQcGDAcCBxQGC4EBCAULBwQEFQcLgQEIBggIBgIVBwyB
- AQgIBAkHARUHDYEBCRMcCQ2BAQoRHAkOgQELDhwKD4EBDAwbChGBAQ4HGwwSgQEsDxOBASgRFYEBKQ4X
- gQEpDBmBASoIHIEBKwMggQFOgQFOgQFOgQFOgQFOgQFOgQFOgdA=',
- '0AFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQE1DwqBASkbCoEBHiYKgQETMQqBAQc9CoEBBjQU
- gQEGIQQKGYEBBhcOBxyBAQcOFAcegQEHBhsHH4EBJwYhgQEmBiKBASUGFgEMgQEkBhUDDIEBIwYWBAuB
- ASMGFwQKgQEiBg8DBgQKgQEhBg8EBwQJgQEhBhAEBwQIgQEgBhEFBgQIgQEgBRMEBwQHgQEfBhQEBgUG
- gQEfBhQEBwQGgQEfBRYEBgIIgQEeBhYEEIEBHgYXBA+BAR4FGAMQgQEeBSuBAR0GK4EBHQYrgQEdBiuB
- AR0GK4EBHQYrgQEdBiuBAR0GK4EBHQYrgQEdBiuBAR4FK4EBHgYqgQEeBiqBAR4HKYEBHwYpgQEfByiB
- ASAHJ4EBIAcngQEhByaBASEJJIEBIgkjgQEjCiGBASQLH4EBJQwdgQEmDxmBASgTE4EBKhMRgQErEhGB
- AS4PEYEBMAwSgQE0CBKBAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6B0A==',
- '0AFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQEXATaBARQENoEBEgY2gQESBzWBARMGNYEBEwc0gQEUBjSB
- ARQGNIEBFQYzgQEVBiABEoEBFgYeAxGBARYGHAYQgQEWBxoHEIEBFwYYCg+BARcHFQsQgQEYBhMLEoEB
- GAYRCxSBARkGDgsWgQEZBgwLGIEBGgYJCxqBARoHBwocgQEbBgUKHoEBGwcCCiCBARwRIYEBHA8jgQEd
- DCWBAR0KJ4EBHAoogQEbCSqBARoILIEBGQgtgQEXCC+BARYIMIEBFQgxgQEVBzKBARQHM4EBEwc0gQES
- BzWBARIGNoEBEQY3gQERBjeBAREFOIEBEAY4gQEQBjiBARAGOIEBEAY4gQEQBjiBARAGOIEBEAY4gQEQ
- BjiBARAHN4EBEAc3gQERBzaBAREINYEBEgkzgQETCiEDDYEBEw0WCw2BARQtDYEBFisNgQEXKg2BARon
- DYEBHSARgQEjDxyBAU6BAU6BAU6BAU6BAU6BAU6BAU6B0A==',
- '0AFOgQFOgQFOgQFOgQFOgQFOgQFOgQEXBDOBARcLLIEBFxQjgQEXIRaBARchFoEBGh4WgQEiFhaBASsN
- FoEBNgEXgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQEkDR2BAR4WGoEBGR0YgQEVIxaBARApFYEB
- DRcLCxSBAQ4QFAkTgQEODBoIEoEBDgkeBxKBAQ4GIgcRgQEPAiYGEYEBNwcQgQE4BhCBATgGEIEBOAYQ
- gQE4BhCBATkFEIEBOQUQgQE5BRCBATgGEIEBOAYQgQE4BhCBATgGEIEBNwcQgQE3BhGBATcGEYEBNgcR
- gQE1BxKBATUHEoEBNAcTgQEzCBOBATIIFIEBMQgVgQEvCRaBAS4JF4EBLAoYgQEqCxmBAScMG4EBJQ0c
- gQEhDx6BARwTH4EBGBQigQEZESSBARoNJ4EBGgoqgQEbBS6BAU6BAU6BAU6BAU6BAU6BAU6BAU6B0A==',
- '0AFOgQFOgQFOgQFOgQFOgQFDAgmBAUEECYEBQgQIgQE7AQYFB4EBOQQGBAeBATkEBwQGgQE5BQYFBYEB
- OgQHBAWBATsEBgUEgQE7BQYEBIEBPAQGBASBATwFBgEGgQEQBhsIBAQNgQEQKQQFDIEBECkFAQ+BARAp
- FYEBECkVgQEQKRWBAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6B
- AU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAQ0EPYEBDAY8gQEMBjyBAQwGPIEBDAU9gQEMBT2BAQsG
- PYEBCwY9gQELBj2BAQsGPYEBCwY9gQELBj2BAQsHPIEBCwc8gQEMBzuBAQwIOoEBDQg5gQENCiUCEIEB
- DgwdBxCBAQ8QDhEQgQEQLhCBAREtEIEBEysQgQEWJROBARobGYEBToEBToEBToEBToEBToHQ',
- '0AFOgQFOgQFOgQFOgQFCAwmBAUEECYEBQQUIgQE5AwYFB4EBOAQHBAeBASkCDgQGBQaBASYGDQUGBAaB
- ASYGDgQHBAWBASYGDgUGBAWBAScFDwQHBASBAScGDwQGAwWBAScGDwUNgQEoBRAEDYEBKAUQAw6BASgG
- IIEBKQUQAw2BASkFDAcNgQEpBgYMDYEBCgMdFw2BAQsVAh8NgQELNQ6BAQsxEoEBCysYgQELJh2BARkI
- CwUdgQEsBhyBAS0FHIEBLQUcgQEuBRuBAS4FG4EBLwUagQEvBRqBATAFGYEBMAYYgQExBRiBATEGF4EB
- MgUXgQEyBhaBATMGFYEBNAUVgQE0BhSBATUGE4EBEAIWCgMHEoEBEAYSFRGBAQ8GExURgQEPBRQUEoEB
- DgYaDROBAQ4GIwQTgQEOBTuBAQ0GO4EBDQY7gQENBTyBAQ0FPIEBDQU8gQENBTyBAQ0FPIEBDQU8gQEN
- BjuBAQ0GO4EBDgY6gQEOBzmBAQ4IOIEBDwg3gQEQCh4BFYEBEQwVBxWBARInFYEBEyYVgQEVJBWBARgh
- FYEBGxoZgQFOgQFOgQFOgQFOgdA=',
- '0AFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQEJBz6BAQkGP4EBCQY/gQEJBigDFIEB
- CQYlBhSBAQkGJQcTgQEJBiYHEoEBCQYnBhKBAQkGJwcRgQEJBigGEYEBCQYoBxCBAQkGKQYQgQEJBioG
- D4EBCQYqBg+BAQkGKgcOgQEJBisGDoEBCgUrBg6BAQoFLAYNgQEKBSwGDYEBCgUtBgyBAQoFLQYMgQEK
- BS0GDIEBCgUuBguBAQoFLgYLgQEKBS4GC4EBCgYtBguBAQoGLgYKgQEKBi4GCoEBCgYuBgqBAQoGLwYJ
- gQELBS8GCYEBCwUvBgmBAQsFLwYJgQELBhMBGgYJgQELBhMCGgYIgQELBhMDGQYIgQEMBRMEGAYIgQEM
- BhEGFwYIgQEMBhEGFwYIgQEMBhAGGQUIgQENBg8GGQUIgQENBg8GGQUIgQENBg4GGgILgQEOBg0GJ4EB
- DgcLBiiBAQ4HCgcogQEPBwgHKYEBEAcGCCmBARAKAQkqgQEREiuBARIRK4EBEhAsgQETDi2BARULLoEB
- FwcwgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgdA=',
- '0AFOgQFOgQFOgQFOgQFOgQFOgQFOgQElBiOBASYFI4EBJgUjgQEmBSOBASYFI4EBJgUjgQEmBSOBASYF
- I4EBJgUQBQ6BAQ4IEAUGDw6BAQ4yDoEBDjIOgQEOMg6BAQ4rFYEBGhIigQEmBSOBASYFI4EBJgUjgQEm
- BSOBASYFI4EBJgUjgQEmBSOBASYFI4EBJgUjgQEmBRQCDYEBDQMWBQwKDYEBDQ8JHA2BAQ4zDYEBDjMN
- gQEOMg6BARAnF4EBJQYjgQEmBSOBASYFI4EBJgUjgQEmBSOBASYFI4EBJgUjgQEmBSOBASYFI4EBJgUj
- gQEmBSOBAR0EBQUjgQEXFCOBARQZIYEBEh4egQERIRyBARAJDBAZgQEPBxARF4EBDgYSExWBAQ4FEwYD
- CxSBAQ4FEwYFCxKBAQ0FFAYHChGBAQ0FFAYJCg+BAQ0FFAYKCg6BAQ0GEwYMCQ2BAQ4FEwYNCQyBAQ4G
- EQYQBg2BAQ4HDwcRBQ2BAQ8IDAgSAw6BAQ8bFAEPgQERGCWBARIWJoEBFBIogQEXDSqBAU6BAU6BAU6B
- AU6BAU6BAU6B0A==',
- '0AFOgQFOgQFOgQFOgQFOgQFOgQEpBh+BASkGH4EBKQYfgQEqBR+BASoFH4EBKgUfgQEqBR+BASoFH4EB
- KgUfgQEqBR+BARkuB4EBBkEHgQEHQAeBAQdAB4EBB0AHgQEHDBcFH4EBKgUfgQEqBR+BASoFH4EBKgUf
- gQEqBR+BASoFH4EBKgUfgQEgDx+BAR4RH4EBHBMfgQEbFB+BARoIBAkfgQEZBwkGH4EBGQYLBh6BARgG
- DQUegQEYBQ4GHYEBFwYPBR2BARcFEAUdgQEXBRAFHYEBFwUQBhyBARcFEAYcgQEXBQ8HHIEBFwUPBxyB
- ARcGDgccgQEXBg0IHIEBGAYMBx2BARgHCggdgQEZCAYKHYEBGhcdgQEbFh2BARwVHYEBHgsBBh6BASAG
- BAYegQEpBh+BASkGH4EBKAYggQEnByCBASYHIYEBJQcigQEkCCKBASIJI4EBIAokgQEeCyWBARwLJ4EB
- GQ0ogQEWDiqBARcMK4EBGAktgQEZBTCBARoCMoEBToEBToEBToEBToEBToEBToHQ',];
- $m="";for($k=0;$k<min(13,intdiv(__LINE__-119,80)+1);$k++){$C=str_replace("\n","",
- $c[$k]);$f=!0;foreach(str_split(base64_decode($C))as$l){$L=ord($l);$m.=str_repeat
- ($f?"#":chr(32),$L&127);$f=!$f;if($L&128){$m.="\n";$f=!0;continue;}}}print(
- str_replace([chr(96),chr(37),chr(64)],[implode("\n",array_map(fn($C)=>"'".trim(
- chunk_split(str_replace("\n","",$C),80,"\n"))."',",$c)),"\n{$m}","{$s}\nQ;\n"],$s));
- ]]>
- </codeblock>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2024-12-33/2024-reflections.dj b/vhosts/blog/content/posts/2024-12-33/2024-reflections.dj
new file mode 100644
index 00000000..88b6c9b9
--- /dev/null
+++ b/vhosts/blog/content/posts/2024-12-33/2024-reflections.dj
@@ -0,0 +1,84 @@
+---
+[article]
+uuid = "d7f98354-83fc-4cf1-8769-2784f0ebb6c8"
+title = "2024幎の振り返り"
+description = "2024幎にやったこずを振り返る"
+tags = [
+]
+
+[[article.revisions]]
+date = "2025-01-02"
+remark = "公開"
+---
+{#intro}
+# はじめに
+
+ご存じのずおり、4 ず 11 ず 23 で割り切れる幎は閏幎ずいうや぀で 12 月が 33 日たである。
+1幎の振り返りを曞く猶予が平幎よりも長くなるので倧倉に郜合がよい。
+
+去幎のや぀: [/posts/2023-12-31/2023-reflections/](/posts/2023-12-31/2023-reflections/)
+
+{#conference}
+# 登壇・カンファレンス参加
+
+参加たたは登壇した勉匷䌚やカンファレンス。
+LT 等も含めお蚈 8 回の登壇をおこなった。
+たた、4぀のカンファレンスでコアスタッフたたは圓日スタッフずしお参加した。
+
+* PHP カンファレンス北海道 2024 オンラむンで参加
+* [PHP 勉匷䌚@東京 第 160 回 登壇](/slides/2024-01-24/phpstudy-tokyo-160/)
+* [YAPC::Hiroshima 2024 参加](/posts/2024-02-10/yapcjapan-2024-report/)
+* [PHPカンファレンス関西 2024 参加](/posts/2024-02-22/phpkansai-2024-report/)
+* PHPerKaigi 2024
+
+ * [登壇](/slides/2024-03-08/phperkaigi-2024/)
+ * コアスタッフずしお参加
+
+* [Ya8 2024 登壇](/slides/2024-03-15/ya8-2024/)
+* PHP カンファレンス小田原 2024
+
+ * [登壇](/slides/2024-04-13/phpcon-odawara-2024/)
+ * 圓日スタッフずしお参加
+
+* [PHP 勉匷䌚@東京 第 163 回 LT で登壇](/slides/2024-04-25/phpstudy-tokyo-163/)
+* [PHP カンファレンス銙川 2024 参加](/posts/2024-05-11/phpconkagawa-2024-report/)
+* [ScalaMatsuri 2024 参加](/posts/2024-06-19/scalamatsuri-2024-report/)
+* [PHP 勉匷䌚@東京 第 166 回 登壇](/slides/2024-07-18/phpstudy-tokyo-166/)
+* iOSDC Japan 2024 コアスタッフずしお参加
+* Nix meetup #1 参加
+* [PHP 勉匷䌚@東京 第 169 回 登壇](/slides/2024-10-30/phpstudy-tokyo-169/)
+* [玅癜ぺぱ合戊 LT で登壇](/slides/2024-11-30/cohackpp/)
+* PHP カンファレンス 2024 圓日スタッフずしお参加
+
+{#articles}
+# 曞いた蚘事
+
+今幎はこのブログに月1蚘事以䞊の蚘事を曞くずいう目暙を立おおいた。本数ずしおは 12 本以䞊あるが、10月ず11月はれロになっおしたった。
+瀟内蚘事を瀟倖向けにリラむトする䜜業を䞭々進められおいないので、2025幎は定期的に消化しおいきたい。
+
+* 瀟倖蚘事 (このブログ): 15本
+* 瀟内蚘事: 22本
+
+ * 幎間で最も蚘事を曞いた人ずしお瀟内衚地された
+
+{#coding}
+# 䜜ったもの
+
+今幎は䞻に WebAssembly ランタむムず、カンファレンスの䌁画で䜿うシステムを䜜っおいた。
+埌者のシステムでもサンドボックス化のための技術ずしお WebAssembly を甚いおいるので、今幎は WebAssembly ず戯れた䞀幎だったず蚀える。
+
+* [Waddiwasi: pure PHP で曞かれた WebAssembly ランタむム](https://github.com/nsfisis/php-waddiwasi)
+* [Albatross.PHP: PHPerKaigi 2024 のコヌドゎルフ䌁画で䜿われたシステム](https://github.com/nsfisis/phperkaigi-2024-albatross)
+* [Albatross.swift: iOSDC Japan 2024 のコヌドバトル䌁画で䜿われたシステム](https://github.com/nsfisis/iosdc-japan-2024-albatross)
+* [ReparoJSON: 文法゚ラヌを盎すだけの JSON フォヌマッタ](/posts/2024-07-19/reparojson-fix-only-json-formatter/)
+
+{#misc}
+# その他
+
+* [MN-Core Challenge #1 に参加](/posts/2024-09-28/mncore-challenge-1/)
+* ISUCON 14 に参加
+
+{#outro}
+# おわりに
+
+今幎も倧倉お䞖話になりたした。よいお幎を
diff --git a/vhosts/blog/content/posts/2024-12-33/2024-reflections.ndoc b/vhosts/blog/content/posts/2024-12-33/2024-reflections.ndoc
deleted file mode 100644
index f28c005b..00000000
--- a/vhosts/blog/content/posts/2024-12-33/2024-reflections.ndoc
+++ /dev/null
@@ -1,101 +0,0 @@
----
-[article]
-uuid = "d7f98354-83fc-4cf1-8769-2784f0ebb6c8"
-title = "2024幎の振り返り"
-description = "2024幎にやったこずを振り返る"
-tags = [
-]
-
-[[article.revisions]]
-date = "2025-01-02"
-remark = "公開"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- ご存じのずおり、4 ず 11 ず 23 で割り切れる幎は閏幎ずいうや぀で 12 月が 33 日たである。
- 1幎の振り返りを曞く猶予が平幎よりも長くなるので倧倉に郜合がよい。
- </p>
- <p>
- 去幎のや぀: <a href="/posts/2023-12-31/2023-reflections/">/posts/2023-12-31/2023-reflections/</a>
- </p>
- </section>
- <section id="conference">
- <h>登壇・カンファレンス参加</h>
- <p>
- 参加たたは登壇した勉匷䌚やカンファレンス。
- LT 等も含めお蚈 8 回の登壇をおこなった。
- たた、4぀のカンファレンスでコアスタッフたたは圓日スタッフずしお参加した。
- </p>
- <ul>
- <li>PHP カンファレンス北海道 2024 オンラむンで参加</li>
- <li><a href="/slides/2024-01-24/phpstudy-tokyo-160/">PHP 勉匷䌚@東京 第 160 回 登壇</a></li>
- <li><a href="/posts/2024-02-10/yapcjapan-2024-report/">YAPC::Hiroshima 2024 参加</a></li>
- <li><a href="/posts/2024-02-22/phpkansai-2024-report/">PHPカンファレンス関西 2024 参加</a></li>
- <li>PHPerKaigi 2024
- <ul>
- <li><a href="/slides/2024-03-08/phperkaigi-2024/">登壇</a></li>
- <li>コアスタッフずしお参加</li>
- </ul>
- </li>
- <li><a href="/slides/2024-03-15/ya8-2024/">Ya8 2024 登壇</a></li>
- <li>PHP カンファレンス小田原 2024
- <ul>
- <li><a href="/slides/2024-04-13/phpcon-odawara-2024/">登壇</a></li>
- <li>圓日スタッフずしお参加</li>
- </ul>
- </li>
- <li><a href="/slides/2024-04-25/phpstudy-tokyo-163/">PHP 勉匷䌚@東京 第 163 回 LT で登壇</a></li>
- <li><a href="/posts/2024-05-11/phpconkagawa-2024-report/">PHP カンファレンス銙川 2024 参加</a></li>
- <li><a href="/posts/2024-06-19/scalamatsuri-2024-report/">ScalaMatsuri 2024 参加</a></li>
- <li><a href="/slides/2024-07-18/phpstudy-tokyo-166/">PHP 勉匷䌚@東京 第 166 回 登壇</a></li>
- <li>iOSDC Japan 2024 コアスタッフずしお参加</li>
- <li>Nix meetup #1 参加</li>
- <li><a href="/slides/2024-10-30/phpstudy-tokyo-169/">PHP 勉匷䌚@東京 第 169 回 登壇</a></li>
- <li><a href="/slides/2024-11-30/cohackpp/">玅癜ぺぱ合戊 LT で登壇</a></li>
- <li>PHP カンファレンス 2024 圓日スタッフずしお参加</li>
- </ul>
- </section>
- <section id="articles">
- <h>曞いた蚘事</h>
- <p>
- 今幎はこのブログに月1蚘事以䞊の蚘事を曞くずいう目暙を立おおいた。本数ずしおは 12 本以䞊あるが、10月ず11月はれロになっおしたった。
- 瀟内蚘事を瀟倖向けにリラむトする䜜業を䞭々進められおいないので、2025幎は定期的に消化しおいきたい。
- </p>
- <ul>
- <li>瀟倖蚘事 (このブログ): 15本</li>
- <li>瀟内蚘事: 22本
- <ul>
- <li>幎間で最も蚘事を曞いた人ずしお瀟内衚地された</li>
- </ul>
- </li>
- </ul>
- </section>
- <section id="coding">
- <h>䜜ったもの</h>
- <p>
- 今幎は䞻に WebAssembly ランタむムず、カンファレンスの䌁画で䜿うシステムを䜜っおいた。
- 埌者のシステムでもサンドボックス化のための技術ずしお WebAssembly を甚いおいるので、今幎は WebAssembly ず戯れた䞀幎だったず蚀える。
- </p>
- <ul>
- <li><a href="https://github.com/nsfisis/php-waddiwasi">Waddiwasi: pure PHP で曞かれた WebAssembly ランタむム</a></li>
- <li><a href="https://github.com/nsfisis/phperkaigi-2024-albatross">Albatross.PHP: PHPerKaigi 2024 のコヌドゎルフ䌁画で䜿われたシステム</a></li>
- <li><a href="https://github.com/nsfisis/iosdc-japan-2024-albatross">Albatross.swift: iOSDC Japan 2024 のコヌドバトル䌁画で䜿われたシステム</a></li>
- <li><a href="/posts/2024-07-19/reparojson-fix-only-json-formatter/">ReparoJSON: 文法゚ラヌを盎すだけの JSON フォヌマッタ</a></li>
- </ul>
- </section>
- <section id="misc">
- <h>その他</h>
- <ul>
- <li><a href="/posts/2024-09-28/mncore-challenge-1/">MN-Core Challenge #1 に参加</a></li>
- <li>ISUCON 14 に参加</li>
- </ul>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- 今幎も倧倉お䞖話になりたした。よいお幎を
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2025-01-08/phperkaigi-2023-tokens-q1.dj b/vhosts/blog/content/posts/2025-01-08/phperkaigi-2023-tokens-q1.dj
new file mode 100644
index 00000000..c3a5eb49
--- /dev/null
+++ b/vhosts/blog/content/posts/2025-01-08/phperkaigi-2023-tokens-q1.dj
@@ -0,0 +1,350 @@
+---
+[article]
+uuid = "ce8f20e8-c79f-48f8-982d-53edd4d20483"
+title = "PHPerKaigi 2023 トヌクン問題解説 (1/5)"
+description = "PHPerKaigi 2023 でデゞタルサヌカス株匏䌚瀟から出題した問題を解説する。党5問䞭の第1問。"
+tags = [
+ "conference",
+ "php",
+ "phperkaigi",
+ "piet",
+]
+
+[[article.revisions]]
+date = "2025-01-08"
+remark = "公開"
+
+[[article.revisions]]
+date = "2025-01-11"
+remark = "読みやすさのため䞀郚の文蚀を調敎"
+---
+{#intro}
+# はじめに
+
+::: note
+これは PHPerKaigi 2023 の蚘事です。今は 2025 幎ですが、PHPerKaigi 2023 の蚘事です。
+:::
+
+2023-03-23 から 2023-03-25 にかけお開催された [PHPerKaigi 2023](https://phperkaigi.jp/2023/) では、PHPer チャレンゞずいう䌁画がおこなわれた。
+PHPer チャレンゞずは、スポンサヌのパンフレットやカンファレンス䌚堎などから「#」蚘号で始たる文字列を集め、景品などを埗るずいう䌁画である。
+この文字列は「PHPer トヌクン」ず呌ばれおいる。匊瀟 [デゞタルサヌカス株匏䌚瀟](https://www.dgcircus.com/) からは、トヌクン問題ずいう圢で、PHP に関する問題を解くず PHPer トヌクンが埗られるようになっおいる問題を出題した。
+
+[PHPerKaigi 2023 の参加レポ](/posts/2023-04-04/phperkaigi-2023-report/) でも曞いたずおり、この幎のトヌクン問題は「昚幎の PHPerKaigi 2022 が終わった段階から䜜り始め、玄半幎かけお制䜜」された。
+PHPerKaigi 圓日も [PHPer チャレンゞ解説セッション](/slides/2023-03-25/phperkaigi-2023-tokens/) ずいう圢で解説の機䌚を頂いたのだが、せっかく時間をかけお䜜題したので蚘事の圢でも残しおおこうず思う。
+
+この蚘事では、党5問ある䞭の第1問に぀いお解説する。他の問題に぀いおは以䞋のリンクを参照のこず。
+
+1. [第1問 (この蚘事)](/posts/2025-01-08/phperkaigi-2023-tokens-q1/)
+1. 第2問 (TODO: 執筆䞭)
+1. 第3問 (TODO: 執筆䞭)
+1. 第4問 (TODO: 執筆䞭)
+1. 第5問 (TODO: 執筆䞭)
+
+それぞれの問題はこちらの GitHub リポゞトリ ( [nsfisis/PHPerKaigi2023-tokens](https://github.com/nsfisis/PHPerKaigi2023-tokens) ) からも閲芧できる。
+
+{#quiz}
+# Q1: An Art of Computer Programming
+
+第1問『An Art of Computer Programming』はこちら。
+
+![党䜓がQRコヌドになっおおり、䞭倮には小さな文字で「Password is one of the PHPer tokens.」ず曞かれおいる](/posts/2025-01-08/phperkaigi-2023-tokens-q1/Q1.png)
+
+{#how-to-solve}
+# 解き方
+
+たずはトヌクンを埗る方法を解説抜きで説明する。次のように実行する。
+
+```
+$ echo "#iwillblog" | php Q1.png >/dev/null
+```
+
+無事に実行できおいれば「#ModernPHPisStaticallyTypedLanguage」ずいうトヌクンが埗られる。
+
+{#commentary}
+# 解説
+
+{#read-as-image}
+## 画像ずしお解釈する
+
+たずは玠盎に画像ずしお芋おみよう。
+党䜓は QR コヌドになっおいる。適圓な QR コヌドリヌダで読み蟌むず、次のようなテキストが衚瀺されるはずだ。
+
+```
+Guess password. $ echo "password" | php Q1.png >/dev/null
+```
+
+メッセヌゞは、この画像の実行方法ずこの問題でやるべきこず (パスワヌドの掚枬) を瀺しおいる。
+
+次に QR コヌドの䞭倮郚に目を向けるず、小さな文字で「Password is one of the PHPer tokens.」ず曞かれおいるのがわかる。
+他の PHPer トヌクンの䞭から適切な1぀を芋぀けだし、「パスワヌド」ずしお枡すこずで答えずなる PHPer トヌクンが埗られるずいうわけだ。
+
+{#password}
+## パスワヌド
+
+䞍正なパスワヌドを䜿っお実行しおみるず、次のような゚ラヌメッセヌゞが衚瀺される。
+
+```
+$ echo "foo" | php Q1.png >/dev/null
+401 Unauthorized
+```
+
+すでに [「解き方」の節](#section--how-to-solve) で瀺したように、パスワヌドである PHPer トヌクンは「#iwillblog」である。これを䞎えお実行するず正解のトヌクンが埗られる。
+
+このパスワヌドの遞択にはずある事情がある。
+今回の問題の䜜問は前回の開催 (PHPerKaigi 2022) 盎埌からスタヌトしおおり、この時点では PHPerKaigi 2023 で登録される PHPer トヌクンにどのようなものがあるかはたったくわからない状態であった。
+䜜問䜜業を早期に終わらせるには、次回開催でも確実に䜿われるであろう定番のトヌクンを予枬しお遞ぶ必芁があったのだ。
+かくしお、私が知る限り毎回登堎しおいるトヌクンである「#iwillblog」に癜矜の矢が立おられた。
+
+なお、解いおくださった方の䞭には、先頭の「#」を入力せずに䜕床も詊しおしたい答えが埗られずじたいになった方もいらっしゃるようだった。
+問題を眮いおいたリポゞトリにヒントずしおパスワヌドのトヌクンが「i」で始たるず曞いおいたのだが、これが意図せずミスリヌドになっおしたった。
+これは私のミスである。
+
+{#png-steganography}
+## PNG ステガノグラフィ
+
+QR コヌドも蚀っおいるように、このファむルは PNG 画像であるにもかかわらず PHP で実行するこずができる。なぜこのようなこずが可胜なのか。
+
+PNG 画像のフォヌマットは、次のようになっおいる。
+
+1. マゞックナンバヌなど
+1. PNG ヘッダ (`IHDR` チャンク)
+1. 実際の画像デヌタ (`IDAT` チャンク)
+1. PNG フッタ (`IEND` チャンク)
+
+PNG フッタの埌ろにあるデヌタは、画像ビュヌアには解釈されず、画像の衚瀺には圱響を䞎えない。したがっお、PNG フッタの埌ろには任意のデヌタを埋め蟌むこずができる。
+
+さお、PHP には、PHP プログラムの始たりを瀺すための PHP タグ (`&lt;?php` たたは `&lt;?`) がある。
+CLI で実行する堎合、PHP タグよりも前にあるデヌタは暙準出力ぞそのたた出力される。
+
+この画像ファむルは次のような構造になっおいた。
+
+1. マゞックナンバヌなど
+1. PNG ヘッダ (`IHDR` チャンク)
+1. 実際の画像デヌタ (`IDAT` チャンク)
+1. PNG フッタ (`IEND` チャンク)
+1. *PHP タグ (`&lt;?php`)*
+1. *通垞の PHP ゜ヌスコヌド*
+
+PNG ファむルずしお読むずきは PNG フッタ以降は無芖され、PHP スクリプトずしお読むずきは PHP タグ以前が無芖されるずいう仕掛けである。
+
+`strings` コマンドを䜿うず、隠されたデヌタを簡単に閲芧できる。
+
+```
+IHDR
+-HHc
+<PLTE
+IDATx
+IEND
+<?php
+error_reporting(-1);
+$b = unpack('C*', file_get_contents(__FILE__));
+$w = $b[20]+2;
+$h = $b[24]+2;
+// (以䞋略)
+```
+
+`IHDR` や `IEND` が PNG 画像の䞀郚で、`&lt;?php` からが実際のプログラムになっおいる。
+もちろんこれを PHP プログラムずしお動かすず、PHP タグより前にある PNG 画像ずしおのデヌタはそのたた暙準出力ぞず出力されおしたう。
+それを防ぐため、QR コヌドを読み蟌んだずきの実行方法
+
+```
+Guess password. $ echo "password" | php Q1.png >/dev/null
+```
+
+には暙準出力を捚おるよう `&gt;/dev/null` ず指定されおいる。
+
+なお、このように PNG 画像などに本来のデヌタずは異なる別のデヌタを隠すこずを「ステガノグラフィ」( [Wikipedia「ステガノグラフィヌ」](https://ja.wikipedia.org/wiki/%E3%82%B9%E3%83%86%E3%82%AC%E3%83%8E%E3%82%B0%E3%83%A9%E3%83%95%E3%82%A3%E3%83%BC) ) ず呌ぶ。
+
+{#php-program}
+## 実行される PHP プログラム
+
+画像の正䜓がわかったずころで、画像に隠されおいた PHP プログラムに぀いお芋おいこう。
+先ほどは䞀郚しか蚘茉しなかったので、党䜓を茉せる。
+なお、ある皋床ゎルフしながら曞いたので、空癜こそ残しおいるものの可読性は非垞に䜎いこずず思う。
+
+```php
+<?php
+error_reporting(-1);
+$b = unpack('C*', file_get_contents(__FILE__));
+$w = $b[20]+2;
+$h = $b[24]+2;
+$cs = [];
+for ($y = 0; $y < $h; $y++)
+ for ($x = 0; $x < $w; $x++)
+ $cs[$y*$w + $x] = ($x*$y === 0 || $x === $w-1 || $y === $h-1)
+ ? 0
+ : $b[122+($y-1)*($w-1)+$x-1];
+$i = stream_isatty(STDIN)
+ ? []
+ : array_map(ord(...), str_split(trim((string) fgets(STDIN))));
+$m = [];
+$pc = 1*$w+1;
+$dp = 0;
+$cc = 1;
+$c0 = 1;
+$b = 0;
+$ns = 0;
+$o = '';
+while (true) {
+ $ns++;
+ if ($ns > 1e5) {
+ echo "infinite loop detected\n";
+ break;
+ $c1 = $cs[$pc];
+ $y = (6 + intdiv($c1-2, 3) - intdiv($c0-2, 3)) % 6;
+ $x = (3 + $c1%3 - $c0%3) % 3;
+ match (($c0 !== 1) * ($c1 !== 1) * ($y*3 + $x)) {
+ 1 => $m[] = $b,
+ 2 => array_pop($m),
+ 3 => $m[] = array_pop($m) + array_pop($m),
+ 4 => $m[] = (fn($x, $y) => $y - $x)(array_pop($m), array_pop($m)),
+ 5 => $m[] = array_pop($m) * array_pop($m),
+ 8 => $m[] = array_pop($m) === 0 ? 1 : 0,
+ 11 => $cc *= pow(-1, array_pop($m)),
+ 12 => $m[] = $m[count($m)-1],
+ 13 => $m = (fn($n, $d, $m, $l) => [
+ ...array_slice($m, 0, $l-$d),
+ ...array_reverse([
+ ...array_reverse(array_slice($m, $l-$d, $d-$n)),
+ ...array_reverse(array_slice($m, $l-$n)),
+ ]),
+ ])(array_pop($m), array_pop($m), $m, count($m)),
+ 15 => !empty($i) and $m[] = array_shift($i),
+ 16 => $o .= sprintf('%d', array_pop($m)),
+ 17 => $o .= sprintf('%c', array_pop($m)),
+ default => 'nop',
+ };
+ $c0 = $c1;
+ for ($j = 0; $j < 8; $j++) {
+ $v = [];
+ if ($c1 === 1) {
+ $x = $pc % $w;
+ $y = intdiv($pc, $w);
+ $e = [($y+1)*$w-1, ($h-1)*$w+$x, $y*$w, $x][$dp];
+ $z = [1, $w, -1, -$w][$dp];
+ for ($ep = $pc; $ep !== $e; $ep += $z)
+ if ($cs[$ep] !== 1) break;
+ $ep -= $z;
+ $pc = $ep;
+ } else {
+ $q = [$pc];
+ $ep = $pc;
+ while (!empty($q)) {
+ $qq = array_pop($q);
+ $v[$qq] = true;
+ foreach ([$qq+1, $qq+$w, $qq-1, $qq-$w] as $qp) {
+ if ($cs[$qp] !== $c1) continue;
+ if (isset($v[$qp])) continue;
+ $q[] = $qp;
+ $qx = $qp % $w;
+ $qy = intdiv($qp, $w);
+ $x = $ep % $w;
+ $y = intdiv($ep, $w);
+ if (
+ ($dp === 0 && ($x < $qx || ($x === $qx && ($y<=>$qy) === $cc)))
+ || ($dp === 1 && ($y < $qy || ($y === $qy && ($qx<=>$x) === $cc)))
+ || ($dp === 2 && ($qx < $x || ($qx === $x && ($qy<=>$y) === $cc)))
+ || ($dp === 3 && ($qy < $y || ($qy === $y && ($x<=>$qx) === $cc)))
+ )
+ $ep = $qp;
+ }
+ }
+ }
+ $np = $ep + [1, $w, -1, -$w][$dp];
+ if ($cs[$np] !== 0) {
+ $b = count(array_keys($v));
+ $pc = $np;
+ break;
+ }
+ if ($j === 7) break 2;
+ if ($j % 2 === 0) $cc = -$cc;
+ if ($j % 2 === 1) $dp = ($dp+1) % 4;
+// The original Piet image is wrong: it outputs 403 error for invalid passwords.
+// Failure of authentication should be notified by 401, not 403.
+// I noticed that one month before PHPerKaigi, but I could not read or write (paint)
+// Piet any longer at that time.
+fwrite(STDERR, str_replace('403 Forbidden', '401 Unauthorized', $o));
+```
+
+これは䞀䜓なんなのか。ずばり、難解プログラミング蚀語の䞀぀ Piet のむンタプリタである。
+Piet はピ゚ト・モンドリアン (『赀・青・黄のコンポゞション』などで知られる抜象画家) の䜜品にむンスピレヌションを受けお䜜られた、画像を゜ヌスコヌドずするプログラミング蚀語である。
+むンタプリタは画像の各ピクセルの䞊を進みながら、色等に応じお特定の凊理をおこなっおいく。
+ここでは詳しい蚀語仕様に぀いおは解説しないので、気になる方は [Wikipedia の蚘事「Piet」](https://ja.wikipedia.org/wiki/Piet) などを参照しおほしい。
+
+プログラムの冒頭にあるこの箇所
+
+```php
+$b = unpack('C*', file_get_contents(__FILE__));
+```
+
+で `__FILE__` ぀たりこの画像ファむルを読み蟌んでいる。
+先ほど Piet は画像を゜ヌスコヌドにしおいるず説明した。
+そう、今回の問題の画像ファむル `Q1.png` は、PHP 補 Piet むンタプリタであるず同時に、Piet の゜ヌスコヌド画像でもあるのだ。
+QR コヌド䞭倮のカラフルな郚分が Piet の呜什になっおいる。
+
+{#piet-source-code}
+## Piet の゜ヌスコヌド
+
+さお、Piet でどのようなコヌドが曞かれお (いや、描かれお) いるのかを解説したいずころだが、今の私にはできそうにない。
+ずいうのも、すでに述べたように Piet は「難解プログラミング蚀語」である。
+およそ人が描いたり読んだりするようには䜜られおいない。性質ずしおは、パズルに近い代物である。
+
+ずいうわけで、ここではあらたしを説明するだけでご容赊いただきたい。
+それぞれの郚分はおおよそ次のようなこずをやっおいる (再怜蚌・再読解はしおいないので倧嘘かもしれない)。
+
+* 巊䞊: 入力受け付け
+
+ * 暙準入力から1文字ず぀読み蟌み、入力がなくなるたでスタックに積む。倚分。
+
+* 䞊蟺、右蟺: パスワヌドの怜蚌
+
+ * 入力がパスワヌドず䞀臎するか (= `#iwillblog` かどうか) を調べる。倚分。
+
+* 䞋蟺、巊蟺、䞊蟺の3列目、右蟺の3列目、䞋蟺の2列目: トヌクンの出力
+
+ * パスワヌドず䞀臎しおいればここに飛んでくる。正解のトヌクンを出力する。倚分。
+
+* 右蟺の2列目、䞊蟺の2列目: 䞍正解のメッセヌゞ出力
+
+ * パスワヌドず䞀臎しおいなければここに飛んでくる。䞍正解のずきのメッセヌゞを出力する。倚分。
+
+ずころで、先ほど掲茉した Piet のむンタプリタの゜ヌスコヌド末尟には次のような箇所がある。
+
+```php
+// The original Piet image is wrong: it outputs 403 error for invalid passwords.
+// Failure of authentication should be notified by 401, not 403.
+// I noticed that one month before PHPerKaigi, but I could not read or write (paint)
+// Piet any longer at that time.
+fwrite(STDERR, str_replace('403 Forbidden', '401 Unauthorized', $o));
+```
+
+コメントにも曞かれおいるが、この Piet の゜ヌスコヌド画像には誀りがあった。
+本来 HTTP のステヌタスコヌドを真䌌るのなら、認蚌の倱敗には 401 を返さなければならない。
+しかし、Piet の゜ヌスは 403 を返すように曞いおしたっおいた。
+そのこずに私が気付いたのは PHPerKaigi 2023 が開催されるひず月前で、その時点で私はこの Piet の゜ヌスコヌドを (ちょうどこの蚘事でそうなっおいるのず同じように) 読解できなくなっおいた。
+さらに悪いこずに、正しいメッセヌゞ「401 Unauthorized」は元の「403 Forbidden」よりも3文字長い。
+3文字出力が長くなるずいうこずは、それだけ Piet で塗るべきピクセルが増えるこずを意味する。
+もはや3文字远加で出力するだけの䜙癜はこの画像に残されおいなかった (ず思う。腕ききの Piet プログラマならできるかもしれないので挑戊しおみおほしい)。
+
+これを解決するために私が遞んだのは、むンタプリタを改造し、本来のメッセヌゞずは異なるメッセヌゞを無理やり出力させお垳尻を合わせるこずだった。
+そういうわけでこの Piet むンタプリタは完党な Piet むンタプリタではなく、「403 Forbidden」ずいうテキストを絶察に出力できない。
+
+{#misc}
+## その他小ネタ
+
+ここたでで問題の栞心郚分は説明し終えたので、ここからは残った小ネタを玹介しおおく。
+
+この問題のタむトル『An Art of Computer Programming』は、ドナルド・クヌヌスの『The Art of Computer Programming』をパロディしたものである。
+
+この問題で埗られるトヌクン「#ModernPHPisStaticallyTypedLanguage」は特に元ネタがあるわけではない。圓然のような顔で嘘を䞻匵したかったのでこうなった。
+
+{#outro}
+# おわりに
+
+この問題の自己評䟡はこちら。
+問題の出題順はおおよそ䜜成した順になっおいるのだが、そのせいで難易床高めの問題が1問目に配眮されおしたった。
+これは反省点の䞀぀である。
+
+* 難しさ: ★★★★
+* お気に入り床: ★★
+* 鮮やかさ: ★★★★★★★
diff --git a/vhosts/blog/content/posts/2025-01-08/phperkaigi-2023-tokens-q1.ndoc b/vhosts/blog/content/posts/2025-01-08/phperkaigi-2023-tokens-q1.ndoc
deleted file mode 100644
index ede3fdfb..00000000
--- a/vhosts/blog/content/posts/2025-01-08/phperkaigi-2023-tokens-q1.ndoc
+++ /dev/null
@@ -1,406 +0,0 @@
----
-[article]
-uuid = "ce8f20e8-c79f-48f8-982d-53edd4d20483"
-title = "PHPerKaigi 2023 トヌクン問題解説 (1/5)"
-description = "PHPerKaigi 2023 でデゞタルサヌカス株匏䌚瀟から出題した問題を解説する。党5問䞭の第1問。"
-tags = [
- "conference",
- "php",
- "phperkaigi",
- "piet",
-]
-
-[[article.revisions]]
-date = "2025-01-08"
-remark = "公開"
-
-[[article.revisions]]
-date = "2025-01-11"
-remark = "読みやすさのため䞀郚の文蚀を調敎"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <note>
- これは PHPerKaigi 2023 の蚘事です。今は 2025 幎ですが、PHPerKaigi 2023 の蚘事です。
- </note>
- <p>
- 2023-03-23 から 2023-03-25 にかけお開催された <a href="https://phperkaigi.jp/2023/">PHPerKaigi 2023</a> では、PHPer チャレンゞずいう䌁画がおこなわれた。
- PHPer チャレンゞずは、スポンサヌのパンフレットやカンファレンス䌚堎などから「#」蚘号で始たる文字列を集め、景品などを埗るずいう䌁画である。
- この文字列は「PHPer トヌクン」ず呌ばれおいる。匊瀟<a href="https://www.dgcircus.com/">デゞタルサヌカス株匏䌚瀟</a>からは、トヌクン問題ずいう圢で、PHP に関する問題を解くず PHPer トヌクンが埗られるようになっおいる問題を出題した。
- </p>
- <p>
- <a href="/posts/2023-04-04/phperkaigi-2023-report/">PHPerKaigi 2023 の参加レポ</a> でも曞いたずおり、この幎のトヌクン問題は「昚幎の PHPerKaigi 2022 が終わった段階から䜜り始め、玄半幎かけお制䜜」された。
- PHPerKaigi 圓日も <a href="/slides/2023-03-25/phperkaigi-2023-tokens/">PHPer チャレンゞ解説セッション</a> ずいう圢で解説の機䌚を頂いたのだが、せっかく時間をかけお䜜題したので蚘事の圢でも残しおおこうず思う。
- </p>
- <p>
- この蚘事では、党5問ある䞭の第1問に぀いお解説する。他の問題に぀いおは以䞋のリンクを参照のこず。
- </p>
- <ol>
- <li><a href="/posts/2025-01-08/phperkaigi-2023-tokens-q1/">第1問 (この蚘事)</a></li>
- <li>第2問 (TODO: 執筆䞭)</li>
- <li>第3問 (TODO: 執筆䞭)</li>
- <li>第4問 (TODO: 執筆䞭)</li>
- <li>第5問 (TODO: 執筆䞭)</li>
- </ol>
- <p>
- それぞれの問題はこちらの GitHub リポゞトリ (<a href="https://github.com/nsfisis/PHPerKaigi2023-tokens">nsfisis/PHPerKaigi2023-tokens</a>) からも閲芧できる。
- </p>
- </section>
- <section id="quiz">
- <h>Q1: An Art of Computer Programming</h>
- <p>
- 第1問『An Art of Computer Programming』はこちら。
- </p>
- <img src="/posts/2025-01-08/phperkaigi-2023-tokens-q1/Q1.png" alt="党䜓がQRコヌドになっおおり、䞭倮には小さな文字で「Password is one of the PHPer tokens.」ず曞かれおいる"></img>
- </section>
- <section id="how-to-solve">
- <h>解き方</h>
- <p>
- たずはトヌクンを埗る方法を解説抜きで説明する。次のように実行する。
- </p>
- <codeblock>
- <![CDATA[
- $ echo "#iwillblog" | php Q1.png >/dev/null
- ]]>
- </codeblock>
- <p>
- 無事に実行できおいれば「#ModernPHPisStaticallyTypedLanguage」ずいうトヌクンが埗られる。
- </p>
- </section>
- <section id="commentary">
- <h>解説</h>
- <section id="read-as-image">
- <h>画像ずしお解釈する</h>
- <p>
- たずは玠盎に画像ずしお芋おみよう。
- 党䜓は QR コヌドになっおいる。適圓な QR コヌドリヌダで読み蟌むず、次のようなテキストが衚瀺されるはずだ。
- </p>
- <codeblock>
- <![CDATA[
- Guess password. $ echo "password" | php Q1.png >/dev/null
- ]]>
- </codeblock>
- <p>
- メッセヌゞは、この画像の実行方法ずこの問題でやるべきこず (パスワヌドの掚枬) を瀺しおいる。
- </p>
- <p>
- 次に QR コヌドの䞭倮郚に目を向けるず、小さな文字で「Password is one of the PHPer tokens.」ず曞かれおいるのがわかる。
- 他の PHPer トヌクンの䞭から適切な1぀を芋぀けだし、「パスワヌド」ずしお枡すこずで答えずなる PHPer トヌクンが埗られるずいうわけだ。
- </p>
- </section>
- <section id="password">
- <h>パスワヌド</h>
- <p>
- 䞍正なパスワヌドを䜿っお実行しおみるず、次のような゚ラヌメッセヌゞが衚瀺される。
- </p>
- <codeblock>
- <![CDATA[
- $ echo "foo" | php Q1.png >/dev/null
- 401 Unauthorized
- ]]>
- </codeblock>
- <p>
- すでに<a href="#section--how-to-solve">「解き方」の節</a>で瀺したように、パスワヌドである PHPer トヌクンは「#iwillblog」である。これを䞎えお実行するず正解のトヌクンが埗られる。
- </p>
- <p>
- このパスワヌドの遞択にはずある事情がある。
- 今回の問題の䜜問は前回の開催 (PHPerKaigi 2022) 盎埌からスタヌトしおおり、この時点では PHPerKaigi 2023 で登録される PHPer トヌクンにどのようなものがあるかはたったくわからない状態であった。
- 䜜問䜜業を早期に終わらせるには、次回開催でも確実に䜿われるであろう定番のトヌクンを予枬しお遞ぶ必芁があったのだ。
- かくしお、私が知る限り毎回登堎しおいるトヌクンである「#iwillblog」に癜矜の矢が立おられた。
- </p>
- <p>
- なお、解いおくださった方の䞭には、先頭の「#」を入力せずに䜕床も詊しおしたい答えが埗られずじたいになった方もいらっしゃるようだった。
- 問題を眮いおいたリポゞトリにヒントずしおパスワヌドのトヌクンが「i」で始たるず曞いおいたのだが、これが意図せずミスリヌドになっおしたった。
- これは私のミスである。
- </p>
- </section>
- <section id="png-steganography">
- <h>PNG ステガノグラフィ</h>
- <p>
- QR コヌドも蚀っおいるように、このファむルは PNG 画像であるにもかかわらず PHP で実行するこずができる。なぜこのようなこずが可胜なのか。
- </p>
- <p>
- PNG 画像のフォヌマットは、次のようになっおいる。
- </p>
- <ol>
- <li>マゞックナンバヌなど</li>
- <li>PNG ヘッダ (<code>IHDR</code> チャンク)</li>
- <li>実際の画像デヌタ (<code>IDAT</code> チャンク)</li>
- <li>PNG フッタ (<code>IEND</code> チャンク)</li>
- </ol>
- <p>
- PNG フッタの埌ろにあるデヌタは、画像ビュヌアには解釈されず、画像の衚瀺には圱響を䞎えない。したがっお、PNG フッタの埌ろには任意のデヌタを埋め蟌むこずができる。
- </p>
- <p>
- さお、PHP には、PHP プログラムの始たりを瀺すための PHP タグ (<code>&lt;?php</code> たたは <code>&lt;?</code>) がある。
- CLI で実行する堎合、PHP タグよりも前にあるデヌタは暙準出力ぞそのたた出力される。
- </p>
- <p>
- この画像ファむルは次のような構造になっおいた。
- </p>
- <ol>
- <li>マゞックナンバヌなど</li>
- <li>PNG ヘッダ (<code>IHDR</code> チャンク)</li>
- <li>実際の画像デヌタ (<code>IDAT</code> チャンク)</li>
- <li>PNG フッタ (<code>IEND</code> チャンク)</li>
- <li><strong>PHP タグ (<code>&lt;?php</code>)</strong></li>
- <li><strong>通垞の PHP ゜ヌスコヌド</strong></li>
- </ol>
- <p>
- PNG ファむルずしお読むずきは PNG フッタ以降は無芖され、PHP スクリプトずしお読むずきは PHP タグ以前が無芖されるずいう仕掛けである。
- </p>
- <p>
- <code>strings</code> コマンドを䜿うず、隠されたデヌタを簡単に閲芧できる。
- </p>
- <codeblock>
- <![CDATA[
- IHDR
- -HHc
- <PLTE
- IDATx
- IEND
- <?php
- error_reporting(-1);
- $b = unpack('C*', file_get_contents(__FILE__));
- $w = $b[20]+2;
- $h = $b[24]+2;
- // (以䞋略)
- ]]>
- </codeblock>
- <p>
- <code>IHDR</code> や <code>IEND</code> が PNG 画像の䞀郚で、<code>&lt;?php</code> からが実際のプログラムになっおいる。
- もちろんこれを PHP プログラムずしお動かすず、PHP タグより前にある PNG 画像ずしおのデヌタはそのたた暙準出力ぞず出力されおしたう。
- それを防ぐため、QR コヌドを読み蟌んだずきの実行方法
- </p>
- <codeblock>
- <![CDATA[
- Guess password. $ echo "password" | php Q1.png >/dev/null
- ]]>
- </codeblock>
- <p>
- には暙準出力を捚おるよう <code>&gt;/dev/null</code> ず指定されおいる。
- </p>
- <p>
- なお、このように PNG 画像などに本来のデヌタずは異なる別のデヌタを隠すこずを「ステガノグラフィ」(<a href="https://ja.wikipedia.org/wiki/%E3%82%B9%E3%83%86%E3%82%AC%E3%83%8E%E3%82%B0%E3%83%A9%E3%83%95%E3%82%A3%E3%83%BC">Wikipedia「ステガノグラフィヌ」</a>) ず呌ぶ。
- </p>
- </section>
- <section id="php-program">
- <h>実行される PHP プログラム</h>
- <p>
- 画像の正䜓がわかったずころで、画像に隠されおいた PHP プログラムに぀いお芋おいこう。
- 先ほどは䞀郚しか蚘茉しなかったので、党䜓を茉せる。
- なお、ある皋床ゎルフしながら曞いたので、空癜こそ残しおいるものの可読性は非垞に䜎いこずず思う。
- </p>
- <codeblock language="php">
- <![CDATA[
- <?php
- error_reporting(-1);
- $b = unpack('C*', file_get_contents(__FILE__));
- $w = $b[20]+2;
- $h = $b[24]+2;
- $cs = [];
- for ($y = 0; $y < $h; $y++)
- for ($x = 0; $x < $w; $x++)
- $cs[$y*$w + $x] = ($x*$y === 0 || $x === $w-1 || $y === $h-1)
- ? 0
- : $b[122+($y-1)*($w-1)+$x-1];
- $i = stream_isatty(STDIN)
- ? []
- : array_map(ord(...), str_split(trim((string) fgets(STDIN))));
- $m = [];
- $pc = 1*$w+1;
- $dp = 0;
- $cc = 1;
- $c0 = 1;
- $b = 0;
- $ns = 0;
- $o = '';
- while (true) {
- $ns++;
- if ($ns > 1e5) {
- echo "infinite loop detected\n";
- break;
- $c1 = $cs[$pc];
- $y = (6 + intdiv($c1-2, 3) - intdiv($c0-2, 3)) % 6;
- $x = (3 + $c1%3 - $c0%3) % 3;
- match (($c0 !== 1) * ($c1 !== 1) * ($y*3 + $x)) {
- 1 => $m[] = $b,
- 2 => array_pop($m),
- 3 => $m[] = array_pop($m) + array_pop($m),
- 4 => $m[] = (fn($x, $y) => $y - $x)(array_pop($m), array_pop($m)),
- 5 => $m[] = array_pop($m) * array_pop($m),
- 8 => $m[] = array_pop($m) === 0 ? 1 : 0,
- 11 => $cc *= pow(-1, array_pop($m)),
- 12 => $m[] = $m[count($m)-1],
- 13 => $m = (fn($n, $d, $m, $l) => [
- ...array_slice($m, 0, $l-$d),
- ...array_reverse([
- ...array_reverse(array_slice($m, $l-$d, $d-$n)),
- ...array_reverse(array_slice($m, $l-$n)),
- ]),
- ])(array_pop($m), array_pop($m), $m, count($m)),
- 15 => !empty($i) and $m[] = array_shift($i),
- 16 => $o .= sprintf('%d', array_pop($m)),
- 17 => $o .= sprintf('%c', array_pop($m)),
- default => 'nop',
- };
- $c0 = $c1;
- for ($j = 0; $j < 8; $j++) {
- $v = [];
- if ($c1 === 1) {
- $x = $pc % $w;
- $y = intdiv($pc, $w);
- $e = [($y+1)*$w-1, ($h-1)*$w+$x, $y*$w, $x][$dp];
- $z = [1, $w, -1, -$w][$dp];
- for ($ep = $pc; $ep !== $e; $ep += $z)
- if ($cs[$ep] !== 1) break;
- $ep -= $z;
- $pc = $ep;
- } else {
- $q = [$pc];
- $ep = $pc;
- while (!empty($q)) {
- $qq = array_pop($q);
- $v[$qq] = true;
- foreach ([$qq+1, $qq+$w, $qq-1, $qq-$w] as $qp) {
- if ($cs[$qp] !== $c1) continue;
- if (isset($v[$qp])) continue;
- $q[] = $qp;
- $qx = $qp % $w;
- $qy = intdiv($qp, $w);
- $x = $ep % $w;
- $y = intdiv($ep, $w);
- if (
- ($dp === 0 && ($x < $qx || ($x === $qx && ($y<=>$qy) === $cc)))
- || ($dp === 1 && ($y < $qy || ($y === $qy && ($qx<=>$x) === $cc)))
- || ($dp === 2 && ($qx < $x || ($qx === $x && ($qy<=>$y) === $cc)))
- || ($dp === 3 && ($qy < $y || ($qy === $y && ($x<=>$qx) === $cc)))
- )
- $ep = $qp;
- }
- }
- }
- $np = $ep + [1, $w, -1, -$w][$dp];
- if ($cs[$np] !== 0) {
- $b = count(array_keys($v));
- $pc = $np;
- break;
- }
- if ($j === 7) break 2;
- if ($j % 2 === 0) $cc = -$cc;
- if ($j % 2 === 1) $dp = ($dp+1) % 4;
- // The original Piet image is wrong: it outputs 403 error for invalid passwords.
- // Failure of authentication should be notified by 401, not 403.
- // I noticed that one month before PHPerKaigi, but I could not read or write (paint)
- // Piet any longer at that time.
- fwrite(STDERR, str_replace('403 Forbidden', '401 Unauthorized', $o));
- ]]>
- </codeblock>
- <p>
- これは䞀䜓なんなのか。ずばり、難解プログラミング蚀語の䞀぀ Piet のむンタプリタである。
- Piet はピ゚ト・モンドリアン (『赀・青・黄のコンポゞション』などで知られる抜象画家) の䜜品にむンスピレヌションを受けお䜜られた、画像を゜ヌスコヌドずするプログラミング蚀語である。
- むンタプリタは画像の各ピクセルの䞊を進みながら、色等に応じお特定の凊理をおこなっおいく。
- ここでは詳しい蚀語仕様に぀いおは解説しないので、気になる方は <a href="https://ja.wikipedia.org/wiki/Piet">Wikipedia の蚘事「Piet」</a> などを参照しおほしい。
- </p>
- <p>
- プログラムの冒頭にあるこの箇所
- </p>
- <codeblock language="php">
- <![CDATA[
- $b = unpack('C*', file_get_contents(__FILE__));
- ]]>
- </codeblock>
- <p>
- で <code>__FILE__</code> ぀たりこの画像ファむルを読み蟌んでいる。
- 先ほど Piet は画像を゜ヌスコヌドにしおいるず説明した。
- そう、今回の問題の画像ファむル <code>Q1.png</code> は、PHP 補 Piet むンタプリタであるず同時に、Piet の゜ヌスコヌド画像でもあるのだ。
- QR コヌド䞭倮のカラフルな郚分が Piet の呜什になっおいる。
- </p>
- </section>
- <section id="piet-source-code">
- <h>Piet の゜ヌスコヌド</h>
- <p>
- さお、Piet でどのようなコヌドが曞かれお (いや、描かれお) いるのかを解説したいずころだが、今の私にはできそうにない。
- ずいうのも、すでに述べたように Piet は「難解プログラミング蚀語」である。
- およそ人が描いたり読んだりするようには䜜られおいない。性質ずしおは、パズルに近い代物である。
- </p>
- <p>
- ずいうわけで、ここではあらたしを説明するだけでご容赊いただきたい。
- それぞれの郚分はおおよそ次のようなこずをやっおいる (再怜蚌・再読解はしおいないので倧嘘かもしれない)。
- </p>
- <ul>
- <li>巊䞊: 入力受け付け
- <ul>
- <li>暙準入力から1文字ず぀読み蟌み、入力がなくなるたでスタックに積む。倚分。</li>
- </ul>
- </li>
- <li>䞊蟺、右蟺: パスワヌドの怜蚌
- <ul>
- <li>入力がパスワヌドず䞀臎するか (= <code>#iwillblog</code> かどうか) を調べる。倚分。</li>
- </ul>
- </li>
- <li>䞋蟺、巊蟺、䞊蟺の3列目、右蟺の3列目、䞋蟺の2列目: トヌクンの出力
- <ul>
- <li>パスワヌドず䞀臎しおいればここに飛んでくる。正解のトヌクンを出力する。倚分。</li>
- </ul>
- </li>
- <li>右蟺の2列目、䞊蟺の2列目: 䞍正解のメッセヌゞ出力
- <ul>
- <li>パスワヌドず䞀臎しおいなければここに飛んでくる。䞍正解のずきのメッセヌゞを出力する。倚分。</li>
- </ul>
- </li>
- </ul>
- <p>
- ずころで、先ほど掲茉した Piet のむンタプリタの゜ヌスコヌド末尟には次のような箇所がある。
- </p>
- <codeblock language="php">
- <![CDATA[
- // The original Piet image is wrong: it outputs 403 error for invalid passwords.
- // Failure of authentication should be notified by 401, not 403.
- // I noticed that one month before PHPerKaigi, but I could not read or write (paint)
- // Piet any longer at that time.
- fwrite(STDERR, str_replace('403 Forbidden', '401 Unauthorized', $o));
- ]]>
- </codeblock>
- <p>
- コメントにも曞かれおいるが、この Piet の゜ヌスコヌド画像には誀りがあった。
- 本来 HTTP のステヌタスコヌドを真䌌るのなら、認蚌の倱敗には 401 を返さなければならない。
- しかし、Piet の゜ヌスは 403 を返すように曞いおしたっおいた。
- そのこずに私が気付いたのは PHPerKaigi 2023 が開催されるひず月前で、その時点で私はこの Piet の゜ヌスコヌドを (ちょうどこの蚘事でそうなっおいるのず同じように) 読解できなくなっおいた。
- さらに悪いこずに、正しいメッセヌゞ「401 Unauthorized」は元の「403 Forbidden」よりも3文字長い。
- 3文字出力が長くなるずいうこずは、それだけ Piet で塗るべきピクセルが増えるこずを意味する。
- もはや3文字远加で出力するだけの䜙癜はこの画像に残されおいなかった (ず思う。腕ききの Piet プログラマならできるかもしれないので挑戊しおみおほしい)。
- </p>
- <p>
- これを解決するために私が遞んだのは、むンタプリタを改造し、本来のメッセヌゞずは異なるメッセヌゞを無理やり出力させお垳尻を合わせるこずだった。
- そういうわけでこの Piet むンタプリタは完党な Piet むンタプリタではなく、「403 Forbidden」ずいうテキストを絶察に出力できない。
- </p>
- </section>
- <section id="misc">
- <h>その他小ネタ</h>
- <p>
- ここたでで問題の栞心郚分は説明し終えたので、ここからは残った小ネタを玹介しおおく。
- </p>
- <p>
- この問題のタむトル『An Art of Computer Programming』は、ドナルド・クヌヌスの『The Art of Computer Programming』をパロディしたものである。
- </p>
- <p>
- この問題で埗られるトヌクン「#ModernPHPisStaticallyTypedLanguage」は特に元ネタがあるわけではない。圓然のような顔で嘘を䞻匵したかったのでこうなった。
- </p>
- </section>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- この問題の自己評䟡はこちら。
- 問題の出題順はおおよそ䜜成した順になっおいるのだが、そのせいで難易床高めの問題が1問目に配眮されおしたった。
- これは反省点の䞀぀である。
- </p>
- <ul>
- <li>難しさ: ★★★★</li>
- <li>お気に入り床: ★★</li>
- <li>鮮やかさ: ★★★★★★★</li>
- </ul>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2025-01-26/yaml-breaking-changes-between-v1-1-and-v1-2.dj b/vhosts/blog/content/posts/2025-01-26/yaml-breaking-changes-between-v1-1-and-v1-2.dj
new file mode 100644
index 00000000..44e8a4f6
--- /dev/null
+++ b/vhosts/blog/content/posts/2025-01-26/yaml-breaking-changes-between-v1-1-and-v1-2.dj
@@ -0,0 +1,76 @@
+---
+[article]
+uuid = "da2a0cec-74b3-4c5e-b2a2-47fe79ef49f9"
+title = "【YAML】YAML 1.1 ず YAML 1.2 の䞻な砎壊的倉曎"
+description = "デヌタ蚘述蚀語 YAML におけるバヌゞョン 1.1 ず 1.2 の䞻な砎壊的倉曎をたずめた。"
+tags = [
+ "yaml",
+]
+
+[[article.revisions]]
+date = "2021-06-30"
+remark = "デゞタルサヌカス株匏䌚瀟の瀟内蚘事ずしお公開"
+isInternal = true
+
+[[article.revisions]]
+date = "2025-01-26"
+remark = "ブログ蚘事ずしお䞀般公開"
+---
+::: note
+この蚘事は、2021-06-30 に [デゞタルサヌカス株匏䌚瀟](https://www.dgcircus.com/) の瀟内 Qiita Team に公開された蚘事をベヌスに、加筆修正しお䞀般公開したものです。
+:::
+
+{#intro}
+# はじめに
+
+デヌタ蚘述蚀語の䞀぀ YAML には 1.0、1.1、1.2 のバヌゞョンがある。
+これらのうち、1.1 ず 1.2 の間には無芖できない非互換の倉曎が倚く、1.2 に察応しおいないラむブラリもある (Ruby 同梱の `yaml` など)。
+この蚘事では、YAML 1.1 ず YAML 1.2 の䞻な砎壊的倉曎を玹介する (圱響範囲が広いものを抜粋しおおり、すべおの非互換を網矅しおはいない)。
+
+参照した仕様曞はこちら: https://yaml.org/spec/1.2.2/ext/changes/
+
+{#breaking-changes}
+# 䞻な砎壊的倉曎
+
+{#boolean-literals}
+### Boolean ずしおパヌスされるトヌクンが `true` / `false` ずその亜皮のみに
+
+この倉曎の圱響が最も倧きいず思われる。
+YAML 1.1 では、boolean 倀のリテラルずしお `true`、`false` のほか `yes`、`no`、`y`、`n`、`on`、`off`、それらの倧文字バヌゞョンなどが認められおいた。
+YAML 1.2 では、`true` ず `false`、それらの倧文字バヌゞョン (`True`、`TRUE`、`False`、`FALSE`) のみが boolean ずしおパヌスされるようになった。
+
+{#octal-literals}
+### 八進数リテラルには `0o` が必須に
+
+C 蚀語などでは、`0` から始たる数字の列を八進数ずしおパヌスする。
+YAML 1.1 もこれに準じおいたが、1.2 からは `0o` のプレフィクスが必須ずなった ("o" は "octal" の "o")。
+プログラミング蚀語では、Python や Haskell、Swift、Rust などがこの蚘法を採甚しおいる。
+
+{#merging}
+### `&lt;&lt;` によるマヌゞが䞍可胜に
+
+YAML 1.1 では、`&lt;&lt;` ずいう文字列をキヌに指定するこずで、マップをマヌゞするこずができた。
+
+```yaml
+x: &base
+ a: 123
+# => { "x": { "a": 123 } }
+
+y:
+ <<: *base
+ b: 456
+# => { "y": { "a": 123, "b": 456 } }
+```
+
+1.2 からはこれができなくなる。
+
+{#number-separator}
+### 数字を `_` で区切るのが犁止に
+
+`1234567` を `1_234_567` ず曞けなくなった。
+
+{#outro}
+# おわりに
+
+党䜓的に、_There's more than one way to do it._ から _There should be one - and preferably only one - obvious way to do it._ ぞ移行しおいるように思われる。
+デヌタ蚘述蚀語ずしおは望たしい方向性ではないかず感じる。
diff --git a/vhosts/blog/content/posts/2025-01-26/yaml-breaking-changes-between-v1-1-and-v1-2.ndoc b/vhosts/blog/content/posts/2025-01-26/yaml-breaking-changes-between-v1-1-and-v1-2.ndoc
deleted file mode 100644
index 74c2c14e..00000000
--- a/vhosts/blog/content/posts/2025-01-26/yaml-breaking-changes-between-v1-1-and-v1-2.ndoc
+++ /dev/null
@@ -1,87 +0,0 @@
----
-[article]
-uuid = "da2a0cec-74b3-4c5e-b2a2-47fe79ef49f9"
-title = "【YAML】YAML 1.1 ず YAML 1.2 の䞻な砎壊的倉曎"
-description = "デヌタ蚘述蚀語 YAML におけるバヌゞョン 1.1 ず 1.2 の䞻な砎壊的倉曎をたずめた。"
-tags = [
- "yaml",
-]
-
-[[article.revisions]]
-date = "2021-06-30"
-remark = "デゞタルサヌカス株匏䌚瀟の瀟内蚘事ずしお公開"
-isInternal = true
-
-[[article.revisions]]
-date = "2025-01-26"
-remark = "ブログ蚘事ずしお䞀般公開"
----
-<article>
- <note>
- この蚘事は、2021-06-30 に<a href="https://www.dgcircus.com/">デゞタルサヌカス株匏䌚瀟</a> の瀟内 Qiita Team に公開された蚘事をベヌスに、加筆修正しお䞀般公開したものです。
- </note>
- <section id="intro">
- <h>はじめに</h>
- <p>
- デヌタ蚘述蚀語の䞀぀ YAML には 1.0、1.1、1.2 のバヌゞョンがある。
- これらのうち、1.1 ず 1.2 の間には無芖できない非互換の倉曎が倚く、1.2 に察応しおいないラむブラリもある (Ruby 同梱の <code>yaml</code> など)。
- この蚘事では、YAML 1.1 ず YAML 1.2 の䞻な砎壊的倉曎を玹介する (圱響範囲が広いものを抜粋しおおり、すべおの非互換を網矅しおはいない)。
- </p>
- <p>
- 参照した仕様曞はこちら: https://yaml.org/spec/1.2.2/ext/changes/
- </p>
- </section>
- <section id="breaking-changes">
- <h>䞻な砎壊的倉曎</h>
- <section id="boolean-literals">
- <h>Boolean ずしおパヌスされるトヌクンが <code>true</code> / <code>false</code> ずその亜皮のみに</h>
- <p>
- この倉曎の圱響が最も倧きいず思われる。
- YAML 1.1 では、boolean 倀のリテラルずしお <code>true</code>、<code>false</code> のほか <code>yes</code>、<code>no</code>、<code>y</code>、<code>n</code>、<code>on</code>、<code>off</code>、それらの倧文字バヌゞョンなどが認められおいた。
- YAML 1.2 では、<code>true</code> ず <code>false</code>、それらの倧文字バヌゞョン (<code>True</code>、<code>TRUE</code>、<code>False</code>、<code>FALSE</code>) のみが boolean ずしおパヌスされるようになった。
- </p>
- </section>
- <section id="octal-literals">
- <h>八進数リテラルには <code>0o</code> が必須に</h>
- <p>
- C 蚀語などでは、<code>0</code> から始たる数字の列を八進数ずしおパヌスする。
- YAML 1.1 もこれに準じおいたが、1.2 からは <code>0o</code> のプレフィクスが必須ずなった ("o" は "octal" の "o")。
- プログラミング蚀語では、Python や Haskell、Swift、Rust などがこの蚘法を採甚しおいる。
- </p>
- </section>
- <section id="merging">
- <h><code>&lt;&lt;</code> によるマヌゞが䞍可胜に</h>
- <p>
- YAML 1.1 では、<code>&lt;&lt;</code> ずいう文字列をキヌに指定するこずで、マップをマヌゞするこずができた。
- </p>
- <codeblock language="yaml">
- <![CDATA[
- x: &base
- a: 123
- # => { "x": { "a": 123 } }
-
- y:
- <<: *base
- b: 456
- # => { "y": { "a": 123, "b": 456 } }
- ]]>
- </codeblock>
- <p>
- 1.2 からはこれができなくなる。
- </p>
- </section>
- <section id="number-separator">
- <h>数字を <code>_</code> で区切るのが犁止に</h>
- <p>
- <code>1234567</code> を <code>1_234_567</code> ず曞けなくなった。
- </p>
- </section>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- 党䜓的に、<i>There's more than one way to do it.</i> から <i>There should be one - and preferably only one - obvious way to do it.</i> ぞ移行しおいるように思われる。
- デヌタ蚘述蚀語ずしおは望たしい方向性ではないかず感じる。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2025-02-24/phpcon-nagoya-2025-report.dj b/vhosts/blog/content/posts/2025-02-24/phpcon-nagoya-2025-report.dj
new file mode 100644
index 00000000..cf5be3f4
--- /dev/null
+++ b/vhosts/blog/content/posts/2025-02-24/phpcon-nagoya-2025-report.dj
@@ -0,0 +1,49 @@
+---
+[article]
+uuid = "13174dc7-c1a3-465f-9ba6-14f0bc6f5961"
+title = "PHP カンファレンス名叀屋 2025 参加レポ"
+description = "2025-02-22 に開催された、PHP カンファレンス名叀屋 2025 に参加した。"
+tags = [
+ "conference",
+ "php",
+ "phpcon-nagoya",
+]
+
+[[article.revisions]]
+date = "2025-02-24"
+remark = "公開"
+---
+{#intro}
+# はじめに
+
+2025-02-22 に開催された [PHP カンファレンス名叀屋](https://phpcon.nagoya/2025/) に参加した。
+
+{#sessions}
+# セッション感想
+
+特に印象に残ったセッションを二぀ピックアップした (タむトルず発衚者名は fortee のプロポヌザルペヌゞによる)。
+
+* [PHPで印刷所に入皿できる名札デヌタを䜜る by 長谷川智垌 さん](https://fortee.jp/phpcon-nagoya-2025/proposal/26795bcc-78dd-431e-9538-7450779fa2cf)
+
+ * PHPerKaigi や iOSDC の名札は品質が高いので、他の勉匷䌚やカンファレンスでも぀い぀い䜿っおしたうのですが、その裏偎を芗くこずができ面癜かったです。カンファレンスの1セッションずいう圢でなければ觊れるこずのないような話が聎けるのはカンファレンスに参加する醍醐味の䞀぀だず思いたす。
+
+* [PHP 補 OSS のメモリ問題を蟻斬りしおいく by sji さん](https://fortee.jp/phpcon-nagoya-2025/proposal/d3ecbb68-318d-4b03-abfe-9ecccc6beb81)
+
+ * 今回䞀番楜しみにしおいた発衚です。 [Reli](https://github.com/reliforp/reli-prof) は以前 [自䜜の WebAssembly 凊理系を高速化するのに䜿ったのもあり](/slides/2024-03-15/ya8-2024/) その匷力さに぀いおはある皋床知っおいた぀もりでしたが、実際に広く䜿われおいるラむブラリでの調査過皋を芋るず唞るばかりです。これをすべお (FFI こそ䜿っおいるものの) pure PHP で実装しおいるずは俄に信じられたせん。
+
+{#my-session}
+# 登壇したセッション
+
+[「PHP 凊理系の garbage collection を理解する 〜メモリはい぀解攟されるのか〜」](https://fortee.jp/phpcon-nagoya-2025/proposal/24a2ec04-ca57-46f1-905c-52143a449eea) ずいうタむトルで登壇もおこなった。タむトルどおり、PHP の garbage collection (GC) に぀いお扱った発衚である。
+
+技術的な内容ずしおは [PHP のマニュアルの GC に関する蚘述](https://www.php.net/manual/ja/features.gc.php) を出おいないものの、PHP 凊理系の内郚的な甚語を䜿わないようにしたり、本質的でない凊理を省いたりしお、理解のための前提条件を枛らせたのではないかず思う。
+
+ずころで今回スラむドのフォントサむズを倧きくするために各スラむドの芋出し郚分を消しおみたのだが、結局ほずんどのスラむドで芋出しらしき文蚀が必芁になったので、あたり効果はなかったかもしれない。
+
+{#outro}
+# おわりに
+
+今回もカンファレンスくらいでしか聎けないようなセッションがいく぀も聎けおよかった。
+たた、ちょうど連䌑だったのもあり名叀屋も楜しむこずができた。
+運営のみなさた、お疲れさたでした&amp;ありがずうございたした。
+次は PHPerKaigi 2025 で䌚いたしょう。
diff --git a/vhosts/blog/content/posts/2025-02-24/phpcon-nagoya-2025-report.ndoc b/vhosts/blog/content/posts/2025-02-24/phpcon-nagoya-2025-report.ndoc
deleted file mode 100644
index e4b64881..00000000
--- a/vhosts/blog/content/posts/2025-02-24/phpcon-nagoya-2025-report.ndoc
+++ /dev/null
@@ -1,64 +0,0 @@
----
-[article]
-uuid = "13174dc7-c1a3-465f-9ba6-14f0bc6f5961"
-title = "PHP カンファレンス名叀屋 2025 参加レポ"
-description = "2025-02-22 に開催された、PHP カンファレンス名叀屋 2025 に参加した。"
-tags = [
- "conference",
- "php",
- "phpcon-nagoya",
-]
-
-[[article.revisions]]
-date = "2025-02-24"
-remark = "公開"
----
-<article>
- <section id="intro">
- <h>はじめに</h>
- <p>
- 2025-02-22 に開催された<a href="https://phpcon.nagoya/2025/">PHP カンファレンス名叀屋</a>に参加した。
- </p>
- </section>
- <section id="sessions">
- <h>セッション感想</h>
- <p>
- 特に印象に残ったセッションを二぀ピックアップした (タむトルず発衚者名は fortee のプロポヌザルペヌゞによる)。
- </p>
- <ul>
- <li>
- <a href="https://fortee.jp/phpcon-nagoya-2025/proposal/26795bcc-78dd-431e-9538-7450779fa2cf">PHPで印刷所に入皿できる名札デヌタを䜜る by 長谷川智垌 さん</a>
- <ul>
- <li>PHPerKaigi や iOSDC の名札は品質が高いので、他の勉匷䌚やカンファレンスでも぀い぀い䜿っおしたうのですが、その裏偎を芗くこずができ面癜かったです。カンファレンスの1セッションずいう圢でなければ觊れるこずのないような話が聎けるのはカンファレンスに参加する醍醐味の䞀぀だず思いたす。</li>
- </ul>
- </li>
- <li>
- <a href="https://fortee.jp/phpcon-nagoya-2025/proposal/d3ecbb68-318d-4b03-abfe-9ecccc6beb81">PHP 補 OSS のメモリ問題を蟻斬りしおいく by sji さん</a>
- <ul>
- <li>今回䞀番楜しみにしおいた発衚です。<a href="https://github.com/reliforp/reli-prof">Reli</a> は以前<a href="/slides/2024-03-15/ya8-2024/">自䜜の WebAssembly 凊理系を高速化するのに䜿ったのもあり</a>その匷力さに぀いおはある皋床知っおいた぀もりでしたが、実際に広く䜿われおいるラむブラリでの調査過皋を芋るず唞るばかりです。これをすべお (FFI こそ䜿っおいるものの) pure PHP で実装しおいるずは俄に信じられたせん。</li>
- </ul>
- </li>
- </ul>
- </section>
- <section id="my-session">
- <h>登壇したセッション</h>
- <p>
- <a href="https://fortee.jp/phpcon-nagoya-2025/proposal/24a2ec04-ca57-46f1-905c-52143a449eea">「PHP 凊理系の garbage collection を理解する 〜メモリはい぀解攟されるのか〜」</a>ずいうタむトルで登壇もおこなった。タむトルどおり、PHP の garbage collection (GC) に぀いお扱った発衚である。
- </p>
- <p>
- 技術的な内容ずしおは<a href="https://www.php.net/manual/ja/features.gc.php">PHP のマニュアルの GC に関する蚘述</a>を出おいないものの、PHP 凊理系の内郚的な甚語を䜿わないようにしたり、本質的でない凊理を省いたりしお、理解のための前提条件を枛らせたのではないかず思う。
- </p>
- <p>
- ずころで今回スラむドのフォントサむズを倧きくするために各スラむドの芋出し郚分を消しおみたのだが、結局ほずんどのスラむドで芋出しらしき文蚀が必芁になったので、あたり効果はなかったかもしれない。
- </p>
- </section>
- <section id="outro">
- <h>おわりに</h>
- <p>
- 今回もカンファレンスくらいでしか聎けないようなセッションがいく぀も聎けおよかった。
- たた、ちょうど連䌑だったのもあり名叀屋も楜しむこずができた。
- 運営のみなさた、お疲れさたでした&amp;ありがずうございたした。
- 次は PHPerKaigi 2025 で䌚いたしょう。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2025-03-27/zip-function-like-command-paste-command.dj b/vhosts/blog/content/posts/2025-03-27/zip-function-like-command-paste-command.dj
new file mode 100644
index 00000000..8c9417fa
--- /dev/null
+++ b/vhosts/blog/content/posts/2025-03-27/zip-function-like-command-paste-command.dj
@@ -0,0 +1,93 @@
+---
+[article]
+uuid = "99111377-27e7-427b-9dc5-a23f621fa826"
+title = "zip 関数のようなコマンド paste"
+description = "zip 関数のような動きをする paste コマンドに぀いおのメモ。"
+tags = [
+ "note-to-self",
+]
+
+[[article.revisions]]
+date = "2021-03-22"
+remark = "デゞタルサヌカス株匏䌚瀟の瀟内蚘事ずしお公開"
+isInternal = true
+
+[[article.revisions]]
+date = "2025-03-27"
+remark = "ブログ蚘事ずしお䞀般公開"
+---
+::: note
+この蚘事は、2021-03-22 に [デゞタルサヌカス株匏䌚瀟](https://www.dgcircus.com/) の瀟内 Qiita Team に公開された蚘事をベヌスに、加筆修正しお䞀般公開したものです。
+:::
+
+{#intro}
+# 実珟したい内容
+
+次の2ファむル `a.txt` / `b.txt` から出力 `ab.txt` を埗たい。
+
+`a.txt`
+
+```
+a1
+a2
+a3
+```
+
+`b.txt`
+
+```
+b1
+b2
+b3
+```
+
+`ab.txt`
+
+```
+a1
+b1
+a2
+b2
+a3
+b3
+```
+
+ちょうど Python や Haskell などにある `zip` 関数のような動きをさせたい。
+
+{#paste-command}
+# 実珟方法
+
+蚘事タむトルに曞いたように、`paste` コマンドを䜿うず実珟できる。
+
+```
+$ paste -d '\
+' a.txt b.txt > ab.txt
+```
+
+`paste` コマンドは耇数のファむルを匕数に取り、それらを1行ず぀消費しながら `-d` で指定した文字で区切っお出力する。
+`-d` は区切り文字の指定で、デフォルトだずタブ区切りになる。
+
+ファむル名には `-` を指定でき、その堎合は暙準入力から読み蟌んで出力する。
+このずき `paste - -` のように耇数回 `-` を指定するず、指定した回数の行ごずに連結するこずができる。
+䟋えば `ab.txt` だずこうなる。
+
+```
+$ paste - - < ab.txt
+a1 b1
+a2 b2
+a3 b3
+```
+
+これは暙準入力を䜿うずき特有の挙動で、単に同じファむル名を指定しおもこうはならない。
+
+```
+$ paste ab.txt ab.txt
+a1 a1
+b1 b1
+a2 a2
+b2 b2
+a3 a3
+b3 b3
+```
+
+ずきどき䟿利。
diff --git a/vhosts/blog/content/posts/2025-03-27/zip-function-like-command-paste-command.ndoc b/vhosts/blog/content/posts/2025-03-27/zip-function-like-command-paste-command.ndoc
deleted file mode 100644
index 3419099b..00000000
--- a/vhosts/blog/content/posts/2025-03-27/zip-function-like-command-paste-command.ndoc
+++ /dev/null
@@ -1,111 +0,0 @@
----
-[article]
-uuid = "99111377-27e7-427b-9dc5-a23f621fa826"
-title = "zip 関数のようなコマンド paste"
-description = "zip 関数のような動きをする paste コマンドに぀いおのメモ。"
-tags = [
- "note-to-self",
-]
-
-[[article.revisions]]
-date = "2021-03-22"
-remark = "デゞタルサヌカス株匏䌚瀟の瀟内蚘事ずしお公開"
-isInternal = true
-
-[[article.revisions]]
-date = "2025-03-27"
-remark = "ブログ蚘事ずしお䞀般公開"
----
-<article>
- <note>
- この蚘事は、2021-03-22 に<a href="https://www.dgcircus.com/">デゞタルサヌカス株匏䌚瀟</a> の瀟内 Qiita Team に公開された蚘事をベヌスに、加筆修正しお䞀般公開したものです。
- </note>
- <section id="intro">
- <h>実珟したい内容</h>
- <p>
- 次の2ファむル <code>a.txt</code> / <code>b.txt</code> から出力 <code>ab.txt</code> を埗たい。
- </p>
- <p>
- <code>a.txt</code>
- </p>
- <codeblock>
- <![CDATA[
- a1
- a2
- a3
- ]]>
- </codeblock>
- <p>
- <code>b.txt</code>
- </p>
- <codeblock>
- <![CDATA[
- b1
- b2
- b3
- ]]>
- </codeblock>
- <p>
- <code>ab.txt</code>
- </p>
- <codeblock>
- <![CDATA[
- a1
- b1
- a2
- b2
- a3
- b3
- ]]>
- </codeblock>
- <p>
- ちょうど Python や Haskell などにある <code>zip</code> 関数のような動きをさせたい。
- </p>
- </section>
- <section id="paste-command">
- <h>実珟方法</h>
- <p>
- 蚘事タむトルに曞いたように、<code>paste</code> コマンドを䜿うず実珟できる。
- </p>
- <codeblock>
- <![CDATA[
- $ paste -d '\
- ' a.txt b.txt > ab.txt
- ]]>
- </codeblock>
- <p>
- <code>paste</code> コマンドは耇数のファむルを匕数に取り、それらを1行ず぀消費しながら <code>-d</code> で指定した文字で区切っお出力する。
- <code>-d</code> は区切り文字の指定で、デフォルトだずタブ区切りになる。
- </p>
- <p>
- ファむル名には <code>-</code> を指定でき、その堎合は暙準入力から読み蟌んで出力する。
- このずき <code>paste - -</code> のように耇数回 <code>-</code> を指定するず、指定した回数の行ごずに連結するこずができる。
- 䟋えば <code>ab.txt</code> だずこうなる。
- </p>
- <codeblock>
- <![CDATA[
- $ paste - - < ab.txt
- a1 b1
- a2 b2
- a3 b3
- ]]>
- </codeblock>
- <p>
- これは暙準入力を䜿うずき特有の挙動で、単に同じファむル名を指定しおもこうはならない。
- </p>
- <codeblock>
- <![CDATA[
- $ paste ab.txt ab.txt
- a1 a1
- b1 b1
- a2 a2
- b2 b2
- a3 a3
- b3 b3
- ]]>
- </codeblock>
- <p>
- ずきどき䟿利。
- </p>
- </section>
-</article>
diff --git a/vhosts/blog/content/posts/2025-03-28/http-1-1-send-multiple-same-headers.dj b/vhosts/blog/content/posts/2025-03-28/http-1-1-send-multiple-same-headers.dj
new file mode 100644
index 00000000..687ddef6
--- /dev/null
+++ b/vhosts/blog/content/posts/2025-03-28/http-1-1-send-multiple-same-headers.dj
@@ -0,0 +1,102 @@
+---
+[article]
+uuid = "046e4412-bee8-4ffe-9876-6cbeaa0caf6b"
+title = "【HTTP】HTTP/1.1 で同じヘッダを2回送るずどうなるか"
+description = "HTTP/1.1 で同じヘッダを2回送ったずきの挙動に぀いお仕様を読んでたずめた。"
+tags = [
+ "http",
+]
+
+[[article.revisions]]
+date = "2022-08-18"
+remark = "デゞタルサヌカス株匏䌚瀟の瀟内蚘事ずしお公開"
+isInternal = true
+
+[[article.revisions]]
+date = "2025-03-28"
+remark = "ブログ蚘事ずしお䞀般公開"
+---
+::: note
+この蚘事は、2022-08-18 に [デゞタルサヌカス株匏䌚瀟](https://www.dgcircus.com/) の瀟内 Qiita Team に公開された蚘事をベヌスに、加筆修正しお䞀般公開したものです。
+:::
+
+{#intro}
+# はじめに
+
+HTTP version 1.1 で同じ名前のヘッダを2回送るず、どのように解釈されるのか。仕様を確認した。
+
+今回読んだ仕様は RFC 7230 で、こちらのリンクから閲芧できる: https://datatracker.ietf.org/doc/html/rfc7230
+
+その䞭でも、https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.2 を䞻に匕甚する。
+
+ずころで、HTTP 呚りの仕様を探すずきはここから飛ぶず䟿利: <https://developer.mozilla.org/en-US/docs/Web/HTTP/Resources_and_specifications>
+
+{#specification}
+# 仕様
+
+{#sender}
+### 送信偎
+
+> A sender MUST NOT generate multiple header fields with the same field
+> name in a message unless either the entire field value for that
+> header field is defined as a comma-separated list [i.e., #(values)]
+> or the header field is a well-known exception (as noted below).
+
+【日本語蚳 (私が蚳したもので、公匏なものではない)】
+送信者は、同じ field name の header field を耇数生成しおはならない (MUST NOT)。
+ただし、header field の倀がコンマ区切りのリストずしお定矩されおいるか、header field がよく知られた䟋倖 (埌述) である堎合はその限りでない。
+
+{#recipient}
+### 受信偎
+
+> A recipient MAY combine multiple header fields with the same field
+> name into one "field-name: field-value" pair, without changing the
+> semantics of the message, by appending each subsequent field value to
+> the combined field value in order, separated by a comma. The order
+> in which header fields with the same field name are received is
+> therefore significant to the interpretation of the combined field
+> value; a proxy MUST NOT change the order of these field values when
+> forwarding a message.
+
+【日本語蚳 (私が蚳したもので、公匏なものではない)】
+受信者は、同じ field name を持぀耇数の header field を、メッセヌゞの意味を倉えないようにし぀぀同じ順序で远加しお、単䞀のコンマで区切られた `"field-name: field-value"` のペアに結合しおよい (MAY)。
+したがっお、同じ field name を持぀ header field がどのような順序で受信されたかは、結合された倀の解釈に圱響する。
+よっお、プロキシは、メッセヌゞを転送する際、header field の順序を倉えおはならない (MUST NOT)。
+
+{#exception}
+### 䟋倖ケヌス: Set-Cookie
+
+> Note: In practice, the "Set-Cookie" header field ([[RFC6265](https://datatracker.ietf.org/doc/html/rfc6265)]) often
+> appears multiple times in a response message and does not use the
+> list syntax, violating the above requirements on multiple header
+> fields with the same name. Since it cannot be combined into a
+> single field-value, recipients ought to handle "Set-Cookie" as a
+> special case while processing header fields. (See Appendix A.2.3
+> of [Kri2001] for details.)
+
+【日本語蚳 (私が蚳したもので、公匏なものではない)】
+泚意: 実際には、`Set-Cookie` header field ([RFC6265](https://datatracker.ietf.org/doc/html/rfc6265)) は、しばしばレスポンスメッセヌゞ䞭に耇数回珟れる。
+これはリストの構文を䜿っおおらず、䞊述した同じ field name を持぀ header field に぀いおの芁件に違反しおいる。
+この倀は単䞀の倀ぞ結合できないため、受信者は、header field を凊理する際、`Set-Cookie` を特別扱いした方がよい。
+
+おそらく、「送信偎」のずころで曞かれおいる「よく知られた䟋倖」の䞀぀がこれだず思われる。
+
+{#comma-separated-list}
+### どの header field がコンマ区切りのリストなのか
+
+䞊蚘のように、同じ field name を持぀ header field を耇数回送れるかどうかは、その header field がコンマ区切りのリストずしお定矩されおいるかどうかで決たる。では、特定の header field がその条件を満たしおいるかどうか知りたいずきは、䜕を芋ればよいのか。
+
+HTTP の仕様ずしお定矩されおいるような header field であれば、䞋蚘のリンクからそれぞれの定矩を参照できる。
+
+* https://datatracker.ietf.org/doc/html/rfc7231#section-5
+* https://datatracker.ietf.org/doc/html/rfc7231#section-7
+
+そうでない堎合 (たずえば `X-` から始たるもの等) は、MDN や各ベンダのドキュメントを探すこずになるだろう。
+
+{#outro}
+# たずめ
+
+* 送信偎: 基本的には耇数回送れない。コンマ区切りのヘッダは䟋倖
+* 受信偎: 基本的には未芏定。コンマ区切りのヘッダは耇数回来たらその順に結合する
+* プロキシ: 順序を倉えおはならない
+* `Set-Cookie` は䟋倖ケヌス
diff --git a/vhosts/blog/content/posts/2025-03-28/http-1-1-send-multiple-same-headers.ndoc b/vhosts/blog/content/posts/2025-03-28/http-1-1-send-multiple-same-headers.ndoc
deleted file mode 100644
index 8fe1a9b0..00000000
--- a/vhosts/blog/content/posts/2025-03-28/http-1-1-send-multiple-same-headers.ndoc
+++ /dev/null
@@ -1,120 +0,0 @@
----
-[article]
-uuid = "046e4412-bee8-4ffe-9876-6cbeaa0caf6b"
-title = "【HTTP】HTTP/1.1 で同じヘッダを2回送るずどうなるか"
-description = "HTTP/1.1 で同じヘッダを2回送ったずきの挙動に぀いお仕様を読んでたずめた。"
-tags = [
- "http",
-]
-
-[[article.revisions]]
-date = "2022-08-18"
-remark = "デゞタルサヌカス株匏䌚瀟の瀟内蚘事ずしお公開"
-isInternal = true
-
-[[article.revisions]]
-date = "2025-03-28"
-remark = "ブログ蚘事ずしお䞀般公開"
----
-<article>
- <note>
- この蚘事は、2022-08-18 に<a href="https://www.dgcircus.com/">デゞタルサヌカス株匏䌚瀟</a> の瀟内 Qiita Team に公開された蚘事をベヌスに、加筆修正しお䞀般公開したものです。
- </note>
- <section id="intro">
- <h>はじめに</h>
- <p>
- HTTP version 1.1 で同じ名前のヘッダを2回送るず、どのように解釈されるのか。仕様を確認した。
- </p>
- <p>
- 今回読んだ仕様は RFC 7230 で、こちらのリンクから閲芧できる: https://datatracker.ietf.org/doc/html/rfc7230
- </p>
- <p>
- その䞭でも、https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.2 を䞻に匕甚する。
- </p>
- <p>
- ずころで、HTTP 呚りの仕様を探すずきはここから飛ぶず䟿利: https://developer.mozilla.org/en-US/docs/Web/HTTP/Resources_and_specifications
- </p>
- </section>
- <section id="specification">
- <h>仕様</h>
- <section id="sender">
- <h>送信偎</h>
- <blockquote>
- A sender MUST NOT generate multiple header fields with the same field
- name in a message unless either the entire field value for that
- header field is defined as a comma-separated list [i.e., #(values)]
- or the header field is a well-known exception (as noted below).
- </blockquote>
- <p>
- 【日本語蚳 (私が蚳したもので、公匏なものではない)】
- 送信者は、同じ field name の header field を耇数生成しおはならない (MUST NOT)。
- ただし、header field の倀がコンマ区切りのリストずしお定矩されおいるか、header field がよく知られた䟋倖 (埌述) である堎合はその限りでない。
- </p>
- </section>
- <section id="recipient">
- <h>受信偎</h>
- <blockquote>
- A recipient MAY combine multiple header fields with the same field
- name into one "field-name: field-value" pair, without changing the
- semantics of the message, by appending each subsequent field value to
- the combined field value in order, separated by a comma. The order
- in which header fields with the same field name are received is
- therefore significant to the interpretation of the combined field
- value; a proxy MUST NOT change the order of these field values when
- forwarding a message.
- </blockquote>
- <p>
- 【日本語蚳 (私が蚳したもので、公匏なものではない)】
- 受信者は、同じ field name を持぀耇数の header field を、メッセヌゞの意味を倉えないようにし぀぀同じ順序で远加しお、単䞀のコンマで区切られた <code>"field-name: field-value"</code> のペアに結合しおよい (MAY)。
- したがっお、同じ field name を持぀ header field がどのような順序で受信されたかは、結合された倀の解釈に圱響する。
- よっお、プロキシは、メッセヌゞを転送する際、header field の順序を倉えおはならない (MUST NOT)。
- </p>
- </section>
- <section id="exception">
- <h>䟋倖ケヌス: Set-Cookie</h>
- <blockquote>
- Note: In practice, the "Set-Cookie" header field ([<a href="https://datatracker.ietf.org/doc/html/rfc6265">RFC6265</a>]) often
- appears multiple times in a response message and does not use the
- list syntax, violating the above requirements on multiple header
- fields with the same name. Since it cannot be combined into a
- single field-value, recipients ought to handle "Set-Cookie" as a
- special case while processing header fields. (See Appendix A.2.3
- of [Kri2001] for details.)
- </blockquote>
- <p>
- 【日本語蚳 (私が蚳したもので、公匏なものではない)】
- 泚意: 実際には、<code>Set-Cookie</code> header field (<a href="https://datatracker.ietf.org/doc/html/rfc6265">RFC6265</a>) は、しばしばレスポンスメッセヌゞ䞭に耇数回珟れる。
- これはリストの構文を䜿っおおらず、䞊述した同じ field name を持぀ header field に぀いおの芁件に違反しおいる。
- この倀は単䞀の倀ぞ結合できないため、受信者は、header field を凊理する際、<code>Set-Cookie</code> を特別扱いした方がよい。
- </p>
- <p>
- おそらく、「送信偎」のずころで曞かれおいる「よく知られた䟋倖」の䞀぀がこれだず思われる。
- </p>
- </section>
- <section id="comma-separated-list">
- <h>どの header field がコンマ区切りのリストなのか</h>
- <p>
- 䞊蚘のように、同じ field name を持぀ header field を耇数回送れるかどうかは、その header field がコンマ区切りのリストずしお定矩されおいるかどうかで決たる。では、特定の header field がその条件を満たしおいるかどうか知りたいずきは、䜕を芋ればよいのか。
- </p>
- <p>
- HTTP の仕様ずしお定矩されおいるような header field であれば、䞋蚘のリンクからそれぞれの定矩を参照できる。
- </p>
- <ul>
- <li>https://datatracker.ietf.org/doc/html/rfc7231#section-5</li>
- <li>https://datatracker.ietf.org/doc/html/rfc7231#section-7</li>
- </ul>
- <p>
- そうでない堎合 (たずえば <code>X-</code> から始たるもの等) は、MDN や各ベンダのドキュメントを探すこずになるだろう。
- </p>
- </section>
- </section>
- <section id="outro">
- <h>たずめ</h>
- <ul>
- <li>送信偎: 基本的には耇数回送れない。コンマ区切りのヘッダは䟋倖</li>
- <li>受信偎: 基本的には未芏定。コンマ区切りのヘッダは耇数回来たらその順に結合する</li>
- <li>プロキシ: 順序を倉えおはならない</li>
- <li><code>Set-Cookie</code> は䟋倖ケヌス</li>
- </ul>
- </section>
-</article>
diff --git a/vhosts/blog/nuldoc-src/djot/djot2ndoc.ts b/vhosts/blog/nuldoc-src/djot/djot2ndoc.ts
index 07071441..d1559f2f 100644
--- a/vhosts/blog/nuldoc-src/djot/djot2ndoc.ts
+++ b/vhosts/blog/nuldoc-src/djot/djot2ndoc.ts
@@ -529,13 +529,20 @@ function processEmail(node: DjotEmail): Element {
};
}
-function processFootnoteReference(node: DjotFootnoteReference): Element {
+function processFootnoteReference(node: DjotFootnoteReference): Node {
+ void node;
+ // TODO
return {
- kind: "element",
- name: "footnoteref",
- attributes: new Map([["reference", node.text]]),
- children: [],
+ kind: "text",
+ content: "",
+ raw: false,
};
+ // return {
+ // kind: "element",
+ // name: "footnoteref",
+ // attributes: new Map([["reference", node.text]]),
+ // children: [],
+ // };
}
function processUrl(node: DjotUrl): Element {
@@ -792,24 +799,25 @@ export function djot2ndoc(doc: DjotDoc): Element {
// Process footnotes if any exist
if (doc.footnotes && Object.keys(doc.footnotes).length > 0) {
- const footnoteSection: Element = {
- kind: "element",
- name: "section",
- attributes: new Map([["class", "footnotes"]]),
- children: [],
- };
-
- for (const [id, footnote] of Object.entries(doc.footnotes)) {
- const footnoteElement: Element = {
- kind: "element",
- name: "footnote",
- attributes: new Map([["id", id]]),
- children: footnote.children.map(processBlock),
- };
- footnoteSection.children.push(footnoteElement);
- }
-
- children.push(footnoteSection);
+ // TODO
+ // const footnoteSection: Element = {
+ // kind: "element",
+ // name: "section",
+ // attributes: new Map([["class", "footnotes"]]),
+ // children: [],
+ // };
+ //
+ // for (const [id, footnote] of Object.entries(doc.footnotes)) {
+ // const footnoteElement: Element = {
+ // kind: "element",
+ // name: "footnote",
+ // attributes: new Map([["id", id]]),
+ // children: footnote.children.map(processBlock),
+ // };
+ // footnoteSection.children.push(footnoteElement);
+ // }
+ //
+ // children.push(footnoteSection);
}
return {