From c0c73379890f1a4ee6ee07b1aee188c33ef66ab0 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Wed, 2 Apr 2025 00:11:46 +0900 Subject: feat(blog/nuldoc): dynamically join nested section ids --- .../content/posts/2021-03-30/phperkaigi-2021.ndoc | 36 +++++++++---------- ...e-between-autocmd-bufwrite-and-bufwritepre.ndoc | 4 +-- .../vim-swap-order-of-selected-lines.ndoc | 4 +-- .../posts/2022-04-09/phperkaigi-2022-tokens.ndoc | 34 +++++++++--------- .../content/posts/2022-05-01/phperkaigi-2022.ndoc | 8 ++--- .../php-conference-okinawa-code-golf.ndoc | 8 ++--- .../write-fizzbuzz-in-php-2-letters-per-line.ndoc | 10 +++--- .../2022-10-28/setup-server-for-this-site.ndoc | 38 ++++++++++---------- .../phperkaigi-2023-unused-token-quiz-3.ndoc | 8 ++--- ...mplementation-of-minimal-png-image-encoder.ndoc | 14 ++++---- .../posts/2023-04-04/phperkaigi-2023-report.ndoc | 6 ++-- .../posts/2023-06-25/phpconfuk-2023-report.ndoc | 4 +-- .../2023-10-02/compile-php-runtime-to-wasm.ndoc | 4 +-- .../blog/content/posts/2023-12-03/isucon-13.ndoc | 8 ++--- .../posts/2024-03-17/phperkaigi-2024-report.ndoc | 2 +- .../pipefail-option-in-gitlab-ci-cd.ndoc | 4 +-- .../content/posts/2024-12-04/cohackpp-report.ndoc | 4 +-- .../2025-01-08/phperkaigi-2023-tokens-q1.ndoc | 12 +++---- ...aml-breaking-changes-between-v1-1-and-v1-2.ndoc | 8 ++--- .../http-1-1-send-multiple-same-headers.ndoc | 8 ++--- vhosts/blog/nuldoc-src/ndoc/to_html.ts | 42 +++++++++++++++++++--- .../posts/2021-03-30/phperkaigi-2021/index.html | 4 +-- 22 files changed, 151 insertions(+), 119 deletions(-) (limited to 'vhosts/blog') diff --git a/vhosts/blog/content/posts/2021-03-30/phperkaigi-2021.ndoc b/vhosts/blog/content/posts/2021-03-30/phperkaigi-2021.ndoc index 2dd50bae..9589e49b 100644 --- a/vhosts/blog/content/posts/2021-03-30/phperkaigi-2021.ndoc +++ b/vhosts/blog/content/posts/2021-03-30/phperkaigi-2021.ndoc @@ -31,7 +31,7 @@ remark = "公開" 発表はトラック A、B に分かれていたのだが、今回はすべて A トラックを視聴している (切り替えるのが面倒だっただけ)。

-
+
凡例

@@ -42,9 +42,9 @@ remark = "公開" 感想など

-
+
Day 0 前夜祭 (2021/03/27) -
+
17:30 [A]

PHP で AWS Lambda @@ -100,7 +100,7 @@ remark = "公開" だという先入観を持っていたのだが、この発表のデモによればそうでもないらしい。

-
+
18:10 [A]

大規模サイトの SEO @@ -152,7 +152,7 @@ remark = "公開" は大して知らないので新鮮な話が多かった。その分語れることも少ない……。

-
+
18:50 [A]

@@ -214,7 +214,7 @@ remark = "公開" いわゆる「健常者」にとって、こうした問題を普段の生活の中で意識するのは難しい。だからこそ情報へのアンテナは張っておくようにしたい。

-
+
19:30 [A]

PHP で FUSE @@ -281,9 +281,9 @@ remark = "公開"

-
+
Day 1 (2021/03/27) -
+
10:50 [A]

ATDD @@ -377,7 +377,7 @@ remark = "公開" 高レベルテストの自動化は現在のプロジェクトでも感じており、自動化のチャンスは伺っている。とはいえセッションでも指摘されているように自動化することにコストがかかりすぎる領域があるのも事実で、そのバランスが難しい。

-
+
11:50 [A]

型解析を用いたリファクタリング @@ -418,13 +418,13 @@ remark = "公開" Ruby の typeprof には注目している。

-
+
12:30 [A]

昼食をとっていた。事前に何か食料を買っておくべきだった。

-
+
13:10 [A]

Documentation as Code @@ -487,7 +487,7 @@ remark = "公開" 情報を起点にするのは理にかなっている。問題はトレースをいつ、どう取るかだろうか。それを自動化しなければ、実態との乖離が避けられないだろう。

-
+
14:10 [A]

cookie による session 管理 @@ -497,7 +497,7 @@ remark = "公開" やセッションの話としては非常に分かりやすくまとめられていたので、知らない人が学ぶにはいい教材だろう。

-
+
14:50 [A]

PHP のエラーと例外 @@ -610,7 +610,7 @@ remark = "公開" のように、すでに例外が言語システムに根ざしている言語ではどうすればよいか。この場合も同じく静的検証の力を借りることになるだろう。

-
+
15:30 [A]

Laravel のメール認証 @@ -620,7 +620,7 @@ remark = "公開" の知識がない私にはまったくついていけなかった。また、個人的にタイトルがややミスリーディングに感じた。

-
+
16:10 [A]

gRPC @@ -674,7 +674,7 @@ remark = "公開" というエコシステムに乗れることのメリットが大きいと感じる。そのエコシステムにうまく乗れない時点で、うーんという感じ。

-
+
16:50 [A]

アーキテクチャテスト @@ -723,7 +723,7 @@ remark = "公開"

-
+
Day 2 (2021/03/28)

冒頭に書いた通り、2日目から体調が悪くまともに聴けていない。途中までは頭痛を我慢しつつ見ていたのだが、まともに入ってこなかった。 @@ -732,7 +732,7 @@ remark = "公開" 残念ではあるが、いずれにせよ見られていない発表は他にもあるので、今週末にでもまとめて見ようと思う。

-
+
全体の感想

Day 2 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 index 44713acd..705cf6c4 100644 --- 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 @@ -54,7 +54,7 @@ remark = "Qiita から移植" neovim (上に同じ)

-
+
vim のソースコード

以下は、autocmd events @@ -90,7 +90,7 @@ remark = "Qiita から移植" ]]>

-
+
neovim のソースコード

neovim の場合でも同様のマッピングが定義されているが、こちらの場合は Lua 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 index 699a0e28..149d038d 100644 --- 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 @@ -42,7 +42,7 @@ remark = "Qiita から移植"

よく紹介されている手法 -
+
tac / tail

tactail -r などの外部コマンドを ! @@ -58,7 +58,7 @@ remark = "Qiita から移植" オプションは環境によって利用できないことがあり、複数の環境を行き来する場合に採用しづらい

-
+
:g/^/m0

こちらは外部コマンドに頼らず、Vim の機能のみを使う。g:global 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 index 68ef7dd2..c0540482 100644 --- a/vhosts/blog/content/posts/2022-04-09/phperkaigi-2022-tokens.ndoc +++ b/vhosts/blog/content/posts/2022-04-09/phperkaigi-2022-tokens.ndoc @@ -111,16 +111,16 @@ remark = "2問目、3問目の解説を追加、1問目に加筆"

この問題は、単に適切なバージョンの PHP で動かせばトークンが得られる。

-
+
解説 -
+
絵文字

まず目につくのは大量の絵文字だろう。 PHP は識別子に使用できる文字の範囲が広く、絵文字も使うことができる。

-
+
プログラム全体

Brainf*ck のインタプリタとプログラムになっている。 Brainf*ck @@ -182,7 +182,7 @@ remark = "2問目、3問目の解説を追加、1問目に加筆" なお、$🐘 はいわゆる main 関数であり、プログラムの実行部分である。

-
+
絵文字の選択

おおよそ意味に合致するよう選んでいるが、$🤡$🎪 @@ -190,7 +190,7 @@ remark = "2問目、3問目の解説を追加、1問目に加筆" のマスコットの象に由来する。

-
+
strict_types

declare 文の strict_types に指定できるのは、01 @@ -198,7 +198,7 @@ remark = "2問目、3問目の解説を追加、1問目に加筆" 8.1 から追加された、0O または 0o から始まる八進数リテラルを使った。

-
+
URL

ソースコードのライセンスを示したこの部分だが、 @@ -213,7 +213,7 @@ remark = "2問目、3問目の解説を追加、1問目に加筆" 以降は行コメントになっている。

-
+
リテラルなしで数値を生成する

ソースコード中に、ほとんど数値リテラルが書かれていないことにお気づきだろうか。 @@ -242,7 +242,7 @@ remark = "2問目、3問目の解説を追加、1問目に加筆" にし、さらにビット反転して -1 にしている。

-
+
if 文なしで条件分岐

三項演算子ないし match 式を使うことで、if @@ -251,7 +251,7 @@ remark = "2問目、3問目の解説を追加、1問目に加筆" のような形で分岐することもできる。

-
+
whilefor 文なしでループ

不動点コンビネータを使って無名再帰する @@ -321,7 +321,7 @@ remark = "2問目、3問目の解説を追加、1問目に加筆"

ここでは、私の想定解を解説する。

-
+
読解

まずはソースコードを読んでいく。 @@ -369,7 +369,7 @@ remark = "2問目、3問目の解説を追加、1問目に加筆" 5文字ごとに区切ったあと、改行で結合している。

-
+
ヒント

次に、ソースコードに書いてあるヒントを読んでいく。 @@ -387,7 +387,7 @@ remark = "2問目、3問目の解説を追加、1問目に加筆" ファイルに追加ヒントとして書かれている)。

-
+
解く

ここまでわかれば、あと一歩で解ける。すなわち、0x14B499C# @@ -501,9 +501,9 @@ remark = "2問目、3問目の解説を追加、1問目に加筆"

実際にはもう少しパイプで繋げなければならない。

-
+
解説 -
+
プログラム全体

コメントにもあるとおり、これは quine (風) のプログラムになっている。 @@ -515,14 +515,14 @@ remark = "2問目、3問目の解説を追加、1問目に加筆" 異なるのはトークンになっている部分のみである。

-
+
トークン

$xs がトークンに対応している。変換のロジックは riddle.php とほぼ同じなので省略する。

-
+
状態保持

トークンの何文字目まで出力したかを、ソースコードを変えずに (quine @@ -531,7 +531,7 @@ remark = "2問目、3問目の解説を追加、1問目に加筆" から情報を取得している。

-
+
ROT 13

Quine は、素朴に書くとプログラムの一部が 2回記述されてしまう。 diff --git a/vhosts/blog/content/posts/2022-05-01/phperkaigi-2022.ndoc b/vhosts/blog/content/posts/2022-05-01/phperkaigi-2022.ndoc index a43a140c..28151668 100644 --- a/vhosts/blog/content/posts/2022-05-01/phperkaigi-2022.ndoc +++ b/vhosts/blog/content/posts/2022-05-01/phperkaigi-2022.ndoc @@ -28,7 +28,7 @@ remark = "公開"

感想 -
+
厳選おすすめトーク

多くの素晴らしいトークの中から、特におすすめのものを 5つ選んだ。 @@ -103,21 +103,21 @@ remark = "公開"

-
+
トークン問題の作成

今回は、PHPer チャレンジ用に弊社のトークン問題を 3題作成した。 こちらについては別途記事にしているので、そちらを参照されたい。

-
+
PHPer チャレンジ

1位になった。
また、賞品として Echo Show 15 をいただいた。

-
+
カンファレンス全体への感想

去年の参加レポ では、こんなことを書いた。 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 index 062a8b02..056ac438 100644 --- 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 @@ -70,7 +70,7 @@ remark = "公開"

使用したテクニック -
+
指数表記

割と多くの言語のゴルフで使えるテクニック。 @@ -78,7 +78,7 @@ remark = "公開" このコードでは 10000500020001000 を指数表記している。

-
+
foreach や for の中身を1つの文に

foreachforif などの後ろには、 @@ -86,7 +86,7 @@ remark = "公開" C言語などでも使える。

-
+
$r に初期値を入れない

PHP では、$r[] = ...... のような配列の末尾に追加する式を実行したとき、 @@ -102,7 +102,7 @@ remark = "公開" もし 0 が渡されたケースを無視するなら、これが不要になるので 4 バイト縮む。

-
+
PHP タグの外に文字列を置く

PHP では、<?php ?> で囲われた部分の外側にある文字列は、そのまま出力される。 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 index 6a7d4a31..f8b0d62e 100644 --- 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 @@ -202,7 +202,7 @@ remark = "小さな文言の修正・変更"

解説 -
+
普通の (?) fizzbuzz

まずは普通に書くとしよう。 @@ -220,7 +220,7 @@ remark = "小さな文言の修正・変更" 素直に書いた fizzbuzz とは言い難いが、このくらいは普通だということにしておかないと、この先がやっていられないので許してほしい。

-
+
for の排除

for は、3文字もある長いキーワードである。 @@ -244,7 +244,7 @@ remark = "小さな文言の修正・変更" なお、echo は文 (statement) であり式 (expression) ではないので、式である printf に置き換えた。

-
+
関数呼び出しの短縮

rangearray_walkprintf は長すぎるのでどうにかせねばならない。 @@ -273,7 +273,7 @@ remark = "小さな文言の修正・変更" 次のテクニックへ移ろう。

-
+
余談: PHP 8.x で動作しなくてもいいなら

今回使ったテクニックを説明する前に、余談として、文字列リテラルの短縮法として今回採用しなかったものを紹介する。 @@ -318,7 +318,7 @@ remark = "小さな文言の修正・変更" むしろ、このことがわかっていたからこそ PHP 8.x での動作を要件に課したところがある。

-
+
文字列リテラルの短縮

実際に使った手法の説明に移る。 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 index a601b8b4..c10ad115 100644 --- 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 @@ -36,14 +36,14 @@ remark = "ssh_config に IdentitiesOnly yes を追加"

事前準備 -
+
サーバのホスト名を決める

モチベーションが上がるという効能がある。今回は藤原定家から取って teika にした。 たいていいつも源氏物語の帖か小倉百人一首の歌人から選んでいる。

-
+
SSH の鍵生成

ローカルマシンで鍵を生成する。 @@ -59,7 +59,7 @@ remark = "ssh_config に IdentitiesOnly yes を追加" GitHub Actions からサーバへのデプロイ用。

-
+
SSH の設定

.ssh/config に設定しておく。 @@ -78,13 +78,13 @@ remark = "ssh_config に IdentitiesOnly yes を追加"

基本のセットアップ -
+
SSH 接続

VPS 契約時に設定した管理者ユーザとパスワードを使ってログインする。

-
+
ユーザを作成する

管理者ユーザで作業すると危ないので、メインで使うユーザを作成する。 @@ -99,7 +99,7 @@ remark = "ssh_config に IdentitiesOnly yes を追加" ]]>

-
+
ホスト名を変える
-
+
公開鍵を置く ~/.ssh/github2teika.key.pub の内容をコピーする。

-
+
SSH の設定

SSH の設定を変更し、少しでも安全にしておく。 @@ -147,7 +147,7 @@ remark = "ssh_config に IdentitiesOnly yes を追加" ]]>

-
+
SSH で接続確認

今の SSH セッションは閉じずに、ターミナルを別途開いて疎通確認する。 @@ -159,7 +159,7 @@ remark = "ssh_config に IdentitiesOnly yes を追加" ]]>

-
+
ポートの遮断

デフォルトの 22 番を閉じ、設定したポートだけ空ける。 @@ -177,7 +177,7 @@ remark = "ssh_config に IdentitiesOnly yes を追加" ここでもう一度 SSH の接続確認を挟む。

-
+
GitHub 用の SSH 鍵

GitHub に置いてある private リポジトリをサーバから clone したいので、SSH 鍵を生成して置いておく。 @@ -218,7 +218,7 @@ remark = "ssh_config に IdentitiesOnly yes を追加" ]]>

-
+
パッケージの更新
サイトホスティング用のセットアップ -
+
DNS に IP アドレスを登録する

このサーバは固定の IP アドレスがあるので、A レコードに直接入れるだけで済んだ。

-
+
使うソフトウェアのインストール
-
+
メインユーザが Docker を使えるように
-
+
HTTP/HTTPS を通す

80 番と 443 番を空ける。 @@ -269,7 +269,7 @@ remark = "ssh_config に IdentitiesOnly yes を追加" ]]>

-
+
リポジトリのクローン
-
+
certbot で証明書取得
-
+
サーバを稼動させる
解説 -
+
概要

例外が発生した行数にデータをエンコードし、それを catch で捕まえて表示している。

-
+
例外オブジェクトの連鎖

ExceptionError には $previous というプロパティがあり、コンストラクタの第3引数から渡すことができる。主に 2つの用法がある: @@ -204,7 +204,7 @@ remark = "公開" この知識を元に、トークンの出力部を解析してみる。

-
+
出力部の解析

出力部をコメントや改行を追加して再掲する: @@ -240,7 +240,7 @@ remark = "公開" それでは、エラーチェインを作る箇所、関数 f() を見ていく。

-
+
データ構成部の解析

f() の定義を再掲する (エラーオブジェクトの行数を利用しているので、一部分だけ抜き出すと値が変わることに注意): 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 index 14a24cae..ec39a99f 100644 --- 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 @@ -88,7 +88,7 @@ remark = "公開"

以降は、writeSignaturewriteChunkIhdr などを実装していく。

-
+
PNG signature

PNG signature は、PNG 画像の先頭に固定で付与されるバイト列で、8 バイトからなる。 @@ -132,7 +132,7 @@ remark = "公開" encoding/binary パッケージの binary.Write を使い、固定の 8 バイトを書き込む。

-
+
Chunk の構造

IHDR chunk に進む前に、chunk 一般の構造を確認する。 @@ -209,7 +209,7 @@ remark = "公開" 準備ができたところで、具体的な chunk をエンコードしていく。

-
+
IHDR chunk

IHDR chunk は最初に配置される chunk である。次のようなデータからなる。 @@ -274,12 +274,12 @@ remark = "公開" ]]>

-
+
IDAT chunk

IDAT chunk は、実際の画像データが格納された chunk である。IDAT chunk は deflate アルゴリズムにより圧縮され、zlib 形式で格納される。

-
+
Zlib

まずは zlib について確認する。おおよそ次のような構造になっている。 @@ -360,7 +360,7 @@ remark = "公開" ]]>

-
+
画像データ

では次に、zlib 形式で格納するデータを用意する。PNG 画像は次のような順にスキャンする。 @@ -394,7 +394,7 @@ remark = "公開"

-
+
IEND chunk

最後に IEND chunk を書き込む。これは PNG 画像の最後に配置される chunk で、PNG のデコーダはこの chunk に出会うとそこでデコードを停止する。 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 index b00d9191..e9ad3d96 100644 --- a/vhosts/blog/content/posts/2023-04-04/phperkaigi-2023-report.ndoc +++ b/vhosts/blog/content/posts/2023-04-04/phperkaigi-2023-report.ndoc @@ -76,7 +76,7 @@ remark = "トークセッションの記事版の執筆を中止"

参加者として -