<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>ikuma-t.com</title><description>プログラマikuma-tの個人サイト</description><link>https://ikuma-t.com/</link><item><title>chezmoiの変更をClaude Codeにコミットさせる</title><link>https://ikuma-t.com/blog/commit-chezmoi-diff-automaticaly-by-claude/</link><guid isPermaLink="true">https://ikuma-t.com/blog/commit-chezmoi-diff-automaticaly-by-claude/</guid><description>chezmoiでdotfilesを管理しています。chezmoiでは変更に対して自動でコミットを行うことができ、これまではautoCommitをtrueにすることで、自動コミットを起動させ、自分でコミ</description><pubDate>Sun, 11 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://www.chezmoi.io/&quot; target=&quot;_blank&quot;&gt;chezmoi&lt;/a&gt;でdotfilesを管理しています。&lt;/p&gt;
&lt;p&gt;chezmoiでは変更に対して自動でコミットを行うことができ、これまでは&lt;code&gt;autoCommit&lt;/code&gt;をtrueにすることで、自動コミットを起動させ、自分でコミットメッセージを入力していました。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[git]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;autoCommit &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;autoPush &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;commitMessageTemplate &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;{{ promptString \&quot;Commit message\&quot; }}&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;dotfilesは頻繁に変更が入るのでコミットメッセージを書くのが面倒です。また内容もアプリケーション開発よりも自明なものが多く、自分がコミットメッセージを入力する必要はなおのことないと思い、コミットの入力をClaude Codeに移譲することにしました。&lt;/p&gt;
&lt;p&gt;chezmoi の &lt;a href=&quot;https://www.chezmoi.io/reference/configuration-file/hooks/&quot; target=&quot;_blank&quot;&gt;Hooks&lt;/a&gt; 機能を使って、変更時に事前に登録しておいたコミット処理を起動します。この場合コミット処理は Claude Code に移譲するため &lt;code&gt;autoCommit&lt;/code&gt; は不要になります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[git]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;autoCommit &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;autoPush &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[hooks.add.post]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;command &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;bash&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;args &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;-c&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;cd ~/.local/share/chezmoi &amp;amp;&amp;amp; claude -p \&quot;/commit\&quot;&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[hooks.edit.post]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;command &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;bash&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;args &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;-c&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;cd ~/.local/share/chezmoi &amp;amp;&amp;amp; claude -p \&quot;/commit\&quot;&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;なお &lt;code&gt;-p&lt;/code&gt; は print オプション。これにはスラッシュコマンドも渡せるので、コミットを行うコマンドなりを渡してやれば良いというわけです。&lt;/p&gt;
&lt;p&gt;これで変更反映時に自動で Claude Code によるコミットが実行されるようになりました。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Obsidianでアバターアイコンを挿入できるようにする</title><link>https://ikuma-t.com/blog/insert-avatar-obsidian/</link><guid isPermaLink="true">https://ikuma-t.com/blog/insert-avatar-obsidian/</guid><description>esaやscrapboxでは自分のアバターアイコンを文中にサッと入れられますが、これをObsidianでもやる方法です。手順はシンプルで、テンプレートとして画像を挿入するホットキーを作ります。自分のア</description><pubDate>Fri, 09 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;esaやscrapboxでは自分のアバターアイコンを文中にサッと入れられますが、これをObsidianでもやる方法です。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&quot;lazy&quot; width=&quot;317&quot; height=&quot;82&quot; src=&quot;/_astro/avatar-icon-sample.tfLEiavV_1IbWpc.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;手順はシンプルで、テンプレートとして画像を挿入するホットキーを作ります。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;自分のアイコン画像を適当なフォルダに配置する（CSSで調整しますが、20px x 20pxくらいの正方形で用意）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;テンプレートを作成する。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;![[&lt;/span&gt;&lt;span&gt;me.png|me&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;スタイリングのために、Altをつけています。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;カスタムCSSを配置する&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;img&lt;/span&gt;&lt;span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;alt&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;me&quot;&lt;/span&gt;&lt;span&gt;] {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;width&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;px&lt;/span&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;height&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;px&lt;/span&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;border-radius&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;50&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;vertical-align&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;middle&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;margin-right&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;px&lt;/span&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;display&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inline&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Templater Pluginを利用して、2で作成したテンプレートにホットキーを適用する&lt;/li&gt;
&lt;/ol&gt;</content:encoded><author>ikuma-t</author></item><item><title>Advanced Functional Programming With Elixirを読んだ</title><link>https://ikuma-t.com/blog/advanced-functional-programming-with-elixir/</link><guid isPermaLink="true">https://ikuma-t.com/blog/advanced-functional-programming-with-elixir/</guid><description>Xのタイムラインに流れてきたのがきっかけでAdvancedFunctionalProgrammingwithElixir:ModelBehavior,ManageComplexity,andMaxim</description><pubDate>Tue, 30 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;X のタイムラインに流れてきたのがきっかけで &lt;a href=&quot;https://pragprog.com/titles/jkelixir/advanced-functional-programming-with-elixir/&quot; target=&quot;_blank&quot;&gt;Advanced Functional Programming with Elixir: Model Behavior, Manage Complexity, and Maximize Maintainability by Joseph Koski&lt;/a&gt; を読みました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#本書の概要&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;本書の概要&lt;/h2&gt;
&lt;p&gt;テーマパーク「FunPark」を題材として、各章ごとに FP のデザインを学んでいきます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Build FunPark: Model Real-World Data&lt;/li&gt;
&lt;li&gt;Implement Domain-Specific Equality with Protocols&lt;/li&gt;
&lt;li&gt;Create Flexible Ordering with Protocols&lt;/li&gt;
&lt;li&gt;Combine with Monoids&lt;/li&gt;
&lt;li&gt;Define Logic with Predicates&lt;/li&gt;
&lt;li&gt;Compose in Context with Monads&lt;/li&gt;
&lt;li&gt;Access Shared Environment with Reader&lt;/li&gt;
&lt;li&gt;Manage Absence with Maybe&lt;/li&gt;
&lt;li&gt;Model Outcomes with Either&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;各章ごとに出てくる FP のパターンは次の通りです&lt;/p&gt;





































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;章&lt;/th&gt;&lt;th&gt;出現するパターン&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1-3&lt;/td&gt;&lt;td&gt;Eq, Ord&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;Monoid&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;Predicate&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;6-7&lt;/td&gt;&lt;td&gt;Monad, Reader&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;Maybe&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;Either&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;Effect&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;&lt;a href=&quot;#対象読者&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;対象読者&lt;/h3&gt;
&lt;p&gt;The Pragmatic Bookself では「Expert」とされていますが、これは「Elixir には習熟しているが、完全な FP には傾倒していない人」を想定してのものに感じました。関数型プログラミングの書籍としては、上述の出現するパターンの通り比較的基本的な部分も多いため、Beginner から Intermediate の中間くらいに相当するかと思います。&lt;/p&gt;
&lt;p&gt;近いレベルの書籍としては以下の 2 冊でしょうか。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.shoeisha.co.jp/book/detail/9784798179803&quot; target=&quot;_blank&quot;&gt;なっとく！関数型プログラミング（Michał Płachta 株式会社クイープ 株式会社クイープ）｜翔泳社の本&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tatsu-zine.com/books/domain-modeling-made-functional&quot; target=&quot;_blank&quot;&gt;関数型ドメインモデリング【委託】 - 達人出版会&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これら 2 冊よりも、より具体的に「Monad」「Applicative」といった関数型プログラミングのワードを取り扱っているのが本書です。関数型プログラミングの概念を理解したい、上記 2 冊を読んだがもう少しパターンを補完したい、という方に推奨できる一冊に思います。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#学んだこと&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;学んだこと&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#律laws&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;律（Laws）&lt;/h3&gt;
&lt;p&gt;関数型プログラミングでは、抽象化には必ず「律」（laws）が伴います。律とは、その抽象化が満たすべき数学的な性質のことです。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Monoid の律：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;単位元律：&lt;code&gt;combine(x, empty) = x&lt;/code&gt;、&lt;code&gt;combine(empty, x) = x&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;結合律：&lt;code&gt;combine(combine(a, b), c) = combine(a, combine(b, c))&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Functor の律：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;恒等律：&lt;code&gt;map(id) = id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;合成律：&lt;code&gt;map(f . g) = map(f) . map(g)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;律があることで、コードの振る舞いが予測可能になります。律を満たさない実装は「壊れた抽象化」であり、合成したときに予期しない動作を引き起こします。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#functorapplicativemonad-の階層&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Functor、Applicative、Monad の階層&lt;/h3&gt;
&lt;p&gt;この 3 つは階層構造を成しています：&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Functor     ⊂ Applicative ⊂ Monad&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;(map)         (map + ap)     (map + ap + bind)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Functor は「箱の中身を変換する」能力を持ちます。&lt;code&gt;map&lt;/code&gt; だけで十分な場合は Functor です。&lt;/p&gt;
&lt;p&gt;Applicative は「独立した計算を組み合わせる」能力を追加します。&lt;code&gt;ap&lt;/code&gt; を使って、複数の箱の中身に関数を適用できます。重要なのは、各計算が独立していること。バリデーションで全エラーを集めたい場合は Applicative を使います。&lt;/p&gt;
&lt;p&gt;Monad は「前の計算結果に依存する計算を連鎖させる」能力を追加します。&lt;code&gt;bind&lt;/code&gt;（&lt;code&gt;flatMap&lt;/code&gt;）を使って、前の結果を見てから次の計算を決められます。ただし、依存関係があるため、最初のエラーで停止します。&lt;/p&gt;
&lt;p&gt;本書で &lt;code&gt;traverse&lt;/code&gt; と &lt;code&gt;traverse_a&lt;/code&gt; の違いを学んだとき、この階層の意味が実感できました。&lt;code&gt;traverse&lt;/code&gt; は Monad（依存、最初のエラーで停止）、&lt;code&gt;traverse_a&lt;/code&gt; は Applicative（独立、全エラー収集）です。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#共変と反変covariant--contravariant&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;共変と反変（Covariant / Contravariant）&lt;/h3&gt;
&lt;p&gt;TypeScript の型定義でも出てくる共変と反変。&lt;/p&gt;
&lt;p&gt;共変（Covariant） は、&lt;code&gt;map&lt;/code&gt; で出力を変換します：&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;map: (a -&amp;gt; b) -&amp;gt; F a -&amp;gt; F b&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;反変（Contravariant） は、&lt;code&gt;contramap&lt;/code&gt; で入力を変換します：&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;contramap: (b -&amp;gt; a) -&amp;gt; F a -&amp;gt; F b&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;本書では、FastPass の時刻で等価性を判定したい場合に &lt;code&gt;contramap&lt;/code&gt; を使いました：&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;eq_time&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;do&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Eq&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Utils&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;contramap&lt;/span&gt;&lt;span&gt;(&amp;amp;get_time&lt;/span&gt;&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;また、Patron をチケット階層で順序付けしたい場合にも &lt;code&gt;contramap&lt;/code&gt; を使いました：&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ord_by_ticket_tier&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;do&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Ord&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Utils&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;contramap&lt;/span&gt;&lt;span&gt;(&amp;amp;get_ticket_tier_priority&lt;/span&gt;&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;contramap&lt;/code&gt; は元のデータを変更するわけではなく、「比較のために一時的に射影する」だけです。既存の &lt;code&gt;Eq&lt;/code&gt; や &lt;code&gt;Ord&lt;/code&gt; から新しいものを宣言的に導出できる強力な道具です。著者も章末で「本当に &lt;code&gt;contramap&lt;/code&gt; を理解しているか自問せよ」と強調していました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#lift持ち上げ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;lift（持ち上げ）&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;lift&lt;/code&gt; は、ある文脈の外にある値や関数を、文脈の中に持ち込む操作です。本書では頻繁に登場しました：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;lift_predicate&lt;/code&gt;：述語を Maybe や Either に持ち上げる&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lift_either&lt;/code&gt;：Either を Effect に持ち上げる&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lift_func&lt;/code&gt;：通常の関数を Effect に持ち上げる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;関数型プログラミングに精通している方のツイートなどをみていると「持ち上げる」という概念がよく出てくるので、アハ体験でした。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#kleisli-関数&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Kleisli 関数&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;a -&amp;gt; M b&lt;/code&gt; という形の関数（値を受け取って Monad を返す関数）のことです。&lt;code&gt;bind&lt;/code&gt; は Kleisli 関数を連鎖させる操作です。バリデーション関数（&lt;code&gt;Patron -&amp;gt; Either ValidationError Patron&lt;/code&gt;）は Kleisli 関数の典型例でした。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;10 章のメッセージが良いなと思ったので、日本語訳（訳：Claude）にて引用します。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;チェスと同じだ。もっとゲームをプレイしても上手くならない——構造とフィードバックが必要だ。マスターは「手」で考えない。「パターン」で考える。ボードをシステムとして見る：繰り返し可能、予測可能、合成可能。&lt;/p&gt;
&lt;p&gt;関数型プログラミングも同じシフトを提供する。より小さく、より安定した単位でロジックを合成するツールを与えてくれる——コードの書き方だけでなく、考え方そのものを形作る。&lt;/p&gt;
&lt;p&gt;そのシフトには練習が必要だ。マスタリーは見ることや繰り返すことからは来ない——作ること、実験すること、振り返ることから来る。FunPark の例を実行するだけではダメだ。バリエーションを試せ。自分のを作れ。壊して直せ。理解はそうやって深まる——一度にではなく、一歩一歩。&lt;/p&gt;
&lt;p&gt;この本は君の代わりに仕事はできない。でも道を照らす手助けはできる——何を練習するか、どの順番で、なぜ重要かを示すことで。注意を向けるべき場所、よくある落とし穴の避け方、目的を持って前に進む方法を示すことで。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;なっとく関数型プログラミング、関数型ドメインモデリング、本書と読んできて、だいぶ基本的な概念には馴染みが出てきました。一方で純粋関数型言語が主戦場ではないので、どうしても部分的に関数型っぽい感じで書くにとどまっており、関数型が身についているかというと微妙なところです。マスタリーを目指すために、Haskell を使ってパターン・メンタルモデルを染み込ませる活動をやっていこうと思います。&lt;/p&gt;
&lt;p&gt;また昨年末くらいまでは「関数型プログラミング」のレイヤーもよくわかっていませんでしたが、基礎の部分はだいぶ見えてきました。結果として TypeScript のライブラリで出てくるような概念（例：Optics）はまだリーチできていないことがわかりました。次は Scala の赤い本が良さそうなので読んでみようと思います。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>ページ内検索を活かすために仮想スクロールを採用しないという選択</title><link>https://ikuma-t.com/blog/in-page-search-without-virtual-scroll/</link><guid isPermaLink="true">https://ikuma-t.com/blog/in-page-search-without-virtual-scroll/</guid><description>この記事は株式会社エス・エム・エスAdventCalendar202512月15日の記事です。横断でのコンポーネント改修作業を効率化するために、コンポーネントの利用状況分析ツール「cuin」を個人で開</description><pubDate>Mon, 15 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;この記事は &lt;a href=&quot;https://qiita.com/advent-calendar/2025/bm-sms&quot; target=&quot;_blank&quot;&gt;株式会社エス・エム・エスAdvent Calendar2025&lt;/a&gt; 12月15日の記事です。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;横断でのコンポーネント改修作業を効率化するために、コンポーネントの利用状況分析ツール「&lt;a href=&quot;https://www.npmjs.com/package/@ikuma-t/cuin&quot; target=&quot;_blank&quot;&gt;cuin&lt;/a&gt;」を個人で開発しています &lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;p&gt;このツールは引数として受け取ったディレクトリを対象として、コンポーネントの利用状況の分析を行うことができます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# カレントディレクトリを対象&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;npx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;@ikuma-t/cuin&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# パス指定&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;npx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;@ikuma-t/cuin&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/path/to/directory&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;分析結果として、次の 2 つのコレクションをいくつかの検索条件を用いながら閲覧することができます。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. コンポーネント一覧&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;コンポーネント一覧ページのスクリーンショット&quot; loading=&quot;lazy&quot; width=&quot;2364&quot; height=&quot;1758&quot; src=&quot;/_astro/components.C3DZ9CHJ_1UMw.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. 特定のコンポーネントの利用箇所一覧（以下、詳細ページ）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;詳細ページのスクリーンショット&quot; loading=&quot;lazy&quot; width=&quot;2364&quot; height=&quot;1758&quot; src=&quot;/_astro/component-detail.D3II76bf_Z2dCCTU.png&quot; /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;今回はこのツールの開発において、ページ内検索を利用するために仮想スクロールを使わずに大きめのリストを表示するために行った試行錯誤をお伝えします。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#ページ内検索利用の経緯&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ページ内検索利用の経緯&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#静的解析の限界からテキスト検索の実装を検討&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;静的解析の限界からテキスト検索の実装を検討&lt;/h3&gt;
&lt;p&gt;詳細ページのファセットナビゲーションとして、「コンポーネントの利用箇所のパッケージ」と「使用されている Props とその値の分布」は必須と考え実装していました。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;利用箇所のパッケージと使用されているPropsによるフィルタリングを説明したスクリーンショット&quot; loading=&quot;lazy&quot; width=&quot;2364&quot; height=&quot;1758&quot; src=&quot;/_astro/detail-page-facet-navigation.De3aJFcD_R0Us8.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;これらに加えて検討していたのが、フリーテキストによる検索です。テキスト検索を検討した背景として、コンポーネントの静的解析の限界があります。AST によるコンポーネント解析はその性質上、動的に決まる値を完全に解析することはできません。&lt;/p&gt;
&lt;p&gt;たとえば次のコードにおいて、&lt;code&gt;value&lt;/code&gt;は文字列であることはわかりますが、その値は解析時に決定するものではありません。また&lt;code&gt;onChange&lt;/code&gt;には&lt;code&gt;handleInput&lt;/code&gt;が渡されていることがわかりますが、その定義は別の hooks からきています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { useState } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;react&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { useInput } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./useInput&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyComponent&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;setValue&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;useState&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;handleInput&lt;/span&gt;&lt;span&gt; } &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;useInput&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;text&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt;{value} &lt;/span&gt;&lt;span&gt;onChange&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{handleInput} /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;もちろん最終的な値が静的なものである場合は、定義元を多段で解析をしていくことで値を取得できますが、実行コストがかかるのでこのツールでは対応していません。&lt;/p&gt;
&lt;p&gt;解析を緩めにすることで絞り込みできないケースへの補助的な手段として、テキストによるコンポーネント利用状況の検索を検討していました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#自前実装を見送った理由&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;自前実装を見送った理由&lt;/h3&gt;
&lt;p&gt;検討をしてみたはいいものの、Props や Package のような絞り込み方法が明白なプロパティと異なり、テキスト検索は精度・結果の表示それぞれに自由度があり、どう実装するかが非常に悩みどころでした。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;完全一致で検索させるのか、曖昧検索をするのか&lt;/li&gt;
&lt;li&gt;ソースコードの改行を考慮して検索をするのか&lt;/li&gt;
&lt;li&gt;検索結果はハイライトするのか&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;加えてドッグフーディングをしてみても、そもそもテキストで検索したいケースが常ではなかった（いつもなくてもいいけど、たまに心が検索したがる程度）ため、どう配置しても「かえって邪魔になる」という始末。&lt;/p&gt;
&lt;p&gt;そのため今回はテキスト検索の機能としては実装せず、検索したくなった時にはブラウザのページ内検索を活用する方針としました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#仮想スクロールではページ内検索ができない&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;仮想スクロールではページ内検索ができない&lt;/h2&gt;
&lt;p&gt;ページ内検索自体は普通にブラウザを使っていれば使える機能ですが、このツールでは当初仮想スクロールを採用しており、ページ内検索を利用することができませんでした。&lt;/p&gt;
&lt;p&gt;仮想スクロールは表示されていない範囲の DOM を描画しないため、ビューポートに現れない要素についてはページ内検索の対象になりません。&lt;/p&gt;
&lt;p&gt;仮想スクロールを利用していたのは、いずれのコレクションも少なくとも 1,000 件以上の表示 (詳細ページは 5,000 件) を想定していたことや、詳細ページは特に1要素ごとの情報も多いためです。&lt;/p&gt;
&lt;p&gt;ページ内検索を利用できるようにするために何の工夫もなしに仮想スクロールをやめてみたところ、初期描画は辛うじて出来ても、以降のフィルタリングやソートで画面がフリーズしてしまったことから、いくつか調整を行う必要がありました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#仮想スクロールを使わずに描画するための調整&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;仮想スクロールを使わずに描画するための調整&lt;/h2&gt;
&lt;p&gt;ここからは仮想スクロールを使わずにリストを表示するために行なった試行錯誤を紹介します。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#前提&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;前提&lt;/h3&gt;
&lt;p&gt;実装の制約として、以下の理由でReact Server Component や Astro といった (ランタイムかビルド時に関わらず)サーバを要求するアーキテクチャは使えないことを前置きしておきます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;npm として配布する関係上、UI 部分を事前にビルドしておきたいため&lt;/li&gt;
&lt;li&gt;将来的に GitHub Pages などの静的ホスティングを行いたい場合に、サーバランタイムが足かせになるため&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p&gt;また以降で述べる話については、全体的にパフォーマンスの根拠となる検証値がないのですが、悪しからず…。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#react-から-solidjs-への切り替え&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;React から SolidJS への切り替え&lt;/h3&gt;
&lt;p&gt;いきなりだいぶ荒療治ですが、React で書かれていたコンポーネントを &lt;a href=&quot;https://www.solidjs.com/&quot; target=&quot;_blank&quot;&gt;SolidJS&lt;/a&gt; に置き換えました。&lt;/p&gt;
&lt;p&gt;もちろん React のまま &lt;code&gt;useMemo&lt;/code&gt; や &lt;code&gt;useDeferredValue&lt;/code&gt; を利用して適切なレンダリング・体験に調整していく方法もありますが、画面数も多くなかったことと、クライアントサイドフィルタリングが重いことから、いっそのこと仮想 DOM を使わないのが近道なのでは？と思い、バッサリ切り替えました。&lt;/p&gt;
&lt;p&gt;なお仮想 DOM を使わないフレームワークの選択としては Svelte、 Vue Vapor Mode、SolidJS、（部分的に）Qwik などがありますが、もともと JSX で書いていたことからそれを維持できる SolidJS を採択しています。&lt;/p&gt;
&lt;p&gt;この時点で一覧ページでのフィルタリング、詳細ページも 500 件くらいであればフリーズせずに動作するようになりました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#details-要素を利用する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;details 要素を利用する&lt;/h3&gt;
&lt;p&gt;SolidJS への切り替えだけでは詳細ページの想定件数に届いていないのでもう少し調整が必要です。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;details要素を使ったコンポーネントの利用詳細の1要素のスクリーンショット&quot; loading=&quot;lazy&quot; width=&quot;1588&quot; height=&quot;608&quot; src=&quot;/_astro/details.CZGofLih_1WJXe.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;仕様としてコンポーネントの各要素はいわゆるアコーディオン UI としています。初期実装では特に深く考えず UI ライブラリ（Ark UI）の Accordion を利用していましたが、これを HTML の &lt;code&gt;details&lt;/code&gt; 要素に置き換えました。&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;details&lt;/code&gt; 要素に置き換えるメリットは次の 2 つです。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;アコーディオン自体を表現するための JavaScript が不要になる&lt;/li&gt;
&lt;li&gt;（Safari を除くブラウザで &lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;）&lt;code&gt;details&lt;/code&gt; が閉じていても、内部をページ内検索できる &lt;sup&gt;&lt;a href=&quot;#user-content-fn-3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;code&gt;details&lt;/code&gt; 要素自体は &lt;code&gt;open&lt;/code&gt; 属性を指定することで開閉状態を切り替えることができます。今回の実装では表示する要素が 300 件を超えた場合、&lt;code&gt;open=false&lt;/code&gt; で &lt;code&gt;details&lt;/code&gt; 要素を閉じた状態で初期表示するようにしました。&lt;/p&gt;
&lt;p&gt;false になっている要素は DOM として存在しますが、描画処理自体は行われないため、初期描画時の負荷を削減できます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#details-の開閉をバッチ処理にする&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;details の開閉をバッチ処理にする&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;details&lt;/code&gt; 要素が閉じることで初期描画は軽くできますが、実際に閲覧する際に1つ1つ &lt;code&gt;details&lt;/code&gt; 要素を開いていくことはストレスなので、合わせて全開閉用のボタンも配置しています。&lt;/p&gt;
&lt;p&gt;開閉自体は先述の通り &lt;code&gt;open&lt;/code&gt; を変更したい状態に合わせて書き換える（開くのであれば &lt;code&gt;open=true&lt;/code&gt;）だけなのですが、これも純粋にループで行うと開閉処理中は画面が固まってしまいます。&lt;/p&gt;
&lt;p&gt;そのためいくらかの件数ごとにバッチ処理にした上で、Viewport の中央から放射線状に開閉が行われていく実装としました。単純なバッチ処理としていないのは、上から順にバッチで開閉していくと、リスト下部にいた際にボタンを押したタイミングと開閉が行われるタイミングがズレるためです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;DEFAULT_BATCH_SIZE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// 全details要素の取得（実態はSet）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;items&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Array&lt;/span&gt;&lt;span&gt;&lt;span&gt;.from&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;getItems&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// ビューポートの中央の要素を取得&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;centerIndex&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;findCenterElement&lt;/span&gt;&lt;span&gt;(items);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// 要素の中央から順にインデックスを配置&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;indices&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;centerOutIndices&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;items&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; centerIndex);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// バッチサイズごとに分割して処理を実施する&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;batches&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;batchIterate&lt;/span&gt;&lt;span&gt;(indices&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;DEFAULT_BATCH_SIZE&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt;&amp;gt;((resolve) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;processBatch&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; { value: &lt;/span&gt;&lt;span&gt;batch&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;done&lt;/span&gt;&lt;span&gt; } &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;batches&lt;/span&gt;&lt;span&gt;&lt;span&gt;.next&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (done) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;resolve&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;idx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;of&lt;/span&gt;&lt;span&gt; batch) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;// callbackでdetailsのトグルを開閉&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;callback&lt;/span&gt;&lt;span&gt;(items[idx]);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;requestAnimationFrame&lt;/span&gt;&lt;span&gt;(processBatch);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;requestAnimationFrame&lt;/span&gt;&lt;span&gt;(processBatch);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;

省略した関数部分
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;findCenterElement&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;E&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;HTMLElement&lt;/span&gt;&lt;span&gt;&amp;gt;(&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;items&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;E&lt;/span&gt;&lt;span&gt;[]&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;target&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;window&lt;/span&gt;&lt;span&gt;.innerHeight &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; low &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; high &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;items&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;while&lt;/span&gt;&lt;span&gt; (low &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; high) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// biome-ignore lint/suspicious/noBitwiseOperators: perf&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mid&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (low &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; high) &lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rect&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; items[mid]&lt;/span&gt;&lt;span&gt;.getBoundingClientRect&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pos&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rect&lt;/span&gt;&lt;span&gt;.top &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rect&lt;/span&gt;&lt;span&gt;.height &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (pos &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; target) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;low &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; mid &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;high &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; mid;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;candidates&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [low &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; low&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; low &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;.filter&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;(i) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;&amp;gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;items&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; closestIndex &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; candidates[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; closestDistance &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Number&lt;/span&gt;&lt;span&gt;.POSITIVE_INFINITY;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;of&lt;/span&gt;&lt;span&gt; candidates) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rect&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; items[i]&lt;/span&gt;&lt;span&gt;.getBoundingClientRect&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pos&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rect&lt;/span&gt;&lt;span&gt;.top &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rect&lt;/span&gt;&lt;span&gt;.height &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;distance&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Math&lt;/span&gt;&lt;span&gt;&lt;span&gt;.abs&lt;/span&gt;&lt;span&gt;(pos &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; target);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (distance &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; closestDistance) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;closestDistance &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; distance;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;closestIndex &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; i;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; closestIndex;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;function*&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;centerOutIndices&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;totalCount&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;centerIndex&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Generator&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (totalCount &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;center&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;clamp&lt;/span&gt;&lt;span&gt;(centerIndex&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; totalCount &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; upper &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; center;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; lower &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; center &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;while&lt;/span&gt;&lt;span&gt; (upper &lt;/span&gt;&lt;span&gt;&amp;gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;span&gt; lower &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; totalCount) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (upper &lt;/span&gt;&lt;span&gt;&amp;gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;yield&lt;/span&gt;&lt;span&gt; upper;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;upper &lt;/span&gt;&lt;span&gt;-=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (lower &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; totalCount) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;yield&lt;/span&gt;&lt;span&gt; lower;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;lower &lt;/span&gt;&lt;span&gt;+=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;function*&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;batchIterate&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt;(&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;items&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Iterable&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;batchSize&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Generator&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[]&amp;gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; batch&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;item&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;of&lt;/span&gt;&lt;span&gt; items) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;batch&lt;/span&gt;&lt;span&gt;&lt;span&gt;.push&lt;/span&gt;&lt;span&gt;(item);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;batch&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;gt;=&lt;/span&gt;&lt;span&gt; batchSize) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;yield&lt;/span&gt;&lt;span&gt; batch;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;batch &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;batch&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;yield&lt;/span&gt;&lt;span&gt; batch;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;

&lt;p&gt;開閉ではないですが、イメージとしては以下の動画のように中央から徐々に処理を適用します。&lt;/p&gt;

  

&lt;p&gt;これを実際にツールに適用したものが次の動画です。&lt;/p&gt;

  

&lt;p&gt;リスト全体の中央付近で「ExpandAll」をクリックした際に、detailsを開く作業は3秒程度かかっている（右上のExpandAllがdisabledになっている）のですが、ビューポートで見えている範囲については開く作業が瞬時に終わっています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#content-visibility-を利用して要素の描画をやめる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;content-visibility を利用して要素の描画をやめる&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;details&lt;/code&gt; 要素で描画するようにして、大量件数の場合に初期描画で閉じるようにしても、各要素をすべて開いた場合には描画は重くなります。その対策として各 &lt;code&gt;details&lt;/code&gt; 要素には &lt;code&gt;content-visibility: auto&lt;/code&gt; を付与しています。&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;content-visibility&lt;/code&gt; は要素がビューポートに近づくまで要素のレンダリングを遅らせることができる CSS プロパティです。CSS 版仮想スクロールみたいなものですが、JavaScript での仮想スクロールと異なり、要素自体は DOM に存在するためページ内検索の対象になります。&lt;/p&gt;
&lt;p&gt;このプロパティを&lt;code&gt;details&lt;/code&gt;のコンテンツ部分に適用し、リスト下部の不要な要素のレンダリングを抑制しました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#shiki-のハイライトを遅延させる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Shiki のハイライトを遅延させる&lt;/h3&gt;
&lt;p&gt;各 &lt;code&gt;details&lt;/code&gt; の要素は利用箇所のコードブロックを持っており、これは &lt;a href=&quot;https://shiki.matsu.io/&quot; target=&quot;_blank&quot;&gt;Shiki&lt;/a&gt; によってシンタックスハイライトされています（本当はシンタックスハイライトのような処理は事前ビルド or サーバサイドでやれると良いのですが、前提の通りクライアントサイドでハイライトをする必要があります）。&lt;/p&gt;
&lt;p&gt;シンタックスハイライトは &lt;code&gt;details&lt;/code&gt; に含まれる要素の中では比較的重い JavaScript 処理なので、要素が実際にビューポートに入るまでは処理を遅延したいです。先ほどの&lt;code&gt;content-visibility&lt;/code&gt;はあくまでDOMの話なので、JavaScriptに対しては別途制御をかける必要があります。&lt;/p&gt;
&lt;p&gt;こういうケースでは &lt;code&gt;IntersectionObserver&lt;/code&gt; を利用してビューポートに入ったかを監視することが多いと思いますが、今回のように&lt;code&gt;content-visibility: auto&lt;/code&gt; を活用している前提においては &lt;code&gt;contentvisibilityautostatechange&lt;/code&gt; イベントを利用することができます&lt;sup&gt;&lt;a href=&quot;#user-content-fn-4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/API/Element/contentvisibilityautostatechange_event&quot; target=&quot;_blank&quot;&gt;Element: contentvisibilityautostatechange イベント - Web API | MDN&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;contentvisibilityautostatechange&lt;/code&gt;イベントは &lt;code&gt;content-visibility: auto&lt;/code&gt; が適用された要素のレンダリング状態が変化した時に発火するイベントで、対象の要素のレンダリングがスキップされるかどうかを &lt;code&gt;skipped&lt;/code&gt; で判定することができます。&lt;/p&gt;
&lt;p&gt;MDN のコード例がわかりやすいので拝借します（引用元：&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/API/ContentVisibilityAutoStateChangeEvent&quot; target=&quot;_blank&quot;&gt;ContentVisibilityAutoStateChangeEvent - Web API | MDN&lt;/a&gt;）。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;canvasElem&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;document&lt;/span&gt;&lt;span&gt;&lt;span&gt;.querySelector&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;canvas&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;canvasElem&lt;/span&gt;&lt;span&gt;&lt;span&gt;.addEventListener&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;contentvisibilityautostatechange&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; stateChanged);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;canvasElem&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;style&lt;/span&gt;&lt;span&gt;.contentVisibility &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;auto&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;stateChanged&lt;/span&gt;&lt;span&gt;(event) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;event&lt;/span&gt;&lt;span&gt;.skipped) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;stopCanvasUpdates&lt;/span&gt;&lt;span&gt;(canvasElem);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;startCanvasUpdates&lt;/span&gt;&lt;span&gt;(canvasElem);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// キャンバスの更新を始める必要があるときに呼び出されます。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;startCanvasUpdates&lt;/span&gt;&lt;span&gt;(canvas) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// …&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// キャンバスの更新を停止する必要がある場合に呼び出されます。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;stopCanvasUpdates&lt;/span&gt;&lt;span&gt;(canvas) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// …&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;stateChanged&lt;/code&gt; 関数で使われている &lt;code&gt;skipped&lt;/code&gt; がこのイベント固有のプロパティで、レンダリングされる場合（=ビューポートに &lt;code&gt;content-visibility: auto&lt;/code&gt; の要素が近づいた場合）は &lt;code&gt;false&lt;/code&gt;(=レンダリングする) になります。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;同様の仕組みを適用することで、前述の仕組みと合わせて、&lt;code&gt;details&lt;/code&gt; 要素が開いた状態でビューポートに近づくまでシンタックスハイライトを行わないようにすることできます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// ※ コードはイメージです&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;handleStateChange&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (e&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ContentVisibilityAutoStateChangeEvent&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;.skipped) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;syntaxHighlight&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;details&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;summary&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ChevronDownIcon&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;{&lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt;.summary}&amp;lt;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;summary&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;onContentVisibilityAutoStateChange&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt;{handleStateChange} &lt;/span&gt;&lt;span&gt;style&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;content-visibility&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;auto&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;contain-intrinsic-size&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;auto 200px&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}}&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt;.children}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;details&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#デモ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;デモ&lt;/h2&gt;

  

&lt;p&gt;約5,000件の利用箇所をもつコンポーネント（というか&lt;code&gt;div&lt;/code&gt;ですが）を対象に操作をしてみました。ページ内検索は検索してからブラウザ側のフィードバックが返ってくるまでに少し時間がかかりますが、仮想スクロールなしでページが固まることもなく、ページ内検索も利用できました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;今回はページ内検索を活かすために、仮想スクロールを使わずにそれなりの要素を描画するための試行錯誤を紹介しました。&lt;/p&gt;
&lt;p&gt;今回採択している方針や検証の基準は、利用ユーザーが開発者であるという前提のもとに、「NEWLY AVAILABLE であっても問題なし」「（開発者である自分の PC で）ある程度軽快に動けばよし」という判断をしているものなので、すべてのケースでそのまま利用できるわけではありませんが、仮想スクロールを使いたくないケースでの実装の参考になればと思います。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;以上、&lt;a href=&quot;https://qiita.com/advent-calendar/2025/bm-sms&quot; target=&quot;_blank&quot;&gt;株式会社エス・エム・エスAdvent Calendar2025&lt;/a&gt; 12月15日の記事でした！明日は&lt;a href=&quot;https://x.com/Schumi543&quot; target=&quot;_blank&quot;&gt;@Schumi543&lt;/a&gt;さんです！&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;&lt;a href=&quot;#footnote-label&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;ツール開発の背景については、&lt;a href=&quot;https://speakerdeck.com/ikumatadokoro/querying-design-system-dezainsisutemunoyi-si-jue-ding-wozhi-erugou-zao-jian-suo&quot; target=&quot;_blank&quot;&gt;スライド - Speakerdeck&lt;/a&gt; にあるのでそちらを参照してください。 &lt;a href=&quot;#user-content-fnref-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;2025/12 月時点の実装状況による。Chrome、Edge、Firefoxの各Stable版、Safari（Technology Preview）で実装済。refs: &lt;a href=&quot;https://wpt.fyi/results/html?label=master&amp;amp;label=stable&amp;amp;aligned&amp;amp;view=interop&amp;amp;q=label:interop-2025-details&quot; target=&quot;_blank&quot;&gt;https://wpt.fyi/results/html?label=master&amp;amp;label=stable&amp;amp;aligned&amp;amp;view=interop&amp;amp;q=label:interop-2025-details&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;2 についてはライブラリによっては対応しているものがあるかもしれませんが、もともと使っていた &lt;a href=&quot;https://ark-ui.com/docs/components/accordion&quot; target=&quot;_blank&quot;&gt;Accordion | Ark UI&lt;/a&gt; ではページ内検索の対象とならないようでした。 &lt;a href=&quot;#user-content-fnref-3&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;contentvisibilityautostatechangeのBaselineは&lt;code&gt;content-visibility&lt;/code&gt;と同じです。 &lt;a href=&quot;#user-content-fnref-4&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><author>ikuma-t</author></item><item><title>JSConf JP 2025に参加した</title><link>https://ikuma-t.com/blog/jsconfjp-2025/</link><guid isPermaLink="true">https://ikuma-t.com/blog/jsconfjp-2025/</guid><description>JSConfJP2025に参加してきました。現地参加は2年連続2回目です。PreEventJSConf.jp2025PreEvent-connpassLTの機会をいただけたので、今年はPreEvent</description><pubDate>Mon, 17 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://jsconf.jp/2025/ja&quot; target=&quot;_blank&quot;&gt;JSConf JP 2025&lt;/a&gt; に参加してきました。現地参加は 2 年連続 2 回目です。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#preevent&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;PreEvent&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://nodejs.connpass.com/event/371397/&quot; target=&quot;_blank&quot;&gt;JSConf.jp 2025 Pre Event - connpass&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;LT の機会をいただけたので、今年は PreEvent@Google 渋谷オフィス にも行きました。&lt;/p&gt;

&lt;p&gt;今年からデザインシステム関連の活動も少しずつやり始めていて、その中でコンポーネントの利用状況にアクセスできたら便利なのに（そしてそんなのはエンジニアリングの得意なところだろうに）と思って調べたり、自分で作っていたもの &lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; を発表しました。&lt;/p&gt;
&lt;p&gt;すでにツールがあることを知らなかったのは事実なんですが、実際 SaaS である Omlet を使わないとなると、react-scanner に何かしらの View を作りたくなると思うので、そのイメージにつながるといいなと思っています。&lt;/p&gt;
&lt;p&gt;発表中でも触れましたが、今回の内容に近いところを GitHub の人も言っているので、気になる方は見てみてください。&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;ここから本編&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;&lt;a href=&quot;#グッズ購入&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;グッズ購入&lt;/h2&gt;
&lt;p&gt;地味に楽しみにしていたグッズ購入。&lt;/p&gt;
&lt;p&gt;昨年は「接続安定 200」と書かれたのお守りを購入したんですが、今年はトートバッグとステッカーと缶バッジを購入。来場者がもらえる シャツとトートバッグも可愛くて使いやすそう。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&quot;lazy&quot; width=&quot;4000&quot; height=&quot;2252&quot; src=&quot;/_astro/bug-chan-goods.BLUjYGFx_1sYH43.jpg&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;MacBookに入手したステッカーを貼り付けている。W3Cの新しいロゴのステッカー、バグちゃんの404 TIME_NOT_FOUNDのステッカー、スパゲッティコードならぬ本当にスパゲティを食べているバグちゃんの缶バッジ、Baselineのロゴステッカーが並んでいる&quot; loading=&quot;lazy&quot; width=&quot;4000&quot; height=&quot;2252&quot; src=&quot;/_astro/bug-chan-sticker.By5hW4s9_P8on.jpg&quot; /&gt;&lt;/p&gt;
&lt;p&gt;いままで PC にステッカーを貼るタイプの人間ではなかったのですが、PreEvent 会場の Google さんから Baseline、サイボウズさんのスポンサーブースで W3C の新ロゴステッカーを入手できたこともあり、バグちゃんのステッカーと一緒に貼ることにしました。&lt;/p&gt;
&lt;p&gt;前日の PreEvent で作者の &lt;a href=&quot;https://x.com/shellyy_jelly?lang=ja&quot; target=&quot;_blank&quot;&gt;shelly&lt;/a&gt; さんにもお話できてよかった。来年のグッズも楽しみです。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#ブース&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ブース&lt;/h2&gt;
&lt;p&gt;多分全ブース回ったはず。サイボウズさんのブースで FE 横断の改善活動について聞けたのが面白かったです（「俺たちがコンテンツだ」は強い）。&lt;/p&gt;
&lt;p&gt;あとブース横のコーヒースタンドの従量課金コーヒー美味しかったです。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#セッション&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;セッション&lt;/h2&gt;
&lt;p&gt;聞いたセッション。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://jsconf.jp/2025/en/talks/vertical-text-web-javascript&quot; target=&quot;_blank&quot;&gt;縦書きWebの実用を支えるJavaScript | JSConf JP 2025&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://jsconf.jp/2025/en/talks/proposal-composites-object-comparison&quot; target=&quot;_blank&quot;&gt;Proposal-CompositesによるObject比較の未来 | JSConf JP 2025&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://jsconf.jp/2025/en/talks/error-prototype-stack&quot; target=&quot;_blank&quot;&gt;`Error.prototype.stack` の今と未来 | JSConf JP 2025&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://jsconf.jp/2025/en/talks/by-allen&quot; target=&quot;_blank&quot;&gt;From Chaos to Harmony: A History of JavaScript（混沌から調和へ ― JavaScriptの歴史） | JSConf JP 2025&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://jsconf.jp/2025/en/talks/andromeda-future-of-typescript&quot; target=&quot;_blank&quot;&gt;Andromeda - The Future Of TypeScript | JSConf JP 2025&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://jsconf.jp/2025/en/talks/evolving-nodejs-module-loader&quot; target=&quot;_blank&quot;&gt;Evolving the Node.js module loader | JSConf JP 2025&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://jsconf.jp/2025/en/talks/evolution-nodejs-inspector&quot; target=&quot;_blank&quot;&gt;Evolution of the Node.js Inspector | JSConf JP 2025&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://jsconf.jp/2025/en/talks/javascript-parser-using-support&quot; target=&quot;_blank&quot;&gt;JavaScript パーサーに using 対応をする過程で与えたエコシステムへの影響 | JSConf JP 2025&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://jsconf.jp/2025/en/talks/module-harmony&quot; target=&quot;_blank&quot;&gt;Module Harmony | JSConf JP 2025&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://jsconf.jp/2025/en/talks/technical-discussion-tc39&quot; target=&quot;_blank&quot;&gt;Technical Discussion with TC39 | JSConf JP 2025&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://jsconf.jp/2025/en/talks/sponsor-lt-session&quot; target=&quot;_blank&quot;&gt;Sponsor LT x 12 | JSConf JP 2025&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://jsconf.jp/2025/en/talks/embracing-technical-welfare-and-rediscovering-web-development&quot; target=&quot;_blank&quot;&gt;技術的福祉の受容、および Web 開発との「出会い直し」 | JSConf JP 2025&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;午後のセッション聞いているうちに「CommonJS…」という気持ちになりました😇&lt;/p&gt;
&lt;p&gt;どのセッションも DeepDive していて面白かったのですが、個人的には Technical Discussion with TC39 がすごい良かったですね。今出ている Proposal から話をしているので当たり前といえばそうなんですが、 そこまでのトークで出ていた Composites、Module Harmony、using、ES2015 など全部繋がっていてとても良いセッションでした。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#懇親会&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;懇親会&lt;/h2&gt;
&lt;p&gt;Nuxt の話、Electron の話、帳票エンジンの話など色々とお話できました。お話しいただいた皆さんありがとうございました。&lt;/p&gt;
&lt;p&gt;最近仮想 DOM を使わずに実装したい箇所があって SolidJS を選んでいるケースがあったんですが、Vue の Vapor Mode もあるぞ、という話を懇親会で教えてもらったのでちょっと試そうと思ってます。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;今年のセッションもどれも聞いていて刺激になるものばかりでした。JavaScript はやっぱり面白いですね。来年は自分も本セッションで話せるように、仕込んでいこうと思いました。&lt;/p&gt;
&lt;p&gt;運営の皆さん、登壇者の皆さん、素敵な機会をありがとうございました。また来年。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;&lt;a href=&quot;#footnote-label&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;だいぶ荒い実装ですが、一応公開しています。 &lt;a href=&quot;https://www.npmjs.com/package/@ikuma-t/cuin&quot; target=&quot;_blank&quot;&gt;https://www.npmjs.com/package/@ikuma-t/cuin&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><author>ikuma-t</author></item><item><title>goghを購入した（Steam版）</title><link>https://ikuma-t.com/blog/introduce-gogh/</link><guid isPermaLink="true">https://ikuma-t.com/blog/introduce-gogh/</guid><description>作業支援系アプリ？ゲームのgoghを購入しました。これ系のアプリを使ったことがないのですが、結構多機能です。アバター作成チル系のBGMタイマーTodo管理日課管理キャラ育成M3MacbookAirでも</description><pubDate>Sat, 23 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;goghのプレイ画面&quot; loading=&quot;lazy&quot; width=&quot;2360&quot; height=&quot;1640&quot; src=&quot;/_astro/gogh.B0reoaVx_Z2oaXWS.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;作業支援系アプリ？ゲームの &lt;a href=&quot;https://gogh.gg/about/jp&quot; target=&quot;_blank&quot;&gt;gogh&lt;/a&gt; を購入しました。これ系のアプリを使ったことがないのですが、結構多機能です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;アバター作成&lt;/li&gt;
&lt;li&gt;チル系の BGM&lt;/li&gt;
&lt;li&gt;タイマー&lt;/li&gt;
&lt;li&gt;Todo 管理&lt;/li&gt;
&lt;li&gt;日課管理&lt;/li&gt;
&lt;li&gt;キャラ育成&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;M3 Macbook Air でもサクサク動いています。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>スペースなしのGitエイリアスを設定する</title><link>https://ikuma-t.com/blog/dynamic-git-alias/</link><guid isPermaLink="true">https://ikuma-t.com/blog/dynamic-git-alias/</guid><description>Gitのエイリアス自分の環境では、gitに対してzshでgを割り当て、各gitコマンドに対してgitconfigでエイリアスを設定しています。.zshrcaliasg=&quot;git&quot;~/.config/g</description><pubDate>Sun, 10 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#git-のエイリアス&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Git のエイリアス&lt;/h2&gt;
&lt;p&gt;自分の環境では、&lt;code&gt;git&lt;/code&gt; に対して zsh で &lt;code&gt;g&lt;/code&gt; を割り当て、各 git コマンドに対して gitconfig でエイリアスを設定しています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;.zshrc&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;alias&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;git&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;~/.config/git/config&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[alias]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# [Basic Snapshotting]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;commit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--amend&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--no-edit&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;status&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;commit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-m&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;fix&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;commit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--fixup&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;fixup&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;!f() { git fix \&quot;$1\&quot; &amp;amp;&amp;amp; git ria \&quot;$1^\&quot;; }; f&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;restore&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;rs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;restore&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--staged&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;z&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;reset&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--soft&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;HEAD^&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;zs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;reset&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--soft&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;zh&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;reset&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--hard&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# [Branch and Merging]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;branch&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;co&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;checkout&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;sw&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;switch&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;swc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;switch&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-c&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;merge&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;stash&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ta&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;stash&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--apply&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;tp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;stash&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pop&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;td&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;stash&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;drop&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;tag&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tag&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;w&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;worktree&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;#[Sharing and Updating Projects]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fetch&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pull&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pf&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--force-if-includes&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--force-with-lease&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;remote&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;remote&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# [Inspection and Comparison]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;d&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;diff&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ds&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;diff&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--staged&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;たとえば commit であれば &lt;code&gt;g c&lt;/code&gt; で実行できるわけですが、毎回スペースを追加するのは面倒です。かといって、各コマンドごとにスペースを含まないエイリアス（コミットの例であれば、&lt;code&gt;gc=&apos;git commit&apos;&lt;/code&gt;）を都度貼るのは非効率です。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#スペースなし版エイリアスを自動で設定する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;スペースなし版エイリアスを自動で設定する&lt;/h2&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;.zshrc&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;command&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-v&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;git&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;/dev/null&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&amp;gt;&amp;amp;1&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; alias &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt;&lt;span&gt; $(&lt;/span&gt;&lt;span&gt;git&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;config&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--get-regexp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;^alias\.&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sed&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;s/^alias\.\([^ ]*\) .*/\1/&apos;&lt;/span&gt;&lt;span&gt;); &lt;/span&gt;&lt;span&gt;do&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;alias&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;${alias}&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;git ${alias}&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;done&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;fi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;git config --get-regexp&lt;/code&gt; で正規表現に一致した gitconfig の内容を取得できるので、これを使って動的にエイリアスを貼ります。&lt;/p&gt;
&lt;p&gt;これで次のようにスペースなしで git コマンドを実行できるようになります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;❯&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;alias&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;gc&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;gc&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&apos;git c&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;</content:encoded><author>ikuma-t</author></item><item><title>VSCodeでプロジェクトの設定と異なるSeverityでESLintエラーを報告する</title><link>https://ikuma-t.com/blog/eslint-rules-customization/</link><guid isPermaLink="true">https://ikuma-t.com/blog/eslint-rules-customization/</guid><description>課題：ESLintルールはそのままに、自分のエディタ上の表示を変更したいとあるTypeScriptプロジェクトにおいて、「あるESLintをチェックすることはOKだが、視認性の関係でエディタ上でのSe</description><pubDate>Sat, 01 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#課題-eslintルールはそのままに自分のエディタ上の表示を変更したい&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;課題： ESLintルールはそのままに、自分のエディタ上の表示を変更したい&lt;/h2&gt;
&lt;p&gt;とあるTypeScriptプロジェクトにおいて、「あるESLintをチェックすることはOKだが、視認性の関係でエディタ上でのSeverityを変更したい」という要求がありました。&lt;/p&gt;
&lt;p&gt;例えば&lt;code&gt;@typescript-eslint/no-unused-vars&lt;/code&gt;を&lt;code&gt;error&lt;/code&gt;に指定していると、使用していない変数がある場合にエディタ上で赤く波線が表示されます。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;未使用の変数hogeのVSCode上でホバーしている。Lintエラーであることを示す波線が変数名の下に出ており、エラーであるため赤い色で表示されている。&quot; loading=&quot;lazy&quot; width=&quot;1628&quot; height=&quot;402&quot; src=&quot;/_astro/no-unused-vars.B0ifbqUd_ZHSbOU.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;使われていない変数があることをチェックするのはルールとして残しておきたいが、エディタ上ではエラーではなく警告を示す黄色の波線として表示したい、という要求です。
解決策の一つは愚直にルールのSeverityを変更することですが、これは他の開発者にも影響を与えてしまうという問題があります。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#vscodeのeslintrulescustomizationsを使ってseverityを変更する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;VSCodeの&lt;code&gt;eslint.rules.customizations&lt;/code&gt;を使ってSeverityを変更する&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint&quot; target=&quot;_blank&quot;&gt;VSCodeのESLint拡張&lt;/a&gt;には、このような要求を満たすための設定があります。それが&lt;code&gt;eslint.rules.customizations&lt;/code&gt;です。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;eslint.rules.customizations (@since 2.1.20) - force rules to report a different severity within VS Code compared to the project’s true ESLint configuration. Contains these properties:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;設定できるプロパティは次の3つです。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;rule&lt;/code&gt;: 対象とするESLintのルール名。ワイルドカードとして&lt;code&gt;*&lt;/code&gt;、否定として&lt;code&gt;!&lt;/code&gt;が使えます。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;severity&lt;/code&gt;: ルールのSeverity。&lt;code&gt;default&lt;/code&gt;、&lt;code&gt;off&lt;/code&gt;、&lt;code&gt;info&lt;/code&gt;、&lt;code&gt;warn&lt;/code&gt;、&lt;code&gt;error&lt;/code&gt;、&lt;code&gt;downgrade&lt;/code&gt;、&lt;code&gt;upgrade&lt;/code&gt;のいずれかを指定します。 後2つはeslintの設定に対して緩めるか、厳しくするかの指定です。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fixable&lt;/code&gt;: autofixを有効にするかどうか。&lt;code&gt;true&lt;/code&gt;か&lt;code&gt;false&lt;/code&gt;を指定します（※autofixが可能なルールのみ）。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;先にあげた例を実現するならば、次のように設定します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;eslint.rules.customizations&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;rule&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;*no-unused-vars&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;severity&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;downgrade&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;// もしくはwarnでもよい&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;img alt=&quot;未使用の変数hogeのVSCode上でホバーしている。警告はエラーの時と同じだが、Lintエラーが出ていることを示す波線が警告の黄色になっている&quot; loading=&quot;lazy&quot; width=&quot;1326&quot; height=&quot;454&quot; src=&quot;/_astro/change-to-warn.D9vbnoX4_Z1Rf7CR.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;もともとエラーの赤線だったものが、警告の黄色線に変わり、期待していた挙動を実現できました。&lt;/p&gt;
&lt;p&gt;記載はユーザー固有のsettings.jsonでも適用されるため、もしプロジェクト全体に影響を与えたくない場合は個人の設定として適用することができます
（オーバーライドする設定なので、ワークスペース側の設定に書くことはないと思いますが）。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Astro Content Layer で個人ブログのコンテンツ取得はもっと楽になる</title><link>https://ikuma-t.com/blog/astro-content-layer/</link><guid isPermaLink="true">https://ikuma-t.com/blog/astro-content-layer/</guid><description>この記事は株式会社エス・エム・エスAdventCalendar202412月10日分の記事です。もうそろそろ冬休みですね。「冬休みは個人ブログを作って（あるいはリニューアルして）、来年はアウトプットを</description><pubDate>Tue, 10 Dec 2024 00:00:00 GMT</pubDate><content:encoded>&lt;article&gt;&lt;p&gt;この記事は &lt;a href=&quot;https://qiita.com/advent-calendar/2024/bm-sms&quot; target=&quot;_blank&quot;&gt;株式会社エス・エム・エス Advent Calendar 2024&lt;/a&gt; 12月10日 分の記事です。&lt;/p&gt;&lt;/article&gt;
&lt;p&gt;もうそろそろ冬休みですね。「冬休みは個人ブログを作って（あるいはリニューアルして）、来年はアウトプットを頑張るぞ！」という方も多いのではないでしょうか。&lt;/p&gt;
&lt;p&gt;Astro や Eleventy、Next.jsなど、各フレームワークによりMarkdownブログは超速で作れるようになりましたが、外部のCMSからデータを取得するとなるとやや面倒です。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://5-0-0-beta.docs.astro.build/en/guides/upgrade-to/v5/&quot; target=&quot;_blank&quot;&gt;Astro v5&lt;/a&gt; からは &lt;a href=&quot;https://astro.build/blog/future-of-astro-content-layer/&quot; target=&quot;_blank&quot;&gt;Content Layer&lt;/a&gt;という機能が追加され、外部のコンテンツデータを利用したサイト作成がより簡単になりました。この記事では、Content Layer が何を解決し、どのようにコンテンツサイト構築に使えるのかを紹介します。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#なぜ-content-layer-を使うのか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;なぜ Content Layer を使うのか&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#個人ブログ開発はどうコンテンツを取得するかが9割&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;個人ブログ開発はどうコンテンツを取得するかが9割&lt;/h3&gt;
&lt;p&gt;個人ブログを自作する際に必要な技術はさまざまですが、コアとなる技術はコンテンツを取得し HTML として描画できる形に変換することです。もちろん正しいマークアップや魅力的なスタイリングなども重要ですが、それらもコンテンツがあってこそ必要になるものであり、コンテンツがなければ何も始まりません。&lt;/p&gt;
&lt;p&gt;これまでの Astro においても、この部分を簡素化するために&lt;a href=&quot;https://5-0-0-beta.docs.astro.build/en/guides/content-collections/&quot; target=&quot;_blank&quot;&gt;Content Collections&lt;/a&gt;という機能が提供されていました。&lt;/p&gt;
&lt;p&gt;これは zod によるメタデータ（タイトルや公開日など）のバリデーションと、ファイルシステムからのデータ取得を簡単にするための Query API を提供するもので、以下のようなスキーマ情報を定義するだけで、Markdown ファイルによるブログ記事の取得を簡単に行うことができます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/content/config.ts&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { defineCollection&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; z } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;astro:content&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// defineCollection を用いて、ブログのメタ情報を定義（これとは別に本文が含まれる）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;blog&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;defineCollection&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;schema&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;z&lt;/span&gt;&lt;span&gt;&lt;span&gt;.object&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;z&lt;/span&gt;&lt;span&gt;&lt;span&gt;.string&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;z&lt;/span&gt;&lt;span&gt;&lt;span&gt;.string&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;.optional&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;publishDate&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;z&lt;/span&gt;&lt;span&gt;&lt;span&gt;.date&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;category&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;z&lt;/span&gt;&lt;span&gt;&lt;span&gt;.enum&lt;/span&gt;&lt;span&gt;([&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;tech&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;idea&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;life&apos;&lt;/span&gt;&lt;span&gt;&lt;span&gt;])&lt;/span&gt;&lt;span&gt;.default&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;idea&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;draft&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;z&lt;/span&gt;&lt;span&gt;&lt;span&gt;.boolean&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;.default&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;tags&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;z&lt;/span&gt;&lt;span&gt;&lt;span&gt;.optional&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;z&lt;/span&gt;&lt;span&gt;&lt;span&gt;.array&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;z&lt;/span&gt;&lt;span&gt;&lt;span&gt;.string&lt;/span&gt;&lt;span&gt;()))&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;collections&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; { blog };&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/pages/blog/1.astro&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { getEntry&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; render } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;astro:content&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;entry&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;getEntry&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;blog&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;1&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;Content&lt;/span&gt;&lt;span&gt; } &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;render&lt;/span&gt;&lt;span&gt;(entry);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;/* メタデータを表示する */&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;&amp;gt;Published on: {&lt;/span&gt;&lt;span&gt;entry&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;published&lt;/span&gt;&lt;span&gt;&lt;span&gt;.toDateString&lt;/span&gt;&lt;span&gt;()}&amp;lt;/&lt;/span&gt;&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;/* Markdownがhtmlに変換されているので、そのまま記事を描画できる */&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Content&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#content-layer-はコンテンツ取得を抽象化する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Content Layer はコンテンツ取得を抽象化する&lt;/h3&gt;
&lt;p&gt;Content Collections は便利な機能ですが、ローカルの Markdown ファイルでしか利用できないという課題がありました。&lt;/p&gt;
&lt;p&gt;そこで Content Collections をベースに、より抽象的に「コンテンツを取得する」機能を提供するのが Content Layer です。&lt;/p&gt;
&lt;p&gt;コンテンツを取得するためのAPI（Content Collections）はそのままに、次の概念が追加されています。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;代替テキスト&quot; loading=&quot;lazy&quot; width=&quot;5424&quot; height=&quot;1920&quot; src=&quot;/_astro/content-layer.C7EgzgiR_ZRCPrY.png&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Loader: データソースからデータをフェッチし、DataStore に格納するための関数&lt;/li&gt;
&lt;li&gt;Schema: zodにより定義された、コンテンツのメタデータのスキーマ情報&lt;/li&gt;
&lt;li&gt;DataStore: データソースから取得されたデータを保持するストア&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;DataEntry: DataStoreに格納される1つ1つのデータ。メタデータとして&lt;code&gt;data&lt;/code&gt;、HTMLとしてレンダリングされた際に表示するコンテンツとして&lt;code&gt;rendered&lt;/code&gt;を持つ。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;コンテンツが DataEntry として抽象化されたことによって、規定のインターフェースを満たすようにデータをフェッチして格納する関数さえ実装できれば、どのようなデータソースからでも同じようにデータを取得することができるようになりました。&lt;/p&gt;
&lt;p&gt;また Loader はビルド時（開発時はサーバ起動時）にすべてのデータをフェッチし、zodによるスキーマバリデーションを行うため、ランタイムでのデータ取得エラーやバリデーションエラーを防ぐことができます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#content-layer-の実例speakerdeck-の-rss-フィードから登壇ページを実装する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Content Layer の実例：Speakerdeck の RSS フィードから登壇ページを実装する&lt;/h3&gt;
&lt;p&gt;実例として、&lt;a href=&quot;/talk&quot;&gt;このサイトの登壇ページ&lt;/a&gt;は Speakerdeck の RSS と Content Layer を組み合わせて実現されています。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;代替テキスト&quot; loading=&quot;lazy&quot; width=&quot;836&quot; height=&quot;844&quot; src=&quot;/_astro/talk-page.BP8May8z_4gtey.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Content Layer がない場合、次の内容を自前で実装する必要がありました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Speakerdeck の RSS を fetch し、特定のデータ構造にパースする関数&lt;/li&gt;
&lt;li&gt;キャッシュ取得のビルドプロセスへの組み込み&lt;/li&gt;
&lt;li&gt;キャッシュデータからコンテンツを取得するユーティリティ関数&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Content Layer を利用することで、これらの実装を省略し、Speakerdeck のデータを取得するための Loader を実装するだけで済みます。
加えて RSS フィードについては、コミュニティですでに公開されている Loader があるため、自前で実装する必要もありません。&lt;/p&gt;
&lt;p&gt;マークアップは省略していますが、登壇ページの実装はおよそこれだけです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/content/config.ts&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { defineCollection } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;astro:content&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;talks&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;defineCollection&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// コミュニティで公開されている feedLoader を利用&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;loader&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;feedLoader&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;url&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;https://speakerdeck.com/ikumatadokoro.rss&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;collections&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;talks&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/pages/talk/index.astro&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { getCollection } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;astro:content&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;talks&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;getCollection&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;talks&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;talksByYear&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Map&lt;/span&gt;&lt;span&gt;&lt;span&gt;.groupBy&lt;/span&gt;&lt;span&gt;(talks&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; (talk) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;talk&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt;.pubdate&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;&lt;span&gt;.getFullYear&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;talksByYear&lt;/span&gt;&lt;span&gt;&lt;span&gt;.entries&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;.map&lt;/span&gt;&lt;span&gt;(([year&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; talks]) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;&amp;gt;{year}&amp;lt;/&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{talks.map((talk) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; (&amp;lt;&lt;/span&gt;&lt;span&gt;TalkCard&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;talk&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{talk} /&amp;gt;))}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;))}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#content-layer-を利用する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Content Layer を利用する&lt;/h2&gt;
&lt;p&gt;Content Layer を利用する際には、コミュニティで公開されている Loader を利用するか、独自の Loader を実装するかの2つの方法があります。&lt;/p&gt;
&lt;p&gt;細かい使い方や定義は &lt;a href=&quot;https://5-0-0-beta.docs.astro.build/en/reference/content-loader-reference/&quot; target=&quot;_blank&quot;&gt;Astro の公式ドキュメント&lt;/a&gt; に譲るとして、実際にどのような形式で使えるのかを見ていきます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#コミュニティが公開している-loader-を利用する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;コミュニティが公開している Loader を利用する&lt;/h3&gt;
&lt;p&gt;自分が利用したいデータソースの Loader がすでにコミュニティで公開されている場合は、それを利用することで手軽にコンテンツを取得できます。&lt;/p&gt;
&lt;p&gt;Loader は npm パッケージとして公開されており、現在公開されている Loader は &lt;a href=&quot;https://astro.build/integrations/?search=&amp;amp;categories%5B%5D=loaders&quot; target=&quot;_blank&quot;&gt;Astro公式のIntegration&lt;/a&gt; ページから確認することができます。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;代替テキスト&quot; loading=&quot;lazy&quot; width=&quot;1141&quot; height=&quot;1025&quot; src=&quot;/_astro/astro-integration.k7q0r7E6_Z1JXzl8.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;現在コミュニティで公開されている Loader の例としては、次のようなものがあります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Notion&lt;/li&gt;
&lt;li&gt;Google Spread Sheet&lt;/li&gt;
&lt;li&gt;RSS Feed&lt;/li&gt;
&lt;li&gt;GitHub Discussions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;使用方法は設定ファイルである &lt;code&gt;src/content/config.ts&lt;/code&gt; に対象の &lt;code&gt;loader&lt;/code&gt;を指定するだけです。&lt;/p&gt;
&lt;p&gt;多くの Loader は取得元を特定するために追加の引数を受け付けます。たとえば先ほど例に挙げた RSS の Loader は、取得元の URL を引数として受け付けます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/content/config.ts&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;talks&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;defineCollection&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// feedLoader は フィードの url を引数に取り、Loader を返す関数&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;loader&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;feedLoader&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;url&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;https://speakerdeck.com/ikumatadokoro.rss&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;この状態で開発サーバを起動すると、コンテンツの取得およびインメモリの KV ストアへの格納が行われ、RSS フィードから取得した内容をアプリ内で描画できるようになります。簡単ですね！&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#独自の-loader-を実装する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;独自の Loader を実装する&lt;/h3&gt;
&lt;p&gt;自分が利用したいデータソースのLoaderがない場合や、必要なメタ情報のスキーマが異なる場合は、自分で Loader を実装することもできます。&lt;/p&gt;
&lt;p&gt;Loader は&lt;code&gt;defineCollection&lt;/code&gt;の中に直接記述することもできますが（&lt;a href=&quot;https://5-0-0-beta.docs.astro.build/en/reference/content-loader-reference/#inline-loaders&quot; target=&quot;_blank&quot;&gt;Inline loaders&lt;/a&gt;）、保守性の観点から別途関数として定義することをおすすめします（&lt;a href=&quot;https://5-0-0-beta.docs.astro.build/en/reference/content-loader-reference/#object-loaders&quot; target=&quot;_blank&quot;&gt;Object loaders&lt;/a&gt;）。&lt;/p&gt;
&lt;p&gt;Loader関数の全体感は次のようになっており、最終的にLoaderの名前（&lt;code&gt;name&lt;/code&gt;）、スキーマ（&lt;code&gt;schema&lt;/code&gt;）、データ取得処理（&lt;code&gt;load&lt;/code&gt;）をプロパティに持つオブジェクトを返すように実装します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;src/content/loader/awesomeLoader.ts&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; Loader&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; LoaderContext } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;astro/loaders&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;awesomeLoader&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (options&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { yourApiOptions&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Loader&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;schema&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/* メタデータのスキーマ定義 */&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;load&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/* データ取得処理 */&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; { name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;awesomeLoader&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; schema&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; load };&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;schema&lt;/code&gt;はタイトルや日付、タグなどのコンテンツのメタ情報を表すもので、zodにより定義されます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;schema&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;z&lt;/span&gt;&lt;span&gt;&lt;span&gt;.object&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;z&lt;/span&gt;&lt;span&gt;&lt;span&gt;.string&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;createdAt&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;z&lt;/span&gt;&lt;span&gt;&lt;span&gt;.date&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;load&lt;/code&gt;はデータを取得して DataStore に格納するための関数です。利用したいデータソースによって詳細な実装は変わりますが、大まかには次の3段構成で捉えると実装しやすいでしょう。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;load&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; (context&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;LoaderContext&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// 1. データを取得し、必要に応じて加工する&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;apiUrl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;https://...&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fetch&lt;/span&gt;&lt;span&gt;(apiUrl);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt;&lt;span&gt;.json&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// 2. 取得したデータのバリデーションを行う&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;parsedData&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;&lt;span&gt;.parseData&lt;/span&gt;&lt;span&gt;(json);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// 3. データをStoreに保存する&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;store&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;.store;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;store&lt;/span&gt;&lt;span&gt;&lt;span&gt;.set&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;parsedData&lt;/span&gt;&lt;span&gt;.id&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;data: parsedData&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;rendered&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;html&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;parseData&lt;/span&gt;&lt;span&gt;.body&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;context&lt;/code&gt;からは Loader に必要な情報が提供されており、具体的には Vite の機能を利用したHMRを実現するための&lt;code&gt;watcher&lt;/code&gt;や、ログを記録するための&lt;code&gt;logger&lt;/code&gt;などがあります。&lt;/p&gt;
&lt;p&gt;より詳細を知りたい方は &lt;a href=&quot;https://5-0-0-beta.docs.astro.build/en/reference/content-loader-reference/#loadercontext&quot; target=&quot;_blank&quot;&gt;Astro Content Loader API | Docs&lt;/a&gt; を参照してください。&lt;/p&gt;
&lt;article&gt;&lt;p&gt;コラム：Markdownコンテンツのパース&lt;/p&gt;&lt;p&gt;実際にLoaderを実装しようとすると、MarkdownコンテンツをHTMLとして扱えるようにしたいケースが多いと思います。&lt;/p&gt;&lt;p&gt;Astro が提供する&lt;code&gt;render&lt;/code&gt; APIを用いることで、DataStoreに格納された各DataEntryの&lt;code&gt;rendered&lt;/code&gt;プロパティをHTMLとして描画できます。&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { render } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;astro:content&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;entry&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;getEntry&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;blog&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;1&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;Content&lt;/span&gt;&lt;span&gt; } &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;render&lt;/span&gt;&lt;span&gt;(entry);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Content&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;しかしこの&lt;code&gt;render&lt;/code&gt;関数はあくまで&lt;code&gt;string&lt;/code&gt;型の&lt;code&gt;entry.rendered.html&lt;/code&gt;をそのまま表示するだけで、MarkdownをHTMLに変換する機能は内包されていません。&lt;/p&gt;&lt;p&gt;この部分は自前で実装する必要があり、たとえば&lt;code&gt;@astrojs/markdown-remark&lt;/code&gt;を利用することでMarkdownをHTMLに変換することができます。&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { AstroConfig } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;astro&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { DataEntry } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;astro:content&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { createMarkdownProcessor } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;@astrojs/markdown-remark&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;renderToString&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; (config&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;AstroConfig&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; entry&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;DataEntry&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;processor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;createMarkdownProcessor&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;config&lt;/span&gt;&lt;span&gt;.markdown);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;processor&lt;/span&gt;&lt;span&gt;&lt;span&gt;.render&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;entry&lt;/span&gt;&lt;span&gt;.body &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;html&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt;.code&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/article&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;

&lt;p&gt;2024年は人生初の北海道（生まれてからずっと千葉県民）のカンファレンス&lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;に行き、「個人ブログ、もうリニューアルしないぞ！」という発表をしてきました。&lt;/p&gt;
&lt;p&gt;長期休みは個人ブログを作り直しがちで、ちょうど1年前のお正月にブログを作り直しています…。北の大地で交わした約束を反故にするわけにもいきませんので、今年の年末年始は自分ではない誰かのブログをリニューアルさせることを目標にこちらの記事を執筆しました。&lt;/p&gt;
&lt;p&gt;冗談はさておき。個人ブログを開発することは、普段扱っているアプリケーションとは異なる視点での開発ができるためおすすめです。今回紹介した Content Layer を使って、より簡単にコンテンツを取得することができるようになりましたので、ぜひ今年の年末年始は個人ブログを作ってみてはいかがでしょうか。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#参考&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;参考&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://astro.build/blog/future-of-astro-content-layer/&quot; target=&quot;_blank&quot;&gt;The Astro Content Layer | Astro&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://5-0-0-beta.docs.astro.build/en/guides/content-collections/&quot; target=&quot;_blank&quot;&gt;Content collections | Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.astro.build/ja/guides/content-collections/#%E3%82%B3%E3%83%AC%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E5%AE%9A%E7%BE%A9&quot; target=&quot;_blank&quot;&gt;コンテンツコレクション | Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://5-0-0-beta.docs.astro.build/en/reference/content-loader-reference/&quot; target=&quot;_blank&quot;&gt;Astro Content Loader API | Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section&gt;&lt;h2&gt;&lt;a href=&quot;#footnote-label&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;記事執筆時点（2024/12/10）ではインメモリのKey-Valueストアとして実装されている &lt;a href=&quot;#user-content-fnref-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://techramenconf.net/&quot; target=&quot;_blank&quot;&gt;Tech RAMEN Conference 2024&lt;/a&gt;。旭川で開催されたいろいろと異色のカンファレンス。 &lt;a href=&quot;#user-content-fnref-2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><author>ikuma-t</author></item><item><title>Make Impossible States Impossibleを意識してReactのPropsを設計する</title><link>https://ikuma-t.com/blog/make-impossible-states-impossible/</link><guid isPermaLink="true">https://ikuma-t.com/blog/make-impossible-states-impossible/</guid><description>このブログ記事は下記のLT登壇資料を文字起こし（？）したものです。Reactが関数型プログラミングの影響を受けているということをきっかけに、最近1は関数型プログラミングを少しずつ学んでいます。関数型プ</description><pubDate>Fri, 15 Nov 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;このブログ記事は下記のLT登壇資料を文字起こし（？）したものです。&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;Reactが関数型プログラミングの影響を受けているということをきっかけに、最近 &lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; は関数型プログラミングを少しずつ学んでいます。&lt;/p&gt;
&lt;p&gt;関数型プログラミングそのものにももちろん興味はありつつ、日常のプログラミングで使えるエッセンスとしても何か学びはないか、という視点で向き合っています。
いろいろとやっていく中で、「Make Impossible States Impossible」という考えを知りました 。「不可能な状態が起こらないように型/インターフェイスを設計しよう」という意味です。&lt;/p&gt;
&lt;p&gt;考え方自体はAPIの設計において汎用的に使える指針であり、フロントエンドに関連のある領域だと、&lt;a href=&quot;https://book.productionreadygraphql.com/&quot; target=&quot;_blank&quot;&gt;Production Ready GraphQL&lt;/a&gt;や&lt;a href=&quot;https://kentcdodds.com/blog/make-impossible-states-impossible&quot; target=&quot;_blank&quot;&gt;Kent C. Dodds氏のブログ記事&lt;/a&gt;で取り上げられていました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#make-impossible-states-impossible-とは&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Make Impossible States Impossible とは&lt;/h2&gt;
&lt;p&gt;繰り返しになりますが、&lt;strong&gt;Make Impossible States Impossible&lt;/strong&gt;、あるいは &lt;strong&gt;Make Illegal States Unrepresentable&lt;/strong&gt; は「不可能な状態が起こらないように型/インターフェイスを設計しよう」という設計思想です。&lt;/p&gt;
&lt;p&gt;関数型プログラミング言語のコミュニティを出自とする設計思想で、TypeScriptやReactの界隈でも何度か取り上げられているようです。少し前に日本語訳が発売された&lt;a href=&quot;https://www.amazon.co.jp/dp/B0DDBPNBVJ&quot; target=&quot;_blank&quot;&gt;関数型ドメインモデリング&lt;/a&gt;でも「Making Illigal States Unrepresentable In Our Domain」というセクションで紹介されています。&lt;/p&gt;
&lt;p&gt;具体的な出典については、&lt;a href=&quot;/blog/make-impossible-states-impossible#make-impossible-states-impossible--make-illegal-states-unrepresentable-%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E8%A8%80%E5%8F%8A%E3%81%95%E3%82%8C%E3%81%9F%E8%A8%98%E4%BA%8B%E5%8B%95%E7%94%BB&quot;&gt;Appendix&lt;/a&gt;に掲載しましたので、そちらをご参照ください。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#reactでの実践例&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Reactでの実践例&lt;/h2&gt;
&lt;p&gt;ここからはReactのコードを例に、Make Impossible States Impossibleの適用を見てみます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#単一のプロパティでの例はさほど問題にならない&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;単一のプロパティでの例はさほど問題にならない&lt;/h3&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;たとえば&lt;code&gt;primary&lt;/code&gt;と&lt;code&gt;secondary&lt;/code&gt;、2つのスタイルを持つボタンコンポーネントを考えます。&lt;/p&gt;
&lt;p&gt;実装パターンの1つはそれぞれをスイッチ的なフラグで定義することです（2値しかないと、1つのフラグで管理することが可能ですが、ここではサンプルのためご容赦ください）。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Props&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;primary&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;secondary&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Button&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;primary&lt;/span&gt;&lt;span&gt; /&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// primary&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Button&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;secondary&lt;/span&gt;&lt;span&gt; /&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// secondary&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これは一見良さそうですが、少し考えると&lt;code&gt;primary&lt;/code&gt;と&lt;code&gt;secondary&lt;/code&gt;を同時に指定することができてしまいます。これは不整合な状態を引き起こします。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Button&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;primary&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;secondary&lt;/span&gt;&lt;span&gt; /&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// ??&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;この例では、&lt;code&gt;primary&lt;/code&gt;と&lt;code&gt;secondary&lt;/code&gt;のそれぞれが2つの値を取るため、合計で4つの状態が考えられます。このように、プロパティの数が増えると、「プロパティが取りうる値のパターン」と「プロパティの数」の積だけ状態が増えてしまい、結果として不正な状態が発生しやすくなります。&lt;/p&gt;
&lt;p&gt;これを解消するための方法の1つは、Union型を使ってプロパティを排他的に定義することです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Props&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;variant&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;primary&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;secondary&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Button&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;variant&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;primary&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Button&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;variant&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;secondary&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;variant&lt;/code&gt;&lt;sup&gt;&lt;a href=&quot;#user-content-fn-3&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;は&lt;code&gt;primary&lt;/code&gt;か&lt;code&gt;secondary&lt;/code&gt;のどちらかを取るため、不正な状態が発生しません。また取りうる状態も2つ（取りうる値の組み合わせの数の和）になりました。&lt;/p&gt;
&lt;p&gt;この例のように&lt;code&gt;variant&lt;/code&gt;でスタイルを定義するパターンは多くのUIライブラリが同様に実装していることもあり、割と当たり前になっていると個人的には感じています&lt;sup&gt;&lt;a href=&quot;#user-content-fn-4&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;p&gt;そのため、単一のプロパティを使った状態についてはMake Impossible States Impossibleも自然に実現されることが多いでしょう。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#複数のプロパティでの例&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;複数のプロパティでの例&lt;/h3&gt;
&lt;p&gt;問題となるのは複数のプロパティの例です。コンポーネントの状態に作用するプロパティが複数ある場合、「それぞれのプロパティが取りうる値の数」と「プロパティの数」の積だけ、発生しうる状態が増えてしまいます。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;ここで実例として、Empty Stateコンポーネントを考えます。Empty Stateコンポーネントは、データが存在しない場合の統一的な見た目を提供するコンポーネントです。次の画像のような見た目をしています。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;このコンポーネントのPropsは、シンプルに次のように定義できます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Props&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;buttonText&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;onClick&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;初期時点では新規作成ボタンだけが要件としてあり、すべてのプロパティは必須です。この時点では特に問題はありません。&lt;/p&gt;
&lt;p&gt;ここで要件として、新たに「アプリ内で新規リソースを作成するわけではない場合、ボタンをリンクのスタイルで表示したい」という要件が追加されたとします。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type Props = {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;title: string;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;description: string;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;buttonText: string;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;buttonText?: string;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;onClick: () =&amp;gt; void;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;onClick+: () =&amp;gt; void;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;/* リンクのテキスト。これを指定するとリンクを示すアイコンが表示されます */&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;linkText?: string;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;/* 外部リンクかどうか。アイコンが変わるのと別タブで開く挙動が追加されます */&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;isExternalLink?: boolean;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;/* リンク先URL。これを指定するとリンクが有効になります */&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;href?: string;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;追加の変更だけで要件のスタイルを実現できました。しかしここには問題があります。ここまでで述べてきたように、「&lt;code&gt;linkText&lt;/code&gt;を指定しているが、&lt;code&gt;href&lt;/code&gt;を指定していない」「&lt;code&gt;buttonText&lt;/code&gt;と&lt;code&gt;href&lt;/code&gt;が同時に指定してある」など、不正な状態が発生してしまいます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#discriminated-unionによる解決&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Discriminated Unionによる解決&lt;/h3&gt;
&lt;p&gt;解決策の1つは、TypeScript の Discriminated Union を用いて、状態を排他的に定義することです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;AddResourceButtonProps&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;button&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;buttonText&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;onClick&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;AddResourceLinkProps&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;link&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;linkText&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;href&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;isExternalLink&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Props&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;addResourceUIProps&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;AddResourceButtonProps&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;AddResourceLinkProps&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;このサンプルでは、&lt;code&gt;type&lt;/code&gt;がタグとしての機能を果たしているため、&lt;code&gt;type=&quot;button&quot;&lt;/code&gt;の時には&lt;code&gt;AddResourceButtonProps&lt;/code&gt;のプロパティが、&lt;code&gt;type=&quot;link&quot;&lt;/code&gt;の時には&lt;code&gt;AddResourceLinkProps&lt;/code&gt;のプロパティだけが指定できるようになります。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#compositionによる解決&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Compositionによる解決&lt;/h3&gt;
&lt;p&gt;もう1つの解決策は、Compositionを使うことです。Empty Stateコンポーネントが内包するButtonのスタイルが複数あることがそもそもの複雑さの原因なので、これを分離することで問題を解決します。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;渡された関数、ここではButtonコンポーネントを呼び出すことだけを任せます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Props&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;PropsWithChildren&lt;/span&gt;&lt;span&gt;&amp;lt;{&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;ボタンのスタイルは&lt;code&gt;children&lt;/code&gt;に渡す&lt;code&gt;Button&lt;/code&gt;コンポーネント側で定義します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/* Buttonのパターン */&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;EmptyStatePanel&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;...&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;...&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Button&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;variant&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;primary&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;md&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;onClick&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{createPost}&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;記事を書く&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;Button&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;EmptyStatePanel&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/* Linkのパターン */&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;EmptyStatePanel&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;...&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;...&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Button&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;variant&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;secondary&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;lg&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;asChild&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Link&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;href&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt;{supportPageURL} &lt;/span&gt;&lt;span&gt;external&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;サポートページへ&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;Link&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;Button&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;EmptyStatePanel&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/* Linkのパターン（LinkButtonをスタイル使い回しのために別途用意する */&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;LinkButton&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FC&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;PropsWithChildren&lt;/span&gt;&lt;span&gt;&amp;lt;{ href&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; }&amp;gt;&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; ({ href&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; children }) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Button&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;variant&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;secondary&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;lg&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;asChild&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Link&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;href&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt;{href} &lt;/span&gt;&lt;span&gt;external&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{children}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;Link&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;Button&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;EmptyStatePanel&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;...&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;...&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;LinkButton&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;href&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{supportPageURL}&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;サポートページへ&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;LinkButton&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;EmptyStatePanel&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;Buttonに関する状態はButtonコンポーネント側で管理されるため、EmptyStatePanelコンポーネントでは先ほどのような不整合な状態が発生しません（前提として、Buttonコンポーネントが不正な状態が定義できないようになっている必要がありますが）。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#既存コンポーネントの変更の際には状態の増加に気をつける&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;既存コンポーネントの変更の際には状態の増加に気をつける&lt;/h2&gt;
&lt;p&gt;新規でコンポーネントを作成する際には、組み合わせの数が少ないか、組み合わせ自体があっても実装者がすべてのパターンを意識して設計するため、自然とMake Impossible States Impossibleを満たした設計になりやすいと感じます。&lt;/p&gt;
&lt;p&gt;反対に既存のコンポーネントに対して変更を加える際には、新しく追加しようとしている状態だけにフォーカスが向いているために、不正な状態が発生しやすいと感じます。&lt;/p&gt;
&lt;p&gt;特に既存の汎用コンポーネントを修正する際には、既存の構造に引っ張られることもあり、&lt;code&gt;isFoo&lt;/code&gt;のようなフラグ的なPropsを生やす引力が働きやすいのもかもしれません。&lt;/p&gt;
&lt;p&gt;フラグが1個増えたら、単体で状態が2個増え、最終的に同じ箇所に影響するPropsの数の2倍分、考えうる状態が増えます。そのため、既存のコンポーネントに対して変更を加える際には、状態の増加に気をつけることが重要です。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#まとめ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;まとめ&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Make Impossible States Impossibleは、不正な状態が発生しないように型/インターフェイスを設計する考え方。&lt;/li&gt;
&lt;li&gt;API 設計においても、React コンポーネントの Props 設計においても適用できる。React では Discriminated Union や Composition を使うことで実現できる。&lt;/li&gt;
&lt;li&gt;特に既存コンポーネントを実装する際には、既存実装の引力が働きやすいことと、実装対象にフォーカスしていることが多いので、新しく追加する実装が不正な状態を引き起こさないかを意識することが重要。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;React における Make Impossible States Impossible の考え方について、簡単な例を交えて紹介しました。&lt;/p&gt;
&lt;p&gt;TypeScriptの文脈だと、最近はTSバックエンドで語られることご多い気がしますが、冒頭で述べた通りAPI設計で汎用的に使える考え方なので、ReactのProps設計にも適用できます。
実践方法である Discriminated Union や Composition については、React や TypeScript では基本的なものです。重要なのはこれらのテクニックというより、これらを適用するための1つの指針としての Make Impossible States Impossible の考え方を意識することだと感じます。&lt;/p&gt;
&lt;p&gt;今回挙げた例では「単一責任の原則」「不要な結合関係を排除する」などさまざまな視点からもアプローチができると思いますので、あくまで設計時に使える1つの視点として参考にしていただければと思います。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#appendix&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Appendix&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#make-impossible-states-impossible--make-illegal-states-unrepresentable-について言及された記事動画&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Make Impossible States Impossible / Make Illegal States Unrepresentable について言及された記事・動画&lt;/h3&gt;
&lt;p&gt;私が調べた範囲で記載します。2011年くらいから言及されていて、2016-2019あたりの記事が多い印象です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.janestreet.com/effective-ml-revisited/&quot; target=&quot;_blank&quot;&gt;Jane Street Tech Blog - Effective ML Revisited&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;2011年で調べた中ではもっとも古い出典。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kentcdodds.com/blog/make-impossible-states-impossible&quot; target=&quot;_blank&quot;&gt;Make Impossible States Impossible&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;React界隈で有名なKent C. Dodds氏によるブログ記事&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=VU1NKX6Qkxc&quot; target=&quot;_blank&quot;&gt;David Khourshid - Infinitely Better UIs with Finite Automata - YouTube&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;XStateの作者（&lt;a href=&quot;https://stately.ai/&quot; target=&quot;_blank&quot;&gt;stately.ai&lt;/a&gt;社のファウンダー）であるDavid Khourshid氏による動画&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=IcgmSRJHu_8&quot; target=&quot;_blank&quot;&gt;“Making Impossible States Impossible” by Richard Feldman - YouTube&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;わりと色々なところで言及されることの多い、Elm Conference 2016でのRichard Feldman氏の講演&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.amazon.co.jp/dp/B0DDBPNBVJ&quot; target=&quot;_blank&quot;&gt;関数型ドメインモデリング&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Part II. Modeling The Domain 6. Integrity and Consistency in the Domain の中で「Making Illigal States Unrepresentable In Our Domain」というセクションがある。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fsharpforfunandprofit.com/posts/designing-with-types-making-illegal-states-unrepresentable/&quot; target=&quot;_blank&quot;&gt;Designing with types: Making illegal states unrepresentable | F# for fun and profit&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;上記の関数型ドメインモデリングの著者のブログ記事&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://qiita.com/ymtszw/items/dff02ad6350032688676&quot; target=&quot;_blank&quot;&gt;「ADT, 直和・直積, State Machine」 #TypeScript - Qiita&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;上記の著者のブログをベースに解説された日本後の記事&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/stereobooster/pragmatic-types/blob/master/posts/making-impossible-states-impossible.md&quot; target=&quot;_blank&quot;&gt;pragmatic-types/posts/making-impossible-states-impossible.md at master · stereobooster/pragmatic-types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=P7dTPoxCg4w&quot; target=&quot;_blank&quot;&gt;Patrick Stapfer: Making Unreasonable States Impossible - ReasonML Munich Meetup - YouTube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sporto.github.io/elm-patterns/basic/impossible-states.html&quot; target=&quot;_blank&quot;&gt;Make impossible states impossible - Elm Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://elm-radio.com/episode/impossible-states/&quot; target=&quot;_blank&quot;&gt;Make Impossible States Impossible&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://moboudra.com/post/making-impossible-states-impossible-in-typescript&quot; target=&quot;_blank&quot;&gt;Making Impossible States Impossible with TypeScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dev.to/lieberkind/making-impossible-states-impossible-with-typescript-3hj&quot; target=&quot;_blank&quot;&gt;Making impossible states impossible with TypeScript - DEV Community&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jackfranklin.co.uk/blog/avoiding9-impossible-states-react/&quot; target=&quot;_blank&quot;&gt;Making impossible states impossible: data structures in React - Jack Franklin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://whereisthemouse.com/avoid-impossible-ui-states-with-react-typescript-and-xstate&quot; target=&quot;_blank&quot;&gt;Avoid impossible UI states with React, Typescript and xState&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://varenya.hashnode.dev/making-impossible-states-impossible-ft-zod-and-typescript&quot; target=&quot;_blank&quot;&gt;Making impossible states impossible ft. Zod and Typescript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dorshinar.me/posts/avoid-impossible-state-with-typescript&quot; target=&quot;_blank&quot;&gt;Avoiding impossible state with TypeScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gitnation.com/contents/making-impossible-states-with-fp-ts-and-typescript-in-a-react-application&quot; target=&quot;_blank&quot;&gt;Making Impossible States with fp-ts and TypeScript in a React Application by Cristhian Motoche&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rwieruch/react-making-impossible-views-impossible&quot; target=&quot;_blank&quot;&gt;rwieruch/react-making-impossible-views-impossible: React UI State: An example to make impossible views impossible.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://soonernotfaster.com/posts/making-invalid-state-impossible-in-typescript-and-react/&quot; target=&quot;_blank&quot;&gt;Making Invalid State Impossible: in TypeScript and React | Steven Solomon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://scrapbox.io/mrsekut-p/Making_Illegal_States_Unrepresentable&quot; target=&quot;_blank&quot;&gt;Making Illegal States Unrepresentable - mrsekut-p&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#xstate-と-zagjs-と状態と&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;XState と Zag.js と状態と&lt;/h3&gt;
&lt;p&gt;上記のリストの中に、状態管理ライブラリの&lt;a href=&quot;https://stately.ai/docs/xstate&quot; target=&quot;_blank&quot;&gt;XState&lt;/a&gt;の作者による動画がありました。&lt;/p&gt;
&lt;p&gt;XStateはステートマシンを中心に据えた状態ライブラリで、状態と遷移を明示的に定義することで、不正な状態を排除することができます。&lt;/p&gt;
&lt;p&gt;さらにこの XState を内包した Zag.js は Chakra UI によるコンポーネントライブラリ（？）で、状態に応じた data 属性や、アクセシビリティのための属性を付与してくれます。&lt;/p&gt;
&lt;p&gt;本記事の中では「状態」についての定義には触れませんでしたが、不正な状態を作らないためには、何が適正な状態かを明確に意識することも当然ながら重要です。&lt;/p&gt;
&lt;p&gt;Zag.js ではさまざまなコンポーネントの状態をステートマシンとして定義しているため、UIコンポーネントにおける状態の参考になるかもしれません。&lt;/p&gt;
&lt;p&gt;Zag.js のソースの追い方はまた別途記事にしようと思います。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;&lt;a href=&quot;#footnote-label&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;2024年の夏前くらい？どこからどこまでが最近なんでしょうね。 &lt;a href=&quot;#user-content-fnref-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;この名前もどこが出典なのかはわかりませんが（意味的に自然にたどり着いている可能性も十二分にある）、関数型プログラミング言語であるOCamlには&lt;code&gt;variant&lt;/code&gt;という概念があり、ここに影響を受けている部分は少なからずあるかもしれません。 &lt;a href=&quot;#user-content-fnref-3&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;とはいいつつ、Vuetifyの2系とかはもともとスタイルごとにbooleanで指定する形式で、Vuetify3系で&lt;code&gt;variant&lt;/code&gt;に変更されたので、ここ数年の話なのかもしれません。 &lt;a href=&quot;#user-content-fnref-4&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><author>ikuma-t</author></item><item><title>CSSで親のコンテナのサイズをはみ出す子要素を作る</title><link>https://ikuma-t.com/blog/break-container-size-css/</link><guid isPermaLink="true">https://ikuma-t.com/blog/break-container-size-css/</guid><description>コンテナから要素をはみ出したいこのブログでは全体のレイアウトを定義した上で、その中にヘッダーやフッター、メインコンテンツを配置しています。イメージとしては次のようなHTML構造です。&amp;lt;divcl</description><pubDate>Mon, 04 Nov 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#コンテナから要素をはみ出したい&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;コンテナから要素をはみ出したい&lt;/h2&gt;
&lt;p&gt;このブログでは全体のレイアウトを定義した上で、その中にヘッダーやフッター、メインコンテンツを配置しています。&lt;/p&gt;
&lt;p&gt;イメージとしては次のようなHTML構造です。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;container&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;header&lt;/span&gt;&lt;span&gt;&amp;gt;...&amp;lt;/&lt;/span&gt;&lt;span&gt;header&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;&amp;gt;...&amp;lt;/&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;footer&lt;/span&gt;&lt;span&gt;&amp;gt;...&amp;lt;/&lt;/span&gt;&lt;span&gt;footer&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;.container&lt;/code&gt;に対しては&lt;code&gt;max-width&lt;/code&gt;を設定して、コンテンツが画面幅いっぱいに広がらないようにしています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;.container&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;max-width&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;1200&lt;/span&gt;&lt;span&gt;px&lt;/span&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;margin&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0 &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これによって共通の幅を確保できるのはいいのですが、たとえばヘッダーは横幅いっぱいに広げたい場合どうすればいいでしょうか？&lt;/p&gt;
&lt;p&gt;解決策の1つはスタイルを共通ではなく、各セクションごとに定義することです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;header&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;full-width&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;...&amp;lt;/&lt;/span&gt;&lt;span&gt;header&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;container&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;...&amp;lt;/&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;footer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;container&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;...&amp;lt;/&lt;/span&gt;&lt;span&gt;footer&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これでもよいのですが、そのほかのスタイルをTailwind CSSで複数適用していたため、できれば共通のスタイルを使いたいところです。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#calcでネガティブマージンを利用してはみ出す&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;calcでネガティブマージンを利用してはみ出す&lt;/h2&gt;
&lt;p&gt;はみ出したい子要素に対して、以下のスタイルを適用することで、やりたいことを実現できます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;body&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;container-type&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inline-size&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/* ヘッダーをはみださせる */&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;header&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;width&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;vw&lt;/span&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;margin-inline&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;calc&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;(50&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;&lt;span&gt; 50&lt;/span&gt;&lt;span&gt;cqi&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;/* 親の幅に要素を寄せたい場合 */&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;/* padding-inline: calc(50cqi - 50%); */&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/* 変更なし */&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;.container&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;max-width&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;1200&lt;/span&gt;&lt;span&gt;px&lt;/span&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;margin&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0 &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;HTMLについては、次のようになります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;container&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;header&lt;/span&gt;&lt;span&gt;&amp;gt;...&amp;lt;/&lt;/span&gt;&lt;span&gt;header&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;&amp;gt;...&amp;lt;/&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;footer&lt;/span&gt;&lt;span&gt;&amp;gt;...&amp;lt;/&lt;/span&gt;&lt;span&gt;footer&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;適用のイメージについて、個人的には次のように考えるとわかりやすいかと思います。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;親要素を基準に、&lt;code&gt;100vw&lt;/code&gt;で要素を横幅いっぱいに広がる。親基準なので、画面の端からではなく親の端から広がる。これを調整したい。&lt;/li&gt;
&lt;li&gt;親要素の左右それぞれに対して（つまり半分ずつに分割して考える）、画面幅の要素から親要素を引いた値をうめたい。これをネガティブマージンで再現する。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;margin-inline&lt;/code&gt;を利用して、水平方向に対して、2のマージンを適用する。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;細かいポイントがコンテナクエリを使っていることです。&lt;code&gt;50vw&lt;/code&gt;だと、スクロールバーを含めた部分までで横幅を計算するので、横スクロールバーが生じてしまいます。&lt;/p&gt;
&lt;p&gt;bodyに対しての純粋な半分が欲しいので、bodyをコンテナに指定した上で、その半分である&lt;code&gt;50cqi&lt;/code&gt;を指定すればこの問題も解決です（&lt;code&gt;cqi&lt;/code&gt;はコンテナーのインライン（横書きだと水平方向）の1%をさす単位です）。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#参考&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;参考&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://lopan.jp/breaking-out/&quot; target=&quot;_blank&quot;&gt;コンテナからの解放。&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/CSS/CSS_containment/Container_queries&quot; target=&quot;_blank&quot;&gt;CSS コンテナークエリー - CSS: カスケーディングスタイルシート | MDN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>ikuma-t</author></item><item><title>技術書典17 オフライン会場での戦利品紹介</title><link>https://ikuma-t.com/blog/tech-book-fest-17/</link><guid isPermaLink="true">https://ikuma-t.com/blog/tech-book-fest-17/</guid><description>技術書典17オフライン会場に行ってきました！昨日（2024/11/03）に池袋サンシャインシティで開催された技術書典17のオフライン会場に行ってきました！オフライン会場は前回の技術書典16で初参加。そ</description><pubDate>Mon, 04 Nov 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#技術書典17-オフライン会場に行ってきました&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;技術書典17 オフライン会場に行ってきました！&lt;/h2&gt;
&lt;p&gt;昨日（2024/11/03）に池袋サンシャインシティで開催された技術書典17のオフライン会場に行ってきました！&lt;/p&gt;
&lt;p&gt;オフライン会場は前回の技術書典16で初参加。その際は一般来場者としてでした。2回目となる今回はサークル主として自著を提げて参加しました。&lt;/p&gt;
&lt;p&gt;そのため前回ほどゆっくりは会場を回れなかったのですが、色々なサークルの方の書籍を購入できたので、簡単な感想と共に戦利品紹介をしたいと思います。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#現地会場での戦利品紹介&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;現地会場での戦利品紹介&lt;/h2&gt;
&lt;p&gt;今回は現物で10冊、在庫が売切で電子で購入させていただいたのが1冊で、現地では計11冊購入させていただきました！&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;現地で購入できた物理本たちの集合写真。全10冊の書籍が並べて撮影されている&quot; loading=&quot;lazy&quot; width=&quot;3064&quot; height=&quot;2190&quot; src=&quot;/_astro/korega-senrihin.ICePwur6_2vFgGh.jpg&quot; /&gt;&lt;/p&gt;
&lt;p&gt;戦利品を書籍の五十音順で簡単に紹介します。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#あざといlt&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;あざといLT&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;あざといLTのカバー写真&quot; loading=&quot;lazy&quot; width=&quot;304&quot; height=&quot;432&quot; src=&quot;/_astro/azaoi-lt.iVxRQgBD_24Wl4u.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://techbookfest.org/product/uXNrgrx0ZkWdwM54Xv34XR?productVariantID=hbdFKYmiUtjG2C4xFbeQQ8&quot; target=&quot;_blank&quot;&gt;あざといLT：LT同好会&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;X上で面識のある&lt;a href=&quot;https://twitter.com/Kaitou1192&quot; target=&quot;_blank&quot;&gt;kaitou&lt;/a&gt;さんが書かれている、ということもあったのですが、自分自身がときどき外部登壇をしているので参考にしたい！と思い購入しました！&lt;/p&gt;
&lt;p&gt;「LT登壇の必勝法は一点突破」というセクションがありまして、中身がぼやけがちな自分には結構刺さりましたね … …。聞き手の課題感・レベル感を想像して、それに対して自分の出せる手札から珠玉の一品を出すために、KJ法使ってみようと思います！&lt;/p&gt;
&lt;p&gt;ちょうど今月またLTの機会があるので、その際は本書の内容を参考にします！&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#アクセシビリティを考えはじめるための本&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;アクセシビリティを考えはじめるための本&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;アクセシビリティを考えはじめるための本のカバー&quot; loading=&quot;lazy&quot; width=&quot;306&quot; height=&quot;432&quot; src=&quot;/_astro/accesiblity-wo-kangeehajimeru-tame-no-hon.CE7vkTtA_6feju.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://techbookfest.org/product/2KX3LTZs66Y6v8cZZ62mDW?productVariantID=8PkSFLD4Af6j6qYLaqkzNt&quot; target=&quot;_blank&quot;&gt;アクセシビリティを考えはじめるための本：20 Hour Exception&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;「アクセシビリティの重要さは認識しているし、それを実現するために重要な技術トレンドもとりあえず追いかけてはいるが、自分が向き合っているサービスにその観点を落とし込みきれていない」という課題感を持っていたので、とてもありがたい内容でした。これは普段のお仕事のときにも常に横に置いておく一冊になりそうです。&lt;/p&gt;
&lt;p&gt;あとこれは本の内容ではないのですが、行間・字間が適切に取られていて読みやすかったです（後半の章に「知覚しやすい表現を使う」というセクションがあり、「なるほど〜」と一人で納得していました）。&lt;/p&gt;
&lt;p&gt;急いで購入していたので、ボイスオーバーによる売り上げの読み上げを存分に味わうことはできなかったのが少し心残りですが、現物を購入できたのでよし！&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#amazon-bedrockとgithub-actionsで文章自動レビューを実装してみる本&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Amazon BedrockとGitHub Actionsで文章自動レビューを実装してみる本&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;Amazon BedrockとGitHub Actionsで文章自動レビューを実装してみる本のカバー&quot; loading=&quot;lazy&quot; width=&quot;305&quot; height=&quot;432&quot; src=&quot;/_astro/amazon-bedrock-to-github-actions-de-bunsyou-jidou-review-wo-jissou-sitemiru-hon.Bi5Xe4g9_Z16wdg7.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://techbookfest.org/product/1hA7SzbSbdMMapEmNdbud0?productVariantID=ps5Ls6e501e4GK3VzYtJWq&quot; target=&quot;_blank&quot;&gt;Amazon BedrockとGitHub Actionsで文章自動レビューを実装してみる本：杜の都の開発室&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ブログ執筆にはtextlintでのチェックを入れているのですが、もう少しチューニングした形でチェックしてもらえたらたしかに嬉しいなあと思い、購入しました。&lt;/p&gt;
&lt;p&gt;Amazon BedrockはAWS開催のワークショップに参加して試していたのですが、ちょっとお高いな〜というイメージがありそれ以来使っていませんでした。なので最後の第4章の「トークン数とコストの把握」の内容はありがたかったです。今の記事投稿ペースくらいならBedrockを使ってもいいかも、と思いました！&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#好きなことなら本当に続けられるのか100日連続イラスト投稿してきた日々を振り返る--鍛錬するとコードレビューがループするへーしゃの技術戦略室室長が語ったコードレビューの在り方&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;好きなことなら本当に続けられるのか　〜100日連続イラスト投稿してきた日々を振り返る〜 / 鍛錬するとコードレビューがループする　〜へーしゃの技術戦略室室長が語ったコードレビューの在り方〜&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;好きなことなら本当に続けられるのかのカバー&quot; loading=&quot;lazy&quot; width=&quot;301&quot; height=&quot;432&quot; src=&quot;/_astro/sukinakotonara-hontou-ni-tuzukerarerunoka.DYH-ZgKf_Z1KE51m.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;みずりゅさんのサークルの書籍を2冊購入させていただきました。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;好きなことなら本当に続けられるのかのカバー&quot; loading=&quot;lazy&quot; width=&quot;301&quot; height=&quot;432&quot; src=&quot;/_astro/sukinakotonara-hontou-ni-tuzukerarerunoka.DYH-ZgKf_Z1KE51m.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://techbookfest.org/product/mQQ6NMBRaLdnr13FT8uZPr?productVariantID=sANGE1ru0cgdpxmLCUfpha&quot; target=&quot;_blank&quot;&gt;好きなことなら本当に続けられるのか　〜100日連続イラスト投稿してきた日々を振り返る〜：URAMASU&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;習慣化の技術、みたいな書籍はときどき読んでいるのですが、なかなか続けられないのが実情（私は日記を途絶え途絶えやっています）。みずりゅさんは100日以上イラスト投稿を続けられていて「すごい！」と心で微笑んでいました。&lt;/p&gt;
&lt;p&gt;今回の技術書典参加にあたり自分も人物イラストで表紙を描こうと思ったのですが、まったく納期に間に合う気がしませんでしたので、今回はキャラクターで妥協しました。次回以降の機会に備えて練習しようかなあ。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;img alt=&quot;鍛錬するとコードレビューがループするのカバー&quot; loading=&quot;lazy&quot; width=&quot;291&quot; height=&quot;432&quot; src=&quot;/_astro/tanrensuruto-ko-do-review-ga-ru-pu-suru.WQvVkRpF_19hh8I.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://techbookfest.org/product/a5iJ9TZAiDFHhH8UCTyJYg?productVariantID=9WicsCgcKcph4GXphjRntj&quot; target=&quot;_blank&quot;&gt;鍛錬するとコードレビューがループする　〜へーしゃの技術戦略室室長が語ったコードレビューの在り方〜：URAMASU&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;もう1冊はコードレビューについての書籍。コードレビューのプラクティスの関係性を図で表現したものです。 個別の要素についての内容を深ぼったものは結構ある印象ですが、こういう全体像の関係性をまとめたものはありそうでなかったので、参考になりました！改善施策を考える上で非常に助かりますね。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;みずりゅさんは過去にGleamに関する書籍を出されていることもあり（Gleamだからかサークル配置が隣）、今回ご挨拶できてよかったです。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#店舗を読み解く技術小売業ドメイン知識入門&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;店舗を読み解く技術～小売業ドメイン知識入門～&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;店舗を読み解く技術のカバー&quot; loading=&quot;lazy&quot; width=&quot;305&quot; height=&quot;432&quot; src=&quot;/_astro/tenpo-wo-yomitoku-gijyutu.DGOgZeqE_1U09Er.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://techbookfest.org/product/3UL8Czdcm8bnSvWXyB2G7C?productVariantID=s3D8XR1JNNfHFKUr64CVR9&quot; target=&quot;_blank&quot;&gt;店舗を読み解く技術～小売業ドメイン知識入門～：株式会社プレーンテキスト&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;自分は小売業ドメインでは働いていないのですが、実利がなくても業界の知識覚えるのっておもしろいよね！ということで購入。&lt;/p&gt;
&lt;p&gt;2章の「店を読む技術」がとくにおもしろく、「そんなところに専門用語ついているんだ」「そういう分類で現場の人は店を見ているのか！」と勉強になりました。ゴンドラエンド、日常でもつかいたいですね。&lt;/p&gt;
&lt;p&gt;業界を捉える視点を整理するための書籍、という意味でもとてもよいと感じました。もちろん自分が携わる業界を知るには実際に働く人のところへ行くのが一番だとは思うのですが、エンジニアとしては常にそうしてもいられないし、どうしても座学で把握する必要があります。新しい業界を見る際に、本書の構成は良いガイドラインになりそうだな〜と思っています。&lt;/p&gt;
&lt;p&gt;これは余談ですが、本書に出てくる「クルベ」を運営する「ベルク」は私のお気に入りのスーパーです。ベルク大好きエンジニア座談会とかいつか開催されないかなと勝手に思っています、はい。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#虎の穴ラボの薄い本vol8&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;虎の穴ラボの薄い本。vol.8&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;虎の穴ラボの薄い本。vol.8のカバー&quot; loading=&quot;lazy&quot; width=&quot;306&quot; height=&quot;432&quot; src=&quot;/_astro/torarabo-8.DsldwzmG_Z2eSK15.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://techbookfest.org/product/qVunHzeLL6tr279K8RuEV8?productVariantID=h6LLTMCGwwU6V574j0f2hT&quot; target=&quot;_blank&quot;&gt;虎の穴ラボの薄い本。vol.8：虎の穴ラボ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://hk-it.hatenablog.com/entry/2024/09/17/201653&quot; target=&quot;_blank&quot;&gt;東葛.dev&lt;/a&gt;で知り合った&lt;a href=&quot;https://twitter.com/hk_it7&quot; target=&quot;_blank&quot;&gt;kouno&lt;/a&gt;さんに献本いただき入手しました（協賛ブースは地味に遠かったので、なかなか離れられない1人サークルにはありがたかったです！）。&lt;/p&gt;
&lt;p&gt;自分は普段フロントエンドやっているので、Next.jsでのマーケティングツール導入、DenoでのWeb・CLI開発あたりを興味深く読ませていただきました。Cliffyは昔このブログのCLIを作るときに使っていたんですが、結構便利ですよね〜。&lt;/p&gt;
&lt;p&gt;あとは随所に散りばめられているキャラの挿絵がとてもかわいくてよかったです …!最終ページの地方住まいマップもニコニコしながら読ませていただきました🤭&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#ポッドキャストをやりたい-と思ったらまず読む本&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;「ポッドキャストをやりたい！」 と思ったらまず読む本&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;ポッドキャストをやりたい！と思ったらまず読む本のカバー&quot; loading=&quot;lazy&quot; width=&quot;305&quot; height=&quot;432&quot; src=&quot;/_astro/podcast-wo-yaritai-toomottara-mazu-yomu-hon.C0vJkHgu_U4hj7.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://techbookfest.org/product/iTx5CrYj0RWzxASzLYHYzy?productVariantID=fD7GfeKfzSFAwnZTJVybD8&quot; target=&quot;_blank&quot;&gt;「ポッドキャストをやりたい！」 と思ったらまず読む本：小沢あや&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;「ポッドキャストをやりたい！」と思っているので、購入させていただきました！ポッドキャスト、なかなか進まず、しかしながら今年中に始めたいと思っていたので、どんぴしゃりな内容でした。&lt;/p&gt;
&lt;p&gt;ハウツーの部分ももちろん刺さったのですが、「変にバズらず、狭く、深く、ゆっくり届く」という章が自分にはとても興味深かったです。やさしいせかいだ … …。ますますやってみたい意欲が高まりましたね。&lt;/p&gt;
&lt;p&gt;頑張って今年中に技術系のLTを軸にしたひとりポッドキャストを始めたいと思ってるので、本書の内容参考にします！&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#まじでめちゃくちゃ分かりやすい棒針編み入門漫画1巻&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;まじでめちゃくちゃ分かりやすい棒針編み入門漫画＜1巻＞&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;まじでめちゃくちゃ分かりやすい棒針編み入門漫画＜1巻＞のカバー&quot; loading=&quot;lazy&quot; width=&quot;305&quot; height=&quot;432&quot; src=&quot;/_astro/maji-de-metyakutya-wakariyasui-bouhariami-nyumon.BMxXGco7_1cYRc7.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://techbookfest.org/product/wWdEXb0e1b0YwLi4N0Mv17?productVariantID=bXrpUEwbj5NcWvHLNDxSBT&quot; target=&quot;_blank&quot;&gt;まじでめちゃくちゃ分かりやすい棒針編み入門漫画＜1巻＞：オノデラユズカオ制作&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;自分は過去に&lt;a href=&quot;/blog/sisyu&quot;&gt;刺繍をはじめてみた&lt;/a&gt;こともあるのですが、どうも室内でできる趣味領域を開拓したい傾向があり、その流れで購入しました。&lt;/p&gt;
&lt;p&gt;棒針編み、アニメとかで見て憧れますよね〜。できたらいいなと思いつつ、自分はあまり裁縫系（というか立体視？）が得意ではなく、書籍にある図を見ても「どれをどうしたらこうなるんじゃい … …」と途方に暮れることもしばしば。一方この本は図も大きくめちゃめちゃわかりやすいので、なんだか自分でもできる気がしました（漫画だけでも読み物として面白かったです）！&lt;/p&gt;
&lt;p&gt;やったことは愚か道具すらないのですが、本書を読んで冬休みの予定が決まりましたね。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#ruby-on-rails8入門&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Ruby on Rails8入門！&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;Ruby on Rails8入門！のカバー&quot; loading=&quot;lazy&quot; width=&quot;305&quot; height=&quot;432&quot; src=&quot;/_astro/rails-8-nyumon.CNaNseVn_2pkD7c.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://techbookfest.org/product/41bEtMuRb2xADJH5E0WWVC?productVariantID=2hufyTuCnbtJu8bCHDG6pU&quot; target=&quot;_blank&quot;&gt;Ruby on Rails8入門！：def合同会社&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;お隣のお隣のサークル（といいつつ、お隣のブースはお休みだったので、実質お隣）で販売されていた書籍です。こちらのブースにお越しいただいて話していたのですが、実は意外に接点があり盛り上がっておりました。&lt;/p&gt;
&lt;p&gt;物理本は売り切れとのことだったので電子版で読ませていただきました。&lt;/p&gt;
&lt;p&gt;最近はあまりRubyも書いておらずちゃんと中身まで見ていたのがRails 7系、DHHのポスト等をちらみしてワードだけは追っているが … … というレベル感だったので、本書でキャッチアップできてよかったです。&lt;/p&gt;
&lt;p&gt;Rails、初学者のときはアプリを作るのは簡単だけど、デプロイが難しい、という印象があって、kamalは結構良さそうに思いました。少し前から開発用のDockerも含めてデフォルトで使えるようになっていましたが、ここらへんどんどん便利になっていきますね〜。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#ゆるietf&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ゆるIETF&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;ゆるIETFのカバー&quot; loading=&quot;lazy&quot; width=&quot;310&quot; height=&quot;432&quot; src=&quot;/_astro/yuru-ietf.CNONvRrS_Z2uFV4T.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://techbookfest.org/product/aA3CXwXHh9Z3bG4b7B3D8q?productVariantID=TLPGS2DTAnvQEd2FcrGzL&quot; target=&quot;_blank&quot;&gt;ゆるIETF：asnokaze&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;今回のオフライン会場で絶対に入手したい一冊でした。&lt;a href=&quot;https://asnokaze.hatenablog.com/entry/2024/11/02/100659&quot; target=&quot;_blank&quot;&gt;ASnoKaze blog&lt;/a&gt;は内容わかるときもわからない時もあるのですが、毎回読ませて勉強させていただいています。&lt;/p&gt;
&lt;p&gt;HTTP/3のマスコットキャラの話や言語缶バッジの話など、おもわずふふッとなるお話しが多く、IETFという一般的な印象では固いテーマながら非常に楽しく読ませていただきました。標準化って難しいイメージあるけど、そこにはやっぱり人がいるんだなあという感想です。&lt;/p&gt;
&lt;p&gt;最後の章では最新技術の動向を追う方法についても記載があり、自分はあまりここら辺を実践できていないので、今後の参考にさせていただこうと思います。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#サークル参加&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;サークル参加&lt;/h2&gt;
&lt;p&gt;… … と、ここまで購入してきた書籍は基本的に15分くらいの休憩時間でシュバっと購入して、あとは自身のサークルの販売をやっていました。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;サークル出展の様子。長机の上に、はじめよう！Gleamの見本や購入のための決済バーコード、販売促進ポスターなどを飾っています&quot; loading=&quot;lazy&quot; width=&quot;1708&quot; height=&quot;913&quot; src=&quot;/_astro/omise.DbxSasJm_Og8kt.jpg&quot; /&gt;&lt;/p&gt;
&lt;p&gt;まだマイナーな言語なので、正直数冊売れてくれれば十分だと思っていたのですが、思いの外多くの方にご購入いただけて嬉しかったです！&lt;/p&gt;
&lt;p&gt;オンラインマーケットではまだ電子版および電子+紙版が購入できるので、ぜひチェックしていただければと思います！&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;書籍「はじめよう！Gleam」が積み重なっている。&quot; loading=&quot;lazy&quot; width=&quot;1396&quot; height=&quot;1395&quot; src=&quot;/_astro/hon.BOVaQE6m_2pzkeK.jpg&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://techbookfest.org/product/fULZb6u3f2Lq84BkTCU0hC?productVariantID=4fdAqQ0V0RLFRwYFUnaUHb&quot; target=&quot;_blank&quot;&gt;はじめよう！Gleam：ikuma-t - 技術書典オンラインマーケット&lt;/a&gt;&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Nihonbashi.js #9に参加してStorybookの話をしてきた</title><link>https://ikuma-t.com/blog/nihonbashi-js-9/</link><guid isPermaLink="true">https://ikuma-t.com/blog/nihonbashi-js-9/</guid><description>Nihonbashi.js#9に参加してきたNihonbashi.js#9-connpass2024年11月1日開催のNihonbashi.js#9に参加してきました。WebDeveloperConf</description><pubDate>Fri, 01 Nov 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#nihonbashijs-9に参加してきた&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Nihonbashi.js #9に参加してきた&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://nihonbashi-js.connpass.com/event/332328/&quot; target=&quot;_blank&quot;&gt;Nihonbashi.js #9 - connpass&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;2024年11月1日開催のNihonbashi.js #9に参加してきました。&lt;/p&gt;
&lt;p&gt;Web Developer Conference以来、2度目のサイボウズさんのオフィスでした。前回行っておいたおかげで迷わずにつけた … …。&lt;/p&gt;
&lt;p&gt;LT会→懇親会の流れですすみ、懇親会ではStreamについて色々と教えていただいたり、ほかの会社さんの開発組織事情を聞くことができ、おもしろかったです。&lt;/p&gt;
&lt;p&gt;今回はLT枠で申し込みさせていただいたので、5分間Storybookについて話してきた内容の詳細をこの記事では記録しておきます。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#ltいまさらのstorybook&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;LT：いまさらのStorybook&lt;/h2&gt;

&lt;p&gt;タイトルの「いまさらの」は「みんなもう使っているだろうけど、こっちは業務で使ってひと月だから … …」というエクスキューズです。実際話してみると、全員が全員そういうわけでもなかった模様なので、期待値調整は難しいですね。&lt;/p&gt;
&lt;p&gt;内容としてはスライドの通り2部構成になっています。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Storyで使うTypeScriptの型定義&lt;/li&gt;
&lt;li&gt;Storybook自体がどのように動くか&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;スライドの通りではありますが、少しだけ文章で補足します。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#storyで使うtypescriptの型定義を読み解く&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Storyで使うTypeScriptの型定義を読み解く&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#storyの型定義&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Storyの型定義&lt;/h3&gt;
&lt;p&gt;Storyのファイルを書くと、基本的には次のような形になります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; { Meta&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; StoryObj } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;@storybook/react&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { Button } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./Button&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;meta&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;component&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Button&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;satisfies&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Meta&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;typeof&lt;/span&gt;&lt;span&gt; Button&amp;gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt; meta;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Story&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StoryObj&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;typeof&lt;/span&gt;&lt;span&gt; Button&amp;gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Primary&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Story&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;primary&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;label&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;Button&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;ここには&lt;code&gt;Meta&lt;/code&gt;と&lt;code&gt;StoryObj&lt;/code&gt;の2つの型がありますが、これらはいずれもStorybookが準拠するComponent Story Format 3に必要な属性を規定する型になっています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#csf3に必要な属性を定義するbaseannotationsインターフェイス&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;CSF3に必要な属性を定義するBaseAnnotationsインターフェイス&lt;/h3&gt;
&lt;p&gt;型定義を追っていくと、いずれも最終的には&lt;code&gt;BaseAnnotations&lt;/code&gt;というインターフェイスをimplementしていることがわかります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;BaseAnnotations&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TRenderer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Renderer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Renderer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Args&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Wrapper components or Storybook decorators that wrap a story.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Decorators defined in Meta will be applied to every story variation.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@see&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[Decorators](https:&lt;/span&gt;&lt;span&gt;//storybook.js.org/docs/addons/introduction/#1-decorators)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;decorators&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;DecoratorFunction&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TRenderer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Simplify&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;[]&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;DecoratorFunction&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TRenderer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Simplify&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Custom metadata for a story.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@see&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[Parameters](https:&lt;/span&gt;&lt;span&gt;//storybook.js.org/docs/basics/writing-stories/#parameters)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;parameters&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Parameters&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Dynamic data that are provided (and possibly updated by) Storybook and its addons.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@see&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[Arg&lt;/span&gt;&lt;span&gt; story inputs](https://storybook.js.org/docs/react/api/csf#args-story-inputs)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Partial&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* ArgTypes encode basic metadata for args, such as `name`, `description`, `defaultValue` for an arg. These get automatically filled in by Storybook Docs.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@see&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[Control&lt;/span&gt;&lt;span&gt; annotations](https://github.com/storybookjs/storybook/blob/91e9dee33faa8eff0b342a366845de7100415367/addons/controls/README.md#control-annotations)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;argTypes&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Partial&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ArgTypes&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Asynchronous functions which provide data for a story.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@see&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[Loaders](https:&lt;/span&gt;&lt;span&gt;//storybook.js.org/docs/react/writing-stories/loaders)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;loaders&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;LoaderFunction&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TRenderer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt;&amp;gt;[] &lt;/span&gt;&lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;LoaderFunction&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TRenderer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Function to be called before each story. When the function is async, it will be awaited.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* `beforeEach` can be added to preview, the default export and to a specific story.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* They are run (and awaited) in the order: preview, default export, story&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* A cleanup function can be returned.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;beforeEach&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;BeforeEach&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TRenderer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt;&amp;gt;[] &lt;/span&gt;&lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;BeforeEach&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TRenderer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Define a custom render function for the story(ies). If not passed, a default render function by the renderer will be used.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;render&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ArgsStoryFn&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TRenderer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Named tags for a story, used to filter stories in different contexts.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;tags&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Tag&lt;/span&gt;&lt;span&gt;[];&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;mount&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; (context&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StoryContext&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TRenderer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt;&amp;gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TRenderer&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;mount&apos;&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/ComponentDriven/csf/blob/v0.1.11/src/story.ts#L339&quot; target=&quot;_blank&quot;&gt;https://github.com/ComponentDriven/csf/blob/v0.1.11/src/story.ts#L339&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;BaseAnnotationsはStorybook側のリポジトリではなく、csfのリポジトリで定義されています。中身としてはいつもStoryを定義している際に使っている属性を含んだ型となっているようです。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#componentレベルstoryレベルでの設定を実現するためのmeta型storyobj型&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Componentレベル・Storyレベルでの設定を実現するためのMeta型、StoryObj型&lt;/h3&gt;
&lt;p&gt;MetaとStoryObjは定義する属性としてはほぼ同じですが、設定の粒度が異なります。前者はComponentレベル、後者はStoryレベルの設定を可能にします。&lt;/p&gt;
&lt;p&gt;具体的な例として、コンポーネントに渡すargsを実例に、型による設定レベルの切り分けの実際をみていきます。なおサンプルのコンポーネントとしては、Reactで以下のように定義されたButtonコンポーネントを使います。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ButtonProps&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;label&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;variant&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;solid&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;ghost&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;outline&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;onClick&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Button&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FC&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ButtonProps&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;meta&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;satisfies&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Meta&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;typeof&lt;/span&gt;&lt;span&gt; Button&amp;gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt; meta&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Story&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StoryObj&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;typeof&lt;/span&gt;&lt;span&gt; meta&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#metacomponentレベルではコンポーネントのpropsを任意で設定できる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Meta（Componentレベル）ではコンポーネントのPropsを任意で設定できる&lt;/h3&gt;
&lt;p&gt;まずStoryレベルのMetaでは、すべてのPropsを任意で指定できるようにしています。Componentレベルはあくまで共通で設定したい場合に使うものであるためです。
具体的な型としては次のような定義になっています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Metadata to configure the stories for a component.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@see&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[Default&lt;/span&gt;&lt;span&gt; export](https://storybook.js.org/docs/formats/component-story-format/#default-export)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Meta&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TCmpOrArgs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Args&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;TCmpOrArgs&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;ComponentType&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;&amp;gt;] &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ComponentAnnotations&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ReactRenderer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ComponentProps&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TCmpOrArgs&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ComponentAnnotations&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ReactRenderer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TCmpOrArgs&lt;/span&gt;&lt;span&gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;ここで&lt;code&gt;TCmpOrArgs&lt;/code&gt;は&lt;code&gt;typeof Button&lt;/code&gt;なので、&lt;code&gt;ComponentAnnotations&amp;lt;ReactRenderer, ComponentProps&amp;lt;TCmpOrArgs&amp;gt;&amp;gt;&lt;/code&gt;がかえります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ComponentAnnotations&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TRenderer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Renderer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Renderer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Args&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;BaseAnnotations&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TRenderer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Title of the component which will be presented in the navigation. **Should be unique.**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Components can be organized in a nested structure using &quot;/&quot; as a separator.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Since CSF 3.0 this property is optional -- it can be inferred from the filesystem path&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@example&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* export default {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*   ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*   title: &apos;Design System/Atoms/Button&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@see&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[Story&lt;/span&gt;&lt;span&gt; Hierarchy](https://storybook.js.org/docs/basics/writing-stories/#story-hierarchy)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ComponentTitle&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Id of the component (prefix of the story id) which is used for URLs.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* By default is inferred from sanitizing the title&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@see&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[Story&lt;/span&gt;&lt;span&gt; Hierarchy](https://storybook.js.org/docs/basics/writing-stories/#story-hierarchy)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ComponentId&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Used to only include certain named exports as stories. Useful when you want to have non-story exports such as mock data or ignore a few stories.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@example&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* includeStories: [&apos;SimpleStory&apos;, &apos;ComplexStory&apos;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* includeStories: /.*Story$/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@see&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[Non-story&lt;/span&gt;&lt;span&gt; exports](https://storybook.js.org/docs/formats/component-story-format/#non-story-exports)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;includeStories&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StoryDescriptor$1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Used to exclude certain named exports. Useful when you want to have non-story exports such as mock data or ignore a few stories.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@example&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* excludeStories: [&apos;simpleData&apos;, &apos;complexData&apos;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* excludeStories: /.*Data$/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@see&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[Non-story&lt;/span&gt;&lt;span&gt; exports](https://storybook.js.org/docs/formats/component-story-format/#non-story-exports)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;excludeStories&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StoryDescriptor$1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* The primary component for your story.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Used by addons for automatic prop table generation and display of other component metadata.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;component&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;TRenderer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Record&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;unknown&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Required&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})[&lt;/span&gt;&lt;span&gt;&apos;component&apos;&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Auxiliary subcomponents that are part of the stories.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Used by addons for automatic prop table generation and display of other component metadata.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@example&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* import { Button, ButtonGroup } from &apos;./components&apos;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* export default {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*   ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*   subcomponents: { Button, ButtonGroup }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* By defining them each component will have its tab in the args table.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;subcomponents&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Record&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TRenderer&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;component&apos;&lt;/span&gt;&lt;span&gt;]&amp;gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Function that is executed after the story is rendered.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;play&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;PlayFunction&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TRenderer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Override the globals values for all stories in this component&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;globals&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Globals&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;そしてこのComponentAnnotationsは先ほどのBaseAnnotaionsをimplementしています。ComponentAnnotationsには&lt;code&gt;args&lt;/code&gt;はありませんが、これはBaseAnnotationsに定義されています。&lt;/p&gt;
&lt;p&gt;型引数の&lt;code&gt;TArgs&amp;gt;&lt;/code&gt;には&lt;code&gt;ComponentProps&amp;lt;TCmpOrArgs&amp;gt;&amp;gt;&lt;/code&gt;が渡りますので、合わせると&lt;code&gt;args&lt;/code&gt;の型は次のようになります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Partial&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ComponentProps&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ComponentProps&lt;/span&gt;&lt;span&gt;&amp;lt;typeof&lt;/span&gt;&lt;span&gt; Button&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;したがって、&lt;code&gt;args&lt;/code&gt;はButtonのすべてのPropsをOptionalで受け入れる型になり、Componentレベルの設定を満たすことになります。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#storyobjstoryレベルではcomponentレベルで定義したpropsは任意になる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;StoryObj（Storyレベル）ではComponentレベルで定義したPropsは任意になる&lt;/h3&gt;
&lt;p&gt;つづいてStoryObjです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Story object that represents a CSFv3 component example.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@see&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[Named&lt;/span&gt;&lt;span&gt; Story exports](https://storybook.js.org/docs/formats/component-story-format/#named-story-exports)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StoryObj&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TMetaOrCmpOrArgs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Args&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;TMetaOrCmpOrArgs&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;render&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ArgsStoryFn&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ReactRenderer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;&amp;gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;component&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Component&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;DefaultArgs&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Simplify&lt;/span&gt;&lt;span&gt;&amp;lt;(&lt;/span&gt;&lt;span&gt;Component&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ComponentType&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ComponentProps&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Component&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;unknown&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ArgsFromMeta&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ReactRenderer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TMetaOrCmpOrArgs&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StoryAnnotations&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ReactRenderer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;AddMocks&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;DefaultArgs&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SetOptional&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;DefaultArgs&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;never&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TMetaOrCmpOrArgs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ComponentType&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StoryAnnotations&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ReactRenderer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ComponentProps&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TMetaOrCmpOrArgs&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StoryAnnotations&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ReactRenderer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TMetaOrCmpOrArgs&lt;/span&gt;&lt;span&gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;StoryObjは分岐が多くぱっと見読みづらいです。Reactコンポーネントで形成するMetaを渡した場合の型を抜粋するとこの部分のなります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;StoryAnnotations&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ReactRenderer&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; AddMocks&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; DefaultArgs&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; SetOptional&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; keyof TArgs &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; keyof DefaultArgs&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;StoryAnnotationsは名前から察するとおり、さきほどのComponentAnnotationsのStory版です。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StoryAnnotations&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TRenderer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Renderer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Renderer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Args&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TRequiredArgs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Partial&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;BaseAnnotations&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TRenderer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Override the display name in the UI (CSF v3)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StoryName&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Override the display name in the UI (CSF v2)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;storyName&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StoryName&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Function that is executed after the story is rendered.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;play&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;PlayFunction&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TRenderer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Override the globals values for this story&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;globals&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Globals&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;/** &lt;/span&gt;&lt;span&gt;@deprecated&lt;/span&gt;&lt;span&gt; */&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;story&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Omit&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;StoryAnnotations&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TRenderer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TArgs&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;story&apos;&lt;/span&gt;&lt;span&gt;&amp;gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; ({} &lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TRequiredArgs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TRequiredArgs&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TRequiredArgs&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;ここでは&lt;code&gt;args&lt;/code&gt;の型は、3つめの型引数に渡した型、つまり&lt;code&gt;SetOptional&amp;lt;TArgs, keyof TArgs &amp;amp; keyof DefaultArgs&amp;gt;&lt;/code&gt;になります。&lt;code&gt;SetOptional&lt;/code&gt;自体は何かというと、type-festで定義されている型ユーティリティで、指定したキーをOptionalにするものです。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/sindresorhus/type-fest/blob/main/source/set-optional.d.ts&quot; target=&quot;_blank&quot;&gt;https://github.com/sindresorhus/type-fest/blob/main/source/set-optional.d.ts&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ここでは&lt;code&gt;keyof TArgs &amp;amp; keyof DefaultArgs&lt;/code&gt;がOptionalにする対象なので、Componentレベルで定義したProps（&lt;code&gt;DefaultArgs&lt;/code&gt;）があれば、それらはOptionalになります。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#storyの型定義のまとめ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Storyの型定義のまとめ&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;csfから提供されるBaseAnnotationsという型によってComponent Story Formatに必要な属性を規定する&lt;/li&gt;
&lt;li&gt;MetaもStoryObjもBaseAnnotationsをimplementしたCSFを定義する型&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#storyはどのようにコンポーネントカタログになるのか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Storyはどのようにコンポーネントカタログになるのか&lt;/h2&gt;
&lt;p&gt;たとえば&lt;code&gt;storybook dev&lt;/code&gt;コマンドを実行した時に、定義したStoryがどういう過程を経てStorybookのあのUIになっているのかが気になっていました。
Storybookと実際のアプリケーションとの環境間差異を把握したいためです。全体像を把握しておけば新しいBundlerやPluginが追加になっても、ある程度想像がつくようになると考え、ざっとですが、&lt;code&gt;storybook dev&lt;/code&gt;からUIが立ち上がるまでを追いかけてみました。&lt;/p&gt;
&lt;p&gt;対象バージョン：Storybook 8.3.6&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#結論&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;結論&lt;/h3&gt;

&lt;h3&gt;&lt;a href=&quot;#エントリポイント&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;エントリポイント&lt;/h3&gt;
&lt;h3&gt;&lt;a href=&quot;#2つのbuilder&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;2つのBuilder&lt;/h3&gt;
&lt;p&gt;ManagerBuilderとPreviewBuilderという2つのBuilderが取得されています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;previewBuilder&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;managerBuilder&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&lt;span&gt;.all&lt;/span&gt;&lt;span&gt;([&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;getPreviewBuilder&lt;/span&gt;&lt;span&gt;(builderName&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;options&lt;/span&gt;&lt;span&gt;.configDir)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;getManagerBuilder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;useStatics&lt;/span&gt;&lt;span&gt;(router&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; options)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/storybookjs/storybook/blob/v8.3.6/code/core/src/core-server/dev-server.ts#L76-L80&quot; target=&quot;_blank&quot;&gt;https://github.com/storybookjs/storybook/blob/v8.3.6/code/core/src/core-server/dev-server.ts#L76-L80&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これらについては&lt;a href=&quot;https://storybook.js.org/docs/builders/builder-api&quot; target=&quot;_blank&quot;&gt;StorybookのドキュメントのBuilder APIのセクション&lt;/a&gt;に説明があります。&lt;/p&gt;
&lt;p&gt;画像の通りではありますが、アプリケーションのコンポーネントを描画するiframe部分のためのビルドツールをPreview Builderと読んでおり、それ以外のStorybook自体のUI部分のためのビルドツールをManager Builderと呼ぶそうです。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#manager-builder&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Manager Builder&lt;/h3&gt;
&lt;p&gt;Manager BuilderではStorybookのUIをビルドします。実際にはStorybookに内包される部分だけではなく、StorybookのUI部分に作用するAdd-Onもビルドの対象です、&lt;/p&gt;
&lt;p&gt;実態を追っていきます。まずManagerBuilder自体の取得は次のとおり、動的なimportによって実行されます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;getManagerBuilder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Builder&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;unknown&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;@storybook/core/builder-manager&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/storybookjs/storybook/blob/v8.3.6/code/core/src/core-server/utils/get-builders.ts#L7-L9&quot; target=&quot;_blank&quot;&gt;https://github.com/storybookjs/storybook/blob/v8.3.6/code/core/src/core-server/utils/get-builders.ts#L7-L9&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;（Manager BuilderとBuilder Managerだと違う意味に取れそうなものですが … …）。&lt;/p&gt;
&lt;p&gt;ここで取得されたManager Builderもといbuilder-managerパッケージに対して、dev-server側は&lt;code&gt;start&lt;/code&gt;を呼び出しています。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;start&lt;/code&gt;関数自体はそこそこに長い処理ですが、やっていることとしてはesbuildによるビルド実行→sirvを介してビルドした静的ファイルをサーブする、という2点です。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;getData&lt;/code&gt;関数ではesbuildのインスタンスやHTMLファイルのエントリポイントとなるejsファイルを取得します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;getData&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; (options&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Options&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;refs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;getRefs&lt;/span&gt;&lt;span&gt;(options);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;favicon&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;options&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;presets&lt;/span&gt;&lt;span&gt;&lt;span&gt;.apply&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;&amp;gt;(&lt;/span&gt;&lt;span&gt;&apos;favicon&apos;&lt;/span&gt;&lt;span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;.then&lt;/span&gt;&lt;span&gt;((p) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;basename&lt;/span&gt;&lt;span&gt;(p));&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;features&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;options&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;presets&lt;/span&gt;&lt;span&gt;&lt;span&gt;.apply&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Record&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;(&lt;/span&gt;&lt;span&gt;&apos;features&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;logLevel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;options&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;presets&lt;/span&gt;&lt;span&gt;&lt;span&gt;.apply&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;&amp;gt;(&lt;/span&gt;&lt;span&gt;&apos;logLevel&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;options&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;presets&lt;/span&gt;&lt;span&gt;&lt;span&gt;.apply&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;&amp;gt;(&lt;/span&gt;&lt;span&gt;&apos;title&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;docsOptions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;options&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;presets&lt;/span&gt;&lt;span&gt;&lt;span&gt;.apply&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;docs&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; {});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tagsOptions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;options&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;presets&lt;/span&gt;&lt;span&gt;&lt;span&gt;.apply&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;tags&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; {});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;readTemplate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;template.ejs&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;customHead&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;options&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;presets&lt;/span&gt;&lt;span&gt;&lt;span&gt;.apply&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;&amp;gt;(&lt;/span&gt;&lt;span&gt;&apos;managerHead&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// we await these, because crucially if these fail, we want to bail out asap&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;instance&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;config&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&lt;span&gt;.all&lt;/span&gt;&lt;span&gt;([&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;//&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;executor&lt;/span&gt;&lt;span&gt;&lt;span&gt;.get&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;getConfig&lt;/span&gt;&lt;span&gt;(options)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;refs&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;features&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;docsOptions&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;customHead&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;instance&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;config&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;logLevel&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;favicon&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;tagsOptions&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/storybookjs/storybook/blob/v8.3.6/code/core/src/builder-manager/index.ts#L133-L145&quot; target=&quot;_blank&quot;&gt;https://github.com/storybookjs/storybook/blob/v8.3.6/code/core/src/builder-manager/index.ts#L133-L145&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/storybookjs/storybook/blob/next/code/core/src/builder-manager/utils/data.ts#L9-L41&quot; target=&quot;_blank&quot;&gt;https://github.com/storybookjs/storybook/blob/next/code/core/src/builder-manager/utils/data.ts#L9-L41&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ここで読み込まれるのは、次のejsファイルです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;!&lt;/span&gt;&lt;span&gt;DOCTYPE&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;html&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;html&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;lang&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;en&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;head&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;meta&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;charset&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;utf-8&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;lt;%= typeof title !== &apos;undefined&apos;? title : &apos;Storybook&apos;%&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;meta&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;viewport&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;content&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;width=device-width, initial-scale=1, maximum-scale=1&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;% if (favicon.endsWith(&apos;.svg&apos;)) {%&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;link&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rel&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;icon&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;image/svg+xml&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;href&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;./&amp;lt;%= favicon %&amp;gt;&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;% } else if (favicon.endsWith(&apos;.ico&apos;)) { %&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;link&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rel&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;icon&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;image/x-icon&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;href&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;./&amp;lt;%= favicon %&amp;gt;&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;% } %&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;style&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 省略&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;style&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;link&lt;/span&gt;&lt;span&gt; href=&quot;./sb-manager/runtime.js&quot; rel=&quot;modulepreload&quot; /&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;% files&lt;/span&gt;&lt;span&gt;.js&lt;/span&gt;&lt;span&gt;.forEach(file =&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; { %&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;link&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;href&lt;/span&gt;&lt;span&gt;=&quot;&amp;lt;%= &lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;span&gt; %&amp;gt;&quot; &lt;/span&gt;&lt;span&gt;rel&lt;/span&gt;&lt;span&gt;=&quot;&lt;/span&gt;&lt;span&gt;modulepreload&lt;/span&gt;&lt;span&gt;&quot; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;% }); %&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &amp;lt;% if (typeof &lt;/span&gt;&lt;span&gt;head&lt;/span&gt;&lt;span&gt; !== &apos;undefined&apos;) { %&amp;gt; &amp;lt;%&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;head&lt;/span&gt;&lt;span&gt; %&amp;gt; &amp;lt;% } %&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;style&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;#storybook-root&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;hidden&lt;/span&gt;&lt;span&gt;] {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;display&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;none&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!important&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;style&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;% files.css.forEach(file =&amp;gt; { %&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;link&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;href&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&amp;lt;%= file %&amp;gt;&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rel&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;stylesheet&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;% }); %&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;head&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;body&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;root&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;% if (typeof globals !== &apos;undefined&apos; &amp;amp;&amp;amp; Object.keys(globals).length) { %&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&amp;lt;%&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; varName &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; globals) { &lt;/span&gt;&lt;span&gt;%&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&amp;lt;%&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (globals[varName] &lt;/span&gt;&lt;span&gt;!==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;undefined&lt;/span&gt;&lt;span&gt;) { &lt;/span&gt;&lt;span&gt;%&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;window[&lt;/span&gt;&lt;span&gt;&apos;&amp;lt;%=varName%&amp;gt;&apos;&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;%-&lt;/span&gt;&lt;span&gt; (globals[varName]) &lt;/span&gt;&lt;span&gt;%&amp;gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&amp;lt;%&lt;/span&gt;&lt;span&gt; } &lt;/span&gt;&lt;span&gt;%&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&amp;lt;%&lt;/span&gt;&lt;span&gt; } &lt;/span&gt;&lt;span&gt;%&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;% } %&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;module&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./sb-manager/globals-runtime.js&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&amp;lt;%&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;files&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;js&lt;/span&gt;&lt;span&gt;&lt;span&gt;.forEach&lt;/span&gt;&lt;span&gt;(file &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;%&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&amp;lt;%= file %&amp;gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&amp;lt;%&lt;/span&gt;&lt;span&gt; }); &lt;/span&gt;&lt;span&gt;%&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./sb-manager/runtime.js&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;% if (!ignorePreview) { %&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;link&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;href&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;./sb-preview/runtime.js&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rel&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;prefetch&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;script&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;% } %&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;body&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;html&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/storybookjs/storybook/blob/v8.3.6/code/core/assets/server/template.ejs&quot; target=&quot;_blank&quot;&gt;https://github.com/storybookjs/storybook/blob/v8.3.6/code/core/assets/server/template.ejs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ランタイムとして同梱される&lt;code&gt;./sb-manager/runtime.js&lt;/code&gt;では、StorybookのUIをレンダリングする&lt;code&gt;renderStorybookUI&lt;/code&gt;関数を呼び出しています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;document&lt;/span&gt;&lt;span&gt; } &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; global;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rootEl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;document&lt;/span&gt;&lt;span&gt;&lt;span&gt;.getElementById&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;root&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// We need to wait for the script tag containing the global objects&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// to be run by Webkit before rendering the UI. This is fine in most browsers.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;setTimeout&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// @ts-expect-error (non strict)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;renderStorybookUI&lt;/span&gt;&lt;span&gt;(rootEl&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ReactProvider&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/storybookjs/storybook/blob/v8.3.6/code/core/src/manager/runtime.ts#L45-L53&quot; target=&quot;_blank&quot;&gt;https://github.com/storybookjs/storybook/blob/v8.3.6/code/core/src/manager/runtime.ts#L45-L53&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ここから先はいつものReactの世界でした。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;renderStorybookUI&lt;/span&gt;&lt;span&gt;(domNode&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;HTMLElement&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; provider&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Provider&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;(provider &lt;/span&gt;&lt;span&gt;instanceof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Provider&lt;/span&gt;&lt;span&gt;)) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;throw&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ProviderDoesNotExtendBaseProviderError&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;root&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;createRoot&lt;/span&gt;&lt;span&gt;(domNode);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;root&lt;/span&gt;&lt;span&gt;&lt;span&gt;.render&lt;/span&gt;&lt;span&gt;(&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Root&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;root&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;provider&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{provider} /&amp;gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/storybookjs/storybook/blob/v8.3.6/code/core/src/manager/index.tsx&quot; target=&quot;_blank&quot;&gt;https://github.com/storybookjs/storybook/blob/v8.3.6/code/core/src/manager/index.tsx&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#storybookのレイアウト&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Storybookのレイアウト&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Layout&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;hasTab&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{hasTab}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;managerLayoutState&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{managerLayoutState}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;setManagerLayoutState&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{setManagerLayoutState}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;slotMain&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&amp;lt;&lt;/span&gt;&lt;span&gt;Preview&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;main&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;withLoader&lt;/span&gt;&lt;span&gt; /&amp;gt;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;slotSidebar&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&amp;lt;&lt;/span&gt;&lt;span&gt;Sidebar&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;onMenuClick&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{() &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;setMobileAboutOpen&lt;/span&gt;&lt;span&gt;((state) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;state)} /&amp;gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;slotPanel&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&amp;lt;&lt;/span&gt;&lt;span&gt;Panel&lt;/span&gt;&lt;span&gt; /&amp;gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;slotPages&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;pages&lt;/span&gt;&lt;span&gt;&lt;span&gt;.map&lt;/span&gt;&lt;span&gt;(({ id&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; render: Content }) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Content&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{id} /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;))}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/storybookjs/storybook/blob/v8.3.6/code/core/src/manager/App.tsx#L26-L35&quot; target=&quot;_blank&quot;&gt;https://github.com/storybookjs/storybook/blob/v8.3.6/code/core/src/manager/App.tsx#L26-L35&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Previewコンポーネントが実際にコンポーネントを描画する領域で、いくつかコンポーネントを潜っていくと、iframeを見つけることができます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StyledIframe&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;styled&lt;/span&gt;&lt;span&gt;&lt;span&gt;.iframe&lt;/span&gt;&lt;span&gt;(({ theme }) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; ({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;backgroundColor&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;theme&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;background&lt;/span&gt;&lt;span&gt;.preview&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;display&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;block&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;boxSizing&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;content-box&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;height&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;100%&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;width&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;100%&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;border&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;0 none&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;transition&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;background-position 0s, visibility 0s&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;backgroundPosition&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;-1px -1px, -1px -1px, -1px -1px, -1px -1px&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;margin&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;`auto`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;boxShadow&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;0 0 100px 100vw rgba(0,0,0,0.5)&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/storybookjs/storybook/blob/v8.3.6/code/core/src/manager/components/preview/Iframe.tsx#L7-L18&quot; target=&quot;_blank&quot;&gt;https://github.com/storybookjs/storybook/blob/v8.3.6/code/core/src/manager/components/preview/Iframe.tsx#L7-L18&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#preview-builder&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Preview Builder&lt;/h3&gt;
&lt;p&gt;Preview Builderは先述の通り、ユーザーが定義したStoryのためのBuilderです。Builderは次のインターフェイスを満たすことを必要としており、実際にdev serverの中でも&lt;code&gt;start&lt;/code&gt;や&lt;code&gt;bail&lt;/code&gt;などが呼び出されています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Builder&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Config&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Stats&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;start&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; (args&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;options&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Options&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;startTime&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ReturnType&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;typeof&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;process&lt;/span&gt;&lt;span&gt;.hrtime&amp;gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;router&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Router&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Server&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;stats&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Stats&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;totalTime&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ReturnType&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;typeof&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;process&lt;/span&gt;&lt;span&gt;.hrtime&amp;gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;bail&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; (e&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Error&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt;&amp;gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&amp;gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; (arg&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;options&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Options&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;startTime&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ReturnType&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;typeof&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;process&lt;/span&gt;&lt;span&gt;.hrtime&amp;gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Stats&lt;/span&gt;&lt;span&gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;bail&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; (e&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Error&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt;&amp;gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;getConfig&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; (options&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Options&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Config&lt;/span&gt;&lt;span&gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;corePresets&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;[];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;overridePresets&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;[];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://storybook.js.org/docs/builders/builder-api#builder-api&quot; target=&quot;_blank&quot;&gt;https://storybook.js.org/docs/builders/builder-api#builder-api&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;現在Storybookで利用できるBuilderにはwebpackとViteがあるので、今回は@storybook/builder-viteを読んでみます。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#builder-vite&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;builder-vite&lt;/h4&gt;
&lt;p&gt;builder-viteもStorybookのリポジトリに格納されています。
&lt;a href=&quot;https://github.com/storybookjs/storybook/tree/v8.3.6/code/builders/builder-vite&quot; target=&quot;_blank&quot;&gt;https://github.com/storybookjs/storybook/tree/v8.3.6/code/builders/builder-vite&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;start&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ViteBuilder&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;start&apos;&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; ({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;startTime&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;options&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;router&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; devServer&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;server &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;createViteServer&lt;/span&gt;&lt;span&gt;(options &lt;/span&gt;&lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Options&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; devServer);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;previewResolvedDir&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;join&lt;/span&gt;&lt;span&gt;(corePath&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;dist/preview&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;router&lt;/span&gt;&lt;span&gt;&lt;span&gt;.use&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&apos;/sb-preview&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;sirv&lt;/span&gt;&lt;span&gt;(previewResolvedDir&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;maxAge&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;300000&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dev&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;immutable&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;router&lt;/span&gt;&lt;span&gt;&lt;span&gt;.use&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;iframeMiddleware&lt;/span&gt;&lt;span&gt;(options &lt;/span&gt;&lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Options&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; server));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;router&lt;/span&gt;&lt;span&gt;&lt;span&gt;.use&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt;.middlewares);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;bail&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;stats&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;toJson&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;throw&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NoStatsForViteDevError&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;totalTime&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;process&lt;/span&gt;&lt;span&gt;&lt;span&gt;.hrtime&lt;/span&gt;&lt;span&gt;(startTime)&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;startの処理はこれだけで、やっていることととしては次のとおりです。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;middlewareModeでViteの&lt;code&gt;createServer&lt;/code&gt;を実行する。&lt;/li&gt;
&lt;li&gt;Storybookのcoreディレクトリを起点としてdist/previewを静的アセットとして配信できるようにします。&lt;/li&gt;
&lt;li&gt;iframeMiddlewareをミドルウェアとして指定します。&lt;/li&gt;
&lt;li&gt;1をミドルウェアとして指定する。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;まず1のmiddlewareModeについて、これによりルーティングの制御は&lt;code&gt;router&lt;/code&gt;、つまりStorybookがpolkaを用いてたてたHTTPサーバに移ります。結果としてルーティング後の処理をViteが受け持てるようになります。
&lt;a href=&quot;https://ja.vite.dev/guide/ssr.html#setting-up-the-dev-server&quot; target=&quot;_blank&quot;&gt;サーバーサイドレンダリング | Vite&lt;/a&gt;がわかりやすく、この例ではexpressを使っていますが、polkaを使っていても同じ要領で読めるかと思います。&lt;/p&gt;
&lt;p&gt;次に2のdist/previewですが、これはViteが配信するiframe.htmlで読み込まれるスクリプトを指しています。&lt;/p&gt;
&lt;p&gt;3のiframeMiddlewareは同じファイルに定義されており、どうも&lt;code&gt;iframe.html&lt;/code&gt;でリクエストが来た場合に、@storybook/buider-vite/input/iframe.htmlをごにょごにょして返すmiddlewareのようです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;iframeMiddleware&lt;/span&gt;&lt;span&gt;(options&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Options&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; server&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ViteDevServer&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Middleware&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; (req&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; res&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; next) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;.url &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;url&lt;/span&gt;&lt;span&gt;&lt;span&gt;.match&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt;\/iframe\.html(&lt;/span&gt;&lt;span&gt;$|&lt;/span&gt;&lt;span&gt;\?)/&lt;/span&gt;&lt;span&gt;)) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;next&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// the base isn&apos;t used for anything, but it&apos;s required by the URL constructor&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;url&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;URL&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;.url&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;http://localhost:6006&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// We need to handle `html-proxy` params for style tag HMR https://github.com/storybookjs/builder-vite/issues/266#issuecomment-1055677865&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// e.g. /iframe.html?html-proxy&amp;amp;index=0.css&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;url&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;searchParams&lt;/span&gt;&lt;span&gt;&lt;span&gt;.has&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;html-proxy&apos;&lt;/span&gt;&lt;span&gt;)) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;next&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;indexHtml&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;readFile&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;require&lt;/span&gt;&lt;span&gt;&lt;span&gt;.resolve&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;@storybook/builder-vite/input/iframe.html&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;encoding&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;utf8&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;generated&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;transformIframeHtml&lt;/span&gt;&lt;span&gt;(indexHtml&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; options);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;transformed&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt;&lt;span&gt;.transformIndexHtml&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;/iframe.html&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; generated);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;res&lt;/span&gt;&lt;span&gt;&lt;span&gt;.setHeader&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;Content-Type&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;text/html&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;res&lt;/span&gt;&lt;span&gt;.statusCode &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;200&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;res&lt;/span&gt;&lt;span&gt;&lt;span&gt;.write&lt;/span&gt;&lt;span&gt;(transformed);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;res&lt;/span&gt;&lt;span&gt;&lt;span&gt;.end&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;というわけでViteの世界のエントリポイントはiframe.htmlになりそうなので、次はここを起点に処理をみます。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#iframehtml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;iframe.html&lt;/h4&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;body&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&amp;lt;!-- [BODY HTML SNIPPET HERE] --&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;storybook-root&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;storybook-docs&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;module&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;src&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;./sb-preview/runtime.js&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;module&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;src&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;/virtual:/@storybook/builder-vite/vite-app.js&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;body&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;iframe.htmlの中身は薄く、bodyとしてはこれだけです。いくつかdivがあるのでStorybookのUIと照らし合わせると、たしかにiframeの中にこの要素がありますね。&lt;/p&gt;
&lt;p&gt;さきほども出てきましたが、&lt;code&gt;sb-preview/runtime.js&lt;/code&gt;が出てきているので、これを確認します。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#sb-previewruntimejs&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;sb-preview/runtime.js&lt;/h4&gt;
&lt;p&gt;実際のディレクトリでいうと、code/core/src/previewを指していそうです。このモジュールでは、Storybookの各モジュールをグローバルスコープに突っ込む役割を担っています。&lt;/p&gt;
&lt;p&gt;あまり具体的な処理はなかったので、もう1つのscriptをみます。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#storybookbuilder-vitevite-appjs&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;@storybook/builder-vite/vite-app.js&lt;/h4&gt;
&lt;p&gt;Viteの仮想モジュールなのですが、具体的にどのファイルの処理で生成されるものを指しているのかいまいちわからず … …。&lt;/p&gt;
&lt;p&gt;残念ながら今回はここでタイムアップです。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;発表ではStorybook 8.3で発表されたexperimental-nextjs-viteにも触れたのですが、こちらもあまり深追いはできておらず、サラッと紹介する程度でした。まだまだコード読解力が足りませんね。&lt;/p&gt;
&lt;p&gt;ただ今回のドキュメントリーディング、コードリーディングを経て、だいぶStorybookに対して自信が持てました。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>「こんにちは TAG-さん!」とは何か</title><link>https://ikuma-t.com/blog/what-is-hello-tag-san/</link><guid isPermaLink="true">https://ikuma-t.com/blog/what-is-hello-tag-san/</guid><description>こんにちはTAG-さん!https://github.com/w3ctag/design-reviews/issuesW3CTechnicalArchitectureGroupが保有するdesign-</description><pubDate>Sat, 04 May 2024 06:50:06 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#こんにちは-tag-さん&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;こんにちは TAG-さん!&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/w3ctag/design-reviews/issues&quot; target=&quot;_blank&quot;&gt;https://github.com/w3ctag/design-reviews/issues&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;W3C Technical Architecture Group が保有する design-reviews というリポジトリでは、新しい仕様に対するレビューが GitHub Issue で行われています。&lt;/p&gt;
&lt;p&gt;直近の Issue のすべてが「こんにちは TAG-さん! 」で始まっており、なぜ突然日本語が出てくるのか不思議に思ったので調査することにしました。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://storage.googleapis.com/zenn-user-upload/97e4e2bfdf0a-20240504.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#調査結果&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;調査結果&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;この挨拶文は ISSUE TEMPLATE に含まれている。&lt;/li&gt;
&lt;li&gt;W3C TAG では定期的に Face to Face Meeting を行っており、その開催地に合わせて挨拶文が変わる。&lt;/li&gt;
&lt;li&gt;ただし厳密な運用はしておらず、「こんにちは TAG-さん!」は 2023 年 04 月に開催された東京での MTG に合わせたもの。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#調査詳細&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;調査詳細&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#issue-template-を確認する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Issue template を確認する&lt;/h3&gt;
&lt;p&gt;全員同じ始まりということはおそらくテンプレートがそういう形式なのだろうということで、確認したところ、確かにテンプレートに「こんにちは TAG-さん! 」の文字列が含まれていました。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/w3ctag/design-reviews/blob/main/.github/ISSUE_TEMPLATE/005-early-design-review.md?plain=1#L11&quot; target=&quot;_blank&quot;&gt;https://github.com/w3ctag/design-reviews/blob/main/.github/ISSUE_TEMPLATE/005-early-design-review.md?plain=1#L11&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/w3ctag/design-reviews/blob/main/.github/ISSUE_TEMPLATE/010-specification-review.md?plain=1#L11&quot; target=&quot;_blank&quot;&gt;https://github.com/w3ctag/design-reviews/blob/main/.github/ISSUE_TEMPLATE/010-specification-review.md?plain=1#L11&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/w3ctag/design-reviews/blob/main/.github/ISSUE_TEMPLATE/020-dispute-escalation.md?plain=1#L10&quot; target=&quot;_blank&quot;&gt;https://github.com/w3ctag/design-reviews/blob/main/.github/ISSUE_TEMPLATE/020-dispute-escalation.md?plain=1#L10&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ISSUE TEMPLATE は 3 種類あります。&lt;/p&gt;





















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;template 名&lt;/th&gt;&lt;th&gt;内容&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;005-early-design-review&lt;/td&gt;&lt;td&gt;初期段階での方向性について考えやガイダンスを提供してほしい場合に使用&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;010-specification-review&lt;/td&gt;&lt;td&gt;現在取り組んでいる Web 技術の仕様についてレビューしてもらいたいの場合に使用&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;020-dispute-escalation-review&lt;/td&gt;&lt;td&gt;現在の論争について意見を求める場合に使用&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;&lt;a href=&quot;#issue-template-の起源&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Issue template の起源&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/w3ctag/design-reviews/commit/68a1436aa797b7b30002a5ec39f4ce1dfa451942&quot; target=&quot;_blank&quot;&gt;https://github.com/w3ctag/design-reviews/commit/68a1436aa797b7b30002a5ec39f4ce1dfa451942&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;git blame すると、2019年05月23日にこのテンプレートが作成されたことがわかります。
ここを確認すると、この時点で「こんにちはTAG!」（現在は「こんにちは TAG-さん!」）という文字列が含まれていることがわかりました。&lt;/p&gt;
&lt;p&gt;作成された際のコミットメッセージは次のとおりであり、もともと「specification review」というテンプレートがどこか（メーリングリストとか？）にあったことが伺えます。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Create issue templates in the new format
Make issue templates in the new format. Use the existing template as a “specification review” template, and create a somewhat different template for “dispute resolution”.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;なお Issue Template をこのリポジトリに作成した人物は Google に勤めるエンジニアの L. David Baron さんです。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/dbaron&quot; target=&quot;_blank&quot;&gt;https://github.com/dbaron&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#もっとissue-template-の起源&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;もっと！Issue template の起源&lt;/h3&gt;
&lt;p&gt;現在の Issue Template はここまでしか辿れませんが、日付と過去に別のテンプレートがあった、という情報が手に入ったので、リポジトリ全体の History を参照してみました。&lt;/p&gt;
&lt;p&gt;すると、2019年05月09日に ISSUE_TEMPLATE.md を変更しているコミットを発見。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/w3ctag/design-reviews/commit/426a9a8b3fc6314deb9f44a60ade76d2edaca6fd&quot; target=&quot;_blank&quot;&gt;https://github.com/w3ctag/design-reviews/commit/426a9a8b3fc6314deb9f44a60ade76d2edaca6fd&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;このファイルの履歴を辿ってみます。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/w3ctag/design-reviews/commits/426a9a8b3fc6314deb9f44a60ade76d2edaca6fd/ISSUE_TEMPLATE.md&quot; target=&quot;_blank&quot;&gt;https://github.com/w3ctag/design-reviews/commits/426a9a8b3fc6314deb9f44a60ade76d2edaca6fd/ISSUE_TEMPLATE.md&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;まず 2016年11月02日にテンプレートのファイルが作成されていました。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/w3ctag/design-reviews/commit/9ed6f17be379a5d0d9397c5311ac9634fcab84d4&quot; target=&quot;_blank&quot;&gt;https://github.com/w3ctag/design-reviews/commit/9ed6f17be379a5d0d9397c5311ac9634fcab84d4&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;コミットメッセージには「F2Fからの Issue template。共同で構築。」と記載があります。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Issue template from F2F. Collaboratively constructed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;この「F2F」について検索してみると、どうも W3C が開催している「Face to Face」 Meeting のことを指しているようです。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#tag-meeting-2016tokyo&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;TAG Meeting 2016@Tokyo&lt;/h3&gt;
&lt;p&gt;2016年11月02日あたりに開催された TAG の Meeting を検索してみると、どんぴしゃで2016/10/31 - 2016/11/02 @東京 開催のMTGがあることがわかりました。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.w3.org/events/happenings/2016/technical-architecture-group-tag-meeting-2/&quot; target=&quot;_blank&quot;&gt;https://www.w3.org/events/happenings/2016/technical-architecture-group-tag-meeting-2/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Web サイトのリンクがあったので眺めてみる。どうも日経ビルでやっていたそうな。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/w3ctag/meetings/tree/gh-pages/2016/11-tokyo&quot; target=&quot;_blank&quot;&gt;https://github.com/w3ctag/meetings/tree/gh-pages/2016/11-tokyo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;議事録があるようですが、どれも W3C TAG のトップページに飛んでしまい参照できませんでした。最新の MTG の議事録の格納場所に移動されていないかみてみたものの、最近では直接 GitHub に保存しているのでダメそうです。&lt;/p&gt;
&lt;p&gt;これ以上は追えないものの、ここを起源にテンプレートが生まれたことがわかりました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#greeting-の変遷&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;greeting の変遷&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/w3ctag/design-reviews/commit/6bd78d4e674e5428c32f914bec64739164ba7a54&quot; target=&quot;_blank&quot;&gt;https://github.com/w3ctag/design-reviews/commit/6bd78d4e674e5428c32f914bec64739164ba7a54&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;テンプレートが作成されて以降、初めて挨拶部分が変更されたのがこのコミット。2017年07月にはたしかにロンドンで F2F MTG が開催されており、これに合わせて「Dear Sirs and Madam of TAG!」に変わっている。&lt;/p&gt;
&lt;p&gt;テンプレートができた時から、初めて挨拶部分が変更されたときまでに、02-boston、04-tokyo の2回が開催されている。ボストンについてはアメリカなので変更の余地がありませんが、なぜ東京は変えなかったのか…（東京の時に Hello で作ったので、変えようと思わなかったのかも？）？&lt;/p&gt;
&lt;p&gt;何はともあれ、2017年07月以降、その回の MTG の会期中に、次回の開催地の挨拶文に変わるという文化が始まったようです。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#改めてこんにちは-tag-さんを確認する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;改めて「こんにちは TAG-さん!」を確認する&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/w3ctag/design-reviews/commit/d7015be036a57a19e9be170eeb914e425db9b65c&quot; target=&quot;_blank&quot;&gt;https://github.com/w3ctag/design-reviews/commit/d7015be036a57a19e9be170eeb914e425db9b65c&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;この変更が入ったのは、2023年02月13日。確かに2023年04月には東京で F2F MTG が開催されているものの、それ以降も MTG は開催されており、一方で挨拶文は変わっていない。&lt;/p&gt;
&lt;p&gt;よくよくみてみると、必ずしも毎回挨拶文が変わっているわけでもなく、厳格な運用（挨拶文の変更に厳格な運用も何もないが…）はされていないようでした。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;あまり重要ではない情報の調査に時間を使ってしまったような気がしましたが、調査の過程で W3C TAG に少し詳しくなれたのでよかったです。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>GraphQLの「Serving over HTTP」とは何か</title><link>https://ikuma-t.com/blog/what-is-serving-ver-http-in-graphql/</link><guid isPermaLink="true">https://ikuma-t.com/blog/what-is-serving-ver-http-in-graphql/</guid><description>サマリモダンなWebアプリケーションフレームワークは、HTTPを用いてやり取りを行い、ミドルウェアを利用して認証やリクエストの検証、変換を行うパイプライン型のアーキテクチャを採用しているGraphQL</description><pubDate>Fri, 03 May 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#サマリ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;サマリ&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;モダンな Web アプリケーションフレームワークは、HTTPを用いてやり取りを行い、ミドルウェアを利用して認証やリクエストの検証、変換を行うパイプライン型のアーキテクチャを採用している&lt;/li&gt;
&lt;li&gt;GraphQL においても、事前に認証・検証が行われた上でリクエストを処理するのがベストプラクティス&lt;/li&gt;
&lt;li&gt;そのために、GraphQL のリクエストを REST のような形式でマッピングして処理する&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#serving-over-http&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Serving over HTTP&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://graphql.org/learn/serving-over-http&quot; target=&quot;_blank&quot;&gt;https://graphql.org/learn/serving-over-http&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;GraphQL サーバは GET と POST の 2 種類の HTTP リクエストをハンドリングできるようにします。&lt;/p&gt;
&lt;p&gt;マッピングされるパラメータは次のとおりです。&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;パラメータ&lt;/th&gt;&lt;th&gt;意味&lt;/th&gt;&lt;th&gt;必須&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;query&lt;/td&gt;&lt;td&gt;クエリそのもの&lt;/td&gt;&lt;td&gt;必須&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;variables&lt;/td&gt;&lt;td&gt;クエリの変数&lt;/td&gt;&lt;td&gt;任意&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;operationName&lt;/td&gt;&lt;td&gt;クエリの名前。複数のオペレーションを同時に実行する場合には必須&lt;/td&gt;&lt;td&gt;任意&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;&lt;a href=&quot;#get&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;GET&lt;/h3&gt;
&lt;p&gt;GET リクエストでは、GraphQL Query が &lt;code&gt;query&lt;/code&gt; というクエリパラメータにマッピングされます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;hero.graphql&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;query&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;HeroQuery&lt;/span&gt;&lt;span&gt;($id: &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ID&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;hero(id: $id) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;このクエリは、次のようにエンコードされます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;http://myapi.com/graphql?query&lt;/span&gt;&lt;span&gt;=query&lt;/span&gt;&lt;span&gt;($id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ID!&lt;/span&gt;&lt;span&gt;){hero($id: ID!){name}}&amp;amp;operationName=HeroQuery&amp;amp;variables={&quot;id&quot;:&quot;avagfads732&quot;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#post&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;POST&lt;/h3&gt;
&lt;p&gt;POST リクエストでは、&lt;code&gt;application/json&lt;/code&gt; でリクエストを送信する。次の形式の JSON をボディとして送信されます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;query&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;...&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;variables&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;updateHeroName&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;operationName&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;&quot;id&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;avagfads732&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Andrew&quot;&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#レスポンス&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;レスポンス&lt;/h3&gt;
&lt;p&gt;レスポンスは JSON 形式で返される。GraphQL の仕様に則り、&lt;code&gt;data&lt;/code&gt;フィールドか&lt;code&gt;errors&lt;/code&gt;フィールドが含まれます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;data&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;hero&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Andrew&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;errors&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;message&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Cannot query field &apos;hero&apos; on type &apos;Query&apos;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;locations&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;line&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;column&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#draft-transport-specification--graphql-over-http&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;[Draft] Transport Specification / GraphQL over HTTP&lt;/h2&gt;
&lt;p&gt;ここまでの内容が GraphQL 公式で公開されている内容で、ここから先はまだドラフト段階です。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#仕様の定義場所&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;仕様の定義場所&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://graphql.github.io/graphql-over-http/draft/&quot; target=&quot;_blank&quot;&gt;https://graphql.github.io/graphql-over-http/draft/&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#概要&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;概要&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;GraphQL over HTTP は Serving over HTTP の仕様を拡張したもの。&lt;/li&gt;
&lt;li&gt;HTTP サーバは 1 つ以上の URL を介して、GraphQL スキーマへのリクエストを受け付ける必要がある。&lt;/li&gt;
&lt;li&gt;サーバおよびクライアントは、少なくとも JSON の形式でリクエストをサポートする必要がある。&lt;/li&gt;
&lt;li&gt;レスポンスにおける Media Type は &lt;code&gt;application/graphql-response+json&lt;/code&gt; が推奨。&lt;/li&gt;
&lt;li&gt;サーバは POST リクエストに必ず対応する必要があり、そのほかの GET のようなメソッドも対応する可能性がある。&lt;/li&gt;
&lt;li&gt;サーバはリクエストの処理の成功時にはその結果を、失敗時にはエラーを返す必要がある。&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>ikuma-t</author></item><item><title>skim で移動/コマンド履歴検索をインタラクティブに行う</title><link>https://ikuma-t.com/blog/skim-tips/</link><guid isPermaLink="true">https://ikuma-t.com/blog/skim-tips/</guid><description>モチベーション新しくM3MacbookAirを購入したので、これを機に色々とツールを乗り換えています。FuzzyFinderにはこれまでpecoを使っていたのですが、全部Rust製に統一したいという思</description><pubDate>Thu, 02 May 2024 11:34:51 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#モチベーション&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;モチベーション&lt;/h2&gt;
&lt;p&gt;新しく M3 Macbook Air を購入したので、これを機に色々とツールを乗り換えています。&lt;/p&gt;
&lt;p&gt;Fuzzy Finder にはこれまで peco を使っていたのですが、全部 Rust 製に統一したいという思いがあり、skim に乗り換えました。&lt;/p&gt;
&lt;p&gt;乗り換えたはいいのですが、キーバインドやコマンドの設定を怠っており活用できていなかったので、調べて設定してみた、というのがこの記事の内容です。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#zoxide-の絞り込みに-skim-を使う&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;zoxide の絞り込みに skim を使う&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/ajeetdsouza/zoxide&quot; target=&quot;_blank&quot;&gt;https://github.com/ajeetdsouza/zoxide&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;zoxide には標準で &lt;code&gt;zi&lt;/code&gt; というエイリアスが設定されており、これを使うことでインタラクティブにディレクトリを選択できます。
しかし内部的には &lt;code&gt;fzf&lt;/code&gt; が使われており、そのままだと &lt;code&gt;fzf&lt;/code&gt; もインストールしなければなりません。&lt;/p&gt;
&lt;p&gt;これを &lt;code&gt;skim&lt;/code&gt; で使うための設定が以下の Issue で提案されていました。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/ajeetdsouza/zoxide/issues/228&quot; target=&quot;_blank&quot;&gt;https://github.com/ajeetdsouza/zoxide/issues/228&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;__zoxide_zi&lt;/span&gt;&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;\builtin&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;$( \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;zoxide&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;query&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-ls&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--&lt;/span&gt;&lt;span&gt; &quot;$@&quot; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sk&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;--delimiter=&lt;/span&gt;&lt;span&gt;&apos;[^\t\n ][\t\n ]+&apos; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;-n2..&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;--no-sort&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;--keep-right&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;--height=&lt;/span&gt;&lt;span&gt;&apos;40%&apos; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;--layout=&lt;/span&gt;&lt;span&gt;&apos;reverse&apos; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;--exit-0&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;--select-1&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;--bind=&lt;/span&gt;&lt;span&gt;&apos;ctrl-z:ignore&apos; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;--preview=&lt;/span&gt;&lt;span&gt;&apos;\command -p ls -F --color=always {2..}&apos; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;__zoxide_cd&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;${result&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;7}&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;zle&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-N&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;__zoxide_zi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;setopt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;noflowcontrol&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;bindkey&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;^z&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;__zoxide_zi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;通常のシェルインテグレーションと同様に、&lt;code&gt;__zoxide_zi&lt;/code&gt; 関数を定義し、&lt;code&gt;zoxide query&lt;/code&gt; でディレクトリを取得し、&lt;code&gt;sk&lt;/code&gt; で選択するようにしています。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/ajeetdsouza/zoxide/blob/main/templates/zsh.txt#L69-L73&quot; target=&quot;_blank&quot;&gt;https://github.com/ajeetdsouza/zoxide/blob/main/templates/zsh.txt#L69-L73&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#履歴検索を-skim-で行う&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;履歴検索を skim で行う&lt;/h2&gt;
&lt;p&gt;最適かは分かりませんが、履歴検索を &lt;code&gt;skim&lt;/code&gt; で行う設定を以下のようにしました。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hist&lt;/span&gt;&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;BUFFER&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt;$(&lt;/span&gt;&lt;span&gt;history&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-r&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sk&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--query&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;$LBUFFER&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--reverse&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;CURSOR&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;$#BUFFER&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;zle&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;reset-prompt&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;zle&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-N&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hist&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;bindkey&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;^r&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hist&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#zlebindkey-is-何&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;zle、bindkey is 何？&lt;/h2&gt;
&lt;p&gt;Zsh Line Editor の略で、Zsh のコマンドライン編集機能を提供します。
ターミナル上の文字列やカーソル位置をシェルスクリプト上で操作するための機能のようです。&lt;/p&gt;
&lt;p&gt;今回出てくる &lt;code&gt;-N&lt;/code&gt; オプションは、新しく関数をバインドするためのオプションです。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;-N new-keymap [ old-keymap ]
Create a new keymap, named new-keymap. If a keymap already has that name, it is deleted. If an old-keymap name is given, the new keymap is initialized to be a duplicate of it, otherwise the new keymap will be empty.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;bindkey&lt;/code&gt; は、キーバインドを設定するためのコマンドです。指定したキーに対して、指定した関数をバインドします。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html&quot; target=&quot;_blank&quot;&gt;https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#参考&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;参考&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://speakerdeck.com/naoya/sierunolu-li-toikunrimentarujian-suo-woshi-u&quot; target=&quot;_blank&quot;&gt;https://speakerdeck.com/naoya/sierunolu-li-toikunrimentarujian-suo-woshi-u&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://k-koh.hatenablog.com/entry/2020/10/24/160323&quot; target=&quot;_blank&quot;&gt;https://k-koh.hatenablog.com/entry/2020/10/24/160323&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.rasukarusan.com/entry/2020/04/19/193450&quot; target=&quot;_blank&quot;&gt;https://www.rasukarusan.com/entry/2020/04/19/193450&lt;/a&gt;&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Astro で Warning ReactDOMServer.renderToStaticNodeStream() is deprecated. が出るようになった原因と対応</title><link>https://ikuma-t.com/blog/what-is-react-dom-server-render-to-static-node-stream-is-deprecated/</link><guid isPermaLink="true">https://ikuma-t.com/blog/what-is-react-dom-server-render-to-static-node-stream-is-deprecated/</guid><description>Astroで突然非推奨の警告が出るようになったこのサイトはAstroで実装されており、一部コンポーネントにReactを使用しています。ある日を境に、開発サーバの起動ログに以下のような警告が出るようにな</description><pubDate>Wed, 01 May 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#astro-で突然非推奨の警告が出るようになった&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Astro で突然非推奨の警告が出るようになった&lt;/h2&gt;
&lt;p&gt;このサイトは Astro で実装されており、一部コンポーネントに React を使用しています。
ある日を境に、開発サーバの起動ログに以下のような警告が出るようになりました。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;Warning:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ReactDOMServer.renderToStaticNodeStream&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;is&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;deprecated.&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Use&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ReactDOMServer.renderToPipeableStream&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;and&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;wait&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;pipe&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;until&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;the&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;onAllReady&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;callback&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;has&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;been&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;called&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;instead.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;メッセージで検索してみると、同様の Issue が GitHub に起票されており、対応の Pull Request もマージされていました。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/withastro/astro/issues/10899&quot; target=&quot;_blank&quot;&gt;https://github.com/withastro/astro/issues/10899&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/withastro/astro/pull/10893&quot; target=&quot;_blank&quot;&gt;https://github.com/withastro/astro/pull/10893&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;2024/05/01 時点ではまだリリースされていませんが、数日以内にリリースされると思われるため、@astrojs/react のバージョンアップで修正されると考えられます。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;2024/05/03 追記: 変更がリリースされ、警告が出なくなりました。
&lt;a href=&quot;https://github.com/withastro/astro/blob/HEAD/packages/integrations/react/CHANGELOG.md#332&quot; target=&quot;_blank&quot;&gt;https://github.com/withastro/astro/blob/HEAD/packages/integrations/react/CHANGELOG.md#332&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;この記事ではそもそもなぜこの警告が出るようになったのかを調査しました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#前提&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;前提&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;astro: 4.7.0&lt;/li&gt;
&lt;li&gt;@astrojs/react 3.3.1&lt;/li&gt;
&lt;li&gt;react 18.3.1&lt;/li&gt;
&lt;li&gt;react-dom 18.3.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#どの箇所を起因として警告が出るようになったのか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;どの箇所を起因として警告が出るようになったのか&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/withastro/astro/blob/c238aa81ee91ce85f40740234fe6878faa27dceb/packages/integrations/react/server.js#L153-L173&quot; target=&quot;_blank&quot;&gt;https://github.com/withastro/astro/blob/c238aa81ee91ce85f40740234fe6878faa27dceb/packages/integrations/react/server.js#L153-L173&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Astro の react インテグレーションで &lt;code&gt;ReactDOM.renderToStaticNodeStream()&lt;/code&gt; が使用されている箇所がありました。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/facebook/react/pull/28874&quot; target=&quot;_blank&quot;&gt;https://github.com/facebook/react/pull/28874&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/facebook/react/blob/main/CHANGELOG.md#react-dom&quot; target=&quot;_blank&quot;&gt;https://github.com/facebook/react/blob/main/CHANGELOG.md#react-dom&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;React 側では 2024/04/25 の 18.3.0 のリリースでこの警告を追加しています。&lt;/p&gt;
&lt;p&gt;description を確認すると次の理由から非推奨に指定されたことがわかります。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This API has been legacy, is not widely used (renderToStaticMarkup is more common) and has semantically eqiuvalent implementations with renderToReadableStream and renderToPipeableStream.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ReactDOM.renderToStaticMarkup()&lt;/code&gt; がより一般的に使われている。&lt;/li&gt;
&lt;li&gt;加えて &lt;code&gt;ReactDOM.renderToReadableStream()&lt;/code&gt; と &lt;code&gt;ReactDOM.renderToPipeableStream()&lt;/code&gt; が同等の実装を持っている。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#reactdomserverrendertostaticnodestream-とは何か&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ReactDOMServer.renderToStaticNodeStream() とは何か？&lt;/h2&gt;
&lt;p&gt;ReactDOMServer は、サーバ上で React コンポーネントをレンダリングするための API を指しており、具体的なパッケージは &lt;code&gt;react-dom/server&lt;/code&gt; です。
いわゆる Static-Site Generation や Server-Side Rendering と言われるような事前レンダリングに用いられます。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ja.react.dev/reference/react-dom/server&quot; target=&quot;_blank&quot;&gt;https://ja.react.dev/reference/react-dom/server&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;この API 群には動作環境とレンダリング結果の分類によっていくつかのメソッドが用意されているようです。&lt;/p&gt;









































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;環境&lt;/th&gt;&lt;th&gt;メソッド&lt;/th&gt;&lt;th&gt;ストリーム&lt;/th&gt;&lt;th&gt;ハイドレーション&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Node.js&lt;/td&gt;&lt;td&gt;&lt;code&gt;renderToPipeableStream&lt;/code&gt;&lt;/td&gt;&lt;td&gt;可&lt;/td&gt;&lt;td&gt;可&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Node.js&lt;/td&gt;&lt;td&gt;&lt;code&gt;renderToStaticNodeStream&lt;/code&gt;&lt;/td&gt;&lt;td&gt;可&lt;/td&gt;&lt;td&gt;不可&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Web Stream&lt;/td&gt;&lt;td&gt;&lt;code&gt;renderToReadableStream&lt;/code&gt;&lt;/td&gt;&lt;td&gt;可&lt;/td&gt;&lt;td&gt;可&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ストリームサポートなし&lt;/td&gt;&lt;td&gt;&lt;code&gt;renderToString&lt;/code&gt;&lt;/td&gt;&lt;td&gt;不可&lt;/td&gt;&lt;td&gt;不可&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ストリームサポートなし&lt;/td&gt;&lt;td&gt;&lt;code&gt;renderToStaticMarkup&lt;/code&gt;&lt;/td&gt;&lt;td&gt;不可&lt;/td&gt;&lt;td&gt;不可&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;上記の表の繰り返しになりますが、renderToStaticNodeStream は Node.js 環境において、React コンポーネントをストリームとして出力するための API を指します。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#react-ではなぜ-reactdomserverrendertostaticnodestream-が非推奨となったのか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;React ではなぜ ReactDOMServer.renderToStaticNodeStream() が非推奨となったのか&lt;/h2&gt;
&lt;p&gt;ドキュメントを参照すると、注意点として以下の内容が記載されています。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;renderToStaticNodeStream の出力はハイドレーションすることができません。
React 18 時点において、このメソッドはすべての出力をバッファリングするため、実際にはストリームを使用する利点が得られません。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;この特徴を踏まえると、&lt;code&gt;renderToStaticNodeStream&lt;/code&gt; は実際にはストリームとしての利点を享受できないため、ケースによって既存のメソッドに置き換えることができそうです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ハイドレーションが不要で、ストリームも不要な場合：&lt;code&gt;renderToStaticMarkup&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;ハイドレーションが必要で、ストリームも必要な場合：&lt;code&gt;renderToPipeableStream&lt;/code&gt;（Node.js環境）、&lt;code&gt;renderToReadableStream&lt;/code&gt;（Web Stream）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ユースケースをカバーできる他の API があるので、&lt;code&gt;renderToStaticNodeStream&lt;/code&gt; は非推奨となったと考えられます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#補足-astro-における対応&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;補足: Astro における対応&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;&quot;renderToReadableStream&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; ReactDOM) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;html &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;renderToReadableStreamAsync&lt;/span&gt;&lt;span&gt;(vnode&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; renderOptions);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;html &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;renderToPipeableStreamAsync&lt;/span&gt;&lt;span&gt;(vnode&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; renderOptions);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Astro では、環境に応じて &lt;code&gt;renderToReadableStream&lt;/code&gt; か &lt;code&gt;renderToPipeableStream&lt;/code&gt; を使うようになっていました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#参考&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;参考&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.reddit.com/r/astrojs/comments/1cdbito/libsupabase_error_v46_and_v47_warning/?onetap_auto=true&amp;amp;one_tap=true&amp;amp;rdt=62227&quot; target=&quot;_blank&quot;&gt;https://www.reddit.com/r/astrojs/comments/1cdbito/libsupabase_error_v46_and_v47_warning/?onetap_auto=true&amp;amp;one_tap=true&amp;amp;rdt=62227&lt;/a&gt;&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Go におけるツールの依存関係を追跡できるようにする</title><link>https://ikuma-t.com/blog/how-to-track-tool-dependencies/</link><guid isPermaLink="true">https://ikuma-t.com/blog/how-to-track-tool-dependencies/</guid><description>解決したい課題gqlgenのように、ツールとしては確かにプロジェクトで使用しているけれども、アプリケーションのコードベースに出てこないパッケージを利用するケースがあります。このようなツールはgomod</description><pubDate>Tue, 30 Apr 2024 13:28:33 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#解決したい課題&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;解決したい課題&lt;/h2&gt;
&lt;p&gt;gqlgen のように、ツールとしては確かにプロジェクトで使用しているけれども、アプリケーションのコードベースに出てこないパッケージを利用するケースがあります。&lt;/p&gt;
&lt;p&gt;このようなツールは &lt;code&gt;go mod tidy&lt;/code&gt; を実行した際に、import されていないため、module が消えてしまいます。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#解決策&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;解決策&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;tools.go&lt;/code&gt; ファイルを作成し、そこで依存関係を追跡するツールをインポートすることで、Go におけるツールの依存関係を追跡できるようにします。
具体的には以下のような &lt;code&gt;tools.go&lt;/code&gt; を作成します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;//go:build tools&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// +build tools&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tools&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;_ &lt;/span&gt;&lt;span&gt;&quot;github.com/99designs/gqlgen&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;_ &lt;/span&gt;&lt;span&gt;&quot;github.com/99designs/gqlgen/graphql/introspection&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;このファイルで import が実行されているため、&lt;code&gt;go mod tidy&lt;/code&gt; を実行してもツールの依存関係が消えることはありません。
また &lt;code&gt;//go:build tools&lt;/code&gt; を記載することで、このファイルは &lt;code&gt;go build&lt;/code&gt; などのビルド時には無視されるようになります。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;// +build tools&lt;/code&gt; は、このファイルが &lt;code&gt;tools&lt;/code&gt; というビルドタグを持つことを示しています。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#参考&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;参考&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://go.dev/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module&quot; target=&quot;_blank&quot;&gt;https://go.dev/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module&lt;/a&gt;&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>GitHub Issue から Markdown ファイルを生成してブログ記事を公開する</title><link>https://ikuma-t.com/blog/publish-blog-from-github-issue/</link><guid isPermaLink="true">https://ikuma-t.com/blog/publish-blog-from-github-issue/</guid><description>モチベーションこのブログはAstroを用いて実装されており、記事はMarkdownファイルとして管理されています。基本的にPCで作業しているのでこの形式でも問題はないのですが、たまにスマホから記事を書</description><pubDate>Sun, 28 Apr 2024 08:27:11 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#モチベーション&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;モチベーション&lt;/h2&gt;
&lt;p&gt;このブログは Astro を用いて実装されており、記事は Markdown ファイルとして管理されています。基本的に PC で作業しているのでこの形式でも問題はないのですが、たまにスマホから記事を書きたいと思うことがあります。&lt;/p&gt;
&lt;p&gt;しかしながら記事は GitHub 上の Markdown ファイルとして管理されているため、スマホで書くにはやや面倒です。特に YAML フロントマターは PC 上では VSCode のスニペットにより簡単に挿入できるのですが、スマートフォンではそうもいきません。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#github-issue-から-markdown-ファイルを生成する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;GitHub Issue から Markdown ファイルを生成する&lt;/h2&gt;
&lt;p&gt;そこで、GitHub Issue から Markdown ファイルを生成する方法を考えました。&lt;/p&gt;
&lt;p&gt;Markdown で管理することを前提として、スマホでも書きやすくするための選択肢としては次のようなものが考えられます。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;GitHub Issue から Markdown ファイルを生成する&lt;/li&gt;
&lt;li&gt;CodeSpaces を利用して、ブラウザ上で記事を編集する&lt;/li&gt;
&lt;li&gt;記事作成用の Web アプリを作成する&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;今回はお手軽に実施したかったことと、CodeSpaces をスマホで触るのは体験としてやや無理がったので、GitHub Issue から Markdown ファイルを生成する方法を選択しました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#実装&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;実装&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#全体の構成&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;全体の構成&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;GitHub Issue を作成する（Issue テンプレートとして、ブログのテンプレを用意しておく）&lt;/li&gt;
&lt;li&gt;GitHub Actions で ラベルが付与されたことをトリガーに GitHub Actions を実行する
&lt;ol&gt;
&lt;li&gt;ラベルを検知し、&lt;code&gt;publish&lt;/code&gt; が付与されていれば後続の処理を実行する&lt;/li&gt;
&lt;li&gt;Issue の内容から Markdown ファイルを生成する&lt;/li&gt;
&lt;li&gt;Issue の内容を元に Markdown ファイルを生成し、新たにブランチを作成する&lt;/li&gt;
&lt;li&gt;プルリクエストを作成する&lt;/li&gt;
&lt;li&gt;対象となった Issue にプルリクエストを紐付け、Issue を Close する&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Cloudflare Pages　のプレビューが走るため、プレビューする&lt;/li&gt;
&lt;li&gt;問題なければマージし、記事が公開される&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;&lt;a href=&quot;#github-actions-の-ワークフロー&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;GitHub Actions の ワークフロー&lt;/h3&gt;
&lt;p&gt;GitHub Actions のワークフローは次のようになります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;publish content from GitHub Issue&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;on&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;issues&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;types&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;labeled&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;workflow_dispatch&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;jobs&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;publish&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;runs-on&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ubuntu-latest&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;steps&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;uses&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;actions/checkout@v4&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Check issue labels&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;contains(github.event.issue.labels.*.name, &apos;publish&apos;) != true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;exit 0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Define title&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;define_title&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;title=$(echo &quot;${{ github.event.issue.title }}&quot; | sed -r &apos;s/([a-z0-9])([A-Z])/\1-\2/g; s/ /-/g&apos; | tr &apos;[A-Z]&apos; &apos;[a-z]&apos;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;echo &quot;title=$title&quot; &amp;gt;&amp;gt; $GITHUB_OUTPUT&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Create Content File&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;echo -e &quot;${{ github.event.issue.body }}&quot; | sed -e &quot;s/publishDate:/publishDate: $(TZ=-9 date -Iseconds)/&quot; | sed -e &quot;s/modDatetime:/modDatetime: $(TZ=-9 date -Iseconds)/&quot; &amp;gt;&amp;gt; src/content/blog/${{ steps.define_title.outputs.title }}.md&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;env&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Commit Content File&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;uses&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;EndBug/add-and-commit@v9&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;with&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;new_branch&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;${{ steps.define_title.outputs.title }}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Create PullRequest&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;gh pr create --title &quot;${{ github.event.issue.title }}&quot; --body &quot;#${{ github.event.issue.number}}&quot; --base main --head ${{ steps.define_title.outputs.title }}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;env&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Close Issue&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;gh issue close ${{ github.event.issue.number }}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;env&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#issue-テンプレート&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Issue テンプレート&lt;/h3&gt;
&lt;p&gt;Issue を起点に作成するので、テンプレートも用意しておきます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;blog&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;about&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;create blog draft&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;labels&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;assignees&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;## &lt;/span&gt;&lt;span&gt;&amp;lt;!-- Issueタイトルはslugとして使用。時刻は埋めなくて良い --&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;author: ikuma-t&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;publishDate:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;modDatetime:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;title:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;featured: false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;draft: false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;tags:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;- description:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;##&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Issue テンプレート自体の YAML フロントマターと衝突するため、やむを得ず一行コメントを挟んでいます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#ショートカットの追加&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ショートカットの追加&lt;/h3&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;MacroDroid を使って、メニュー部分に「ブログを追加」ボタンを設置します。&lt;/p&gt;
&lt;p&gt;Issue Template はクエリパラメータで設定できるので、その URL を登録しておきます。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;GitHub Mobile がインストール済みであれば、ブラウザではなくこちらで Issue を作成することができます。&lt;/p&gt;
&lt;p&gt;Web 版よりも Markdown エディタが使いやすく便利です。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;GitHub Issue から Markdown ファイルを生成する方法を紹介しました。&lt;/p&gt;
&lt;p&gt;画像の挿入には対応していないものの、比較的お気軽に記事を投稿できるようになり満足です。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>このブログのパッケージマネージャを pnpm に変更した</title><link>https://ikuma-t.com/blog/change-package-manager/</link><guid isPermaLink="true">https://ikuma-t.com/blog/change-package-manager/</guid><description>pnpmへ移行もともとこのブログのリポジトリではnpmを使っていましたが、他の箇所ではpnpmやbunを使っていることもあり、速度に不満があったためpnpmに移行しました。移行手順pnpmのインストー</description><pubDate>Sat, 27 Apr 2024 07:35:32 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#pnpm-へ移行&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;pnpm へ移行&lt;/h2&gt;
&lt;p&gt;もともとこのブログのリポジトリでは npm を使っていましたが、他の箇所では pnpm や bun を使っていることもあり、速度に不満があったため pnpm に移行しました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#移行手順&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;移行手順&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;pnpm のインストール&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-g&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pnpm&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;既存の node_modules の削除&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;rm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-rf&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;node_modules&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;package-lock.json の削除&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;rm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;package-lock.json&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;package のインストール&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;pnpm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#補足-pnpm-コマンドのみを許可する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;補足： pnpm コマンドのみを許可する&lt;/h2&gt;
&lt;p&gt;package.json に以下の設定を追加することで、npm や yarn コマンドを使わないようにできます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;preinstall&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;npx only-allow pnpm&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;なお &lt;a href=&quot;https://github.com/pnpm/only-allow&quot; target=&quot;_blank&quot;&gt;only-allow&lt;/a&gt; は特定のパッケージマネージャのみを許可するパッケージです。&lt;/p&gt;
&lt;p&gt;実際のところ、コマンド実行時は &lt;a href=&quot;https://github.com/azu/ni.zsh&quot; target=&quot;_blank&quot;&gt;azu/ni.zsh: Alternative `ni` written in zsh: npm/yarn/pnpm/bun with the same command&lt;/a&gt; を使用しているので間違えることもないですが…。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>VSCode Conference Japan 2024 で登壇しました！</title><link>https://ikuma-t.com/blog/vscode-conference-2024/</link><guid isPermaLink="true">https://ikuma-t.com/blog/vscode-conference-2024/</guid><description>VSCodeConferenceJapan2024で登壇しました！先日4/20に開催されたVSCodeConferenceJapan2024に登壇してきました！VSCodeConferenceJapa</description><pubDate>Mon, 22 Apr 2024 13:38:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#vscode-conference-japan-2024-で登壇しました&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;VSCode Conference Japan 2024 で登壇しました！&lt;/h2&gt;
&lt;p&gt;先日 4/20 に開催された &lt;a href=&quot;https://vscodejp.github.io/conference-2024/&quot; target=&quot;_blank&quot;&gt;VSCode Conference Japan 2024&lt;/a&gt; に登壇してきました！&lt;/p&gt;
&lt;p&gt;VSCode Conference Japan のアーカイブ動画を拝見したことがあったのですが、参加するのははじめてでした。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#自分の登壇内容&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;自分の登壇内容&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#登壇資料登壇動画&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;登壇資料・登壇動画&lt;/h3&gt;

&lt;p&gt;動画のアーカイブもあります。&lt;/p&gt;

&lt;h3&gt;&lt;a href=&quot;#モチベーション&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;モチベーション&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://zenn.dev/ikuma/books/how-to-use-redimine&quot; target=&quot;_blank&quot;&gt;RubyMine入門&lt;/a&gt; や &lt;a href=&quot;https://zenn.dev/ikuma/articles/reading-with-code-tour&quot; target=&quot;_blank&quot;&gt;Code Tour を使ってじっくり確実にコードを読む&lt;/a&gt;、&lt;a href=&quot;https://speakerdeck.com/ikumatadokoro/railsapuriwokosupayokudu-mutamenohuan-jing-zheng-bei&quot; target=&quot;_blank&quot;&gt;Railsアプリをコスパよく読むための環境整備&lt;/a&gt;などなど、エディタ関連のアウトプットはあれど、カンファレンスには登壇したことないなあと思っていたので、今回の機会に登壇してみようと思いました。&lt;/p&gt;
&lt;p&gt;プロポーザルは結構難産なことが多いのですが、ツール系は自分の趣味分野ということもあり、割とあっさりとテーマを決めることができました。&lt;/p&gt;
&lt;p&gt;話せることが結構あるからあっさりテーマが決まったわけですが、登壇時間 15 分に対して、スライド 59 枚は多かったなあと反省しています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#発表の構成&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;発表の構成&lt;/h3&gt;
&lt;p&gt;そのまま並べても資料としては成立するだけのボリュームだったのですが、そうすると Tips 集になってしまって話を聞かなくてもいいかなと思いそう…と感じ、冒頭に「なぜ見た目から始めるのか」という Why からはいる形式に。&lt;/p&gt;
&lt;p&gt;内容は普段業務でもやっている小さな改善系において考えていることの流用ですが、この進め方にしてみたところ扱う Tips の取捨選択がうまくできてよかったです。&lt;/p&gt;

&lt;h3&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h3&gt;
&lt;p&gt;懇親会や X でも「参考になった」と言っていただけてとても嬉しかったです！&lt;/p&gt;
&lt;p&gt;これまで自分の手元に溜め込んでいた「すぐアウトプットできるけど、1つ1つは記事にするほどでもない」ネタたちを一気に放出できてスッキリしました！&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#biomeに寄付をすることにした&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Biomeに寄付をすることにした&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/unvalley_/status/1781603651288809515&quot; target=&quot;_blank&quot;&gt;https://twitter.com/unvalley_/status/1781603651288809515&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;同じく登壇されていた &lt;a href=&quot;https://twitter.com/unvalley_&quot; target=&quot;_blank&quot;&gt;unvalley&lt;/a&gt; さんの登壇内容がとても印象的でした。&lt;/p&gt;

&lt;p&gt;資料内で引用されていた資料も併せて貼っておきます。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://erika.florist/articles/dontunderestimateeditorintegration/&quot; target=&quot;_blank&quot;&gt;https://erika.florist/articles/dontunderestimateeditorintegration/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Biome 自体は新規で小さなツールを書く際に利用していたのですが、これを機にこのサイトでも Biome を利用するようにし、また Open Collective 経由で Biome への寄付を始めました。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://opencollective.com/biome&quot; target=&quot;_blank&quot;&gt;https://opencollective.com/biome&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;とりあえず $5 ずつ月額寄付をしていますが、これからも継続していきたいと思います（給料上がったらもう少し増やす）。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;最近ソフトウェアアーキテクチャの基礎を読んでから、技術に触れる時に Technology Radar の 4 象限を意識するようになりました。
前々から薄々気がついていたのですが、自分はかなりツールに傾倒する傾向があり、時間の使い方的にどうなんだと思っています。趣味という点ではいいんですけどね。&lt;/p&gt;
&lt;p&gt;なので今回ツール系のネタを放出できたのを一つの区切りにして、今後、最低でも半年はツール系のネタは封印してやっていこうと思っています。&lt;/p&gt;
&lt;p&gt;区切りをつけようと思えたのは、年に一度の VSCode のお祭りで登壇できたから &amp;amp; 楽しかったからこそです。運営の皆様、ありがとうございました！&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>現在のディレクトリから新しいリポジトリを作成する</title><link>https://ikuma-t.com/blog/new-repository-from-local/</link><guid isPermaLink="true">https://ikuma-t.com/blog/new-repository-from-local/</guid><description>何度やっても忘れるのでメモ。privaterepositoryTerminalwindowghrepocreate--private$(basename$(pwd))--push-s.publicre</description><pubDate>Mon, 11 Mar 2024 12:00:19 GMT</pubDate><content:encoded>&lt;p&gt;何度やっても忘れるのでメモ。&lt;/p&gt;
&lt;p&gt;private repository&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;gh&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;repo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--private&lt;/span&gt;&lt;span&gt;&lt;span&gt;  $(&lt;/span&gt;&lt;span&gt;basename&lt;/span&gt;&lt;span&gt; $(&lt;/span&gt;&lt;span&gt;pwd&lt;/span&gt;&lt;span&gt;)) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--push&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-s&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;public repository&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;gh&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;repo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--public&lt;/span&gt;&lt;span&gt;&lt;span&gt; $(&lt;/span&gt;&lt;span&gt;basename&lt;/span&gt;&lt;span&gt; $(&lt;/span&gt;&lt;span&gt;pwd&lt;/span&gt;&lt;span&gt;)) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--push&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-s&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;学習用のリポジトリを作成するときに便利。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>ミスドのネット予約を使うと、チョコファッションのチョコを全体にかけられる</title><link>https://ikuma-t.com/blog/tappuri-choco-old-fashionned-donut/</link><guid isPermaLink="true">https://ikuma-t.com/blog/tappuri-choco-old-fashionned-donut/</guid><description>この前初めてミスタードーナツを予約してみた際、「事前予約専用ドーナツ」なるものがあることを知りました。https://www.misterdonut.jp/m_menu/new/240207_net_</description><pubDate>Sun, 10 Mar 2024 11:43:45 GMT</pubDate><content:encoded>&lt;p&gt;この前初めてミスタードーナツを予約してみた際、「事前予約専用ドーナツ」なるものがあることを知りました。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.misterdonut.jp/m_menu/new/240207_net_order/&quot; target=&quot;_blank&quot;&gt;https://www.misterdonut.jp/m_menu/new/240207_net_order/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;自分はミスドで何かを買う時、オールドファッション系のドーナツを頼むことが多いです（お腹に溜まるから）。
当然チョコファッションも購入するのですが、景気とともにチョコの量がどんどん減ってきている気がしており、毎回ちょっぴりしょぼんとしていました。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.misterdonut.jp/m_menu/donut/net_order24_01.html&quot; target=&quot;_blank&quot;&gt;https://www.misterdonut.jp/m_menu/donut/net_order24_01.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;今回見つけた予約専用の「たっぷりチョコファッション」は、表面前面にチョコがかかっているというもの。
注文の手間はかかりますが、通常のチョコファッションに 10円上乗せするだけで、チョコを3倍楽しめます。&lt;/p&gt;
&lt;p&gt;特にオチはないです。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Code Tour を使ってじっくり確実にコードを読む</title><link>https://ikuma-t.com/blog/reading-with-code-tour/</link><guid isPermaLink="true">https://ikuma-t.com/blog/reading-with-code-tour/</guid><description>CodeTourを使ってじっくり確実にコードを読む日々のタスクに忙殺されていると、ついつい既存コードを流し読みして、ざっと動くコードを書いてしまいたくなります。一発でうまく動けば短期的にはいいのですが</description><pubDate>Sun, 10 Mar 2024 10:28:45 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#code-tour-を使ってじっくり確実にコードを読む&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Code Tour を使ってじっくり確実にコードを読む&lt;/h2&gt;
&lt;p&gt;日々のタスクに忙殺されていると、ついつい既存コードを流し読みして、ざっと動くコードを書いてしまいたくなります。
一発でうまく動けば短期的にはいいのですが、長期的にはコードの理解が追いつかなったり、一発でうまく動かなかった場合にかえって時間がかかってしまいます。&lt;/p&gt;
&lt;p&gt;VSCode の拡張機能である Code Tour を使うと、コード上にメモを残しながら読み進めることができるので、既存のコードを読む際に便利です。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#code-tour-とは&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Code Tour とは&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=vsls-contrib.codetour&quot; target=&quot;_blank&quot;&gt;https://marketplace.visualstudio.com/items?itemName=vsls-contrib.codetour&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;VSCode の拡張機能で、コード上にメモを残しつつ、そのメモをたどることができるツールです。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;代替テキスト&quot; loading=&quot;lazy&quot; width=&quot;1049&quot; height=&quot;360&quot; src=&quot;/_astro/tour-example.DCqFLWfP_Z1MChGk.png&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#使い方&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;使い方&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#ツアーを始める&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ツアーを始める&lt;/h3&gt;
&lt;p&gt;コマンドパレットから「Code Tour: Record Tour」を選択すると、ツアーの記録モードになります。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ツアーの名前&lt;/li&gt;
&lt;li&gt;どのソースに紐づけるか（紐付けなし、ブランチ、タグ）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;を選択すると、リポジトリ直下に &lt;code&gt;.tours/${指定したツアー名}.tour&lt;/code&gt; というファイルが作成され、ツアーの記録が開始されます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#メモを残す&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;メモを残す&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;代替テキスト&quot; loading=&quot;lazy&quot; width=&quot;1058&quot; height=&quot;396&quot; src=&quot;/_astro/tour-basic.CIBwBSU__ZDXXPe.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ツアー記録モードだと、エディタの行番号横に「+」ボタンが表示されます。単一行または複数行を指定することで、その行にメモを残すことができます。
メモには、Markdown が使えるので、コードの説明や、参考リンクなどを記述することができます。&lt;/p&gt;
&lt;p&gt;シンタックスハイライトも適用されるので、「自分の見慣れない文法だったので、小さいサンプルとともにメモしておきたい」「ライブラリの実装を読んだので、関連部分にメモしておきたい」などの場合にも便利です。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;代替テキスト&quot; loading=&quot;lazy&quot; width=&quot;1046&quot; height=&quot;615&quot; src=&quot;/_astro/highlight.D7iAxb_J_Zalmmx.png&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#ツアーの記録を終了する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ツアーの記録を終了する&lt;/h3&gt;
&lt;p&gt;コマンドパレットから「Code Tour: End Tour」を選択すると、ツアーの記録が終了します。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#ツアーを再生する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ツアーを再生する&lt;/h3&gt;
&lt;p&gt;コマンドパレットから「Code Tour: Start Tour」を選択すると、ツアーの再生モードになります。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;代替テキスト&quot; loading=&quot;lazy&quot; width=&quot;1035&quot; height=&quot;628&quot; src=&quot;/_astro/start-tour.BZRo7Lib_Z251fRk.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;各ツアーのメモにはページ送りボタンがあるので、これを利用して前後のツアーに移動することができます。&lt;/p&gt;
&lt;p&gt;なお画像中の Insert: Code はコードブロックがある場合に表示されるもので、これを押すと、そのコードブロックがエディタに挿入されます。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#ユースケース&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ユースケース&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#開発中のサービスの特定機能の概観を理解したい&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;開発中のサービスの特定機能の概観を理解したい&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;代替テキスト&quot; loading=&quot;lazy&quot; width=&quot;1200&quot; height=&quot;495&quot; src=&quot;/_astro/read-feature.Ih1kju_D_ZWayyy.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;サービスの機能の振る舞いは知っているけど、実際のコードとしてはどういう構成になっているのか実は把握できていない、というケースで Code Tour を利用しています。&lt;/p&gt;
&lt;p&gt;読み方は掲載した図の通りで、&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;エントリポイント（UI、ジョブ、CLI…）にメモする&lt;/li&gt;
&lt;li&gt;機能のアウトプットを行って箇所（レスポンスを出力しているところ、帳票やログ出力）にメモする&lt;/li&gt;
&lt;li&gt;どういうデータ構造で保存しているかメモする&lt;/li&gt;
&lt;li&gt;外界からの入力をどう受け取っているのかメモする&lt;/li&gt;
&lt;li&gt;ビジネスロジックをどう実装しているかメモする&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;といった感じです。&lt;/p&gt;
&lt;p&gt;ビジネスロジックの部分は複雑になりがちなので、設計によってはいくつかのファイルに散らばることもありますが、これによりそれぞれのファイルにメモを取るとどうしてもメモが多くなってきたり、Tour も行ったりきたりになってしまいます。&lt;/p&gt;
&lt;p&gt;そのためコアのファイル以外は精読せずに、ざっくりとインターフェースからこんなことをやってくれそう、という内容をコアファイルのメモとして取るようにしています。&lt;/p&gt;
&lt;p&gt;反対にコアとなるファイルはちょっとした文法でもわからないところがあると、全体像がボヤけるので全力で調べてメモを残しています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#特定のライブラリに依存した機能を理解したい&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;特定のライブラリに依存した機能を理解したい&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;代替テキスト&quot; loading=&quot;lazy&quot; width=&quot;1200&quot; height=&quot;512&quot; src=&quot;/_astro/read-feat-with-library.CocO4fkQ_Z1jdFuG.png&quot; /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ここでいうライブラリとは管理機能やドキュメント生成ライブラリなど、土台となるフレームワーク（React、Next.js、Rails、Spring Boot など）の上に乗り、特定の機能群を実現するライブラリを意図しています。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;例えば管理機能を作る場合に React Admin を使っていたりすると、React は知っていても、React Admin がいい感じに隠蔽しているので、どうやって書けば良いかスッとは出てこない、というケースがあります。その際には Code Tour を使って公式ドキュメントと実際のコードを読んでいます。&lt;/p&gt;
&lt;p&gt;管理機能系であれば、通常のコードと別ディレクトリ（例： app/admin）に分かれていることが多いので、ツアーを始める際にはディレクトリをエントリポイントにします。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;代替テキスト&quot; loading=&quot;lazy&quot; width=&quot;503&quot; height=&quot;749&quot; src=&quot;/_astro/directory.DlEKF1yN_Z21aszW.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ディレクトリ を指定して「Add Code Tour Step」を選択することで、ディレクトリに対してメモを取ることができるので、最初に公式ドキュメントや全体像をメモするようにしています。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;代替テキスト&quot; loading=&quot;lazy&quot; width=&quot;1088&quot; height=&quot;493&quot; src=&quot;/_astro/directory-example.BVdNO7t8_AQTV2.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ディレクトリのツアーに対しても、仮装のファイルが開き、通常のソースファイルと同様にメモを確認することができます。&lt;/p&gt;
&lt;p&gt;ディレクトリ内に置かれているファイル数にもよりますが、なんとなく頭の中に知り合いを増やしてからドキュメントを読んだほうが個人的には馴染みが良いです。&lt;/p&gt;
&lt;p&gt;そのためざっとすべてのファイルに目を通しつつ、よくわからないDSL的なものが出てくれば「なんだこれ？」とだけメモし、あとはドキュメントに書いてある内容や実際に動かした挙動で随時編集しています。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;以前はコードを読む際にソースコードのURLとメモをマークダウンファイルに残していましたが、Code Tour を使うようになってからはソースコードとメモが一体化しているので、読み進める際にスムーズになりました。&lt;/p&gt;
&lt;p&gt;私は .tours ディレクトリをグローバルに ignore しているのでチームには共有していませんが、Gist経由で記録したツアーを共有することもできるので、チームでのコードリーディングにも使えるでしょう。&lt;/p&gt;
&lt;p&gt;Code Tour で素敵なコードリーディングライフを！&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>個人ブログを再度Astroで作りました</title><link>https://ikuma-t.com/blog/create-astro-blog-2/</link><guid isPermaLink="true">https://ikuma-t.com/blog/create-astro-blog-2/</guid><description>個人ブログを再度Astroで作りましたRemixで作っていたのですが、雑に作ったせいかときどきクラッシュするので、またまたAstroで作りました。今回は制作時間をかけないようにAstroPaperとい</description><pubDate>Sun, 10 Mar 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#個人ブログを再度astroで作りました&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;個人ブログを再度Astroで作りました&lt;/h2&gt;
&lt;p&gt;Remixで作っていたのですが、雑に作ったせいかときどきクラッシュするので、またまたAstroで作りました。
今回は制作時間をかけないように &lt;a href=&quot;https://github.com/satnaing/astro-paper&quot; target=&quot;_blank&quot;&gt;AstroPaper&lt;/a&gt;というテンプレートを使いました。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>WhichKeyでVSCodeのショートカットをすいすい叩けるようにする</title><link>https://ikuma-t.com/blog/whichkey/</link><guid isPermaLink="true">https://ikuma-t.com/blog/whichkey/</guid><description>はじめにVSCodeを利用し始めてかれこれ1年くらい経ちますが、基本的なものを除いていまいちショートカットが覚えられません。JetBrains系のエディタのプラグインにあるKeyPromoterXのV</description><pubDate>Sat, 06 Jan 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#はじめに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;はじめに&lt;/h2&gt;
&lt;p&gt;VSCode を利用し始めてかれこれ1年くらい経ちますが、基本的なものを除いていまいちショートカットが覚えられません。&lt;/p&gt;
&lt;p&gt;JetBrains 系のエディタのプラグインにある Key Promoter X の VSCode 版を導入してみたのですが、結局正しいキーはなんなのかがわからずうまくいきませんでした。&lt;/p&gt;
&lt;p&gt;これに対し、 Which Key という拡張機能を使うことでショートカットを覚えずに、ショートカットを活用できるようになったので紹介します。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#whichkey-とは&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;WhichKey とは&lt;/h2&gt;
&lt;p&gt;WhichKey は　&lt;a href=&quot;https://vspacecode.github.io/&quot; target=&quot;_blank&quot;&gt;VSpaceCode&lt;/a&gt; という Spacemacs ライクなキーバインドを実現する拡張機能が提供している拡張機能です。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://ikuma.assets.newt.so/v1/5834520b-8e50-44c9-87c4-ac430dedf4c2/Codeat2024-01-06-19.03.17.png&quot; alt=&quot;whichkeyを開いたところ&quot; /&gt;&lt;/p&gt;
&lt;p&gt;キーバインドに対応したコマンドパレット / チートシート機能を提供します。もともと Emacs に搭載されている機能を VSCode の拡張機能として実装したもののようです。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#インストールと初期設定&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;インストールと初期設定&lt;/h2&gt;
&lt;p&gt;VSpaceCodle をインストールしても Which Key は導入されますが、 Whichey 単独でもインストールすることができます。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=VSpaceCode.whichkey&quot; target=&quot;_blank&quot;&gt;https://marketplace.visualstudio.com/items?itemName=VSpaceCode.whichkey&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;私の場合は VSCode NeoVim を利用しているので、以下のようなキー設定を追加して、 &lt;code&gt;cmd&lt;/code&gt; + &lt;code&gt;space&lt;/code&gt; で Whichkey が起動するようにしています（&lt;code&gt;alt&lt;/code&gt; + &lt;code&gt;space&lt;/code&gt; は Raycast ですでに使っていた）。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;alt+space&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;whichkey.show&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;when&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;editorTextFocus&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#メニューのカスタマイズ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;メニューのカスタマイズ&lt;/h2&gt;
&lt;p&gt;表示されるメニューは settings.json で編集することができます。&lt;/p&gt;
&lt;p&gt;1つのキーに対して1つのアクションを指定する場合は以下のように設定します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;whichkey.bindings&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;バインドしたいショートカットキー&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;任意の名前。メニューで表示される&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;VSCodeのコマンドの名前&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;またショートカットキーをネストさせることもできます。その場合は次のように設定します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;whichkey.bindings&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;バインドしたいショートカットキー&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;任意の名前。メニューで表示される&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;bindings&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;bindings&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;// ...以下単一のアクションを設定する場合と同じシンタックス&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#whichkey-自体の設定&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;WhichKey 自体の設定&lt;/h2&gt;
&lt;p&gt;WhichKey 自体の挙動を settings.json に指定できます。
冒頭の初期設定で述べた、 whichkey.show もその一例で、すでに説明した通り WhichKey を起動するためのコマンドです。&lt;/p&gt;
&lt;p&gt;その他の細かな設定については &lt;a href=&quot;https://vspacecode.github.io/docs/whichkey/reference&quot; target=&quot;_blank&quot;&gt;Reference | VSpaceCode&lt;/a&gt; をご参照ください。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#わたしの-which-key&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;わたしの Which Key&lt;/h2&gt;
&lt;p&gt;こんな感じの key bindings を設定しています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;whichkey.bindings&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;q&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Quit&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.closeActiveEditor&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;commands&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.showCommands&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;a&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Toggle Sidebar&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.toggleSidebarVisibility&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;e&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Editors...&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;bindings&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;bindings&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;d&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Close active editor&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.closeActiveEditor&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;e&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Show all editors&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.showAllEditors&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;f&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Focus active editor&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.focusActiveEditorGroup&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;m&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Close other editors&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.closeOtherEditors&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;n&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Next editor&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.nextEditor&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;p&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Previous editor&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.previousEditor&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;u&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Reopen closed editor&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.reopenClosedEditor&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;f&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Find &amp;amp; Replace...&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;bindings&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;bindings&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;f&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;File&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;editor.action.startFindReplaceAction&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;p&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Project&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.replaceInFiles&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;g&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Git&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.view.scm&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;h&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Split Horizontal&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.splitEditorDown&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;m&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Toggle Minimap&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;editor.action.toggleMinimap&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;o&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Open File&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.quickOpen&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;s&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Show search&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.view.search&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;x&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Show explorer&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.view.explorer&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;t&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Terminal...&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;bindings&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;bindings&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;t&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Toggle Terminal&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.togglePanel&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;f&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Focus Terminal&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.terminal.toggleTerminal&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;when&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;!terminalFocus&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;v&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Split Vertical&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.splitEditor&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;w&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Window...&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;bindings&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;bindings&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;h&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Move editor group left&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.moveActiveEditorGroupLeft&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;j&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Move editor group down&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.moveActiveEditorGroupDown&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;k&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Move editor group up&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.moveActiveEditorGroupUp&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;l&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Move editor group right&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.moveActiveEditorGroupRight&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;t&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Toggle editor group sizes&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.toggleEditorWidths&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;m&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Maximize editor group&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.minimizeOtherEditors&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;d&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Close editor group&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.closeEditorsInGroup&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;x&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Close all editor groups&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.closeAllGroups&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;z&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Toggle Mode...&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;bindings&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;bindings&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;f&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Toggle full screen mode&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.toggleFullScreen&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;key&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;z&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Toggle zen mode&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;workbench.action.toggleZenMode&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;WhichKey は見た目もスッキリしているし、ショートカットを忘れずに済むのでおすすめです。ぜひ使ってみてください。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>1年の目標は正月に1回失敗しておくくらいがちょうどよい</title><link>https://ikuma-t.com/blog/first-losing-object-game/</link><guid isPermaLink="true">https://ikuma-t.com/blog/first-losing-object-game/</guid><description>1年の目標は正月に1回失敗しておくくらいがちょうどよいタイトルは今年立てた「日記を毎日書くぞ」が昨日途絶えてしまった自分への言い訳でもあり、毎年考えているものでもある。あまり深く考えずに立てると、今年</description><pubDate>Fri, 05 Jan 2024 02:22:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#1年の目標は正月に1回失敗しておくくらいがちょうどよい&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;1年の目標は正月に1回失敗しておくくらいがちょうどよい&lt;/h2&gt;
&lt;p&gt;タイトルは今年立てた「日記を毎日書くぞ」が昨日途絶えてしまった自分への言い訳でもあり、毎年考えているものでもある。&lt;/p&gt;
&lt;p&gt;あまり深く考えずに立てると、今年の目標は「毎日/毎週/毎月 XXするぞ！」といった類の内容になりがちだが、日本のカレンダー構造的に序盤戦がハードであるため、達成が難しい。&lt;/p&gt;
&lt;p&gt;1月。目標立て始めでモチベは高いものの、休み中に目標達成のために作った環境やルーティンが、仕事の始まりと共に崩壊しがち。&lt;/p&gt;
&lt;p&gt;2月。そもそも月数が他の月に比べて不利。週に2本はブログ書くぞ！といった目標はこのステージによって破られた。&lt;/p&gt;
&lt;p&gt;3月。4月始まりの会社の場合、締めがここになるのでなんやかんや忙しい。&lt;/p&gt;
&lt;p&gt;これらのステージのいずれかで連続ストリークが途絶えると、敗戦ムードとなり目標は自然消滅する。どうせ負け戦になって中途半端に終わるくらいなら、正月早々に負けておいて、次の負けムードのときに「1回負けたけど、まだ持ち直せるよ〜」という心持ちで年末を迎えた方が得策ではないか。&lt;/p&gt;
&lt;p&gt;というわけで今日は忘れずに日記を書きました。えらいぞ🤗&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Kaigi on Rails 2023で登壇しました！</title><link>https://ikuma-t.com/blog/kaigi-on-rails-2023/</link><guid isPermaLink="true">https://ikuma-t.com/blog/kaigi-on-rails-2023/</guid><description>KaigionRails2023で登壇しました！昨日、一昨日（2023/10/27-28）で開催されたKaigionRails2023にSpeakerとして登壇してきました！今年は初のオフライン開催。</description><pubDate>Sun, 29 Oct 2023 08:44:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#kaigi-on-rails-2023-で登壇しました&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Kaigi on Rails 2023 で登壇しました！&lt;/h2&gt;
&lt;p&gt;昨日、一昨日（2023/10/27 - 28）で開催された &lt;a href=&quot;https://kaigionrails.org/2023/&quot; target=&quot;_blank&quot;&gt;Kaigi on Rails 2023&lt;/a&gt; にSpeakerとして登壇してきました！&lt;/p&gt;
&lt;p&gt;今年は初のオフライン開催。私自身Rubyコミュニティのオフラインイベントに参加するのが初めてだったコトと、カンファレンスでのオフライン登壇自体も初めてだったので（今年はスクラムフェス仙台でも登壇したけど、あれはサテライト配信だったので目の前に観客がいなかった）いろんな刺激を受けることができました。&lt;/p&gt;
&lt;p&gt;この記事では参加者・登壇者それぞれの視点で今回のKaigi on Railsで感じたことを振り返っていきたいと思います。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#これがオフライン&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;これが「オフライン」…！&lt;/h2&gt;
&lt;p&gt;初オフライン Kaigi on Rails めちゃめちゃ楽しかったです！発表があって、ブースがあって…という構成は変わらないものの、やっぱり受ける刺激の量は全く異なり、来てよかったなあと感じました。これが「オフライン」…！&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#オフラインしぐさ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;オフラインしぐさ&lt;/h3&gt;
&lt;blockquote&gt;&lt;p&gt;「懇親会の開始前に前説でパックマンルールを説明しよう」「2人で会話している人を見かけたら話しかける狙い目。2人だと話題を繰り出し続けるのも大変だし、会話抜けるタイミングも計れないしで困っているはず」みたいなオフライン懇親会仕草を徐々に取り戻していきたい。失われた技術。&lt;/p&gt;— Takafumi ONAKA (@onk) &lt;a href=&quot;https://twitter.com/onk/status/1683330227576139776?ref_src=twsrc%5Etfw&quot;&gt;July 24, 2023&lt;/a&gt;&lt;/blockquote&gt;

&lt;p&gt;前述の通りオフラインイベント慣れしていなかったので、懇親会やブースではonkさんのツイートに記載のあったロストテクノロジー&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;をふと思い出し。自分は積極的に話しかけるのが苦手なので、会場うろちょろして2人でお話している方々を見つけては「話している人が2人…来るぞikuma！」&lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;と心の中で叫んでいました。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://ikuma.assets.newt.so/v1/d01209d8-8f9c-4c37-8ed1-1809ee884dc4/PXL20231029.jpg&quot; alt=&quot;ポストカードを使った自己紹介&quot; /&gt;&lt;/p&gt;
&lt;p&gt;一応自分のアイコンを含めたポストカードを前日にデザインして持って行きましたが、アイコンによってオンラインの姿と同期ができたのは一定効果があったようです。XのQRコードもつけたのですが、URLが間違っていたらしくこちらは全然意味をなさず…。来月もオフライン登壇の機会があるので、おとなしく&lt;a href=&quot;https://prairie.cards/&quot; target=&quot;_blank&quot;&gt;プレーリーカード&lt;/a&gt; を作成しようと思います。&lt;/p&gt;
&lt;p&gt;オンラインで知っている方/知らなかった人とお話しさせていただくことができて、嬉しかったです！お話しいただいたみなさん、ありがとうございました！&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#冷めても美味しいお弁当よりも今ここでしか味わえない味を&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;冷めても美味しいお弁当よりも、今ここでしか味わえない味を&lt;/h3&gt;
&lt;p&gt;登壇者的には「もっと現地を重視した構成にすればよかったなあ」と反省もありました。&lt;/p&gt;
&lt;p&gt;エンジニアになってからの登壇はすべてオンライン配信だったため、いずれも意識的にオンライン向けに特化させた形になっていました。&lt;/p&gt;
&lt;p&gt;リアルタイムでの反応が弱めなら、終わった後の体験の方に力を入れよう、具体的には後から見た時にも資料からおおよそのコンテキストが汲み取れる状態にする、といった具合です。お弁当用にちょっとおかずの味を濃いめにするみたいな気持ちです。&lt;/p&gt;
&lt;p&gt;当たり前ですがオフラインの場合はすぐそこに聞いている人がいます。次回以降の登壇では以下のようなポイントを意識したいなあと、他の方の発表を見ている中で思いました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;全編とまでは言わないが、心に残すためのインタラクションを&lt;/li&gt;
&lt;li&gt;丁寧に構成された緻密なロジックよりも、その瞬間で理解できる単純なサンプルを&lt;/li&gt;
&lt;li&gt;完全な解説よりも、考える余地というギフトを&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ただ後から見返すための資料はそれはそれでメリットがあるので、そこはバランスですかね〜（2種類作るか）。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#なんだか強くなった気がする&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;なんだか強くなった気がする！&lt;/h2&gt;
&lt;p&gt;今年は最初に自分の番を終えることができたので&lt;sup&gt;&lt;a href=&quot;#user-content-fn-3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;、常にHall A/Bいずれかのセッションを聞かせていただいておりました。&lt;/p&gt;
&lt;p&gt;Kaigi on Railsのコンセプトに「明日からの仕事に使える」がありますが、前回の参加時（エンジニア経験4ヶ月）に比べ、「仕事」も増えたことから「わかりみ」と「やらねば」のオンパレードでした。最近Railsも書いていなかったのですが、発表を聞いていく中で自分の中で眠っているRails筋が活動を再開する音が聞こえたような気もします（それは本当か？）。&lt;/p&gt;
&lt;p&gt;ところで結構AI生成のイラストを使っているスライドが多く見受けられた印象が合って、逆張り系人材としては来年までに油絵や水彩画を学習して、オリジナリティを確保しようかなと思っています、たぶん。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#自分の発表のふりかえり&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;自分の発表のふりかえり&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://ikuma.assets.newt.so/v1/a346b2ca-3c63-4e12-b00b-edc814266856/PXL20231027042202185.jpg&quot; alt=&quot;登壇直前の様子&quot; /&gt;&lt;/p&gt;
&lt;p&gt;昨年に続き、独自系・網羅系でいくと後者の分類のトークでした。&lt;a href=&quot;https://ikuma-t.com/talks/653db95db4a463c532d972b5&quot; target=&quot;_blank&quot;&gt;HTTPを手で書いて学ぶ ファイルアップロードのしくみ - ikuma-t.com&lt;/a&gt;。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#発表のモチベーション&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;発表のモチベーション&lt;/h3&gt;
&lt;p&gt;そもそも今年Kaigi on RailsにCFPを出すのか、そもそも行くのか迷っていました。&lt;/p&gt;
&lt;p&gt;昨年の6月にエンジニアになってから仕事では&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;昨年のKaigi on Railsまで：Rails&lt;/li&gt;
&lt;li&gt;今年のKaigi on Railsまで：React（+ときどきGo）&lt;/li&gt;
&lt;li&gt;今年のKaigi on Railsから：Rails&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;と、1年近くフロントに傾倒していたので、今年はパスかな〜と思っていたのですが、社内でRailsを書いていたhoguccさんとsanfrecce_osakaさんがCFPを出す雰囲気を感じたので、その勢いに便乗して書くことに。&lt;/p&gt;
&lt;p&gt;結果CFPは通って登壇できたし、偶然またRails書くことになったしで、やってよかったです。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#登壇テーマ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;登壇テーマ&lt;/h3&gt;
&lt;p&gt;上述の通り、Railsをテーマにして話すのはちょっと無理があったので、今回も昨年同様「曖昧に使っている技術を最小実装で自分のものにしよう」という方向性で検討。資料中にもあったようないくつかのファイルアップロードに関する経験から、今回はHTTPを手で書いてファイルアップロードの基本を理解する、というテーマにしました。&lt;/p&gt;
&lt;p&gt;「この技術は課題に対してオーバーキルではないか？」という疑念がいつもあり、そういう視点でちょいちょい仕様とかを調べたりしたものがCFPのタネになっているのですが、いかんせんまとめていないので、CFPを書く際も、実際に資料を作る際にも時間がかかる…。生活をリリースして登壇をアドバンス召喚するのはなかなか大変なので、よくアウトプットをされている方たちを真似て&lt;sup&gt;&lt;a href=&quot;#user-content-fn-4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;これ登壇できるかもと思ったら、ストックするようにしたいなとあらためて思いました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#登壇資料&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;登壇資料&lt;/h3&gt;
&lt;p&gt;「フロントでは頑張ってたんだよ〜」という免罪符が欲しかったのか、発表資料はHTML + CSS + JSで書いていて、（ほぼ出番のなかった）資料埋め込みデモはReact + Ruby Wasmでできていたりします。ここは長いので気が向いたら別記事で書こうと思います。&lt;/p&gt;
&lt;p&gt;「ファイルアップロード」が一般的で広いテーマゆえ、今回は昨年よりも内容の取捨選択が難しかったです。&lt;/p&gt;
&lt;p&gt;HTTPの仕様改訂やら、もう少し実世界と繋げた説明やら、JSにおけるBlobとか、もともと入っていたが消えた内容も…。加えて練習時間があまり取れなかったこともあり、半分ぶっつけ本番・超早口で30分に無理やりねじ込む内容になってしまいました…。これは次回以降の反省点です。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#growrbに今年も感謝&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Grow.rbに今年も感謝&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://growrb.doorkeeper.jp/events/159788&quot; target=&quot;_blank&quot;&gt;Grow.rb特別回：登壇相談会2023【登壇ビギナー歓迎】&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;チーフオーガナイザーの大倉さんが開催されているGrow.rbでは、Kaigi on RailsのCFP提出が解禁されると登壇特別回と称したCFP相談会&lt;sup&gt;&lt;a href=&quot;#user-content-fn-5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;が開かれています。&lt;/p&gt;
&lt;p&gt;昨年に引き続き今年もこちらで壁打ちをさせていただいたおかげで、CFPをブラッシュアップできました。大倉さん、アドバイスいただいた皆さん、ありがとうございました！&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;あまりコミュニケーションが得意な人間ではないので、「勉強会やイベントには登壇者として参加することで、謎の免罪符を得る」戦略をFJORD BOOT CAMP時代からやっているのですが&lt;sup&gt;&lt;a href=&quot;#user-content-fn-6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;、この戦略に頼りすぎて、免罪符なしで存在を保つことができるのか不安です。…ってことは存在を保つために、来年もKaigi on RailsのCFP出すしかないな！！&lt;/p&gt;
&lt;p&gt;ブログを書いたし、アンケートも全部答えたのでこれにて私のKaigi on Rails 2023は終了です！運営の皆様、お疲れ様でした！&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;&lt;a href=&quot;#footnote-label&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://ja.wikipedia.org/wiki/%E3%83%AD%E3%82%B9%E3%83%88%E3%83%86%E3%82%AF%E3%83%8E%E3%83%AD%E3%82%B8%E3%83%BC&quot; target=&quot;_blank&quot;&gt;ロストテクノロジー - Wikipedia&lt;/a&gt; 現存しない技術というよりかは取り戻すべき技術 &lt;a href=&quot;#user-content-fnref-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://dic.pixiv.net/a/%E6%9D%A5%E3%82%8B%E3%81%9E%E9%81%8A%E9%A6%AC&quot; target=&quot;_blank&quot;&gt;レベル4のモンスターが2体…来るぞ遊馬！ &lt;/a&gt; &lt;a href=&quot;#user-content-fnref-2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;昨年は &lt;a href=&quot;https://kaigionrails.org/2022/talks/ikumatdkr/&quot; target=&quot;_blank&quot;&gt;Day2の最後&lt;/a&gt; だったので、最後までそわそわ &lt;a href=&quot;#user-content-fnref-3&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;例えば&lt;a href=&quot;https://koic.hatenablog.com/entry/kaigionrails-stayhome-edition&quot; target=&quot;_blank&quot;&gt;koicさんはBasecampで書いている&lt;/a&gt;そう。また&lt;a href=&quot;https://developer.hatenastaff.com/entry/2023/01/31/160000&quot; target=&quot;_blank&quot;&gt;onkさんは社内のscrapboxにLTネタを貯めている&lt;/a&gt;そう。 &lt;a href=&quot;#user-content-fnref-4&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;私の中での通称は「大倉塾」 &lt;a href=&quot;#user-content-fnref-5&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;謎の免罪符とかは言及されていないが、初心者でも登壇してみるのは話しやすくなるしおすすめ、ということは言われていたと思う、たぶん。 &lt;a href=&quot;#user-content-fnref-6&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><author>ikuma-t</author></item><item><title>.env.developmentからdirenvで読み込む用の.envrcを作成するワンライナー</title><link>https://ikuma-t.com/blog/convert-env-to-envrc/</link><guid isPermaLink="true">https://ikuma-t.com/blog/convert-env-to-envrc/</guid><description>ベースとなる環境変数ファイルから、direnv用のファイルを一発で作りたい環境変数のベースとなるファイルを.env.developmentやらで作成しておき、実際の値は.gitignoreに記載された</description><pubDate>Sun, 15 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#ベースとなる環境変数ファイルからdirenv用のファイルを一発で作りたい&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ベースとなる環境変数ファイルから、direnv用のファイルを一発で作りたい&lt;/h2&gt;
&lt;p&gt;環境変数のベースとなるファイルを&lt;code&gt;.env.development&lt;/code&gt;やらで作成しておき、実際の値は.gitignoreに記載された.envなどのファイルを各開発者のローカルで編集する、といった運用はよくある。&lt;/p&gt;
&lt;p&gt;プロジェクトだけで使う環境変数をグローバルにexportするのもアレなので、こういった時には&lt;a href=&quot;https://direnv.net/&quot; target=&quot;_blank&quot;&gt;direnv&lt;/a&gt;が使える。しかし&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;.env.developmentは&lt;code&gt;HOGE=foo&lt;/code&gt;形式で記述されている&lt;/li&gt;
&lt;li&gt;.envrc（direnvの読み込みファイル）は&lt;code&gt;export HOGE=foo&lt;/code&gt;で記述する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;という時に、単純に&lt;code&gt;cp .env.development .envrc&lt;/code&gt;とするだけでは動かない。&lt;/p&gt;
&lt;p&gt;とはいえ全部に手でexportをつけるのもだるいのでワンライナーだとどうやるのか少しばかり試行錯誤してみた。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#結論&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;結論&lt;/h2&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;awk&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;{if (NF &amp;gt; 0 &amp;amp;&amp;amp; $0 !~ /^#/) print &quot;export &quot; $0; else print $0}&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;.env.development&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;.envrc&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#解説&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;解説&lt;/h2&gt;
&lt;p&gt;解説というほどの大きなスクリプトでもないが、小さな心配りを説明する。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;NF &amp;gt; 0&lt;/code&gt;: Number of fieldsが0より大きい、つまり非空行のみを対象にする。環境変数のグループを明示的にするために空行があったりする場合にexportだけが残らないようにする心配り。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$0 !~ /^#/&lt;/code&gt;: &lt;code&gt;#&lt;/code&gt;から始まらない、つまりコメント行でない行を対象にする。&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;HOGE&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;foo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FUGA&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;bar&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# animals&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;TAMA&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;cat&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;POCHI&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;dog&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;例えば上記の.env.developmentから次の.envrcが生成される。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; HOGE&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;foo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; FUGA&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;bar&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# animals&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; TAMA&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;cat&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; POCHI&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;dog&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;</content:encoded><author>ikuma-t</author></item><item><title>O&apos;REILLYのLearning PlatformにLLMを使った質問機能が追加されていた（Beta）</title><link>https://ikuma-t.com/blog/ask-a-question-in-oreilly-learning-platform/</link><guid isPermaLink="true">https://ikuma-t.com/blog/ask-a-question-in-oreilly-learning-platform/</guid><description>O’REILLYの書籍読み放題のサブスクリプションLearningPlatformを開いたら、サイドバーに「Askaquestion」というメニューが追加されていました。近頃ではこの形式のUIを見ると</description><pubDate>Sat, 14 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;O’REILLYの書籍読み放題のサブスクリプションLearning Platformを開いたら、サイドバーに「Ask a question」というメニューが追加されていました。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://ikuma.assets.newt.so/v1/1f9d4bb7-1c05-401e-97a0-73a29efe4654/Arcat2023-10-14-14.19.09.png&quot; alt=&quot;新しくサイドバーに追加されたLearning platformのAsk a questionメニュー&quot; /&gt;&lt;/p&gt;
&lt;p&gt;近頃ではこの形式のUIを見ると「AIか〜」と当たり前のように納得するようになってきましたね。
最初は現在開いている書籍に関して問い合わせできるのかと思ったのですが、そうではなくLearing Platformに登録されている書籍から回答を生成しているようです。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://ikuma.assets.newt.so/v1/a1af0926-82bd-490a-b70b-311c0886874a/Arcat2023-10-14-14.24.30.png&quot; alt=&quot;Javascriptの分割代入について実際に質問してみた例&quot; /&gt;&lt;/p&gt;
&lt;p&gt;日本語書籍も登録はされていて回答の参考にされていましたが、日本語で質問しても回答自体は英語で返ってくる模様。&lt;/p&gt;
&lt;p&gt;1つのトピックに対して複数の書籍をあたりたいケース、例えばプロダクト開発や開発プロセスに関する書籍を探す際には、この機能をきっかけに書籍を見つけるのもありかな〜と思いました。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>dockerのimageとvolumeを選択して消せるか、賑やかしができるdockern（どっかーん）コマンド</title><link>https://ikuma-t.com/blog/dockern-command/</link><guid isPermaLink="true">https://ikuma-t.com/blog/dockern-command/</guid><description>作ったものdockerndenoを使っているので、READMEの通りinstallしてdockernで実行できます。経緯色々とDockerコンテナをガチャガチャしていて、何度もimageやvolume</description><pubDate>Sat, 14 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#作ったもの&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;作ったもの&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/IkumaTadokoro/dockern&quot; target=&quot;_blank&quot;&gt;dockern&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;denoを使っているので、READMEの通りinstallして&lt;code&gt;dockern&lt;/code&gt;で実行できます。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#経緯&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;経緯&lt;/h2&gt;
&lt;p&gt;色々とDockerコンテナをガチャガチャしていて、何度もimageやvolumeをまとめて削除したいケースが発生しました。&lt;/p&gt;
&lt;p&gt;docker compose系のコマンドはエイリアスも貼ってあるし、覚えているのですが、dockerコマンドは全然覚えていないので、ここら辺をラップしてやってくれるコマンドを作ることにしました。
（なおアイデアとライブラリだけ選んでほぼChatGPTで作った）。&lt;/p&gt;
&lt;p&gt;仕事中に「dockerをドッカーンと」とか聞いたような記憶があったので、名前はdockernです。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#ぐるぐるどっかーん&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ぐるぐるどっかーん&lt;/h2&gt;
&lt;p&gt;スプー世代の方はわかると思います。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dockern&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;guru2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ぐるぐるぐるぐるどっかーん🎺&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;まあメインコマンドは&lt;code&gt;dockern&lt;/code&gt;だけで実行できるので、明日以降これを実行することはないでしょう。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわり&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわり&lt;/h2&gt;
&lt;p&gt;今消したいimageやvolumeがないので、あまりしっかり動作確認はしていません。業務中に動かなくなったら都度直していこうと思います。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>WEBRickのqueryをパターンマッチで取り出す</title><link>https://ikuma-t.com/blog/pick-query-from-webrick-query-by-patten-match/</link><guid isPermaLink="true">https://ikuma-t.com/blog/pick-query-from-webrick-query-by-patten-match/</guid><description>WEBRickではリクエストのクエリをreq.queryで取得できます。WEBrick::HTTPRequest#query(Ruby3.2リファレンスマニュアル)この戻り値はHashなので、例えばh</description><pubDate>Sat, 14 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;WEBRickではリクエストのクエリを&lt;code&gt;req.query&lt;/code&gt;で取得できます。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.ruby-lang.org/ja/latest/method/WEBrick=3a=3aHTTPRequest/i/query.html&quot; target=&quot;_blank&quot;&gt;WEBrick::HTTPRequest#query (Ruby 3.2 リファレンスマニュアル)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;この戻り値はHashなので、例えば&lt;code&gt;hoge&lt;/code&gt;を取得するのであれば&lt;code&gt;req.query[&apos;hoge&apos;]&lt;/code&gt;のようにすれば値を取得できます。できますが、せっかくなのでパターンマッチで取得します。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;req.query.transform_keys(&amp;amp;:to_sym)&lt;/code&gt;: req.queryのHashのキーはStringなので、パターンマッチで取得するためにSymbolに変換します。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;req.query.transform_keys(&amp;amp;:to_sym) in :hoge&lt;/code&gt;: パターンマッチでhogeを取り出します。ローカル変数&lt;code&gt;hoge&lt;/code&gt;にreq.query[“hoge”]の値が格納されます。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;気がついたらパターンマッチのカッコは省略可能&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;になっていたので、変数1,2個取り出すくらいならガンガンに省略していきたいですね。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;&lt;a href=&quot;#footnote-label&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Ruby3.1からだったみたい。知らなかった。 &lt;a href=&quot;#user-content-fnref-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><author>ikuma-t</author></item><item><title>slidevでスライドの進捗に応じたプログレスバーを表示する</title><link>https://ikuma-t.com/blog/show-slidev-progress-bar/</link><guid isPermaLink="true">https://ikuma-t.com/blog/show-slidev-progress-bar/</guid><description>Slidevでスライドを作成する際に、現在のページを表示しつつ、全体に対する進捗をプログレスバーとして表示したいと思い作ってみました。Slidevではglobal-bottom.vueというファイルを</description><pubDate>Mon, 09 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Slidevでスライドを作成する際に、現在のページを表示しつつ、全体に対する進捗をプログレスバーとして表示したいと思い作ってみました。&lt;/p&gt;
&lt;p&gt;Slidevではglobal-bottom.vueというファイルを作成すると、自動ですべてのスライドにそのコンポーネントがレンダリングされます。&lt;/p&gt;
&lt;p&gt;以下の内容をglobal-bottom.vueとして配置することで、プログレスバーを表示できます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;setup&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;lang&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;ts&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { computed } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;vue&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;40&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;strokeWidth&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;circumference&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Math&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;PI&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; r&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;progress&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;computed&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;$slidev&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;nav&lt;/span&gt;&lt;span&gt;.currentPage &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;$slidev&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;nav&lt;/span&gt;&lt;span&gt;.total) &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; circumference;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;offset&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;computed&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; circumference &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;progress&lt;/span&gt;&lt;span&gt;.value;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;footer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;abs-br m-3&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;svg&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;w-8&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;viewBox&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;0 0 100 100&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;circle&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;base-circle&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cx&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;50&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cy&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;50&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:r&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;r&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fill&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;none&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:stroke-width&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;strokeWidth&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;circle&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;progress-circle&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ref&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;progressCircle&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cx&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;50&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cy&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;50&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:r&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;r&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;transform&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;rotate(-90 50 50)&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fill&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;none&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:stroke-width&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;strokeWidth&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:stroke-dasharray&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;circumference&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:stroke-dashoffset&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;offset&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;text&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;progress-text&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;font-size&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;9&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;50&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;52&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dominant-baseline&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;middle&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;text-anchor&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;middle&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;{{ $slidev.nav.currentPage }}&amp;lt;/&lt;/span&gt;&lt;span&gt;text&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;svg&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;footer&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;style&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// 色は適当に調節してください&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;:root&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--bg-stroke-color&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#e2e8f0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--progress-stroke-color&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#b91c1c&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--text-fill-color&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#020617&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;.base-circle&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;stroke&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;/span&gt;&lt;span&gt;(--bg-stroke-color)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;.progress-circle&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;stroke&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;/span&gt;&lt;span&gt;(--progress-stroke-color)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;.progress-text&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;fill&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;/span&gt;&lt;span&gt;(--text-fill-color)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;style&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;https://ikuma.assets.newt.so/v1/92ed761f-0500-41e5-b403-23e730301de4/Arcat2023-10-09-20.56.58.gif&quot; alt=&quot;プログレスバーのデモ&quot; /&gt;&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Tailwind CSSのクラスをいい感じにマージするshadcn/uiの`cn`ユーティリティ</title><link>https://ikuma-t.com/blog/what-is-shadcn-ui-cn/</link><guid isPermaLink="true">https://ikuma-t.com/blog/what-is-shadcn-ui-cn/</guid><description>はじめにshadcn/uiをインストールすると、utilsとしてcn関数がついてきます。これが自分でTailwindCSSを使ったコンポーネントを作る際にも便利なのですが、何をやってくれているのか理解</description><pubDate>Fri, 11 Aug 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#はじめに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;はじめに&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://ui.shadcn.com/&quot; target=&quot;_blank&quot;&gt;shadcn/ui&lt;/a&gt;をインストールすると、utilsとして&lt;code&gt;cn&lt;/code&gt;関数がついてきます。これが自分でTailwind CSSを使ったコンポーネントを作る際にも便利なのですが、何をやってくれているのか理解していなかったので調べてみました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#要約&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;要約&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;cn&lt;/code&gt;は&lt;code&gt;twMerge&lt;/code&gt;で&lt;code&gt;clsx&lt;/code&gt;をラップした、「外部から指定されたTailwind CSSのクラス名をマージしつつ、オブジェクトの形式で条件付きのクラスを定義」をすることができるユーティリティ関数である。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#cnの中身&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;cnの中身&lt;/h2&gt;
&lt;p&gt;記事執筆（2023/08/11）時点での&lt;code&gt;cn&lt;/code&gt;関数の実装は次のとおりです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; ClassValue&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; clsx } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;clsx&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { twMerge } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;tailwind-merge&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cn&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;inputs&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ClassValue&lt;/span&gt;&lt;span&gt;[]) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;twMerge&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;clsx&lt;/span&gt;&lt;span&gt;(inputs))&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;twMerge&lt;/code&gt;で&lt;code&gt;clsx&lt;/code&gt;をラップしていることがわかります。他に実装はないので、これら2つの効能を見ていきます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#twmergeの効能&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;twMergeの効能&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/dcastil/tailwind-merge&quot; target=&quot;_blank&quot;&gt;https://github.com/dcastil/tailwind-merge&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;twMerge&lt;/code&gt;はライブラリtailwind-mergeから提供される関数の1つです。&lt;/p&gt;
&lt;p&gt;Tailwind CSSでは同じ効果をもたらす別のプロパティがclassに指定された場合、CSSのルールに則っていずれかのプロパティしか適用されません。例えば、&lt;code&gt;px-2 py-4&lt;/code&gt;を持つコンポーネントに&lt;code&gt;p-5&lt;/code&gt;を適用しても、&lt;code&gt;p-5&lt;/code&gt;は適用されません。&lt;/p&gt;
&lt;p&gt;そういうことを頻繁にやるべきかどうかの議論はさておき、これは既存のコンポーネントのスタイルを外側から上書きする際に不便な挙動です。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;twMerge&lt;/code&gt;を使用することで、衝突するクラス名だけを外から渡したものに上書きすることができます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyButton&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; ({ classNames&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;props }) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// hover:opacity-70はそのままに、Propsとして提供したclassNamesが適用されるようにclassNameがマージされる&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;button&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;className&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;twMerge&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;px-2 py-4 hover:opacity-70&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; classNames)} /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;詳細なマージの挙動については&lt;a href=&quot;https://github.com/dcastil/tailwind-merge/blob/v1.14.0/docs/features.md&quot; target=&quot;_blank&quot;&gt;公式ドキュメント&lt;/a&gt;を参照してください。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#clsxの効能&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;clsxの効能&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/lukeed/clsx&quot; target=&quot;_blank&quot;&gt;https://github.com/lukeed/clsx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;clsxは文字列や配列、オブジェクト含めてclassNameをいい感じに連結することのできるユーティリティライブラリです。&lt;/p&gt;
&lt;p&gt;公式のUsageをそのまま貼り付けます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; clsx &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;clsx&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// or&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { clsx } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;clsx&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Strings (variadic)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;clsx&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;foo&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;bar&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;baz&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;//=&amp;gt; &apos;foo bar baz&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Objects&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;clsx&lt;/span&gt;&lt;span&gt;({ foo&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; bar&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; baz&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt;isTrue&lt;/span&gt;&lt;span&gt;() });&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;//=&amp;gt; &apos;foo baz&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Objects (variadic)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;clsx&lt;/span&gt;&lt;span&gt;({ foo&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; { bar&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;&apos;--foobar&apos;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&apos;hello&apos;&lt;/span&gt;&lt;span&gt; });&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;//=&amp;gt; &apos;foo --foobar&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Arrays&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;clsx&lt;/span&gt;&lt;span&gt;([&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;foo&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;bar&apos;&lt;/span&gt;&lt;span&gt;]);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;//=&amp;gt; &apos;foo bar&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Arrays (variadic)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;clsx&lt;/span&gt;&lt;span&gt;([&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;foo&apos;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&apos;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;bar&apos;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; [[&lt;/span&gt;&lt;span&gt;&apos;baz&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; [[&lt;/span&gt;&lt;span&gt;&apos;hello&apos;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;there&apos;&lt;/span&gt;&lt;span&gt;]]]);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;//=&amp;gt; &apos;foo bar baz hello there&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Kitchen sink (with nesting)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;clsx&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;foo&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;bar&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; { baz&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; bat&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&apos;hello&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&apos;world&apos;&lt;/span&gt;&lt;span&gt;]]]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;cya&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;//=&amp;gt; &apos;foo bar hello world cya&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;さまざまなパターンでの連結と、Falsyな値をパージする機能があります。後者は特にオブジェクト記法でクラスと条件をマッピングしておくことで、条件付きスタイリングの際に重宝します。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#twmergeとclsxを組み合わせて使う理由&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;twMergeとclsxを組み合わせて使う理由&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;「Tailwind CSSのクラス名のマージと、オブジェクトでのクラス名の指定を行いたいから」&lt;/strong&gt; です。&lt;/p&gt;
&lt;p&gt;tailwind-mergeでもクラス名の文字列連結を行うための&lt;code&gt;twJoin&lt;/code&gt;という関数が提供されていますが、こちらはオブジェクトでの記法がサポートされていません。&lt;/p&gt;
&lt;p&gt;実装されていない理由は&lt;a href=&quot;https://github.com/dcastil/tailwind-merge/discussions/137&quot; target=&quot;_blank&quot;&gt;こちらのDiscussion&lt;/a&gt;に記載があります。曰く、オブジェクトの記法はキーにクラス名が、バリューに条件がくることで、そのクラスがいつ適用されるかの認知負荷が高いと判断した、とのことです。リーダブルコードにもこんな感じの条件分岐の話がありましたね。&lt;/p&gt;
&lt;p&gt;Discussionの続きになりますが、スタイルを変更するにはクラスをまずはみるのだからオブジェクトにも対応してほしいとの返信があり、議論の結果としてshadcn/uiでも使用されているcn関数のような記述が返されています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { twMerge &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; twMergeOriginal } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;tailwind-merge&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; clsx &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;clsx&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;twMerge&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;args) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;twMergeOriginal&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;clsx&lt;/span&gt;&lt;span&gt;(args))&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これによりこの関数になんでもかんでもクラス名を指定すれば、自分が最後に指定した内容が意図通りにスタイリングとして反映される便利関数の完成です（雑）。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#型定義&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;型定義&lt;/h3&gt;
&lt;p&gt;再掲になりますが、&lt;code&gt;cn&lt;/code&gt;では次のようにして、&lt;code&gt;clsx&lt;/code&gt;と同等の引数を受け取れるようにしています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; ClassValue&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; clsx } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;clsx&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { twMerge } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;tailwind-merge&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cn&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;inputs&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ClassValue&lt;/span&gt;&lt;span&gt;[]) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;twMerge&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;clsx&lt;/span&gt;&lt;span&gt;(inputs))&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;今回はshadcn/uiで提供されているユーティリティ関数&lt;code&gt;cn&lt;/code&gt;を見てみました。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cn&lt;/code&gt;という名前が&lt;strong&gt;c&lt;/strong&gt;lass&lt;strong&gt;N&lt;/strong&gt;ame由来なのか、shad&lt;strong&gt;cn&lt;/strong&gt;由来なのか気になりますね…。&lt;/p&gt;
&lt;p&gt;shadcn/uiにはもう1つ、ウィンドウ幅に応じてTailwind CSSにおけるブレイクポイントを画面上に表示してくれるDevtools的なものがあるので、また別の機会にそちらの実装をまとめてみようと思います。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>刺繍をはじめてみました</title><link>https://ikuma-t.com/blog/sisyu/</link><guid isPermaLink="true">https://ikuma-t.com/blog/sisyu/</guid><description>刺繍をはじめてみたTwitter|Xでペンギンの刺繍を見かけたことをきっかけに刺繍を始めてみました。ドット絵を過去にやったこともあったのですが、そのときも事物をデフォルメした形で表現するのがいいなあと</description><pubDate>Thu, 10 Aug 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#刺繍をはじめてみた&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;刺繍をはじめてみた&lt;/h2&gt;
&lt;p&gt;Twitter | Xでペンギンの刺繍を見かけたことをきっかけに刺繍を始めてみました。
ドット絵を過去にやったこともあったのですが、そのときも事物をデフォルメした形で表現するのがいいなあと思って始めたので、こういう系統が自分の趣味かもしれません。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#やってみたもの&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;やってみたもの&lt;/h2&gt;
&lt;p&gt;こんな感じの刺繍キットを買ってみました。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://ikuma.assets.newt.so/v1/96975940-63fd-4b4a-924c-16dc9e2b97ca/PXL_20230810_031951281.jpg&quot; alt=&quot;購入した刺繍キットと刺繍枠&quot; /&gt;&lt;/p&gt;
&lt;p&gt;お花を刺繍していって、最後にトートバッグを作るようです。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://ikuma.assets.newt.so/v1/50ecf7b9-de3a-4dd9-9336-294d48018032/PXL_20230810_033251461.jpg&quot; alt=&quot;刺繍枠&quot; /&gt;&lt;/p&gt;
&lt;p&gt;刺繍をやる部分はこのような枠で布を貼るのですが、&lt;strong&gt;この道具のビジュアルが最高&lt;/strong&gt;です。手仕事感が前面に出ていて、クリエイター魂が燃え上がります。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://ikuma.assets.newt.so/v1/ed63a93c-d364-42e4-a812-fc735d6a06a4/PXL_20230810_062740602.jpg&quot; alt=&quot;青い花の刺繍の完成品&quot; /&gt;&lt;/p&gt;
&lt;p&gt;1日目は青い花を縫い終わりました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#習得した技術&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;習得した技術&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;ロングアンドショートステッチ&lt;/li&gt;
&lt;li&gt;フレンチノットステッチ&lt;/li&gt;
&lt;li&gt;サテンステッチ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ロングアンドショートステッチは細かさよりも、均等に幅を刻んでいくことが大事だと学びました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;楽しい！！時間を忘れて縫っていました。針を手に持っているのでスマホを途中で取るという行為もできず、デジタルデトックスが必要な私には非常に良かったと思います。&lt;/p&gt;
&lt;p&gt;新規開発であっても&lt;code&gt;docker-compose&lt;/code&gt;や&lt;code&gt;npm create&lt;/code&gt;をすれば一発で環境が立ち上がる、ミスをすればgitで戻せばよい開発と異なり、環境構築も全くわからんし、ミスったら物理的に戻せない点も非常に刺激的でよかったです。&lt;/p&gt;
&lt;p&gt;今回の進捗は花1つなのですが、これがあと12個 + エコバッグを組み上げる作業があるので、アニポケでサトシがジムバッジ集めてリーグ挑戦するくらいかかりそうな予感はしていますが、ぼちぼちやっていこうと思います。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>技術書を写経する時は、予習の写経・復習の写経の2段階に分けると定着がいい</title><link>https://ikuma-t.com/blog/tech-book-training-twice/</link><guid isPermaLink="true">https://ikuma-t.com/blog/tech-book-training-twice/</guid><description>はじめに：ハンズオン系の技術書を読むときの難点ハンズオン系の技術書、得意ですか？私は結構苦手です。読書自体はそこまで苦手ではなくて、紙面だけで完結するような書籍であれば割とスラスラと読めるのですが、ハ</description><pubDate>Tue, 08 Aug 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#はじめにハンズオン系の技術書を読むときの難点&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;はじめに：ハンズオン系の技術書を読むときの難点&lt;/h2&gt;
&lt;p&gt;ハンズオン系の技術書、得意ですか？私は結構苦手です。&lt;/p&gt;
&lt;p&gt;読書自体はそこまで苦手ではなくて、紙面だけで完結するような書籍であれば割とスラスラと読めるのですが、ハンズオンが含まれると途端に進みが悪くなります。&lt;/p&gt;
&lt;p&gt;読み始めて最初の数章はいいんですが、だんだん写経するのが面倒になってくる一方で、とはいえハンズオンが売りの書籍でハンズオンをやらないと知識定着しないし…という感情のせめぎ合いに、しまいには読み進めること自体を放棄してしまうこともしばしば。&lt;/p&gt;
&lt;p&gt;今回はこの課題感を解消するためにやってみた「予習の写経」「復習の写経」が結構良かったので紹介します。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#技術マスター-予習の写経--復習の写経&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;技術マスター 予習の写経 / 復習の写経&lt;/h2&gt;
&lt;p&gt;アイデアのきっかけは、以前時雨堂さん主催の勉強会の形式にあった「勉強会の中で同じコンテンツを2回繰り返す手法」です。これに倣い、写経を同じセクションに対して2回行うのが、今回紹介する方法になります。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#予習編&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;予習編&lt;/h3&gt;
&lt;p&gt;Git管理下のリポジトリを用意し、そこに読んでいる書籍のハンズオンを実装していきます。もし書籍側から提供されているコードがあればそれを利用するのもいいでしょう。&lt;/p&gt;
&lt;p&gt;この段階では書籍の内容を読むことを中心にして、ざっくりと概要を掴みます。&lt;/p&gt;
&lt;p&gt;書籍にもよりますが、大体1つの章の単位で区切りをつけると良いと思います。あまり復習までの間隔が短すぎると内容を覚えてしまっているので退屈感が増してしまい、もともと解決したかった課題にそのままぶつかることにになるからです。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#スイッチ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;スイッチ&lt;/h3&gt;
&lt;p&gt;予習が終わったら写経したハンズオンをコミットした上で、&lt;strong&gt;実装の詳細を全て消します&lt;/strong&gt;。
例えば次のような形です。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Before&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;greet&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;`Hello &lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// After&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;greet&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// 実装の詳細を消す&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;消す範囲は自由に決めて良いと思いますが、全部消すと内容が思い出せなさすぎるので、コードを見ればなにをすればいいのかがわかるくらいには残すのがポイントです。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#復習編&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;復習編&lt;/h3&gt;
&lt;p&gt;テキストを見ないで吹っ飛ばした実装の詳細を自分で実装します。&lt;/p&gt;
&lt;p&gt;ここでは1つのセクションやファイルが自分で実装できるたびにGitの差分を確認し、復元できているかをチェックします。動作としてはハンズオンでやったとおり動いていても、微妙に実装内容が違ったりすることもあり、思わぬ自分の手癖の発見に繋がったりします。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#メリットデメリット&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;メリット・デメリット&lt;/h2&gt;
&lt;p&gt;一度予習した内容が頭にありつつも、完全に定着していない知識をあぶり出し、定着させられるのがこの方法のメリットです。実装が思いつかない・思い出せない部分は自ずと詳しく読むことになるので、最初の予習時に心理的にサラッと読めるのも良いと感じています。&lt;/p&gt;
&lt;p&gt;一方で一度だけ読む方法に比べれば手間がかかるのは事実です。知識が定着できなかった場合はトータルで見ても時間ロスかもしれません。&lt;/p&gt;
&lt;p&gt;またこの手法は今のところ何かしらのファイルに実装を重ねていくハンズオンでしか実施していませんが、コンソールで試していくタイプのハンズオンには向かないかもしれません。zxがマークダウンを解釈できますが、これの各言語版があると全ては解決かもしれません。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おまけ大ai時代ならではの困りポイント&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おまけ：大AI時代ならではの困りポイント&lt;/h2&gt;
&lt;p&gt;初めてこの方法を思いついて実施してみた時に、穴埋めになったコードをGitHub Copilotが全力で補完してきました😅。実施時はオフにしておくのがよさそうです。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>個人サイトをリニューアルしました！（N度目）</title><link>https://ikuma-t.com/blog/renewal-mysite-with-remix/</link><guid isPermaLink="true">https://ikuma-t.com/blog/renewal-mysite-with-remix/</guid><description>N度目のリニューアルもう何度目かわかりませんが、個人サイトをリニューアルしました。元のサイトはこちらです（vercelにFreeでアップしているので、生き残ってはいる）。本当は以前のサイトをもう少し継</description><pubDate>Mon, 07 Aug 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#n度目のリニューアル&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;N度目のリニューアル&lt;/h2&gt;
&lt;p&gt;もう何度目かわかりませんが、個人サイトをリニューアルしました。&lt;/p&gt;
&lt;p&gt;元のサイトは&lt;a href=&quot;https://ikuma-t-work.vercel.app/&quot; target=&quot;_blank&quot;&gt;こちら&lt;/a&gt;です（vercelにFreeでアップしているので、生き残ってはいる）。&lt;/p&gt;
&lt;p&gt;本当は以前のサイトをもう少し継続して使用する予定だったんですが、色々とローカルでいじっていたらAstroがぶっ壊れてしまい、直すのも面倒なので作り直したという経緯です。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#使用技術&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;使用技術&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Remix&lt;/li&gt;
&lt;li&gt;Tailwind CSS / shadcn/ui&lt;/li&gt;
&lt;li&gt;Newt&lt;/li&gt;
&lt;li&gt;Cloudflare Pages&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;今回はこんな構成で作ってみました。Next.jsのAppRouterを使っても良かったのですが、Cloudflareを使ってみたかったので相性の良いRemixを採用した次第です。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#remix&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Remix&lt;/h3&gt;
&lt;p&gt;かなりゴリゴリ書いてしまったので、正直Remixの開発体験がいいのか悪いのかはジャッジできません。リファクタリングしないといけない箇所がたくさんあるので、修正するなかでまた感想を書こうと思います。&lt;/p&gt;
&lt;p&gt;Cloudflareとの相性という点ではセットアップ時にCloudflare Pagesへのデプロイを指定できるので、ここはめちゃくちゃ良かったですね。あとからちゃんと確認しましたが、npm scriptsでnpm run devをwranglerにリフレクトするような仕草もデフォルトで入っていたので、デプロイはかなりスムーズでした。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#newt&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Newt&lt;/h3&gt;
&lt;p&gt;Astroでローカルがぶっ壊れたのはエラーメッセージ的におそらくMDXのパースと踏んでいたので、同じ轍を踏まぬように今回はCMSを使うことに。&lt;/p&gt;
&lt;p&gt;microCMSを使っても良かったのですが、あえてNewtを使ってみました。なんとなくです。&lt;/p&gt;
&lt;p&gt;CMSのエディタが個人的には好印象で、表示部分はNotionのようにいくつかのビューを選択でき、登録・編集部分では「絵文字」や「カラー」などの珍しいフォーム部品もありました。このブログでも絵文字をCMS側で登録して、それをブログ一覧に表示しています。&lt;/p&gt;
&lt;p&gt;マイナス点としては2つあり、1つはモデルの定義の場所がわかりにくい &amp;amp; 設定変更後保存しなくてもアラートが出ないのでよく保存し忘れること。もう1つはSDKの使い方が微妙に分かりにくいことです。後者はある程度使っていけばわかるようになりますが、初見でGitHubのREADMEを見ただけでは、複雑なクエリの発行が難しかったです。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#cloudflare-pages&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Cloudflare Pages&lt;/h3&gt;
&lt;p&gt;ずっと使おうと思って早数ヶ月、やっとことさ使うことができました。Pagesの方はNetlifyやVercelを使ったときの体験と大体同じなので割愛です。&lt;/p&gt;
&lt;p&gt;今回ブログの動的OGP生成のためにCloudflare Pages functionsを使おうとしたのですが、結果として1MBの制限を超えられず使用を断念しました。&lt;/p&gt;
&lt;p&gt;vercel/ogのcloudflare-pages版が出ていたのでそれを使った実装を考えていたのですが、おそらくvercel/og自体のバンドルサイズやらで容量制限に引っかかっていそうです。考えている過程は&lt;a href=&quot;https://www.timesy.dev/posts/c0a943a1-8b71-4576-8efc-384e498beb4e&quot; target=&quot;_blank&quot;&gt;こちら&lt;/a&gt;を参照いただければと思います。&lt;/p&gt;
&lt;p&gt;まあ固定でもいいっちゃいいんですが、時間がある時にまた対応しようと思います。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#残タスク&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;残タスク&lt;/h2&gt;
&lt;p&gt;とりあえず公開できるくらいにしましたが、まだまだ実装残があります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;記事移行&lt;/li&gt;
&lt;li&gt;技術スタックのページをつくる&lt;/li&gt;
&lt;li&gt;アンカーリンクがページ移動するだけで、リンクが切り替わらない&lt;/li&gt;
&lt;li&gt;ブログ、登壇の動的OGP対応&lt;/li&gt;
&lt;li&gt;リンクカード対応&lt;/li&gt;
&lt;li&gt;ページネーション&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;まずは過去記事を移行しようと思っています。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;もともと記事しかなかった個人サイトもリニューアルするたびに機能が増えていっています。&lt;/p&gt;
&lt;p&gt;前回の更新では登壇情報が増えましたが、今回は以下の機能が増えました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ブログのカテゴリわけとタブ表示&lt;/li&gt;
&lt;li&gt;個人的なお知らせ機能&lt;/li&gt;
&lt;li&gt;年ごとの登壇数集計&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;突然の移管は不本意でしたが、乗り換えることによって、自分の実装力の向上を図ることができ、結果として良かったかなと思っています。&lt;/p&gt;
&lt;p&gt;とはいえ次は1年以上もつといいなあ…。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>[Node/Deno]ちょっとしたCLIで使えるスピナー</title><link>https://ikuma-t.com/blog/cli-spinner/</link><guid isPermaLink="true">https://ikuma-t.com/blog/cli-spinner/</guid><description>はじめにちょっとしたCLIを作っている時に、ある程度長い処理（最近だとOpenAIのAPI呼び出しとか）を実行している際に、ローディング時間が気になります。そんなときにスピナーを表示して、実行中である</description><pubDate>Sat, 03 Jun 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#はじめに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;はじめに&lt;/h2&gt;
&lt;p&gt;ちょっとした CLI を作っている時に、ある程度長い処理（最近だと OpenAI の API 呼び出しとか）を実行している際に、ローディング時間が気になります。&lt;/p&gt;
&lt;p&gt;そんなときにスピナーを表示して、実行中であることを視覚的にわかるようにしたいのですが、これをやるためだけにライブラリを追加するのもやや微妙です。&lt;/p&gt;
&lt;p&gt;そのため、Node.js/Deno でちょっとしたスピナーを作ってみました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#実装&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;実装&lt;/h2&gt;
&lt;p&gt;いずれの場合も基本形は同じで、それぞれのランタイム固有の API に置き換えているくらいです。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#nodejs&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Node.js&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FRAMES&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;⠋&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;⠙&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;⠹&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;⠸&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;⠼&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;⠴&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;⠦&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;⠧&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;⠇&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;⠏&quot;&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Spinner&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;constructor&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; intervalId&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NodeJS&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Timer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;undefined&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;undefined&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; currentCharIndex &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;) {}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;start&lt;/span&gt;&lt;span&gt;(message&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.intervalId &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;setInterval&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;spinner&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FRAMES&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.currentCharIndex&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;spinnerMessage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; message &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;`  &lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;message&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;process&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;stderr&lt;/span&gt;&lt;span&gt;&lt;span&gt;.write&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;`\r&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;spinner&lt;/span&gt;&lt;span&gt;}${&lt;/span&gt;&lt;span&gt;spinnerMessage&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.currentCharIndex &lt;/span&gt;&lt;span&gt;%=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FRAMES&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;stop&lt;/span&gt;&lt;span&gt;(message&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;clearInterval&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.intervalId);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;process&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;stderr&lt;/span&gt;&lt;span&gt;&lt;span&gt;.write&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;`\r&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;message &lt;/span&gt;&lt;span&gt;??&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&quot;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#deno-実装&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Deno 実装&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FRAMES&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;⠋&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;⠙&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;⠹&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;⠸&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;⠼&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;⠴&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;⠦&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;⠧&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;⠇&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;⠏&quot;&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Spinner&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;constructor&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; intervalId&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;undefined&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;undefined&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; currentCharIndex &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;) {}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;start&lt;/span&gt;&lt;span&gt;(message&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.intervalId &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;setInterval&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;spinner&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FRAMES&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.currentCharIndex&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;spinnerMessage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; message &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;`  &lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;message&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;Deno&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;stdout&lt;/span&gt;&lt;span&gt;&lt;span&gt;.write&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TextEncoder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;.encode&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;`\r&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;spinner&lt;/span&gt;&lt;span&gt;}${&lt;/span&gt;&lt;span&gt;spinnerMessage&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.currentCharIndex &lt;/span&gt;&lt;span&gt;%=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FRAMES&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;stop&lt;/span&gt;&lt;span&gt;(message&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;clearInterval&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.intervalId);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;Deno&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;stdout&lt;/span&gt;&lt;span&gt;&lt;span&gt;.write&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TextEncoder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;.encode&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;`\r&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;message &lt;/span&gt;&lt;span&gt;??&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&quot;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#使い方&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;使い方&lt;/h2&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// 使い方（Node.js）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; timers &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;node:timers/promises&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;spinner&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Spinner&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;spinner&lt;/span&gt;&lt;span&gt;&lt;span&gt;.start&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;ロード中...&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;timers&lt;/span&gt;&lt;span&gt;&lt;span&gt;.setTimeout&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;3000&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;spinner&lt;/span&gt;&lt;span&gt;&lt;span&gt;.stop&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Deno&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { sleep } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;https://deno.land/x/sleep/mod.ts&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;spinner&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Spinner&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;spinner&lt;/span&gt;&lt;span&gt;&lt;span&gt;.start&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;ロード中...&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sleep&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;); &lt;/span&gt;&lt;span&gt;// sleepはミリ秒ではなく、秒を渡すインターフェース&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;spinner&lt;/span&gt;&lt;span&gt;&lt;span&gt;.stop&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;spinner 自体には実行時間等の役割は持たせず、あくまで表示のみを行うようにしています。
そのため、何かしら長い処理の前後に &lt;code&gt;spinner.start()&lt;/code&gt; と &lt;code&gt;spinner.stop()&lt;/code&gt; を挟む形で使うことになります。&lt;/p&gt;
&lt;p&gt;このインターフェースは大きめの CLI になるとやや微妙かな？と思ったりしましたが、今回はささっと使える Spinner を用意するのが目的だったのでこれでよしとしています。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#解説&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;解説&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#nodejstimer&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;NodeJS.Timer&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://nodejs.org/api/timers.html#timers&quot; target=&quot;_blank&quot;&gt;https://nodejs.org/api/timers.html#timers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;window.setInterval の場合や Deno の場合も、setInterval の戻り値は number なのですが、Node.js ではイベントループを管理するためのオブジェクトとして NodeJS.Timer という型が用意されています。&lt;/p&gt;
&lt;p&gt;Node.js においては、setInterval の戻り値が&lt;a href=&quot;https://nodejs.org/docs/latest-v18.x/api/timers.html#class-timeout&quot; target=&quot;_blank&quot;&gt;Timeout クラス&lt;/a&gt;であり、このクラスの型が NodeJS.Timer です。&lt;/p&gt;
&lt;p&gt;実際の型定義は以下の通りです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;declare&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;module&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;timers&quot;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; setInterval&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;typeof&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;global&lt;/span&gt;&lt;span&gt;.setInterval;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;global {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;namespace&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NodeJS&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Timer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RefCounted&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;hasRef&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;refresh&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;Symbol&lt;/span&gt;&lt;span&gt;.toPrimitive]()&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/DefinitelyTyped/DefinitelyTyped/blob/3197efc097d522c4bf02b94e1a0766d007d6cdeb/types/node/timers.d.ts#L31-L35&quot; target=&quot;_blank&quot;&gt;https://github.com/DefinitelyTyped/DefinitelyTyped/blob/3197efc097d522c4bf02b94e1a0766d007d6cdeb/types/node/timers.d.ts#L31-L35&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RefCounted&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ref&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;unref&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/DefinitelyTyped/DefinitelyTyped/blob/3197efc097d522c4bf02b94e1a0766d007d6cdeb/types/node/globals.d.ts#L234-L237&quot; target=&quot;_blank&quot;&gt;https://github.com/DefinitelyTyped/DefinitelyTyped/blob/3197efc097d522c4bf02b94e1a0766d007d6cdeb/types/node/globals.d.ts#L234-L237&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ドキュメントを読む限りでは、以下のような感じでした。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;デフォルトでは Timer はイベントループが有効な間は生存する&lt;/li&gt;
&lt;li&gt;このデフォルトの挙動をカスタマイズできるように、ref() と unref() が用意されている&lt;/li&gt;
&lt;li&gt;Timer#refresh() は Timer オブジェクトをリフレッシュする（タイマーがリセットされる）&lt;/li&gt;
&lt;li&gt;Timer#Symbol.toPrimitive() は Timer オブジェクトを数値で返す。これによって、ブラウザでの setInterval との実装の互換性を実現できる。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;今回のように、ブラウザの setInterval と同じような感覚で使用している場合にはあまり効果はないですが、イベントループを意識した処理を書く際にはこれらのインターフェースが役に立つのかも？&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#キャリッジリターン&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;キャリッジリターン&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;\r&lt;/code&gt;のことですが、単純に&lt;code&gt;console.log()&lt;/code&gt;してしまうと、改行が発生してスピナーのフレームが変わるたびに 1 行ずつ表示されてしまいます。&lt;/p&gt;
&lt;p&gt;そのため、それぞれのランタイムの出力を利用して出力し、さらにキャリッジリターンを使って、カーソルを行の先頭に戻すようにしています。
これでその位置に留まり続けるスピナーの完成です。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#カスタマイズ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;カスタマイズ&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#ローディングに表示されるアイコンを変える&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ローディングに表示されるアイコンを変える&lt;/h3&gt;
&lt;p&gt;FRAMES に好きなアイコンを定義すれば、その通りに表示されます。&lt;/p&gt;
&lt;p&gt;今回表示している点字は &lt;a href=&quot;https://github.com/sindresorhus/cli-spinners&quot; target=&quot;_blank&quot;&gt;https://github.com/sindresorhus/cli-spinners&lt;/a&gt; を参考にさせてもらいましたが、これ以外にも適当な絵文字（🍣 とか 🍺 とか）を使っても良いかもしれません。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#標準出力にまぎれないようにする&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;標準出力にまぎれないようにする&lt;/h3&gt;
&lt;p&gt;こういったことをしたいユースケースとしては、「ターミナル上ではローディングを見せたいけど、処理結果を pipe 等で後続処理に渡したいので、標準出力には出力したくない」というケースかと思います。
これは現時点での暫定解なのですが、標準出力ではなく標準エラー出力に出力すればとりあえず解決します。&lt;/p&gt;
&lt;p&gt;解決は解決なんですが、本来エラーのために用意されている箇所を、こういったハックのために使うのはいかがなものかという気もしますね…。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;今回 intervalId を持っていて欲しかったので、イメージしやすくクラスとして作りましたが、関数型でやるとどうなるのかは気になるところ。気が向いたらやってみようと思います。&lt;/p&gt;
&lt;p&gt;…こういっていて気が向いたことはないので、多分やりません。どなたか実装されたら教えてください。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>『問いのデザイン 創造的対話のファシリテーション』を読んだ</title><link>https://ikuma-t.com/blog/vs-chiikawa-mtg/</link><guid isPermaLink="true">https://ikuma-t.com/blog/vs-chiikawa-mtg/</guid><description>はじめにお通夜会議を脱したい「こういう感じで考えてみたんですけど、ご意見ある方いらっしゃいますか？」「…」沈黙が走る。たたき台を作ってまとめる、そこまでは順調に進んだが、実際にチームにシェアする場面で</description><pubDate>Sat, 03 Jun 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#はじめに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;はじめに&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#お通夜会議を脱したい&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;お通夜会議を脱したい&lt;/h3&gt;
&lt;p&gt;「こういう感じで考えてみたんですけど、ご意見ある方いらっしゃいますか？」&lt;/p&gt;
&lt;p&gt;「…」&lt;/p&gt;
&lt;p&gt;沈黙が走る。&lt;/p&gt;
&lt;p&gt;たたき台を作ってまとめる、そこまでは順調に進んだが、実際にチームにシェアする場面で投げかけた一言にはなかなかレスポンスがなく、どう進めようか画面の前で汗ダラダラ…。何か前に進めなければと思って振り絞るも、結局進め方がわからず「ｱｯ…」となってしまう。
なんやかんやしているうちに、1 人が出したよさそうな意見がめちゃめちゃ眩しい…。なんだかいい感じだ！みんなも良さそうと言っているし…ええいもう「なんとかなれ〜！！」。&lt;/p&gt;
&lt;p&gt;…とまあここまで極端ではなくても、参加者の意見をリアルタイムに汲み取りながら進めていくタイプのミーティングでこうした状況になってしまうことはままあります。&lt;/p&gt;
&lt;p&gt;そのためどうにか再現性高くこのお通夜会議&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;を脱したいと思っていました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#問いのデザイン-創造的対話のファシリテーションを読んだ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;『問いのデザイン 創造的対話のファシリテーション』を読んだ&lt;/h3&gt;
&lt;p&gt;&lt;img /&gt;
画像引用元: &lt;a href=&quot;https://book.gakugei-pub.co.jp/gakugei-book/9784761527433/&quot; target=&quot;_blank&quot;&gt;https://book.gakugei-pub.co.jp/gakugei-book/9784761527433/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;前から認識してはいたのですが、課題感が募った今がまさに読み時だろうと思って&lt;a href=&quot;https://book.gakugei-pub.co.jp/gakugei-book/9784761527433/&quot; target=&quot;_blank&quot;&gt;問いのデザイン 創造的対話のファシリテーション&lt;/a&gt;を読んでみたので、この本を読んで得たヒントをまとめてみます。&lt;/p&gt;
&lt;p&gt;なお本書の構成としては「課題のデザイン」「プロセスのデザイン」の前後編に分かれており、ざっくり前者は What を、後者は How を解説した内容になっています。
どちらも参考になる部分がとても多かったですが、今回は特にお通夜会議攻略の糸口という観点で「プロセスのデザイン」に今の自分に刺さるヒントがあったので、そちらの内容を整理してみます。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#ファシリテーションのヒント&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ファシリテーションのヒント&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#課題への道を経験のプロセスとしてデザインする&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;課題への道を経験のプロセスとしてデザインする&lt;/h3&gt;
&lt;p&gt;これは 4 章 ワークショップのデザインに書かれている内容なので、通常運営のミーティングとはややニュアンスが異なるかもしれませんが、自分としては十分応用できる内容だと思いましたので自分の解釈と共に紹介します。&lt;/p&gt;
&lt;p&gt;まず本書におけるワークショップは「普段とは異なる視点から発想する、対話による学びと創造の方法」となっていて、その実現のために経験のプロセスをデザインすることが大事だと言います。
具体的には最終的な課題に対して、「導入」「知る活動」「作る活動」「まとめ」の 4 つのプロセスを設計していきます。美味しい料理を作るために下ごしらえが必要なように、課題に対してアウトプットを出す際にも、情報を知ることなり、それぞれがイメージやビジョンを巡らせるなどの下準備が必要というわけです。&lt;/p&gt;
&lt;p&gt;よくよく考えてみるとお通夜会議も、得てして「問いかけられた側が答えを持っている」かのような前提で始まることが多い気がします。実際のところは、その会議を持ちかけた側が課題に対しての熱量と情報量が高く、反対に持ちかけられた側は日常の別タスクをこなしているところからその課題に向き合うため、全くもって準備万端ではありません。そう考えると反射的に答えられないこともよく頷けます。&lt;/p&gt;
&lt;p&gt;そのため会の目的にもよりますが、最終的な課題へ参加者の頭を切り替えさせるようなアイスブレイクや問いの足場を段階的に設けることが必要になりそうです。
例えばスプリントレトロスペクティブであればいきなり KPT をあげるという「作る活動」に移行するのではなく、まずはチームでいいところも悪いところもあげるようなアイスブレイクを「導入」として用意し、そのスプリントでどんな積み上げをしてきたのかを「知る活動」を設けた上で、KPT に挑むという具合です。
（これに倣って最近では「賛否両論」というアイスブレイクをレトロスペクティブに取り入れてみたりしています。これはまたいつか紹介します。）&lt;/p&gt;
&lt;p&gt;例に挙げたスクラムイベントのようにある程度定期的に開催されるイベントはこのようにかっちりと当てはめやすいですが、日々流動的に発生するミーティングにこれを適用するのはやや難しいなと感じています。
そのため、大枠としてミーティング全体を Input・Output の 2 枠で捉えて、Output に対して必要な Input の部分が荒くないか？という観点でミーティングを観察し、必要に応じて後述の制約を設けた問いを投げるようにしてみています。
現状成功率は 8 割くらいですが、全く道標がない状態よりも大枠を一定のプロセスとして捉えることは、一定成果があるように思います。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#問いに制約を設ける&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問いに制約を設ける&lt;/h3&gt;
&lt;p&gt;もう 1 つなるほどと思ったポイントが、問いに対して制約を設けることです。&lt;/p&gt;
&lt;p&gt;具体的には以下のようなテクニックを使うことで、問いに対して制約を課し、参加者の思考の足がかりを形成することを試みます。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;価値基準を示す形容詞をつける&lt;/li&gt;
&lt;li&gt;ポジティブとネガティブを示す&lt;/li&gt;
&lt;li&gt;時期や期間を指定する&lt;/li&gt;
&lt;li&gt;想定外の制約をつける&lt;/li&gt;
&lt;li&gt;アウトプットの形式に制約をつける&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;お通夜会議でよくある「何か意見あればお願いします」や「感想でもなんでもどうぞ」は、問いかけとしては広すぎるため、参加者からすると「どこから考え始めていいのかわからない」ことに加え、一見どんな意見も許容しているように見えて、参加者心理では回答のガイドラインがないために「この内容を答えてしまっていいのか？」という不安が生まれてしまいます。&lt;/p&gt;
&lt;p&gt;各テクニックの詳細は本書を参照していただくとして、自分がいいなと思ったのが「アウトプットの形式に制約をつける」テクニックです。この方法では、「〇〇するための 3 つの条件は？」「〇〇を起承転結で表すと？」といった具合にアウトプットの形式に制約がかかっています。
お通夜会議では Input のフェーズで話している内容が絞られておらず、自由に発散しているため議論が収束しにくいです。そのため、いくつかの発散が行われたタイミングで「この中から 1 つだけ対応すると考えた時、どれを選びますか？」と問いかけを行うと、参加者の思考の足がかりになり、議論が進みやすくなるのではないかと思いました。&lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;本書を読むまでは、お通夜会議に陥った際に、出口までの順路がぐにゃぐにゃになってしまって、着地できるかどうかは運任せでした。&lt;/p&gt;
&lt;p&gt;最近では少しずつちいかわ状態に陥った際にもリカバリがわかってきて、「今はインプット・アウトプットどちらに当てるべき時間か」「場に投げられている問いは広いか？広いならどう制約をつけたせそうか？」といったことを考えながら発言したりしています&lt;sup&gt;&lt;a href=&quot;#user-content-fn-3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;。
これは別に自分がファシリテーターではなくても有効な考え方で、自分が一参加者の場合もお通夜会議になりそうだったら、今回挙げたようなポイントで出口を探っています。
ファシリテーターはあまり余裕がないので、共通認識として本書の考え方が通っていると、全体の議論の質も上がりそうです。&lt;/p&gt;
&lt;p&gt;色々試しつつ、少し成果を出しつつもありますが、まだまだ課題も色々あります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ファシリテーターとしての帽子と開発者としての帽子を同時に被るのは大変
&lt;ul&gt;
&lt;li&gt;基本的に「この問いが広いのか、狭いのか」「全体の熱量はどのくらいか」といった観点は、議論から一歩引いた姿勢になる。&lt;/li&gt;
&lt;li&gt;日常に湧き起こるミーティングのほとんどは自身も当事者であり、それだけがうまくできていればいいわけではない（本質は課題を解くこと）。&lt;/li&gt;
&lt;li&gt;別の誰かがコントロールしてくれている、誰かが意識しなくても自然とうまく進んでいるときであれば、当事者としてのアクセルを全開にするような切替が求められそうだけど、難しい。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ファシリテーターは黒子だけど、うまく解決できることが楽しくなってくると黒子ではなくなる
&lt;ul&gt;
&lt;li&gt;この手法で楽しくなっちゃっているレベルはまだまだなんだろうなという気持ち&lt;/li&gt;
&lt;li&gt;エンジニアの麻疹のように、まずはガッチリ使い込んで、その後に自分なりの解釈を加えていきたい&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;いつも成功するわけではない
&lt;ul&gt;
&lt;li&gt;いろいろ試している感覚として、お通夜になったときにそこに再度アクセルをかけるのは 8 割 5 分くらいの成功できていますが、それ以降確実に収束の方向性へ迎えるかは正直運なので、確度をあげたい&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;というわけでもう少し意識的に続けてもっと良くできるように頑張ってみたいと思います。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;&lt;a href=&quot;#footnote-label&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;別名ちいかわ会議 &lt;a href=&quot;#user-content-fnref-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ちょくちょく仕事でもこの質問を投げる機会があるんですが、聞く時には脳内で BUMP OF CHICKEN の「ダイヤモンド」が流れています（サビの歌詞参照）。 &lt;a href=&quot;#user-content-fnref-2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;しかしこれが周囲から見て機能しているかはまた別問題である。。。 &lt;a href=&quot;#user-content-fnref-3&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><author>ikuma-t</author></item><item><title>アイコンが重なってて、ホバーするとニュッとするそれ</title><link>https://ikuma-t.com/blog/avatar-overlap-layout/</link><guid isPermaLink="true">https://ikuma-t.com/blog/avatar-overlap-layout/</guid><description>アイコンが重なってて、ホバーするとニュッとするそれを作ろうこれはdev.toの記事リアクションの表示です。Slackでハドルミーティングが発生している時の参加者の表示にもこういったアイコンを重ねるレイ</description><pubDate>Sun, 28 May 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#アイコンが重なっててホバーするとニュッとするそれを作ろう&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;アイコンが重なってて、ホバーするとニュッとするそれを作ろう&lt;/h2&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;これは dev.to の記事リアクションの表示です。Slack でハドルミーティングが発生している時の参加者の表示にもこういったアイコンを重ねるレイアウトがよく見られます。&lt;/p&gt;
&lt;p&gt;よく見かけるけど自分では作ったことがなかったので、&lt;a href=&quot;https://web.dev/css-animated-grid-layouts/&quot; target=&quot;_blank&quot;&gt;CSS Animated Grid Layouts&lt;/a&gt;を参考にしつつ、今回はこちらを少し捻ったもの練習として作ってみました。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#要件&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;要件&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;アイコンの数は 1〜5 個&lt;/li&gt;
&lt;li&gt;アイコンは重ねて表示する&lt;/li&gt;
&lt;li&gt;アイコンのいずれかをホバーすると、全体が広がり、後ろのアイコンも見えるようになる&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#実装&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;実装&lt;/h2&gt;

  See the Pen{&quot; &quot;}
  &amp;lt;a href=&quot;https://codepen.io/ikumatadokoro/pen/RweOMXb&quot;&amp;gt;
    アイコンが重なってて、ホバーするとニュッとするそれ
  &amp;lt;/a&amp;gt;

&lt;p&gt;&lt;a href=&quot;https://codepen.io/ikumatadokoro/pen/RweOMXb?editors=1100&quot; target=&quot;_blank&quot;&gt;https://codepen.io/ikumatadokoro/pen/RweOMXb?editors=1100&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#実装メモ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;実装メモ&lt;/h2&gt;
&lt;p&gt;1 次元配置なので、Flexbox でもいけると思うのですが、今回は参考ソースに合わせて GridLayout での実装になります。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#アイコンを重ねて表示する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;アイコンを重ねて表示する&lt;/h3&gt;
&lt;p&gt;このレイアウトの中核は、アイコンより狭めに設定された列トラックです。&lt;/p&gt;
&lt;p&gt;今回は横方向にアイコンを積んでいくため、&lt;code&gt;grid-auto-flow: column&lt;/code&gt;を指定した上で、&lt;code&gt;grid-template-columns&lt;/code&gt;で列の数を指定します。&lt;/p&gt;
&lt;p&gt;このとき、列幅を以下のように定義しています（必要部分のみ抜粋）。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;.icons&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--gap&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;em&lt;/span&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--icon-size&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;em&lt;/span&gt;&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;/* 実際のアイコンのサイズ */&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--overlap-size&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;em&lt;/span&gt;&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;/* 列トラックのサイズ。アイコンよりも小さめ */&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--num-children-1&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;calc&lt;/span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt;(--num-children) &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; 1)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--grid-cell-size&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--overlap-size&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;/* アイコンよりも小さめの列トラックが定義されているので、重なって見える */&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;display&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;grid&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;grid-auto-flow&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;column&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;grid-template-columns&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;repeat&lt;/span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt;(--num-children)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt;(--grid-cell-size))&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;grid-auto-columns&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;/span&gt;&lt;span&gt;(--grid-cell-size)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;gap&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;/span&gt;&lt;span&gt;(--gap)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;/* 植木算的な感じで全体の幅を要素に応じて調整している */&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;width&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;calc&lt;/span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt;(--grid-cell-size) &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt;(--num-children-1) &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt;(--gap) &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--num-children&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt;(--icon-size) &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt;(--border-size)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これで各列が重なるようになりました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#ホバー表示&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ホバー表示&lt;/h3&gt;
&lt;p&gt;ホバー時は、&lt;code&gt;scale&lt;/code&gt;を使って拡大表示しています。また、&lt;code&gt;z-index&lt;/code&gt;を指定して、ホバーしたアイコンが最前面に表示されるようにしています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;.icons&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&lt;span&gt;:hover&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;scale&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1.1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;z-index&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;border-width&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;/span&gt;&lt;span&gt;(--border-size)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;border-color&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;/span&gt;&lt;span&gt;(--icon-color)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#要素数に応じて幅計算を行うための-css-変数&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;要素数に応じて幅計算を行うための CSS 変数&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;.icons:where&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;:has&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;span&gt;:nth-of-type&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:last-child&lt;/span&gt;&lt;span&gt;)) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--num-children&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;.icons:where&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;:has&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;span&gt;:nth-of-type&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:last-child&lt;/span&gt;&lt;span&gt;)) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--num-children&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;.icons:where&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;:has&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;span&gt;:nth-of-type&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:last-child&lt;/span&gt;&lt;span&gt;)) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--num-children&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;.icons:where&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;:has&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;span&gt;:nth-of-type&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:last-child&lt;/span&gt;&lt;span&gt;)) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--num-children&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;.icons:where&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;:has&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;span&gt;:nth-of-type&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:last-child&lt;/span&gt;&lt;span&gt;)) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--num-children&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;だいぶ力技感がありますが、5 個までの制約のもとに CSS だけで幅を計算するために、上記のような CSS 変数を定義しています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;where&lt;/code&gt;: 条件を満たす要素を選択する。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;has&lt;/code&gt;：子要素又は子孫要素の中に、指定したセレクタにマッチする要素が存在する場合に、その親要素を選択する。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;つまりこのセレクタでは「&lt;code&gt;.icons&lt;/code&gt;クラスの要素で、その最後の子要素が&lt;code&gt;nth-of-type(1)&lt;/code&gt;の要素を持っているもの（=1 番目の要素）を選択する」という意味になります。
要素数が 2 個の場合は、&lt;code&gt;nth-of-type(2)&lt;/code&gt;の要素を持っているもの（=2 番目の要素）を選択する、というように、要素数に応じて幅を計算することが可能になります。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;全ての要素を削減したくはないけど、なんとなくの全体感を把握したい。そんなときに使えるのが「重ねて表示する」レイアウトと考えており、
その目的に hover での展開を加えるメリットがあまりないので、実際にはこのレイアウトを使う日は少ないかも？と思っています
（hover を実装したい時は「各要素は細かく見えるようにしたいけど、全体を見た時に他の要素も多いため、通常時は少し詰めて表示したい」と考えるときではないでしょうか）。&lt;/p&gt;
&lt;p&gt;いずれにせよアイコンを重ねる実装自体は共通で使えるので、grid によるレイアウトの引き出しとして今後も活用していきたいと思います！&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>書籍「Web Workers」を読んだ</title><link>https://ikuma-t.com/blog/read-web-workers/</link><guid isPermaLink="true">https://ikuma-t.com/blog/read-web-workers/</guid><description>画像引用元：https://www.oreilly.co.jp/books/9784873115962/オライリーのWebWorkersを読みました。そろそろCloudflareWorkersを触ろう</description><pubDate>Sun, 21 May 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;画像引用元：&lt;a href=&quot;https://www.oreilly.co.jp/books/9784873115962/&quot; target=&quot;_blank&quot;&gt;https://www.oreilly.co.jp/books/9784873115962/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;オライリーの&lt;a href=&quot;https://www.oreilly.co.jp/books/9784873115962/&quot; target=&quot;_blank&quot;&gt;Web Workers&lt;/a&gt;を読みました。
そろそろ Cloudflare Workers を触ろうと思っていて、そしたら Service Worker は知らんとな → そもそも Worker ってなんとなくわかるけど、ちゃんと説明できないな、ということで少し古めですが本書を読んで基本をかじってみることにしました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#この本で学んだこと&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;この本で学んだこと&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Web Worker は HTML5 の機能の一つで、JavaScript でマルチスレッドを実現するためのもの。メインスレッドの DOM を操作できない制約がある。&lt;/li&gt;
&lt;li&gt;main と worker でオブジェクトは共有されない。メッセージをやりとりすることで通信するが、オブジェクトのコピーによりパフォーマンスに影響が出る場合は、&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/API/Web_Workers_API/Transferable_objects&quot; target=&quot;_blank&quot;&gt;移譲可能オブジェクト&lt;/a&gt;を利用できる。&lt;/li&gt;
&lt;li&gt;Web Worker の種類には Dedicated Worker（専有）と Shared Worker（共有）がある。前者は 1 つのスクリプトからしかアクセスできないが、後者は複数のスクリプトからアクセスできる。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;総じて「そもそも Web Worker ってなにもの？？」という超初歩的な問いに対しての答えを得ることができました。Web Worker における Hello World 的な存在が素数計算だということも初耳でした（今後サンプル作る時にやろう）。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;読んでいる中でいくつか「これはどうなんだろう？」と疑問に思って調べたポイントをいくつかまとめます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#web-worker-vs-promise&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Web Worker VS Promise&lt;/h3&gt;
&lt;p&gt;「メインスレッドから処理を移譲することで、コンテンツの描画をブロックしないでおくことができる」という内容を見た際に、 &lt;strong&gt;これは Promise でも実現できるのでは？&lt;/strong&gt; と思いました。
例えばインポート処理を行うボタンを押した際に、取り込み処理自体は Promise で非同期に実施し、適当にローディングアニメーションを付けて他の箇所は操作可能にしておくという実装はそれほど難しくありません。&lt;/p&gt;
&lt;p&gt;この質問に対しての 1 つの回答は、 &lt;strong&gt;「CPU に負荷のかかる処理は、メインスレッドで順序を入れ替えても解決しないので Web Worker を使う意味はある」&lt;/strong&gt; です。&lt;/p&gt;
&lt;p&gt;例として処理時間が 30 秒かかる画像のリサイズ処理を考えます。Promise で非同期に実行する場合、結局は画像のリサイズ処理を行うスレッドが 1 つしかないので、同期的に 30 秒待つことはなくとも、トータルとしては 30 秒の処理時間が必要になります。&lt;/p&gt;
&lt;p&gt;一方で Web Worker を複数起動すれば、それらはメインスレッドとは別のスレッドとなり、その処理を並列で処理することができます。3 つの Worker をたて、1 つの Worker が捌く量を全体の 1/3 にすることで、ガバガバ計算ですが各スレッド単位での実行時間は 10 秒になります。そしてこれらは並列に処理されるので総実行時間も 10 秒です。&lt;/p&gt;
&lt;p&gt;そのため計算処理自体が重い場合は Web Worker の使用を検討する材料の 1 つになりうるでしょう。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#shared-worker-vs-broadcastchannel&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Shared Worker VS BroadCastChannel&lt;/h3&gt;
&lt;p&gt;これは半分勘違いだったのですが、 &lt;strong&gt;「複数のブラウジング・コンテキスト間で情報を共有できるという側面だけからこれらを見た時に、それぞれをいつ使うのか？」&lt;/strong&gt; と疑問に思いました。&lt;/p&gt;
&lt;p&gt;そこであらためてそれぞれがどういう API なのか書き出してみました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;BroadCastChannelAPI: 異なる文書やウィンドウ間でメッセージを送信するための API&lt;/li&gt;
&lt;li&gt;Shared Worker: 複数の文書やウィンドウから利用可能な共有のワーカースレッドを作成するための API&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;「複数のブラウジング・コンテキスト」をターゲットに機能していることは共通していますが、単純にメッセージを送信するのか、それとも実際に計算処理やコネクションを保持するといった具体的な処理を行うのかという点で、そもそもの目的が異なっています。&lt;/p&gt;
&lt;p&gt;そのためこれらは競合するものではありません。例えば Shared Worker で Web Socker のコネクションを共有し、各ブラウジング・コンテキストに対しては BroadCastChannelAPI を使ってメッセージを送信するといった使い方もできるでしょう。&lt;/p&gt;
&lt;p&gt;実際に実装していないので動くのかはわかりませんが、HTTP/1.1 における Server Sent Event のドメイン接続上限（6 つまで）を、Shared Worker を使って回避するといった使い方も可能なのではないでしょうか。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#この本で学べなかったこと&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;この本で学べなかったこと&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Service Worker について&lt;/li&gt;
&lt;li&gt;結局 Worker を実際のアプリケーションレベルでどう使用すべきか
&lt;ul&gt;
&lt;li&gt;comlink を使うとか？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;TypeScript における Worker の利用方法&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#この本を読む際の注意点&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;この本を読む際の注意点&lt;/h2&gt;
&lt;p&gt;この本は 2013 年に出版された本です。そのため、以下の点に注意して読む必要があります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;出版当時にまだ世に出ていなかった Service Worker についての解説がありません。&lt;/li&gt;
&lt;li&gt;全体的にサンプルコードが古いです。具体的には、大きいところで現状と異なる仕様の Twitter からのデータ取得を行うサンプル（これは今年の頭に出しても動かなくなっていそうですが）や、https ではなく http が使われている、細かいところでは変数宣言で&lt;code&gt;var&lt;/code&gt;が多用されているなど。&lt;/li&gt;
&lt;li&gt;ブラウザの対応状況が諸々異なっています。Can I Use などで適宜確認してください。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;やや内容は古めでしたが、内容がコンパクトだったので数時間で読め、ざっくりと Web Worker とは何者かについて知ることができました。&lt;/p&gt;
&lt;p&gt;Web Worker がメインスレッドの DOM 操作ができないことがわかると、PartyTown が Service Worker から同期 XHR で DOM を参照している仕組みが、俄然興味深いものに感じます。&lt;/p&gt;
&lt;p&gt;というわけで今度は MDN と web.dev あたりを読みながら Service Worker に対する理解を深めていきたいです。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>GitHub Actionsをローカルで試せるactを試してみる</title><link>https://ikuma-t.com/blog/try-act/</link><guid isPermaLink="true">https://ikuma-t.com/blog/try-act/</guid><description>最近開発生産性を取得したりでGitHubActionsをよく書いています。最近ではGitHubActionsのVSCode拡張が出てきたことで、構文的なエラーには気が付きやすくなりましたが、やはり実際</description><pubDate>Wed, 10 May 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;最近開発生産性を取得したりで GitHub Actions をよく書いています。最近では GitHub Actions の VSCode 拡張が出てきたことで、構文的なエラーには気が付きやすくなりましたが、やはり実際に動作するかは GitHub に push しなければならず、やや面倒でした。&lt;/p&gt;
&lt;p&gt;N 番煎じではありますが、ローカルで GitHub Actions を実行できる&lt;a href=&quot;https://github.com/nektos/act&quot; target=&quot;_blank&quot;&gt;nektos/act&lt;/a&gt;を使って、GitHub Actions のローカル実行を試してみました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#act-の概要&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;act の概要&lt;/h2&gt;
&lt;p&gt;act は Docker を利用して、.github/workflows のワークフローを実行するための Go 製のツールです。実行環境は現時点で ubuntu のみです。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/nektos/act#runners&quot; target=&quot;_blank&quot;&gt;https://github.com/nektos/act#runners&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;インストール方法は&lt;a href=&quot;https://github.com/nektos/act#installation-through-package-managers&quot; target=&quot;_blank&quot;&gt;こちら&lt;/a&gt;の通りで、今回は Mac で使用するため、HomeBrew でインストールします。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;brew&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;act&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#act-の使い方&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;act の使い方&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/IkumaTadokoro/forke&quot; target=&quot;_blank&quot;&gt;https://github.com/IkumaTadokoro/forke&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ここからはこのリポジトリをサンプルに進めていきます。このリポジトリでは以下の GitHub Actions が定義されています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;.github/workflows&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;├── lint.yml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;├── test.yml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;└── release.yml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#リポジトリのワークフローの確認&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;リポジトリのワークフローの確認&lt;/h3&gt;
&lt;p&gt;まずは対象のワークフローが認識されているかを確認します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$ act -l&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;WARN  ⚠ You are using Apple M-series chip and you have not specified container architecture, you might encounter issues while running act. If so, try running it with &apos;--container-architecture linux/amd64&apos;. ⚠&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Stage  Job ID   Job name  Workflow name  Workflow file  Events&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;0      lint     lint      Lint           lint.yml       push&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;0      release  release   Release        release.yml    push&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;0      test     test      Test           test.yml       push&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;期待通り、3 つのワークフローが認識されています。
M1 Mac を使っているので、実行時にエラーが出るかもと警告が出ていますが、一旦無視して進めます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#ワークフローの実行&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ワークフローの実行&lt;/h3&gt;
&lt;p&gt;今回は vitest によるテストを実行する Job「test」を実行してみます。特定の Job を指定するには&lt;code&gt;-j&lt;/code&gt;オプションを使います。
初回なので、DryRun（&lt;code&gt;-n&lt;/code&gt;）で実行してみます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$ act -j test -n&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;? Please choose the default image you want to use with act:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- Large size image: +20GB Docker image, includes almost all tools used on GitHub Actions (IMPORTANT: currently only ubuntu-18.04 platform is available)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- Medium size image: ~500MB, includes only necessary tools to bootstrap actions and aims to be compatible with all actions&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- Micro size image: &amp;lt;200MB, contains only NodeJS required to bootstrap actions, doesn&apos;t work with all actions&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Default image and other options can be changed manually in ~/.actrc (please refer to https://github.com/nektos/act#configuration for additional information about file structure)  [Use arrows to move, type to filter, ? for more help]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Large&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;gt; Medium&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Micro&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-1] 🚀  Start image=catthehacker/ubuntu:act-latest&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-2] 🚀  Start image=catthehacker/ubuntu:act-latest&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-3] 🚀  Start image=catthehacker/ubuntu:act-latest&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-2]   🐳  docker pull image=catthehacker/ubuntu:act-latest platform= username= forcePull=true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-3]   🐳  docker pull image=catthehacker/ubuntu:act-latest platform= username= forcePull=true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-1]   🐳  docker pull image=catthehacker/ubuntu:act-latest platform= username= forcePull=true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-3]   🐳  docker create image=catthehacker/ubuntu:act-latest platform= entrypoint=[&quot;tail&quot; &quot;-f&quot; &quot;/dev/null&quot;] cmd=[]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-3]   🐳  docker run image=catthehacker/ubuntu:act-latest platform= entrypoint=[&quot;tail&quot; &quot;-f&quot; &quot;/dev/null&quot;] cmd=[]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-2]   🐳  docker create image=catthehacker/ubuntu:act-latest platform= entrypoint=[&quot;tail&quot; &quot;-f&quot; &quot;/dev/null&quot;] cmd=[]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-2]   🐳  docker run image=catthehacker/ubuntu:act-latest platform= entrypoint=[&quot;tail&quot; &quot;-f&quot; &quot;/dev/null&quot;] cmd=[]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-1]   🐳  docker create image=catthehacker/ubuntu:act-latest platform= entrypoint=[&quot;tail&quot; &quot;-f&quot; &quot;/dev/null&quot;] cmd=[]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-1]   🐳  docker run image=catthehacker/ubuntu:act-latest platform= entrypoint=[&quot;tail&quot; &quot;-f&quot; &quot;/dev/null&quot;] cmd=[]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-2]   ☁  git clone &apos;https://github.com/actions/setup-node&apos; # ref=v3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-3]   ☁  git clone &apos;https://github.com/actions/setup-node&apos; # ref=v3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-1]   ☁  git clone &apos;https://github.com/actions/setup-node&apos; # ref=v3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-2] 🧪  Matrix: map[node-version:18.x os:ubuntu-latest]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-2] ⭐ Run Main actions/checkout@v3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-2]   ✅  Success - Main actions/checkout@v3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-2] ⭐ Run Main Use Node.js 18.x&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-2]   ✅  Success - Main Use Node.js 18.x&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-2] ⭐ Run Main Install&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-2]   ✅  Success - Main Install&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-2] ⭐ Run Main Unit Test&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-2]   ✅  Success - Main Unit Test&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-2] ⭐ Run Post Use Node.js 18.x&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-2]   ✅  Success - Post Use Node.js 18.x&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-2] 🏁  Job succeeded&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-3] 🧪  Matrix: map[node-version:20.x os:ubuntu-latest]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-3] ⭐ Run Main actions/checkout@v3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-3]   ✅  Success - Main actions/checkout@v3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-3] ⭐ Run Main Use Node.js 20.x&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-3]   ✅  Success - Main Use Node.js 20.x&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-3] ⭐ Run Main Install&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-3]   ✅  Success - Main Install&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-3] ⭐ Run Main Unit Test&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-3]   ✅  Success - Main Unit Test&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-3] ⭐ Run Post Use Node.js 20.x&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-3]   ✅  Success - Post Use Node.js 20.x&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-3] 🏁  Job succeeded&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-1] 🧪  Matrix: map[node-version:16.x os:ubuntu-latest]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-1] ⭐ Run Main actions/checkout@v3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-1]   ✅  Success - Main actions/checkout@v3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-1] ⭐ Run Main Use Node.js 16.x&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-1]   ✅  Success - Main Use Node.js 16.x&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-1] ⭐ Run Main Install&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-1]   ✅  Success - Main Install&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-1] ⭐ Run Main Unit Test&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-1]   ✅  Success - Main Unit Test&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-1] ⭐ Run Post Use Node.js 16.x&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-1]   ✅  Success - Post Use Node.js 16.x&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*DRYRUN* [Test/test-1] 🏁  Job succeeded&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;初回ではどのサイズの image を利用するか聞かれます。一般的なワークフローであれば Medium で良さそうです。
無事にワークフロー自体は正常終了したようなので、今度はテストの内容を変えて再度実行してみます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# 日付差分を分単位で計測する関数の期待値を変えて失敗させてみる。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;test.each&amp;lt;[Date, Date, number]&amp;gt;([&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[new Date(&quot;2021-01-01T00:00:00Z&quot;), new Date(&quot;2021-01-01T01:00:00Z&quot;), 60],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[new Date(&quot;2021-01-01T00:00:00Z&quot;), new Date(&quot;2021-01-01T00:06:00Z&quot;), 6],&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[new Date(&quot;2021-01-01T00:00:00Z&quot;), new Date(&quot;2021-01-01T00:06:00Z&quot;), 7],&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[new Date(&quot;2021-01-01T00:00:00Z&quot;), new Date(&quot;2021-01-01T00:05:00Z&quot;), 5],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[new Date(&quot;2021-01-01T00:00:00Z&quot;), new Date(&quot;2021-01-01T00:01:00Z&quot;), 1],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[new Date(&quot;2021-01-01T00:00:00Z&quot;), new Date(&quot;2021-01-01T00:00:01Z&quot;), 0],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;])(`[DEFAULT: minute]calcTimeDiff(%s, %s): %s`, (date1, date2, expected) =&amp;gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;expect(calcTimeDiff(date1, date2)).toBe(expected);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$ act -j test&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-1]   ✅  Success - Main Install&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-1] ⭐ Run Main Unit Test&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-1]   🐳  docker exec cmd=[bash --noprofile --norc -e -o pipefail /var/run/act/workflow/3] user= workdir=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;| &amp;gt; forke@1.1.4 test:ci&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;| &amp;gt; vitest run&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|  RUN  v0.30.1 /Users/ikuma/src/github.com/IkumaTadokoro/forke&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|  ✓ src/lib/__test__/mathUtil.test.ts  (12 tests) 5ms&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|  ✓ src/lib/__test__/stat.test.ts  (9 tests) 8ms&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|  ❯ src/lib/__test__/dateUtil.test.ts  (24 tests | 1 failed) 56ms&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|    ❯ src/lib/__test__/dateUtil.test.ts &amp;gt; calcTimeDiff &amp;gt; [DEFAULT: minute]calcTimeDiff(2021-01-01T00:00:00.000Z, 2021-01-01T00:06:00.000Z): 7&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|      → expected 6 to be 7 // Object.is equality&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;| ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|  FAIL  src/lib/__test__/dateUtil.test.ts &amp;gt; calcTimeDiff &amp;gt; [DEFAULT: minute]calcTimeDiff(2021-01-01T00:00:00.000Z, 2021-01-01T00:06:00.000Z): 7&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;| AssertionError: expected 6 to be 7 // Object.is equality&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|  ❯ src/lib/__test__/dateUtil.test.ts:41:40&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|      39|     [new Date(&quot;2021-01-01T00:00:00Z&quot;), new Date(&quot;2021-01-01T00:00:01Z&quot;…&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|      40|   ])(`[DEFAULT: minute]calcTimeDiff(%s, %s): %s`, (date1, date2, expec…&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|      41|     expect(calcTimeDiff(date1, date2)).toBe(expected);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|        |                                        ^&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|      42|   });&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|      43|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|   - Expected  - 1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|   + Received  + 1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|   - 7&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|   + 6&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;| ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|  Test Files  1 failed | 2 passed (3)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|       Tests  1 failed | 44 passed (45)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|    Start at  20:40:05&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|    Duration  868ms (transform 143ms, setup 0ms, collect 456ms, tests 69ms, environment 0ms, prepare 514ms)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-1]   ❌  Failure - Main Unit Test&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-1] exitcode &apos;1&apos;: failure&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-1] 🏁  Job failed&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;マトリクス実行しているのと、act 側のログが大量に出ているので実行部分のみ抜粋ですが、ローカルファイルの変更を反映してワークフローが実行されていることがわかります。これは便利。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#ログ出力を抑制する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ログ出力を抑制する&lt;/h2&gt;
&lt;p&gt;「act 側のログが大量に出ている」と先に挙げましたが、実例としては次のようなものです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-3]   💬  ::debug::{&quot;archiveLocation&quot;:&quot;***&quot;,&quot;cacheKey&quot;:&quot;node-cache-linux-npm-eb3cb123726e2245d1ac05822a0ed4f5b7ab0e59926ef990db3189e8565ae3f7&quot;,&quot;result&quot;:&quot;hit&quot;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-3]   💬  ::debug::Archive Path: /tmp/71f659f3-b296-414e-a049-7495a8b9fd5e/cache.tzst&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-3]   💬  ::debug::Use Azure SDK: true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-3]   💬  ::debug::Download concurrency: 8&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-3]   💬  ::debug::Request timeout (ms): 30000&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-3]   💬  ::debug::Cache segment download timeout mins env var: undefined&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-3]   💬  ::debug::Segment download timeout (ms): 3600000&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;| Cache Size: ~39 MB (40876809 B)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;| [command]/usr/bin/tar --use-compress-program unzstd -xf /tmp/71f659f3-b296-414e-a049-7495a8b9fd5e/cache.tzst -P -C /Users/ikuma/src/github.com/IkumaTadokoro/forke&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;| Cache restored successfully&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;| Cache restored from key: node-cache-linux-npm-eb3cb123726e2245d1ac05822a0ed4f5b7ab0e59926ef990db3189e8565ae3f7&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-3]   ❓ add-matcher /run/act/actions/actions-setup-node@v3/.github/tsc.json&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-3]   ❓ add-matcher /run/act/actions/actions-setup-node@v3/.github/eslint-stylish.json&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-3]   ❓ add-matcher /run/act/actions/actions-setup-node@v3/.github/eslint-compact.json&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-3]   ✅  Success - Main Use Node.js 20.x&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-3]   ⚙  ::set-env:: NPM_CONFIG_USERCONFIG=/tmp/.npmrc&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-3]   ⚙  ::set-env:: NODE_AUTH_TOKEN=XXXXX-XXXXX-XXXXX-XXXXX&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-3]   ⚙  ::set-output:: node-version=v20.1.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-3]   ⚙  ::set-output:: cache-hit=true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-3]   ⚙  ::add-path:: /opt/hostedtoolcache/node/20.1.0/arm64/bin&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-3] ⭐ Run Main Install&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Test/test-3]   🐳  docker exec cmd=[bash --noprofile --norc -e -o pipefail /var/run/act/workflow/2] user= workdir=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;毎回この量が出るのはしんどいので、これを&lt;code&gt;-q, --quiet&lt;/code&gt;オプションで抑制します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$ act -j test -q&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;…が、期待通りにはなりませんでした。この&lt;code&gt;--quiet&lt;/code&gt;オプションはワークフロー側のログ出力レベルを抑制するもので、今回のワークフローの例で言えば、vitest の実装結果が省略されることになります。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;ログ出力の多さゆえに使えないということはないですが、このツールは試行錯誤中に利用したいものだと思うので、デバッグ用の情報はシンプルな方が嬉しい気がします。
それを加味してもローカルで検証できることで GitHub への push 回数は抑制できると思うので、しかるべきときに使っていきたいですね。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>ワークスペース内の画像のパスをパンッとはれるVSCode拡張をリリースした</title><link>https://ikuma-t.com/blog/publish-srcpan/</link><guid isPermaLink="true">https://ikuma-t.com/blog/publish-srcpan/</guid><description>はじめにワークスペースにある画像のパスをそのままorMarkdown形式でパンッと簡単にエディタに挿入できるVSCode拡張、その名もSrcPanをリリースしました。https://marketpla</description><pubDate>Sat, 06 May 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#はじめに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;はじめに&lt;/h2&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;ワークスペースにある画像のパスをそのまま or Markdown 形式で パンッ と簡単にエディタに挿入できる VSCode 拡張、その名も SrcPan をリリースしました。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=IkumaTadokoro.srcpan&quot; target=&quot;_blank&quot;&gt;https://marketplace.visualstudio.com/items?itemName=IkumaTadokoro.srcpan&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;この VSCode 拡張機能には現時点で以下の機能があります。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ワークスペース内の画像ファイルをサイドバーに一覧表示する機能&lt;/li&gt;
&lt;li&gt;選択した画像をサイドバーでプレビュー表示する機能&lt;/li&gt;
&lt;li&gt;選択した画像のパスをそのまま or Markdown 形式でエディタに挿入する機能&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;&lt;a href=&quot;#なぜ作ったか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;なぜ作ったか&lt;/h2&gt;
&lt;p&gt;このブログは各記事を MDX で作成しています。記事には画像をしばしば挿入しているのですが、これに際して私が感じていた課題点は以下の 2 点です。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ブログコンテンツとブログ自体のコードが 1 つのリポジトリに共存しているため、画像以外のものがファイルエクスプローラーに表示されてしまい、画像を探すのが面倒である&lt;/li&gt;
&lt;li&gt;astro では静的コンテンツのパスは「public」を省略して記述するルールだが、しばしば忘れる&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;これを解決するために、最初に述べたような「画像だけを一覧して、プレビューした上で、Markdown のパスですぐ挿入できる」VSCode 拡張を作りました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#何ができるのか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;何ができるのか&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#基本機能&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;基本機能&lt;/h3&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;拡張機能をアクティビティバーで選択すると、2 つのペインが開きます。&lt;/p&gt;
&lt;p&gt;上部は現在開いてるワークスペースに含まれる画像を、ディレクトリ構造そのままに表示するペインです。そして下部がプレビュー表示ペインで、上部で選択した画像をプレビュー表示します。&lt;/p&gt;
&lt;p&gt;上部のペインで画像をホバーすると、リンク挿入ボタンが表示されます。このボタンをクリックすると、画像のパスをそのまま or Markdown 形式でエディタに挿入します。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#設定挿入するパスのフォーマット変更&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;【設定】挿入するパスのフォーマット変更&lt;/h3&gt;
&lt;p&gt;デフォルトでは、画像のパスをそのまま挿入します。しかし、astro では静的コンテンツのパスは「public」を省略して記述するルールなので、そのディレクトリにある画像だけは、最初のパス部分を省略した形式で挿入したいという要望がありました。
これに対応するため、正規表現でフォーマットを変更したいパスと、変更後のパス形式を指定すると、その形式でパスを挿入できるようにしました。&lt;/p&gt;
&lt;p&gt;例えばこのブログでは先のとおり astro のルールに合わせて「public」から始まるディレクトリでは、その一つ下の階層からのパスを貼り付けるようにしたいです。そこで、settings.json に以下のように設定します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;srcpan.pathFormatRules&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;pathRegExp&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;^\\/public(\\/.+)$&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;replacement&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;$1&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;pathRegExp には正規表現を指定することができ、replacement には任意の文字列を指定することができます。pathRegExp にキャプチャグループを指定した場合は、replacement に&lt;code&gt;$1&lt;/code&gt;のように指定することで、キャプチャされた部分を挿入することができます。
この設定により以下のように、&lt;code&gt;/public&lt;/code&gt;から始まるパスでは、&lt;code&gt;/public&lt;/code&gt;の 1 つ下の階層から始まるパスを挿入できるようになりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;本来のパス： &lt;code&gt;/public./srcpan-view.png&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;挿入されるパス： &lt;code&gt;./srcpan-view.png&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;このルールは配列形式で指定するので、複数のルールを指定することができます。public ディレクトリ、assets ディレクトリでそれぞれ最初の階層を省略したい場合は以下のようにします。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;srcpan.pathFormatRules&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;pathRegExp&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;^\\/public(\\/.+)$&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;replacement&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;$1&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;pathRegExp&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;^\\/assets(\\/.+)$&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;replacement&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;$1&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#設定一覧から除外するディレクトリを指定&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;【設定】一覧から除外するディレクトリを指定&lt;/h3&gt;
&lt;p&gt;デフォルトではワークスペースに含まれる&lt;code&gt;.gitignore&lt;/code&gt;を読み取り、そこに含まれるディレクトリは表示から除外するようになっています（これ自体も設定: useGitIgnore を false にすることで無効化できます）。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// 無効にする場合&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;srcpan.useGitIgnore&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;.gitignore にはないが、一覧に表示する必要ないディレクトリがある場合は、追加で設定を記述することで対象外とすることができます。
例えばこのブログでは&lt;code&gt;public&lt;/code&gt;以外は記事を作成する際に不要です。そのため、src/, integrations/ それぞれのディレクトリを除外するように設定します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;srcpan.excludePatterns&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;src/**/*&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;integrations/**/*&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;ややこしいですが、こちらは glob パターンを配列で指定します。本当はいずれのオプションとも正規表現か glob パターンのどちらかに寄せようと考えていたんですが、パスの方は置換後の文字列を宣言的にかけた方が良いと思い正規表現を採用し、除外するディレクトリの方は glob パターンで指定する方が一般的だと思い glob パターンを採用しました 😅。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#今後の改修予定&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;今後の改修予定&lt;/h2&gt;
&lt;p&gt;現時点では必要最低限の機能（README もろくに書いてない）しか実装していないのですが、今後は以下のような機能を追加していきたいと考えています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#ファイルのアップロード更新機能&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ファイルのアップロード・更新機能&lt;/h3&gt;
&lt;p&gt;現在のファイルツリーは、変更・更新・削除に追随して更新されるようにはなっているのですが、あくまでファイルの更新はエクスプローラーから実施する必要があります。&lt;/p&gt;
&lt;p&gt;一応回避策として、下図のように SrcPan をエクスプローラーに D&amp;amp;D してドッキングすることで一つのサイドバーで完結させることができるのですが、サイドバーの表示領域が窮屈なのでどうにかしたいところです。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#ディレクトリの絞り込み&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ディレクトリの絞り込み&lt;/h3&gt;
&lt;p&gt;特定のディレクトリの画像のみ表示しているとはいえ、ファイル数が多いとそれでも探すのが大変です。そこで、ディレクトリを絞り込む機能を追加したいと考えています。
1 つの記事を書いている際に参照するディレクトリはせいぜい 1 つなので、記事名を入力して絞り込むか、現在開いているファイル名で絞り込む、みたいな機能があるといいかもです。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#プレーン形式と-markdown-以外の形式でのパス挿入&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;プレーン形式と Markdown 以外の形式でのパス挿入&lt;/h3&gt;
&lt;p&gt;これは今後自分の中で需要がどれだけ出てくるかにもよるのですが、import 文と HTML の img タグの形式でパスを挿入する機能があると便利かもしれないな〜と思っています。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;今回初めて VSCode 拡張機能を作ってみたんですが、環境構築が結構簡単で、API も多く想像よりも簡単に実装できました。
パッケージ公開のための&lt;code&gt;vsce&lt;/code&gt;コマンドで&lt;code&gt;*.vsix&lt;/code&gt;ファイルを作ってしまえば、開発チーム内でのみ使用する Extension を作成することができ、チーム内の DX 向上の選択肢が増えたのは大きいですね。&lt;/p&gt;
&lt;p&gt;今回作成した Extension は、&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=IkumaTadokoro.srcpan&quot; target=&quot;_blank&quot;&gt;こちら&lt;/a&gt;からインストールできます。ぜひお試しください。
README 含めてまだまだ整備できていないので、徐々に改善していきたいと思います（機能要望、バグ等あれば GitHub の Issue へどうぞ）！&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#余談名前&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;余談：名前&lt;/h2&gt;
&lt;p&gt;「img の src をパンッと挿入できる」と「ソースパン（フライパン）」を掛けて「SrcPan」と名付けました。音優先でソースパン →「パンッと貼り付けられる」とこじつけましたが、たぶんこの擬音は「パンッ」ではなく、「シュッ」な気がしています 😅。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>VSCode拡張、GistPadを試してみた</title><link>https://ikuma-t.com/blog/try-gist-pad/</link><guid isPermaLink="true">https://ikuma-t.com/blog/try-gist-pad/</guid><description>GistPadが便利というTweetを見かけたので、自分も導入してみました。概要https://marketplace.visualstudio.com/items?itemName=vsls-con</description><pubDate>Thu, 04 May 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;/p&gt;
&lt;p&gt;GistPad が便利という Tweet を見かけたので、自分も導入してみました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#概要&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;概要&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=vsls-contrib.gistfs&quot; target=&quot;_blank&quot;&gt;https://marketplace.visualstudio.com/items?itemName=vsls-contrib.gistfs&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;GistPad は、お気に入りのエディタで快適に GitHub の Gist やリポジトリを編集できる Visual Studio Code の拡張機能です。Gist やリポジトリを開く、作成する、削除する、フォークする、スターを付けることができ、クローン、プッシュ、プルすることなく、まるでローカルにあるかのようにシームレスにファイルの編集を開始することができます。コードスニペット、よく使われる設定やスクリプト、プログラミング関連のメモ、ナレッジベース、インタラクティブなサンプルなどを構築し、参照するためのあなただけの開発者ライブラリのようなものです。 - マーケットプレイス紹介文を DeepL で翻訳&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;&lt;a href=&quot;#導入&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;導入&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;VSCode に GistPad をインストール&lt;/li&gt;
&lt;li&gt;アクティビティーバーの GistPad をクリック&lt;/li&gt;
&lt;li&gt;GitHub にログイン&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;これで自分が作成した Gist の一覧が見られるようになります（鍵付きのものは Secret Gist。鍵がついているけど別に見られて困るものではないのでそのままスクショ掲載しています）。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#気になった機能scratch-notes&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;気になった機能：Scratch Notes&lt;/h2&gt;
&lt;p&gt;表題の決まった Gist とは別に、メモを取るための Gist を作成できる機能が備わっている。デフォルトでは Markdown が生成され、そこに自由にメモができる。&lt;/p&gt;
&lt;p&gt;内部的には Secret Gist が生成されているだけですが、削除・生成を GistPad 側でやってくれるので、気軽にメモができるというメリットがあります。
開発時のちょっとしたメモを取りたいときに使えるかなあと思ったけど、Secret Gist はリンクがわかれば誰でも見れるので、業務用のメモには使えないですね〜。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;上述のように業務の開発時の TODO メモ等には使いにくいですが、個人的な開発のメモや、コードスニペット管理には使えそうです。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>zshrcが吹き飛んだので、修復ついでに色々整理する</title><link>https://ikuma-t.com/blog/restart-shell/</link><guid isPermaLink="true">https://ikuma-t.com/blog/restart-shell/</guid><description>雑に作業しすぎてzshrcは吹っ飛んだし、雑に管理してたので復帰できなかった昨日GitHubCopilotforCLIの順番待ちがようやくまわってきたので設定を.zshrcに追加したんですが、雑にやり</description><pubDate>Sat, 15 Apr 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#雑に作業しすぎて-zshrc-は吹っ飛んだし雑に管理してたので復帰できなかった&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;雑に作業しすぎて zshrc は吹っ飛んだし、雑に管理してたので復帰できなかった&lt;/h2&gt;
&lt;p&gt;昨日 GitHub Copilot for CLI の順番待ちがようやくまわってきたので設定を.zshrc に追加したんですが、雑にやりすぎて完全に上書きしていました（シェルの再起動をしていなかったので、事態を把握するまでに少し時間がかかった）。&lt;/p&gt;
&lt;p&gt;幸い吹っ飛んだのは.zshrc だけで、エイリアス等を書いている別の config は無事だったため、そこまで被害は出なかったのですが、これを機にちゃんと dotfiles もコミットしておこう&amp;amp; ついでに色々シェルを整理しようと思ったので、やったことをまとめておきます。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#chezmoi-への反映を簡易化する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;chezmoi への反映を簡易化する&lt;/h2&gt;
&lt;p&gt;もともと dotfiles の管理には&lt;a href=&quot;https://www.chezmoi.io/&quot; target=&quot;_blank&quot;&gt;chezmoi&lt;/a&gt;を使っていたのですが、.zshrc を直接更新した際に、これをどう chezmoi 側のコピーに反映するかがよくわからず、ほったらかしにしていました。&lt;/p&gt;
&lt;p&gt;直接更新してしまった場合は、&lt;code&gt;chezmoi add&lt;/code&gt;で現在のファイルの内容をそのまま chezmoi 管理下に追加するか、&lt;code&gt;chezmoi merge&lt;/code&gt;で chezmoi 管理下のファイルと現在のファイルをマージするかを選ぶことができます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;chezmoi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/.zshrc&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# or&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;chezmoi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;merge&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/.zshrc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# デフォルトではvimdiffが開く&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;上記は直接編集してしまった場合ですが、基本的には chezmoi 管理下のファイルを更新して apply するのが正しいので、以下手順で反映させます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;chezmoi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;edit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/.zshrc&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;chezmoi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/.zshrc&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;source&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;~/.zshrc&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;ただ毎度これをやるのは面倒臭いので、シェルスクリプト化しておきます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# moi ~/.zshrc のように呼び出すことで、対象のファイルをchezmoi管理下に追加してapplyし、現在のシェルにも反映する&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;moi&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; target_file&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;$1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;chezmoi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;edit&lt;/span&gt;&lt;span&gt; $target_file &lt;/span&gt;&lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;chezmoi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;span&gt; $target_file &lt;/span&gt;&lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;source&lt;/span&gt;&lt;span&gt; $target_file&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;chezmoi には変更を自動でコミット、push する機能もありますが、一応公開リポジトリとしているので自動ではなく手動で管理する方針にしました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#rust-製の-cli-ツールを追加でいくつか入れる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Rust 製の CLI ツールを追加でいくつか入れる&lt;/h2&gt;
&lt;p&gt;もともと&lt;a href=&quot;https://github.com/ajeetdsouza/zoxide&quot; target=&quot;_blank&quot;&gt;zoxide&lt;/a&gt;は入れていたんですが、せっかくなので、いくつかの Rust 製の CLI ツールを入れてみました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/sharkdp/fd&quot; target=&quot;_blank&quot;&gt;fd&lt;/a&gt;: find コマンドの代替&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/lsd-rs/lsd&quot; target=&quot;_blank&quot;&gt;lsd&lt;/a&gt;: ls コマンドの代替
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ls&lt;/code&gt;を割り当てました。アイコンが表示されるので見やすいです。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/dandavison/delta&quot; target=&quot;_blank&quot;&gt;delta&lt;/a&gt;: git diff を見やすくする
&lt;ul&gt;
&lt;li&gt;side-by-side で表示されるので、見やすいです。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#おわり&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわり&lt;/h2&gt;
&lt;p&gt;あれ、意外と整理することなかったな？と思いつつ、今回はここまでです。
chezmoi の作成するファイルが結局どういう体系になっているかがよくわからないので、またわかったら追記します。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>このブログのRSSフィードを配信できるようにした</title><link>https://ikuma-t.com/blog/create-rss/</link><guid isPermaLink="true">https://ikuma-t.com/blog/create-rss/</guid><description>はじめにRSSフィードを配信できるようにしました。https://ikuma-t.com/feed.xmlからご購読いただけます。RemixでのRSSフィードの作り方PRはこちらです。https://</description><pubDate>Wed, 15 Mar 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#はじめに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;はじめに&lt;/h2&gt;
&lt;p&gt;RSSフィードを配信できるようにしました。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.com/feed.xml&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.com/feed.xml&lt;/a&gt; からご購読いただけます。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#remixでのrssフィードの作り方&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;RemixでのRSSフィードの作り方&lt;/h2&gt;
&lt;p&gt;PRはこちらです。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/IkumaTadokoro/site/pull/25/files&quot; target=&quot;_blank&quot;&gt;https://github.com/IkumaTadokoro/site/pull/25/files&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;もうPR以上に説明することもないのですが、やっていることとしては以下の2つになります。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;routes/feed[.]xml.tsx&lt;/code&gt;を作成して、&lt;code&gt;/feed.xml&lt;/code&gt;のコンテンツを作成する&lt;/li&gt;
&lt;li&gt;RSSフィードを配信するloaderを実装する&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;解説することがなさすぎて、秒でおわりにまでたどり着いてしまいました。&lt;/p&gt;
&lt;p&gt;最後にあらためましてチャンネル登録・高評価お願いいたします！&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.com/feed.xml&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.com/feed.xml&lt;/a&gt;&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>登壇資料を掲載するTalksページを作った</title><link>https://ikuma-t.com/blog/create-talks/</link><guid isPermaLink="true">https://ikuma-t.com/blog/create-talks/</guid><description>Talksページを開設したhttps://ikuma-t.com/talksこのブログに登壇資料を一覧できるページを作成してみました（追加が終わってないので、まだ全部の資料はないです。順次追加します）</description><pubDate>Sun, 12 Feb 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#talks-ページを開設した&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Talks ページを開設した&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.com/talks&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.com/talks&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;このブログに登壇資料を一覧できるページを作成してみました（追加が終わってないので、まだ全部の資料はないです。順次追加します）。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#作った経緯&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;作った経緯&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;個人サイトのコンテンツがブログだけってのはなあ…と思ったから&lt;/li&gt;
&lt;li&gt;登壇の記事を書くほどでもないけどって時に、雑にメモをかける場所が欲しかったから&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;LT とか小規模な登壇って、もう資料に載っていることがほぼすべてだからわざわざブログに書くほどでもないことが結構あるんですよね。&lt;/p&gt;
&lt;p&gt;一方でちょっとした経緯とかゆるい感想くらいは備忘として残したいなあと思ったりしていました。&lt;/p&gt;
&lt;p&gt;個人サイトのコンテンツに個人の発表を載せるのは至極当然であろうということで、登壇の一覧+ちょいメモできるようなページを作ってみた感じです 🤙&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#お気に入りポイント&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;お気に入りポイント&lt;/h2&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;特にメモを追記していない場合は、でっかい表紙画像と一言だけが表示され、ちょっと美術品ぽいです。&lt;/p&gt;
&lt;p&gt;最近は頑張って効率化に努めているのでスライドの傾向も似通ってきていますが、基本的に同じデザインだとすぐ飽きる人間なので、そのときどきでころころ変わるスライドの傾向を眺めつつ、ちょっとした一言を眺められるこのテイストが気に入っています。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#そろそろまた登壇しよう&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;そろそろまた登壇しよう&lt;/h2&gt;
&lt;p&gt;最近 Slidev で高速にいい感じのスライドを作るためにテンプレートを整備していて、一通りできた（つもり）ので、また今年も外部の勉強会で登壇していきたいです。なんかいい感じのフロントエンドの勉強会あったら教えてください 🙏。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>ikuma-t.workからikuma-t.comへ移管</title><link>https://ikuma-t.com/blog/transfer-domain/</link><guid isPermaLink="true">https://ikuma-t.com/blog/transfer-domain/</guid><description>はじめにプログラミング勉強し始めて1ヶ月くらいの時に初めてお名前.comでドメインを取得し（ikuma-t.work）、それ以降めんどくさくてずっとお名前.comのまま使っていました。取得した当初も思</description><pubDate>Sat, 04 Feb 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#はじめに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;はじめに&lt;/h2&gt;
&lt;p&gt;プログラミング勉強し始めて 1 ヶ月くらいの時に初めてお名前.com でドメインを取得し（ikuma-t.work）、それ以降めんどくさくてずっとお名前.com のまま使っていました。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;取得した当初も思っていましたが、やはり UX が個人的には辛過ぎる（何か操作しようとするたびに出てくる、やりたい操作から遠ざけようとするモーダルとか）ので、ドメインの更新期限催促が来たこのタイミングで Google Domains に移管することにしました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#work-は-google-domains-でサポート対象外&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.work は Google Domains でサポート対象外&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://zenn.dev/yoo/articles/8e82b0893f7417263d1c&quot; target=&quot;_blank&quot;&gt;お名前.com から Google Domains にドメイン移管する&lt;/a&gt;に則って進めていたのですが、「.work」がサポートされていない…&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://support.google.com/domains/answer/6010092?hl=ja#zippy=%2C%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E6%9C%AB%E5%B0%BE%E3%81%AE%E4%BE%A1%E6%A0%BC&quot; target=&quot;_blank&quot;&gt;料金とサポート対象のドメイン末尾 - Google Domains ヘルプ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ikuma-t.works は取れるんですけど、年間 ¥3,500 するので却下です。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#ikuma-tworkikuma-tcom&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ikuma-t.work→ikuma-t.com&lt;/h2&gt;
&lt;p&gt;というわけで安いドメインを探していたら、ふつうに ikuma-t.com が転がっていたので、これを購入しました。はじめてドメイン買った時、めっちゃ高くて ikuma-t.work にした気がするんですが、今見たらほぼ変わらなかった…。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#vercel-側の設定&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Vercel 側の設定&lt;/h3&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;設定 &amp;gt; domains &amp;gt; ikuma-t.com を新規追加&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;Google Domains 側にも設定&lt;/p&gt;
&lt;p&gt;5 分くらいで反映完了です。ikuma-t.com でアクセスできるようになったら、Vercel 側の ikuma-t.work の設定は消しておきます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#お名前com-の削除&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;お名前.com の削除&lt;/h3&gt;
&lt;p&gt;更新期限が迫っていたのですが、登録していたクレジットカードの有効期限切れで情報が変わったため、自動更新ができていない状態でした（自動更新されていたら乗り換えようと思わなかったかもなのでナイス）。メールはめっちゃ来てるけど…。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;というわけで、自動更新さえ停止してしまえばお片付け終了です。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#サイトの更新&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;サイトの更新&lt;/h3&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;サイト内に「ikuma-t.work」と書いている箇所が結構あったので、これを置換します。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;ページタイトル等も忘れずに変更しておきます。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;以上で&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;2020 年から使っていた ikuma-t.work も連載終了です。これからは ikuma-t.com をよろしくお願いします！&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Renovateを導入してみる</title><link>https://ikuma-t.com/blog/introduce-renovate/</link><guid isPermaLink="true">https://ikuma-t.com/blog/introduce-renovate/</guid><description>はじめに：継続ライブラリアップデートのために…脆弱性が検知されたり、ちょっと開発環境を改善したい、となってnpmパッケージをいざバージョンアップしようと思っても、日常的にアップデートをしていないと期待</description><pubDate>Sat, 28 Jan 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#はじめに継続ライブラリアップデートのために&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;はじめに：継続ライブラリアップデートのために…&lt;/h2&gt;
&lt;p&gt;脆弱性が検知されたり、ちょっと開発環境を改善したい、となって npm パッケージをいざバージョンアップしようと思っても、日常的にアップデートをしていないと期待するバージョンにアップするまでが茨の道デス（諦めたくなることもしばしば）。&lt;/p&gt;
&lt;p&gt;dependabot はよく見かけるんですが、最近ではどうも Renovate がいいぞという記事をよく目にするので、今回は Renovate をこのブログのリポジトリに導入してみようと思い、色々と設定を調べてみました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#renovate-の導入&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Renovate の導入&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#github-apps-のインストール&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;GitHub Apps のインストール&lt;/h3&gt;
&lt;p&gt;GitHub Apps として公開されているので、以下のリンクから Install します。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/marketplace/renovate&quot; target=&quot;_blank&quot;&gt;https://github.com/marketplace/renovate&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;必要な項目を入力して、Save。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;Complete order and begin installation とかあるので、クリックして進みます。スクショ忘れましたが、このあと導入先のリポジトリの選択が求められるので、対象のリポジトリを指定します。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#configure-renovate&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Configure Renovate&lt;/h3&gt;
&lt;p&gt;Renovate をインストールしたリポジトリに対して、自動で Renovate 設定のための PR が立ち上がります。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;これをマージすると、renovate.json という設定ファイルが作成され、Renovate によるライブラリアップデートが開始されます（PR が作成されるようになる）。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#renovate-の設定&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;renovate の設定&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#デフォルトの設定&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;デフォルトの設定&lt;/h3&gt;
&lt;p&gt;作成された renovate.json は以下のようになっています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;$schema&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;https://docs.renovatebot.com/renovate-schema.json&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;extends&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;config:base&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;$schema は JSON の定義なのでさておき、extends というプロパティがあります。これは Renovate やサードパーティ・ローカルが公開したプリセットを読み込むためのものです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.renovatebot.com/configuration-options/#extends&quot; target=&quot;_blank&quot;&gt;Configuration Options - Renovate Docs | Renovate Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.renovatebot.com/config-presets/&quot; target=&quot;_blank&quot;&gt;Shareable Config Presets - Renovate Docs | Renovate Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.renovatebot.com/presets-config/#configbase&quot; target=&quot;_blank&quot;&gt;Full Config Presets - Renovate Docs | Renovate Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;config&lt;/p&gt;&lt;div&gt;&lt;/div&gt; は renovate が提供しているプリセットであり、具体的には以下の内容が適用されています。&lt;p&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;extends&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;:dependencyDashboard&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;// GitHub Issueとしてrenovateのダッシュボードを作成する。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;:semanticPrefixFixDepsChoreOthers&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;// semantic commit messageを見つけたときに、依存関係のあるコミットにはfix、それ以外のコミットにはchoreでコミットする&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;:ignoreModulesAndTests&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;// node_modules, bower_components, vendorとテスト関連のフォルダ（/__tests__/**とか）を無視する&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;:autodetectRangeStrategy&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;// アップデート可能なバージョンの範囲に関する設定をautoにする。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;:prHourlyLimit2&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;// 1時間に作成できるPRの数を2つに制限する&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;:prConcurrentLimit10&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;// 同時にOpen可能なPR数を10個に制限する&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;group:monorepos&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;// 有名なmonorepo構成のパッケージのアップデートを1つのPRにまとめる&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;group:recommended&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;// monorepo以外でよく使われているパッケージ群のアップデートを1つのPRにまとめる&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;workarounds:all&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;// アップデートでよくあるワークグラウンドを一挙に適用する&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;より詳細な説明は下記リンクを参照してください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.renovatebot.com/presets-default/#dependencydashboard&quot; target=&quot;_blank&quot;&gt;https://docs.renovatebot.com/presets-default/#dependencydashboard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.renovatebot.com/presets-default/#semanticprefixfixdepschoreothers&quot; target=&quot;_blank&quot;&gt;https://docs.renovatebot.com/presets-default/#semanticprefixfixdepschoreothers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.renovatebot.com/presets-default/#ignoremodulesandtests&quot; target=&quot;_blank&quot;&gt;https://docs.renovatebot.com/presets-default/#ignoremodulesandtests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.renovatebot.com/presets-default/#autodetectrangestrategy&quot; target=&quot;_blank&quot;&gt;https://docs.renovatebot.com/presets-default/#autodetectrangestrategy&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.renovatebot.com/configuration-options/#rangestrategy&quot; target=&quot;_blank&quot;&gt;https://docs.renovatebot.com/configuration-options/#rangestrategy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.renovatebot.com/presets-default/#prhourlylimit2&quot; target=&quot;_blank&quot;&gt;https://docs.renovatebot.com/presets-default/#prhourlylimit2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.renovatebot.com/presets-default/#prconcurrentlimit10&quot; target=&quot;_blank&quot;&gt;https://docs.renovatebot.com/presets-default/#prconcurrentlimit10&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.renovatebot.com/presets-group/#groupmonorepos&quot; target=&quot;_blank&quot;&gt;https://docs.renovatebot.com/presets-group/#groupmonorepos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.renovatebot.com/presets-group/#grouprecommended&quot; target=&quot;_blank&quot;&gt;https://docs.renovatebot.com/presets-group/#grouprecommended&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.renovatebot.com/presets-workarounds/#workaroundsall&quot; target=&quot;_blank&quot;&gt;https://docs.renovatebot.com/presets-workarounds/#workaroundsall&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#カスタマイズの方針公式-docs-の-key-concepts-を参考にする&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;カスタマイズの方針（公式 Docs の Key concepts を参考にする）&lt;/h3&gt;
&lt;p&gt;ベースとして適用されている設定を把握したところで、設定ファイルを自分のリポジトリに合わせて修正していきます。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#renovate-の-key-concepts&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Renovate の Key concepts&lt;/h4&gt;
&lt;p&gt;ライブラリアップデート方針はチームの状況や言語のエコシステムに依存するので一概にこうとは言えません。そのため、renovate の Docs にある Key concepts を理解し、その上でチームとして必要な設定を行うのが妥当に思えます。&lt;/p&gt;
&lt;p&gt;Key Concepts では次の 5 つのトピックスが紹介されています。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Presets&lt;/li&gt;
&lt;li&gt;Dependency Dashboard&lt;/li&gt;
&lt;li&gt;Pull Requests&lt;/li&gt;
&lt;li&gt;Renovate Scheduling&lt;/li&gt;
&lt;li&gt;Automerge&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Dependency Dashboard はそこまで設定に重要ではないのて、それ以外を見てみます。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#key-concepts-presets&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Key concepts: Presets&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.renovatebot.com/key-concepts/presets/&quot; target=&quot;_blank&quot;&gt;Presets - Renovate Docs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Presets は先ほどの config&lt;/p&gt;&lt;div&gt;&lt;/div&gt; のようなもので、よく使用されるルールをグルーピングしたものです。Presets を使うことで、&lt;p&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;いい感じの設定でボットを動かすことができる&lt;/li&gt;
&lt;li&gt;設定の重複を避けることができる&lt;/li&gt;
&lt;li&gt;他の人と設定を共有しやすくなる（これは Presets を独自に定義することができることから）&lt;/li&gt;
&lt;li&gt;他の誰かの設定を利用し、その上でさらに自分用のルールを拡張しやすくなる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;と記載があります。ESLint でもできるだけ個別適用は避け、既存のルールを利用するのが良いように、&lt;strong&gt;設定の簡易化のために Presets を使用するのが良い&lt;/strong&gt;と感じました。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;具体的には個別のプロパティが表示されている「Configuration &amp;gt; Repository」から設定が必要な値を探すのではなく、「Included Presets」の中から、自分がやりたいことをセットで提供しているルールを適用するのが良さそうです。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#key-concepts-pull-requests&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Key concepts: Pull Requests&lt;/h4&gt;
&lt;p&gt;アップデートの PR をグループしない限りは、PR のタイトルやブランチ名は一意になります。&lt;/p&gt;
&lt;p&gt;アップデートを見送りたいためユーザーが Close した PR があった場合、次回の renovate bot の稼働時にそのブランチ名と PR タイトルから該当のライブラリのアップデートの PR を検索することで状況をチェックし、同一バージョンでのアップデートの PR を再度送らない仕様です。&lt;/p&gt;
&lt;p&gt;ただし「アップデートの PR をグループしない限りは」ということなので、グループ化は例外です。&lt;/p&gt;
&lt;p&gt;例えばすべてのメジャーアップデート以外をまとめるグループ化設定を付与した結果、「All non-major updates」というタイトルでアップデート PR が作成されたとします。もし一度この PR を Close してしまうと、次回以降の PR も「All non-major updates」というタイトルであるがために、renovate は PR を作成しません。&lt;/p&gt;
&lt;p&gt;そのため、設定時にグループ化を行う際には、&lt;strong&gt;そのグループにライブラリアップデートを無視する可能性がないか、グループの粒度は適切かを検討&lt;/strong&gt;した方が良さそうです。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#key-concepts-renovate-scheduling&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Key concepts: Renovate Scheduling&lt;/h4&gt;
&lt;p&gt;カスタマイズの方針がそのまま書いてありました。&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Tell Renovate what timezone you want to use&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;デフォルトでは UTC でスケジュールされているため、ローカルタイムでわかりやすくするには、&lt;strong&gt;チームのタイムゾーンを設定した方が良さそう&lt;/strong&gt;です。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;timezone&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Asia/Tokyo&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Learn about the scheduling syntax&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;renovate のスケジューリングは以下の制約があります&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;最小単位は 1 時間。分単位のスケジュール実行や、正確な時間での粒度をサポートしていない。&lt;/li&gt;
&lt;li&gt;時刻形式は&lt;a href=&quot;https://github.com/breejs/later&quot; target=&quot;_blank&quot;&gt;breejs/later&lt;/a&gt;の形式に則る。
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://breejs.github.io/later/parsers.html#text&quot; target=&quot;_blank&quot;&gt;Parsers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例としてはここら辺が設定できるようです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;every weekend&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;before 5:00am&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[after 10pm, before 5:00am]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[after 10pm every weekday, before 5am every weekday]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;on friday and saturday&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Optional: configure a “in repository schedule”&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;先の制約に基づいて時刻を設定します。例では毎日午前二時と一般的な影響時間外での設定が紹介されています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;schedule&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;before 2am&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;schedule&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;after 10pm every weekday&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;before 5am every weekday&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;every weekend&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;またスケジュール自体にも Presets があるようです。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.renovatebot.com/presets-schedule/&quot; target=&quot;_blank&quot;&gt;Schedule Presets - Renovate Docs | Renovate Docs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;個人的には月初日の午前 3 時以前が起動範囲の schedule&lt;/p&gt;&lt;div&gt;&lt;/div&gt; なんか良さそうな気がしています。&lt;p&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Optional: create packageRules with a custom schedule for specific packages&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;スケジュールは全体に対するものだけではなく、特定のパッケージに対するスケジュールも指定できます。例では aws-sdk のような頻繁に更新されるパッケージだけ週次実行にするサンプルが掲載されています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;packageRules&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;matchPackageNames&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;aws-sdk&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;schedule&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;after 9pm on sunday&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;ライブラリアップデートを自動化して楽にするためのツールがノイズになってしまっては本末転倒なので、&lt;strong&gt;更新頻度が予見できるもの・稼働中に気になったライブラリは、独自スケジュールを設定すると良さそうです。&lt;/strong&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#key-concepts-automerge&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Key concepts: Automerge&lt;/h4&gt;
&lt;p&gt;renovate には CI がとおった PR を自動マージする機能があります。&lt;/p&gt;
&lt;p&gt;ドキュメントでは devDependencies や自動テストがしっかりしている PJ の dependencies であれば自動マージが効果的とありますそりゃそうだ）。&lt;/p&gt;
&lt;p&gt;設定例が上がっていたので抜粋します。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;lockFile のメンテナンスの自動化&lt;/strong&gt;（依存関係は崩さずに、lockFile だけ更新する）。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;lockFileMaintenance&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;enabled&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;automerge&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Linter の自動化&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;packageRules&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;matchDepTypes&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;devDependencies&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;matchPackagePatterns&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;lint&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;prettier&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;automerge&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;非メジャーバージョンの自動化&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;packageRules&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;matchUpdateTypes&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;minor&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;patch&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;matchCurrentVersion&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;!/^0/&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;automerge&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;自動マージはやや怖いですが、&lt;strong&gt;運用の中でチェックが形骸化しているライブラリについては自動マージを検討してもいいかも&lt;/strong&gt;です。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#ここまでのまとめkey-concepts-に合わせた設定方針&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ここまでのまとめ：Key concepts に合わせた設定方針&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;簡易化のため各設定については個別に設定するのではなく、できる限り Presets から選択する。&lt;/li&gt;
&lt;li&gt;ライブラリのグループ化を検討する際は、そのグループにライブラリアップデートを無視する可能性がないか、グループの粒度は適切かを念頭に置く。&lt;/li&gt;
&lt;li&gt;“timezone”でチームのタイムゾーンを指定する。&lt;/li&gt;
&lt;li&gt;更新頻度が予見できるもの・稼働中に気になったライブラリは、独自スケジュールを設定する。&lt;/li&gt;
&lt;li&gt;運用の中でチェックが形骸化しているライブラリについては自動マージを検討してもいいかも。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;&lt;a href=&quot;#カスタマイズの方針個人的にやれた方がいいことが実現できるか確認してみる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;カスタマイズの方針（個人的にやれた方がいいことが実現できるか確認してみる）&lt;/h3&gt;
&lt;p&gt;ここまでは公式の方針に則って汎用的な設定方針を見てきましたが、ここからは実際に個人や仕事で使いたいようなことが実現できるのかを確認していきます。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#生成される-pr-のタイトルを変更したいリリースノートを-pr-タイトルで作成するのでフォーマットタイトル頭にセマンティックコミットメッセージをつけたい&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;生成される PR のタイトルを変更したい。リリースノートを PR タイトルで作成するので、フォーマット（タイトル頭にセマンティックコミットメッセージ）をつけたい。&lt;/h4&gt;
&lt;p&gt;Renovate はベースブランチの直近の 10 件のコミットメッセージを見て、そのリポジトリがセマンティックコミットを採用しているかどうかを判断し、セマンティックコミットがある場合にセマンティックコミットメッセージを採用するようです（おそらくこれが semanticCommits オプションの auto の挙動）。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.renovatebot.com/semantic-commits/&quot; target=&quot;_blank&quot;&gt;Semantic Commit messages - Renovate Docs | Renovate Docs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;PR では Prefix を採用しているが、コミットまではルール化していない場合にはルールが適用されないので、明示的にセマンティックコミットを使うような Presets を指定します。加えて、セマンティックコミットメッセージのスコープも設定することができるので、チームに必要な形式でそれぞれ以下のように設定すると良いでしょう。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// https://docs.renovatebot.com/presets-default/#semanticcommits&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// 結果: chore(deps)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;extends&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;:semanticCommits&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// https://docs.renovatebot.com/presets-default/#semanticcommittypeallarg0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// 結果: ci(deps)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;extends&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;:semanticCommits&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;:semanticCommitTypeAll(ci)&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// https://docs.renovatebot.com/presets-default/#semanticcommittypearg0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// 結果: ci(package)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;extends&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;:semanticCommits&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;:semanticCommitTypeAll(ci)&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;:semanticCommitScope(package)&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// https://docs.renovatebot.com/presets-default/#semanticcommitscopedisabled&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// 結果: ci&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;extends&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;:semanticCommits&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;:semanticCommitTypeAll(ci)&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;:semanticCommitScopeDisabled&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.renovatebot.com/presets-default/#semanticcommits&quot; target=&quot;_blank&quot;&gt;https://docs.renovatebot.com/presets-default/#semanticcommits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;hr /&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;なお commitMessagePrefix や prTitle という指定もあるのですが、前述の通り現状の Renovate が PR タイトルで Close 済みかどうか等を判断しているため、こちらでの設定は推奨されていないようです。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#リポジトリ内のあるフォルダ階層より下だけを対象としたい1-つのリポジトリにフロントエンドとバックエンドが入っていてフロントエンドだけ-renovate-を使用したい&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;リポジトリ内のあるフォルダ階層より下だけを対象としたい。1 つのリポジトリにフロントエンドとバックエンドが入っていて、フロントエンドだけ Renovate を使用したい。&lt;/h4&gt;
&lt;p&gt;config&lt;/p&gt;&lt;div&gt;&lt;/div&gt; を設定することで、node_modules, bower_components, vendor とテスト関連のフォルダ（/&lt;strong&gt;tests&lt;/strong&gt;/**とか）を無視することができますが、リポジトリにあるそれ以外のファイルはすべてアップデートの対象になります。&lt;p&gt;&lt;/p&gt;
&lt;p&gt;ignorePaths を指定することで、無視するパターンを追加することができます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;ignorePaths&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;**/backend/**&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;**/hoge/**&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.renovatebot.com/configuration-options/#ignorepaths&quot; target=&quot;_blank&quot;&gt;https://docs.renovatebot.com/configuration-options/#ignorepaths&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#npm-だけを対象にしたい&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;npm だけを対象にしたい。&lt;/h4&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;extends&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;:onlyNpm&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.renovatebot.com/presets-default/#onlynpm&quot; target=&quot;_blank&quot;&gt;https://docs.renovatebot.com/presets-default/#onlynpm&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#メジャー以外のtypes-は-ci-が通ったらマージしたい&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;メジャー以外の@types は CI が通ったらマージしたい。&lt;/h4&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;packageRules&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;packagePatterns&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;^@types/&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;automerge&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;major&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;automerge&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h4&gt;&lt;a href=&quot;#typescript-はコアすぎるので手動でやりたい&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;TypeScript はコアすぎるので、手動でやりたい。&lt;/h4&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;packageRules&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;excludePackageNames&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;typescript&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.renovatebot.com/configuration-options/#excludepackagenames&quot; target=&quot;_blank&quot;&gt;https://docs.renovatebot.com/configuration-options/#excludepackagenames&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#linter-系は-1-つの-pr-にまとめる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Linter 系は 1 つの PR にまとめる&lt;/h4&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;extends&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;packages:linters&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Presets である”packages&lt;/p&gt;&lt;div&gt;&lt;/div&gt;”が次のようになっています。&lt;p&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;extends&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;packages:emberTemplateLint&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;packages:eslint&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;packages:stylelint&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;packages:tslint&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;matchPackageNames&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;prettier&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;remark-lint&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;standard&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;さらに”packages&lt;/p&gt;&lt;div&gt;&lt;/div&gt;”は以下のようになっています。&lt;p&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;matchPackageNames&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;@types/eslint&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;babel-eslint&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;matchPackagePrefixes&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;@typescript-eslint/&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;eslint&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;TypeScript プロジェクトの場合、ESLint（eslint と@typescript-eslint）と Prettier がカバーできれば良さそうなので、結果として”packages&lt;/p&gt;&lt;div&gt;&lt;/div&gt;”だけの指定で良さそうです。&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.renovatebot.com/presets-packages/#packageslinters&quot; target=&quot;_blank&quot;&gt;https://docs.renovatebot.com/presets-packages/#packageslinters&lt;/a&gt;
&lt;a href=&quot;https://docs.renovatebot.com/presets-packages/#packageseslint&quot; target=&quot;_blank&quot;&gt;https://docs.renovatebot.com/presets-packages/#packageseslint&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#最低-n-人の-approve-が必要でもオートマージできるか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;最低 N 人の Approve が必要でも、オートマージできるか？&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/apps/renovate-approve&quot; target=&quot;_blank&quot;&gt;https://github.com/apps/renovate-approve&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Renovate が提供しているこの Bot を利用することで、最低 1 人の Approve が必要な場合でも自動でマージが可能になるようです。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/apps/renovate-approve-2&quot; target=&quot;_blank&quot;&gt;https://github.com/apps/renovate-approve-2&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;最低 2 人の Approve が必要な場合は、こちらのボットも追加で導入が必要です。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#ラベルをつける&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ラベルをつける&lt;/h4&gt;
&lt;p&gt;デフォルトではラベルは適用されず、labels を指定することで適用されます。あまり差分はありませんが、1~2 個のラベルを指定できる Presets もあります。単純にラベルを付与するだけであればこちらで良いでしょう。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.renovatebot.com/presets-default/#labelarg0&quot; target=&quot;_blank&quot;&gt;https://docs.renovatebot.com/presets-default/#labelarg0&lt;/a&gt;
&lt;a href=&quot;https://docs.renovatebot.com/presets-default/#labelsarg0-arg1&quot; target=&quot;_blank&quot;&gt;https://docs.renovatebot.com/presets-default/#labelsarg0-arg1&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;extends&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;:labels(dependencies, renovate)&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;またラベルはパッケージレベルで付与することもでき、この場合は labels オプションを個別に適用します。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.renovatebot.com/configuration-options/#labels&quot; target=&quot;_blank&quot;&gt;https://docs.renovatebot.com/configuration-options/#labels&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;以下のようにすることで、eslint 系のライブラリである場合は「linting」が適用されます（ラベルルールはマージされず、最後にマッチしたものが適用される）。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;labels&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;dependencies&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;packageRules&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;matchPackagePatterns&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;eslint&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;labels&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;linting&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h4&gt;&lt;a href=&quot;#調べていてへとなったpin&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;調べていて「へ〜」となった、Pin&lt;/h4&gt;
&lt;p&gt;「pin の PR を自動マージ」という設定が何箇所かで出てきて、「pin is 何？」と思っていたんですがこれは npm のバージョン固定の話みたいですね。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://qiita.com/sotarok/items/4ebd4cfedab186355867&quot; target=&quot;_blank&quot;&gt;package.json のチルダ(~) とキャレット(^) - Qiita&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.renovatebot.com/dependency-pinning/&quot; target=&quot;_blank&quot;&gt;https://docs.renovatebot.com/dependency-pinning/&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SemVer で package を指定すると、その範囲でのアップデートが発生する。アップデートによりアプリに動作影響があった場合に、前回値と今回値の中のどれかのバージョンが原因になるが、それを 1 つずつ見ていく必要がある。&lt;/li&gt;
&lt;li&gt;バージョンを固定（Pin）すれば、上記問題は解決する。一方で Renovate を使用していると固定したバージョン以外はすべて PR が作成されるためノイズになる。&lt;/li&gt;
&lt;li&gt;この対応策として Renovate は自動マージを提案する。自動マージに向いているライブラリ/リポジトリの特性は前述の通り。また PR 自動マージでは GitHub の通知がノイズになりうる。これに対しては automergeType を branch に設定すれば、CI が失敗しない限りは PR が作成されずにマージされる。あとは必要に応じてグループ化を行うことも検討されたし。&lt;/li&gt;
&lt;li&gt;.lock ファイルを使用しているのに、なぜ依存関係を固定する必要があるのか？
&lt;ul&gt;
&lt;li&gt;lock ファイルのメリットは複数人での開発時に同じ依存関係をインストールできる点&lt;/li&gt;
&lt;li&gt;yarn upgrade を一括で実行した場合にはどれが開発ソースに対して影響を及ぼすライブラリの変更なのかわからない。&lt;/li&gt;
&lt;li&gt;もちろん手動で一つずつ上げる手もあるけど、固定しておけば、Renovate 側が個別に実行してくれるので「どのパッケージ」の「どのバージョンが壊れたのか」の推測可能性を保ちつつも、より少ない工数でアップデートを行うことができる。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;といいつつも Renovate 自体は”Flexible, so you don’t need to be”というスタンス。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/commitizen/cz-conventional-changelog-default-export/pull/4#issuecomment-358038966&quot; target=&quot;_blank&quot;&gt;https://github.com/commitizen/cz-conventional-changelog-default-export/pull/4#issuecomment-358038966&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;こちらも参照とのこと。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#最終的な-renovatejson&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;最終的な renovate.json&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;$schema&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;https://docs.renovatebot.com/renovate-schema.json&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;extends&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;config:base&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;:timezone(Asia/Tokyo)&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;schedule:monthly&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;:label(renovate)&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;packages:linters&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;:onlyNpm&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;:semanticCommits&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;:semanticCommitTypeAll(task)&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;:semanticCommitScopeDisabled&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;ignorePaths&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;**/backend/**&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;**/hoge/**&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;packageRules&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;packagePatterns&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;^@types/&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;automerge&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;major&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;automerge&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;excludePackageNames&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;typescript&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;まずはこのブログのリポジトリでこの設定で動かしてみて、問題があればまた追記・修正したいと思います。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;dependabot より柔軟、されど設定項目が多いという前評判は確かに,,,という感じでした。
CLI 版を使ってローカルで起動することもできるっぽいので色々実験しつつ、仕事で使っている環境にも入れていきたい所存です。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#参考&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;参考&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.recruit.co.jp/rls/2019-12-10-renovate/&quot; target=&quot;_blank&quot;&gt;Renovate ではじめる依存関係更新の自動化 - Tech Blog - Recruit Engineer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.hatenastaff.com/entry/2020/06/19/113030&quot; target=&quot;_blank&quot;&gt;はてなで使用している Renovate の設定プリセットを公開しました - Hatena Developer Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://zenn.dev/sunadoi/articles/889219ab865583&quot; target=&quot;_blank&quot;&gt;Renovate の導入と半年間の運用の振り返り&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://javascript.plainenglish.io/automate-dependency-updates-by-renovate-not-by-dependabot-6efddd549a3e&quot; target=&quot;_blank&quot;&gt;Automate Dependency Updates With Renovate, Not With Dependabot | JavaScript in Plain English&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.cybozu.io/entry/2021/06/01/080000&quot; target=&quot;_blank&quot;&gt;Renovate による依存関係更新フロー改善ことはじめ - Cybozu Inside Out | サイボウズエンジニアのブログ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.shibayu36.org/entry/2020/11/10/183000&quot; target=&quot;_blank&quot;&gt;Renovate を使ってライブラリアップデートの自動マージ - $shibayu36-&amp;gt;blog;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://zenn.dev/sunadoi/articles/889219ab865583&quot; target=&quot;_blank&quot;&gt;Renovate の導入と半年間の運用の振り返り&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>ikuma-t</author></item><item><title>SJISのファイルをFileReaderで読み込む</title><link>https://ikuma-t.com/blog/file-reader-with-sjis/</link><guid isPermaLink="true">https://ikuma-t.com/blog/file-reader-with-sjis/</guid><description>はじめにSJISの文字コードで表されたテキストファイルをUTF-8として受け取る実装について、ライブラリを使用した実装の記事が多くあります。有名どころだとiconv-liteやEncoding.jsあ</description><pubDate>Fri, 27 Jan 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#はじめに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;はじめに&lt;/h2&gt;
&lt;p&gt;SJIS の文字コードで表されたテキストファイルを UTF-8 として受け取る実装について、ライブラリを使用した実装の記事が多くあります。有名どころだと iconv-lite や Encoding.js あたりでしょうか。&lt;/p&gt;
&lt;p&gt;しかしながら、SJIS to UTF-8 くらいであればブラウザ標準の API で十分対応できたので、この記事で解説します。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#結論&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;結論&lt;/h2&gt;
&lt;p&gt;ブラウザ標準の API で SJIS で表現されたテキストファイルを UTF-8 として受け取るには以下のいずれかの方法を使用する。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;FileReader.readAsText() の第二引数にエンコーディング情報として「sjis」を渡す（reader.readAsText(file, ‘sjis’)）&lt;/li&gt;
&lt;li&gt;ArrayBuffer として読み込んだ内容を、TextDecoder で decode する（decoder.decode(‘sjis’)）&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;&lt;a href=&quot;#ソースコードとデモ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ソースコードとデモ&lt;/h2&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://stackblitz.com/edit/react-ts-3kwzkx?file=App.tsx&quot; target=&quot;_blank&quot;&gt;https://stackblitz.com/edit/react-ts-3kwzkx?file=App.tsx&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#1-filereader-にエンコーディング情報を指定してsjis-を読み込む&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;1. FileReader にエンコーディング情報を指定して、SJIS を読み込む&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#filereader-とは&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;FileReader とは&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/API/FileReader&quot; target=&quot;_blank&quot;&gt;https://developer.mozilla.org/ja/docs/Web/API/FileReader&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;FileReader はブラウザ標準で用意されたオブジェクトで、input タグ（&lt;code&gt;type=&quot;file&quot;&lt;/code&gt;)または DnD で指定したファイルの内容にアクセスできます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// FileReaderのインスタンスを生成する&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;reader&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FileReader&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;reader&lt;/span&gt;&lt;span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;onload&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// ファイル読み込み時のイベントリスナーを指定&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// FileReaderのインスタンスプロパティ result に読み込みを行った結果が格納されている&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; } &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; reader;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;reader&lt;/span&gt;&lt;span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;onerror&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// 読み取りエラー時のイベントリスナーを設定&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// ファイルの読み取りを実行する。正常に動作すれば、reader.onloadが発火する。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;reader&lt;/span&gt;&lt;span&gt;&lt;span&gt;.readAsText&lt;/span&gt;&lt;span&gt;(file);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;その他の使い方は &lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/API/File_API/Using_files_from_web_applications&quot; target=&quot;_blank&quot;&gt;MDN のドキュメント&lt;/a&gt;にまとまっているので割愛します。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#filereader-の-4-種類の読み取りメソッド&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;FileReader の 4 種類の読み取りメソッド&lt;/h3&gt;
&lt;p&gt;FileReader にはファイルの読み込み形式によって 4 種類のインスタンスメソッドが用意されています。各メソッドとそのメソッドを使用した場合に result として取得できる形式は次の通りです。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;readAsArrayBuffer(): ArrayBuffer&lt;/li&gt;
&lt;li&gt;readAsBinaryString(): 生のバイナリデータ&lt;/li&gt;
&lt;li&gt;readAsDataURL(): &lt;code&gt;data:&lt;/code&gt; の URL&lt;/li&gt;
&lt;li&gt;readAsText(): テキスト文字列&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;&lt;a href=&quot;#filereaderreadastext-でエンコーディングを指定する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;FileReader.readAsText でエンコーディングを指定する。&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/API/FileReader/readAsText&quot; target=&quot;_blank&quot;&gt;https://developer.mozilla.org/ja/docs/Web/API/FileReader/readAsText&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;FileReader.readAsText()はデフォルトでは utf-8 でファイル（Blob）を解釈します。そのため、SJIS のテキストファイルをアップロードすると文字化けが発生します。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;UTF-8 以外のエンコーディングの文字列を読み込むために、FileReader.readAsText の第二引数にはエンコーディング文字列を指定することができます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;reader&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FileReader&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;reader&lt;/span&gt;&lt;span&gt;&lt;span&gt;.readAsText&lt;/span&gt;&lt;span&gt;(file&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;sjis&quot;&lt;/span&gt;&lt;span&gt;); &lt;/span&gt;&lt;span&gt;// エンコーディングにSJISを指定&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これで SJIS のファイルでも文字化けせずに表示できるようになりました。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;この方法には一点注意点があり、それは「誤ったエンコーディングで読み取りを行っても、エラーが発生しない」という点です。&lt;/p&gt;
&lt;p&gt;例として先ほど SJIS で読み取るようにした処理を使って、UTF-8 のファイルを読み込んでみると、文字化けが発生します。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;この時、console 等にも警告は出ておらず、正常終了したことになっています。&lt;/p&gt;
&lt;p&gt;そのため FileReader.readAsText にエンコーディングを指定する方法は &lt;strong&gt;「読み取り対象のファイルのエンコーディングが明らかである」&lt;/strong&gt; ときに限り使用すべきです（要件として SJIS しか使わない、別のライブラリを使ってあらかじめエンコーディングを判定しておく、などなど）。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#脱線-filereader-の-promise-化&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;脱線： FileReader の Promise 化&lt;/h3&gt;
&lt;p&gt;FileReader は上述の通りイベントベースの API です。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;reader&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FileReader&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;reader&lt;/span&gt;&lt;span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;onload&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;reader&lt;/span&gt;&lt;span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;onerror&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;そのため、煩雑な処理が読み込み時にあったり、アプリケーションの複数箇所で FileReader を呼ぶ実装があると、コード行数が膨らんだり、処理の分割が難しくなったりします。&lt;/p&gt;
&lt;p&gt;これに対応するために、FileReader 自体を Promise でラップすると取り回しがよくなります。実装例としては次のような感じです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;readFileAsTextAsync&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (file&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;File&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;reader&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FileReader&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;((resolve&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; reject) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;reader&lt;/span&gt;&lt;span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;onload&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;resolve&lt;/span&gt;&lt;span&gt;(&amp;lt;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;reader&lt;/span&gt;&lt;span&gt;.result);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;reader&lt;/span&gt;&lt;span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;onerror&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;reject&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;reader&lt;/span&gt;&lt;span&gt;.error);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;reader&lt;/span&gt;&lt;span&gt;&lt;span&gt;.readAsText&lt;/span&gt;&lt;span&gt;(file);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;ファイルを読み込む関数の中では次のように呼び出します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;getFileContent&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; (inputFile&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;File&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;content&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;readFileAsTextAsync&lt;/span&gt;&lt;span&gt;(inputFile);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// ... ファイルの中身 content を使った処理 ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#脱線-blobtext&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;脱線： Blob.text()&lt;/h3&gt;
&lt;p&gt;上述の Promise 化は FileReader がイベントベースの古い API であることに起因したものですが、そもそも Promise を返す API である Blob.text()があります。FileReader で使用している File オブジェクトは Blob オブジェクトを使用しているので、この text()メソッドも使用できます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;getFileContent&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; (inputFile&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;File&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;content&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inputFile&lt;/span&gt;&lt;span&gt;&lt;span&gt;.text&lt;/span&gt;&lt;span&gt;(); &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// Blob.text()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/API/Blob/text&quot; target=&quot;_blank&quot;&gt;https://developer.mozilla.org/ja/docs/Web/API/Blob/text&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;MDN のドキュメントに差分について記載があるので引用します。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Blob.text() がプロミスを返すのに対し、 FileReader.readAsText() はイベントベースの API です
Blob.text() は常にエンコーディングとして UTF-8 を使用しますが、FileReader.readAsText() は Blob の種類と指定されたエンコーディング名に応じて、異なるエンコーディングを使用することができます&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;単純に Promise 化したいだけであれば、Blob.text()&lt;/li&gt;
&lt;li&gt;今回のようにエンコーディングも指定したい場合は FileReader.readAsText()&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;という使いわけが良さそうです。加えて TypeScript においては、Blob.text()の方が読み込んだ内容の型が string になっているというメリットがあります。&lt;/p&gt;
&lt;p&gt;なにをそんな当たり前のことを、と思うかもしれません。しかしながら FileReader のテキスト読み込み（readAsText）と、実際の読み込み完了時のイベント（onload）は実質的にはつながっているものの、静的には関連性がないため、onload 内で取り扱う FileReader.result は&lt;code&gt;string | ArrayBuffer | null&lt;/code&gt;という型になります（readAsText 以外にも readAsArrayBuffer 等で読み込まれる可能性があるため）。&lt;/p&gt;
&lt;p&gt;そのため&lt;code&gt;resolve(&amp;lt;string&amp;gt;reader.result)&lt;/code&gt;と、アングルブラケット構文による型アサーションを行う必要が出てくるのですが、まず型アサーションを行いたくないのと、as 構文でもない型アサーションがあまり出てこない形式なので尚のこと使いにくいです。&lt;/p&gt;
&lt;p&gt;そのため、個人的には Blob クラスが持っているメソッドを推していきたい派です。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#脱線-filereader-利用終了後のイベントリスナーの破棄&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;脱線： FileReader 　利用終了後のイベントリスナーの破棄&lt;/h3&gt;
&lt;p&gt;MDN のドキュメントの中では、&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;FileReader が使用されなくなったら、メモリーリークを防ぐために removeEventListener() でイベントリスナーを取り外してください。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;とありますが、今回の例では不要です。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://stackoverflow.com/questions/56497788/do-i-need-to-remove-event-listeners-for-filereader-after-im-done-with-it&quot; target=&quot;_blank&quot;&gt;https://stackoverflow.com/questions/56497788/do-i-need-to-remove-event-listeners-for-filereader-after-im-done-with-it&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;イベント自体が FileReader からしか参照されていなく、なおかつ FileReader 自体は Promise でラップされた関数の中に閉じ込められています。
そのため、そもそもメモリ上に展開されるのが Promise をラップしている関数のみとなり、その関数自体も実行が完了すると GC の対象となるので、イベントリスナーが残り続けることによるメモリリークの可能性はない模様です。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#2-arraybuffer-として読み込んだ情報をtextdecoder-で-decode-する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;2. ArrayBuffer として読み込んだ情報を、TextDecoder で decode する&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#arraybuffer-とは&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ArrayBuffer とは&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer&quot; target=&quot;_blank&quot;&gt;https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;JavaScript で用意されている ArrayBuffer はバイナリオブジェクトのことです。Array と名前にありますが、いわゆる配列っぽいことはできません（添字アクセスできないとか、可変じゃないとか）。&lt;/p&gt;
&lt;p&gt;ArrayBuffer 自体は生のバイナリで、それ自体では何もできません。実際の値を参照するには TypedArray（型付き配列）という view オブジェクトが必要になります。
この TypedArray は Uint8Array とか Uint16Array が具体例で、要は生成されたバイナリをどの倍率で見るかが「Uint8」やら「Uint16」やらで表されています。&lt;/p&gt;
&lt;p&gt;まあ色々とありますが、人間が読みやすいテキストではなくて単純なバイナリデータっていうのが重要です。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#デコード-エンコード&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;デコード？ エンコード？&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;エンコードはデータを他の形式へ変換すること&lt;/li&gt;
&lt;li&gt;デコードはエンコードされたデータを元の形式に戻すこと&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;です。これからやろうとしていることは、「何らかの文字コードで表されたテキストをバイナリの形式で読み込み、それを特定の文字コード（SJIS）のルールで表されたものであるとして、その文字コードの形式にデコードする」です。&lt;/p&gt;
&lt;p&gt;ではデコードはどのように行えば良いでしょうか？&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#textdecoder-とは&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;TextDecoder とは&lt;/h3&gt;
&lt;p&gt;デコードを行うために用意されているクラスが TextDecoder です。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/API/TextDecoder&quot; target=&quot;_blank&quot;&gt;https://developer.mozilla.org/ja/docs/Web/API/TextDecoder&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;TextDecoder のコンストラクターにはデコード方式を渡すことができます。型定義はこんな感じでした。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; TextDecoder&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;label&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;options&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TextDecoderOptions&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TextDecoder&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;label: &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Encoding_API/Encodings&quot; target=&quot;_blank&quot;&gt;有効なエンコーディング&lt;/a&gt;を指定&lt;/li&gt;
&lt;li&gt;options: デコード失敗時の挙動を決める fatal と、ファイルの BOM に関する挙動を決める ignoreBOM がある。fatal については後述。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;「何らかの文字コードで表されたテキストをバイナリの形式で読み込み、それを特定の文字コード（SJIS）のルールで表されたものであるとして、その文字コードの形式にデコードする」&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;label の部分には、SJIS として解釈したければ「“csshiftjis”, “ms_kanji”, “shift-jis”, “shift_jis”, “sjis”, “windows-31j”, “x-sjis”」のいずれかを、UTF-8 として解釈したければ、「“unicode-1-1-utf-8”, “utf-8”, “utf8”」を（もしくはデフォルト値なので何もしていない）それぞれ設定すればいいということになります。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#arraybuffer-として読み込んだ文字列を-textdecoder-で-encode-する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ArrayBuffer として読み込んだ文字列を TextDecoder で encode する&lt;/h3&gt;
&lt;p&gt;さきほどの FileReader の例では FileReader.readAsText でテキストとしてファイルを読み込みましたが、今回は ArrayBuffer としてファイルを読み込みます。&lt;/p&gt;
&lt;p&gt;このとき、FileReader の同様の API である readAsArrayBuffer を使っても良いのですが、Blob.text()同様、Promise ベースの Blob.arrayBuffer()が用意されているので今回はこちらを使用します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;getFileContent&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; (inputFile&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;File&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;buffer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inputFile&lt;/span&gt;&lt;span&gt;&lt;span&gt;.arrayBuffer&lt;/span&gt;&lt;span&gt;(); &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// ArrayBufferとして取得される。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;読み込んだバイナリ文字列を SJIS としてデコードします。デコードするためには、TextDecoder の decode メソッドを利用します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;getFileContent&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; (inputFile&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;File&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;buffer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inputFile&lt;/span&gt;&lt;span&gt;&lt;span&gt;.arrayBuffer&lt;/span&gt;&lt;span&gt;(); &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// ArrayBufferとして取得される。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sjisDecoder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TextDecoder&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;sjis&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sjisDecoder&lt;/span&gt;&lt;span&gt;&lt;span&gt;.decode&lt;/span&gt;&lt;span&gt;(buffer);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#補足-textdecoder-の-fatal-オプション&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;補足： TextDecoder の fatal オプション&lt;/h3&gt;
&lt;p&gt;ここまででの実装では、UTF-8 のファイルを渡した場合に、文字化けが発生します。が、これは本来望ましくない結果ですよね？&lt;/p&gt;
&lt;p&gt;TextDecoder のコンストラクターに指定できる fatal オプションを true にすると、読み込んだバイナリと指定した label が異なるエンコーディングであった場合に、TypeError を起こすことができます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;blobReader&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; (inputFile&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;File&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;buffer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inputFile&lt;/span&gt;&lt;span&gt;&lt;span&gt;.arrayBuffer&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;utf8Decoder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TextDecoder&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;utf-8&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; { fatal&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; });&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sjisDecoder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TextDecoder&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;sjis&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sjisDecoder&lt;/span&gt;&lt;span&gt;&lt;span&gt;.decode&lt;/span&gt;&lt;span&gt;(buffer);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;utf8Decoder&lt;/span&gt;&lt;span&gt;&lt;span&gt;.decode&lt;/span&gt;&lt;span&gt;(buffer);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (e&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;unknown&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (e &lt;/span&gt;&lt;span&gt;instanceof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TypeError&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;throw&lt;/span&gt;&lt;span&gt; e;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;少々ネストは発生しますが、これにより SJIS で読み込めない場合は UTF-8 で読み込む、というような挙動ができます。
もちろん多段 try-catch は厳しくなるので、文字コードを幅広く持つ場合はライブラリ等で文字コードを判定してから処理を行うのが無難でしょう。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;標準でできるなら標準でやるのが一番いいと思うんですよね〜（依存ないし、ファイルサイズ的に軽いし）。
最近の dialog 然り、Web でよくやることはブラウザ側が汲み取って来てくれている印象なので、ライブラリに頼る前に標準でいけないか確認していきたいところです。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Gitでマージをdry-runする</title><link>https://ikuma-t.com/blog/git-merge-dry-run/</link><guid isPermaLink="true">https://ikuma-t.com/blog/git-merge-dry-run/</guid><description>はじめに大きめの作業内容なのでトピックブランチを作っていたのですが、作業内容の大きさゆえに時間がかかってしまい、実際にmainにマージする際に「果たしてこのブランチをマージして、デグレとかしないか？コ</description><pubDate>Fri, 13 Jan 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#はじめに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;はじめに&lt;/h2&gt;
&lt;p&gt;大きめの作業内容なのでトピックブランチを作っていたのですが、作業内容の大きさゆえに時間がかかってしまい、実際に main にマージする際に「果たしてこのブランチをマージして、デグレとかしないか？コンフリクト出てないからたぶん大丈夫だけど…」となりました。&lt;/p&gt;
&lt;p&gt;git merge コマンドの&lt;code&gt;--no-commit&lt;/code&gt;オプションを使用すると、実際に発生する差分をチェックすることができて便利だったのでメモしておきます。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#結論&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;結論&lt;/h2&gt;
&lt;p&gt;ローカルのブランチで&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;git merge --no-commit --no-ff ブランチ名&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;内容に問題なければ&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;git commit&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;すると、マージコミットが作られる（FastForward でも作られるので、こだわりがある場合は以下の abort で中止して、再度 git merge するのが吉）。&lt;/p&gt;
&lt;p&gt;やっぱりこれマージしたらあかんわ、ならば&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;git merge --abort&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これでマージのチェックのために一時的に追加されていたステージングエリアが元に戻る。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;&lt;a href=&quot;#使用しているオプション&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;使用しているオプション&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#no-commit&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;—no-commit&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;マージコミットを作成する直前に停止し、コミット内容を精査するためのオプション&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#no-ff&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;—no-ff&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--ff&lt;/code&gt;だと FastForward。つまり、一直線上にある場合にマージコミットが作成されない。&lt;/li&gt;
&lt;li&gt;その反対でどんな関係にあろうとも、マージコミットを作成するオプション&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#abort&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;—abort&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;マージ作業中の場合に、作業を中断してマージ前の状態に戻すためのオプション&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#参考&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;参考&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://zenn.dev/naopusyu/articles/4b73bed8f8de4c&quot; target=&quot;_blank&quot;&gt;Git マージで dry-run をやってみる&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tracpath.com/docs/git-merge/&quot; target=&quot;_blank&quot;&gt;git-merge – Git コマンドリファレンス（日本語版）&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>ikuma-t</author></item><item><title>scaffdogでブログのテンプレートを作成できるようにした</title><link>https://ikuma-t.com/blog/create-blog-template/</link><guid isPermaLink="true">https://ikuma-t.com/blog/create-blog-template/</guid><description>ブログの執筆コストを下げたいブログを書くハードルを下げたかったので、scaffdogでフロントマターまで入力した状態で作成できるようにしました。このブログはリポジトリ内に蓄えたマークダウンファイルを変</description><pubDate>Tue, 03 Jan 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#ブログの執筆コストを下げたい&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ブログの執筆コストを下げたい&lt;/h2&gt;
&lt;p&gt;ブログを書くハードルを下げたかったので、scaffdog でフロントマターまで入力した状態で作成できるようにしました。&lt;/p&gt;
&lt;p&gt;このブログはリポジトリ内に蓄えたマークダウンファイルを変換して表示しており、メタデータは各ファイルの YAML フロントマターで定義されています。こんな感じですね。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;個人サイトをAstroで作り替えました。&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;もともと Next.js で個人サイトというかブログを作って運用していたのですが、これを Astro に置き換えました。理由としては巷でよく言われているところで、個人ブログ程度には Next.js は too much だったからです。...&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;publishDate&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; 2023-01-03&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;layout&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;@layouts/BlogLayout.astro&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;tags&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;astro&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;で、こういうのは入力が面倒なので、前作のブログではどこからでもブログが作成できるように Deno を使ったオレオレブログ CLI を作成していたのですが、GitHub Codespaces 上で作業を行うことで作業ディレクトリの縛りがなくなったため、今回は scaffdog でやってみました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#scaffdog-の導入&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;scaffdog の導入&lt;/h2&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# インストール&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;scaffdog&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# 初期化（ここではpostという名前でテンプレートを作った）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;npx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;scaffdog&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;init&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;作成されたテンプレートに次のように記載しました。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;post&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;root&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;.&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;output&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;src/pages/blog&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ignore&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;.&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;questions&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;fileName&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;ファイル名&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;タイトル&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;tags&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;タグ（カンマ区切りで複数指定）&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# &lt;/span&gt;&lt;span&gt;`{{ inputs.fileName }}.md`&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;```markdown&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;title: &quot;{{ inputs.title }}&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;description: &quot;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;publishDate: &quot;{{ date(&apos;YYYY-MM-DDTHH:mm:ss&apos;) }}&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;inputs.category }}&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;layout: &quot;@layouts/BlogLayout.astro&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;tags: [{ { inputs.tags } }]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;drafts: true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;## TOC&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;```&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;入れ子になっているのでわかりにくいですが、&lt;code&gt;markdown&lt;/code&gt;のコードブロックで囲まれている部分が自動生成対象です。&lt;/p&gt;
&lt;p&gt;ほとんどの項目はフロントマターで定義した質問の回答（&lt;code&gt;inputs.xxx&lt;/code&gt;）をそのまま埋め込んでいますが、日付だけはビルトインの&lt;code&gt;date&lt;/code&gt;関数で現在日付を設定しています。&lt;/p&gt;
&lt;p&gt;あとは npm scripts として次のようなコマンドを入れてあげれば準備 OK です。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;gen&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;scaffdog generate post&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#動作イメージ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;動作イメージ&lt;/h2&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;npx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;gen&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;ℹ&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Output&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;destination&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;directory:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;src/pages/blog&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; ファイル名 create-blog-template&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; タイトル scaffdogでブログのテンプレートを作成できるようにした&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; カテゴリ ブログ&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; タグ（カンマ区切りで複数指定） scaffdog,blog&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;🐶&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Generated&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;file!&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;✔&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;src/pages/blog/create-blog-template.md&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;Done&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;39.86s.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;hr /&gt;
&lt;p&gt;そんで出来上がったのが、この記事というわけです ✌️&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>個人サイトをAstroで作り替えました。</title><link>https://ikuma-t.com/blog/create-blog-with-astro/</link><guid isPermaLink="true">https://ikuma-t.com/blog/create-blog-with-astro/</guid><description>AstroでリプレイスもともとNext.jsで個人サイトというかブログを作って運用していたのですが、これをAstroに置き換えました。理由としては巷でよく言われているところで、個人ブログ程度にはNex</description><pubDate>Tue, 03 Jan 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#astro-でリプレイス&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Astro でリプレイス&lt;/h2&gt;
&lt;p&gt;もともと Next.js で個人サイトというかブログを作って運用していたのですが、これを Astro に置き換えました。
理由としては巷でよく言われているところで、個人ブログ程度には Next.js は too much だったからです。&lt;/p&gt;
&lt;p&gt;候補としては他に STUDIO を使ってノーコードでやってしまうということも考えていたのですが、やはり個人サイトの運用コストを気にしたくはなく、そうなると CMS がいずれ有料になってしまうのは良くないなと思い、結局自前で実装した次第です。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#astro-での開発体験&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Astro での開発体験&lt;/h2&gt;
&lt;p&gt;めちゃめちゃ快適でした。さすがサイトを作るなら Astro でよくね？と公式で言っているだけありますね。Next.js でやると、地味に Markdown の変換部分でプラグイン選定とかがあったりして面倒だったのが、Astro だと全く意識せずにできるという点がグッジョブでした。&lt;/p&gt;
&lt;p&gt;ざっと公式のドキュメントを読んで…っていうのを数ヶ月前にやり、それらの内容を忘れたお正月休みの 1 日で出来上がるくらいなので、基本的に直感的に開発できたかと思います。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#markdown-コンテンツのスタイリングtailwindcss-typography&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Markdown コンテンツのスタイリング(tailwindcss-typography)&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/tailwindlabs/tailwindcss-typography&quot; target=&quot;_blank&quot;&gt;https://github.com/tailwindlabs/tailwindcss-typography&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;今回使用したテンプレートが Tailwind でスタイルをおこなっているものだったのですが、記事部分に以下のような指定しかなく、はじめは「どうやってスタイリングしているんだろうと思いました。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mx-auto prose prose-lg mt-6&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;slot&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;この&lt;code&gt;prose&lt;/code&gt;というプロパティが肝で、これは tailwindcss-typography というプラグインから提供されているものです。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://tailwindcss.com/docs/typography-plugin&quot; target=&quot;_blank&quot;&gt;https://tailwindcss.com/docs/typography-plugin&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;なんとこれを追加するだけで、HTML 部分のスタイリングをいい感じにやってくれるやつだそうで、上記のコードブロックもこのプラグインがよしなにやってくれています。すげー。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;今後は&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ブログ以外のコンテンツ拡充&lt;/li&gt;
&lt;li&gt;Codespaces を用いて ipad でもサクッと記事を更新可能に&lt;/li&gt;
&lt;li&gt;MDX タイプの記事の作成&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;あたりをやっていけるといいかな〜と思っています。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Kaigi on Rails 2022で登壇しました！</title><link>https://ikuma-t.com/blog/kaigi-on-rails-2022/</link><guid isPermaLink="true">https://ikuma-t.com/blog/kaigi-on-rails-2022/</guid><description>KaigionRails2022で登壇しました！10月21日、22日に開催されたKaigionRails2022にSpeakerとして登壇しました！KaigionRails2022初のカンファレンス登</description><pubDate>Sat, 22 Oct 2022 08:44:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#kaigi-on-rails-2022-で登壇しました&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Kaigi on Rails 2022 で登壇しました！&lt;/h2&gt;
&lt;p&gt;10 月 21 日、22 日に開催された Kaigi on Rails 2022 に Speaker として登壇しました！&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://kaigionrails.org/2022/&quot; target=&quot;_blank&quot;&gt;Kaigi on Rails 2022&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;初のカンファレンス登壇で順番最後、かつギリギリまで準備が終わらず、最後の最後までずっとソワソワして参加者としてはガッツリは参加できなかった（アーカイブ見るぞ）のですが、とてもいい経験ができました！運営の皆さん本当にありがとうございました！&lt;/p&gt;
&lt;p&gt;登壇資料はこちらです！&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.com/talks/64cf9c1bd012c445e444b066&quot; target=&quot;_blank&quot;&gt;登壇資料&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;せっかくなので自分の発表についてつらつらと書いていきたいと思います。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#登壇へのモチベーション&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;登壇へのモチベーション&lt;/h2&gt;
&lt;p&gt;スライドにもあるとおり、FJORD BOOT CAMP での学習期間を経て、今年の 6 月からエンジニアとして働き始めています。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://bootcamp.fjord.jp/&quot; target=&quot;_blank&quot;&gt;FJORD BOOT CAMP&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;で、やっぱりエンジニアになったからにはカンファレンスとか登壇してみたいわけですね。学び初めの時は「地域 rb に顔出すのは上級者」くらいの気持ちだった人がそう思っているのは、完全に FJORD BOOT CAMP にいた影響だと思っています。&lt;/p&gt;
&lt;p&gt;なんか知っている人結構いるし、卒業生の中から RubyKaigi に登壇している人もいるし、じぶんもやってみたい！と自然に思えるようになっていました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#登壇テーマの選定&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;登壇テーマの選定&lt;/h2&gt;
&lt;p&gt;今回はブラウザ自動化技術を登壇テーマに選んだんですが、理由としては 2 つありました。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ブラウザ自動化を便利に使っていたが、その中身はよく知らないままだなと思っていたので、その中身を知りたかった&lt;/li&gt;
&lt;li&gt;もともとブラウザ自体に興味があった&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;1 つ目は発表にあった通りで、2 つ目については Web アプリを作る以上ブラウザに載せることがほとんどなので、そこをちゃんと知りたいなあという思いです。&lt;/p&gt;
&lt;p&gt;昨今では CSS フレームワークとかもよくできているので、見栄え的にはあまり考えなくてもまあまあ綺麗なものができるのですが、でももうちょっとブラウザ自体を知らないとブラウザの真価を発揮したりとかセキュリティ意識したりとかいろんな環境を意識して作るとかできないよなあと。&lt;/p&gt;
&lt;p&gt;動きを把握する時にはやっぱり実際に動きが始まるところから見るのがわかりやすいと思うのですが、ブラウザ自動化は自分が知っている領域でもあり、ブラウザに対するエントリポイント的な位置付けなので、今回はここにフォーカスしようという気持ちもありました。&lt;/p&gt;
&lt;p&gt;近いうちに簡易なレンダリングエンジン実装とかやってみたいですね（Olelink とか OleKit とかですかねえ）&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#準備&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;準備&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#実際に-webdriver-や-cdp-を読んでいく&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;実際に WebDriver や CDP を読んでいく&lt;/h3&gt;
&lt;p&gt;発表ではわりとさっくり「意外とシンプルに接続できる」という流れで紹介していましたが、当然のごとくミリしら状態で仕様を見始めたので、なかなかうまくいかず苦労しました。&lt;/p&gt;
&lt;p&gt;資料の中で「Capabilities」や「WebSocket」が用語で 1 ページとってありますが、これは実際に試している中で「なんだこれ」とか「いまいちわからん」と詰まった箇所です（ActionCable ちゃんと使ったことないのがバレた）。&lt;/p&gt;
&lt;p&gt;例えば WebSocket の接続をする際にも WebSocket 自体の理解が曖昧で、最初は色々と回りくどい方法で URL を取得していたのですが、Ruby の CDP クライアント ferrum のソースを読んでいる中で「あ、サブプロセスで起動した Chrome の標準出力を正規表現で抽出して、WebSocket の URL 取得しているじゃん、これでええやん」と理解し、発表のような説明となりました。先人偉大なり。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/rubycdp/ferrum/blob/efb6f2035c442582e815328e633d1f1d6c97e456/lib/ferrum/browser/process.rb#L99-L102%5D&quot; target=&quot;_blank&quot;&gt;https://github.com/rubycdp/ferrum/blob/efb6f2035c442582e815328e633d1f1d6c97e456/lib/ferrum/browser/process.rb#L99-L102&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;大変といえば大変だったんですが、その分色々と自分が知らない知識も増えて面白かったです。例えば上記箇所だと ObjectSpace.define_finalizer を知ることができました（一人 igaiga ふむふむタイム）。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/igaiga555/status/1569154474060705792&quot; target=&quot;_blank&quot;&gt;https://twitter.com/igaiga555/status/1569154474060705792&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://zenn.dev/igaiga/books/rails-practice-note/viewer/ruby_rails_debugging#objectspace%23finalizer&quot; target=&quot;_blank&quot;&gt;ObjectSpace#finalizer&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#chromedppdlgen-の実装を読むのが大変だった&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;chromedp/pdlgen の実装を読むのが大変だった&lt;/h3&gt;
&lt;p&gt;なにが大変だったって、Go の文法を一切知らない状態から始めたのもあるんですが、chromedp で CDP をパースしているライブラリの最新ブランチが master じゃなくて old だったことなんですよね 😅&lt;/p&gt;
&lt;p&gt;自分のローカルに Clone して chromedp/pdlgen を実行した時に panic になって落ちてしまいました。
Go の知識が乏しく「自分の環境が悪いってことかな」と思って何日か文法調べつつ読んでいき、最終的に一部分岐で落ちていることがわかったため、Issue で報告しようとしたタイミングで同じ事象の Issue があることに気が付き…&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/chromedp/pdlgen/issues/16&quot; target=&quot;_blank&quot;&gt;https://github.com/chromedp/pdlgen/issues/16&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I guess its required to use the old branch?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Yes, the old branch is the latest branch.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;old ブランチにしたら動きました 😅&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#実装olaywright-の実装で頭ごっちゃに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;実装：Olaywright の実装で頭ごっちゃに&lt;/h3&gt;
&lt;p&gt;CFP 提出時点で Olenium は動くものができていたので、上記の調べ物をしたのち、Olaywright の実装に取り掛かりました。&lt;/p&gt;
&lt;p&gt;が、この辺りで「フロントエンドエンジニア」となったため、仕事前には Ruby 書いて業務中は TypeScript だけ書いてて、仕事終わったら Ruby 書いて…となり、地味に大変でした。マジで何回 const で変数定義して、const がなくて怒られたと思っているんだ？（===もめっちゃやったなあ）&lt;/p&gt;
&lt;p&gt;まあそれくらいならまだいいんですが、オブジェクトに対する考え方が完全に JavaScript に引っ張られていたのが一番大変でした。今回の発表では JSON をパースして、Ruby のメソッドとして呼び出せるようにしていましたが、そこです。&lt;/p&gt;
&lt;p&gt;縛りなしで、個人的にもっとも実行しやすいインターフェースを考えると、たとえば Target.createTarget という CDP のメソッドは&lt;code&gt;target.create_target(url: &apos;https://google.com&apos;)&lt;/code&gt;という形で呼べるのが Ruby っぽくかつシンプルで分かりやすいと考えました。&lt;/p&gt;
&lt;p&gt;で、これを静的に定義しておこうと思ったところで頭がこんがらがります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Chrome へのメソッド実行は、実際のところメソッド名をただメッセージに渡すだけ。つまりメソッドの中身がないので、わざわざあらかじめ定義しておく意味があまりない。&lt;/li&gt;
&lt;li&gt;JSON で落ちてきた CDP には、そのメソッドに関する説明が多分に入っており、それをすべて削除するような構造になってしまう。
&lt;code&gt;target.create_target()&lt;/code&gt;がメソッドだとすると、CDP でやってくる「Target.createTarget の説明」や「Target.createTarget は experimental かどうか」といった情報を&lt;code&gt;target.create_target.description&lt;/code&gt;、&lt;code&gt;target.create_target.experimental?&lt;/code&gt;のように持たせるのが難しい（私がわからなかっただけなので、できたらどこかで教えてください〜〜！）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;さらにめんどうなことに&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Go の方読んでたら構造体が出てきてクラスが歪み始める&lt;/li&gt;
&lt;li&gt;一日の大半は TypeScript を書いているので、またまたオブジェクトに対する認知が歪み始める&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;となり、かなりの日数手が止まったあげく最終的には以下のような方針・実装になりました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;やっぱり&lt;code&gt;target.create_target.description&lt;/code&gt;とか&lt;code&gt;target.create_target.experimental?&lt;/code&gt;とか呼び出せると嬉しい（なお boolean を返すメソッドには Ruby ライクに「?」つけたかったのですが、忘れていたので実際のコードではやっていないです。）&lt;/li&gt;
&lt;li&gt;WebSocket へメッセージを送信する部分以外は振る舞いではなく、単なる情報（説明とか実験的機能だとか任意のパラメータだとか）の集まりなので、Struct でいいんでは？&lt;/li&gt;
&lt;li&gt;JS の Function オブジェクト的な感じで格納できればなおのことよかったんだけど、それは Ruby ではできない（？）ので、Struct のプロパティの中で他の情報と並列に&lt;code&gt;exec&lt;/code&gt;というプロパティを保持し、ここに Proc オブジェクトを持たせる形で定義する
&lt;ul&gt;
&lt;li&gt;Sturct のメソッドとして定義すりゃよかったんですが、Olaywright クラスで持っている WebSocket の接続情報のコンテキストを渡すのがさっとできなかったので、呼び出しが Proc の呼び出し（&lt;code&gt;exec[]&lt;/code&gt;）になったわけです。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;愚直によぶと&lt;code&gt;browser.domains.page.navigate.exec[url: &apos;https://google.com&apos;]&lt;/code&gt;のような長さになる。これは嫌だ。&lt;/li&gt;
&lt;li&gt;というわけで最終的に必要な Domain の情報を一行パターンマッチでキャプチャすりゃあええやろ（&lt;code&gt;browser.domains in { page: }&lt;/code&gt;）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://gist.github.com/IkumaTadokoro/26e08130f849c9aac8c4b18a1adc7561&quot; target=&quot;_blank&quot;&gt;https://gist.github.com/IkumaTadokoro/26e08130f849c9aac8c4b18a1adc7561&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;かなり頭の中で考えるのに時間を使ってしまって、ちょっと前髪整えますねくらいのリファクタリングはしたんですが、そこまでで力尽きてインスタンス生成に 3 秒かかるプログラムになりました 💦 どう考えてもループしすぎですね、どうもありがとうございました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#実装gem-使うかどうか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;実装：Gem 使うかどうか&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;String#underscore&lt;/code&gt;を refinement で拡張しているところとか別に ActiveSupport 入れてもよかったんですが、ライブラリ使わないでも Ruby 本体だけで欲しいもの書けるんだ！っていう思いも発表にこめたかったので自前で定義しています（発表では見せませんが）。&lt;/p&gt;
&lt;p&gt;じゃあなんで WebSocket はライブラリを使っているかというと、この Gem の管理を現在やっているのが運営のうなすけさんだったので、何か選考に有利に働いてくれないかなあと思い、CFP の時点でこの Gem を使うということを明記したという経緯でした笑&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://rubygems.org/gems/websocket-client-simple&quot; target=&quot;_blank&quot;&gt;https://rubygems.org/gems/websocket-client-simple&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;名前の通りめちゃくちゃシンプルでコードも読みやすいので、想定聴者がジュニア〜中級くらいのこの発表の筋にもあっている気がして、WebSocket の中でもこの Gem にしたというのもあります。&lt;/p&gt;
&lt;p&gt;websocket-client-simple のコードを読む過程で EventEmitter について知り、一人ターミナルチャットアプリやってました。勉強にはなりましたが寂しかったです。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#なんで-irb-で動かすことにしたの&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;なんで irb で動かすことにしたの？&lt;/h3&gt;
&lt;p&gt;苦肉の策で上記の通り多段 Struct をやった結果、Olenium 同様にスクリプトを書いても全然補完が走らず、これはどうしたものかと思ったところ、「irb 上でインスタンス化した後なら補完走るじゃん！！」と思い立ちこうなりました。いやあ irb 便利。&lt;/p&gt;
&lt;p&gt;ちなみに補完が走る際に、Struct ではセッターの方のメソッドも補完が走ります。これはスクリプトを動かす際には使わないのでどうにか消したかったんですが（freeze はしているけど）やり方わからず断念しました（Struct のサブクラスに対して、&lt;a href=&quot;https://docs.ruby-lang.org/ja/latest/function/remove_method.html&quot; target=&quot;_blank&quot;&gt;これ&lt;/a&gt;呼べないですよね？できるのであれば教えてほしいです〜〜）。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#olaywrightusage&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Olaywright.usage&lt;/h3&gt;
&lt;p&gt;こうやって作っていく上でもう Playwright の面影なぞ全くないに等しかったので、もう好き勝手やろうと思って追加しました。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;self.usage&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;puts&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;~USAGE&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span&gt;____  __                          _       __    __&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;/ __ \/ /___ ___  ___      _______(_)___ _/ /_  / /_&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;/ / / / / __ `/ / / / | /| / / ___/ / __ `/ __ \/ __/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;/ /_/ / / /_/ / /_/ /| |/ |/ / /  / / /_/ / / / / /_&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;\____/_/\__,_/\__, / |__/|__/_/  /_/\__, /_/ /_/\__/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;/____/                /____/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●○●&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;┌─────────────────────────┐&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│   What is Olaywright?   ├────────────────────────────┐&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;└┬────────────────────────┘                            │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│  &quot;Ole no&quot; Playwright.                               │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;└─────────────────────────────────────────────────────┘&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;┌─────────────────────────┐&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│       Basic Usage       ├────────────────────────────┐&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;└┬────────────────────────┘                            │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│ # Setup                                             │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│ browser = Olaywright.new                            │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│ browser.domains in { page:, target: }               │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│                                                     │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│ # Exec Command ex) Target.createTarget              │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│ # Notice: Use snake_case. You&apos;re in Ruby world.     │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│ target.create_target.exec[url: &apos;https://google.com&apos;]│&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;└─────────────────────────────────────────────────────┘&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;USAGE&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これは Monodraw というツールで描いてみました。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://monodraw.helftone.com/&quot; target=&quot;_blank&quot;&gt;https://monodraw.helftone.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;GitHub の人が ER 図をアスキーアートで書いてコミットメッセージに貼ることがあるという記事を見かけて、なるほどお！と思ったのをきっかけにインストールし全然違うきっかけで使ってしまいました。非常に便利なので今後も活躍しそうです。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#資料作成&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;資料作成&lt;/h2&gt;
&lt;p&gt;今回の資料、再掲部分も結構ありますが、合計で 78 枚となっています。自己最多量です。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#カラーパレットとコンポーネント&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;カラーパレットとコンポーネント&lt;/h3&gt;
&lt;p&gt;作成は Figma で行なっていたのですが、調査とか実装が煮詰まった時にカラーパレットとコンポーネントを作成していたのが、直前になって非常に役に立ちました。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://ikuma.assets.newt.so/v1/99af1a04-1f50-4be3-aed5-16459b6ca713/figma.png&quot; alt=&quot;figma.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;今回は背景色に真っ白を選択しました。今年の Kaigi on Rails のテーマカラーが大人ダークな色だったので、Youtube に載せた時に画面共有の枠が目立つように白にしたという感じです。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#フォント&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;フォント&lt;/h3&gt;
&lt;p&gt;フォントに関しては今回は 3 種類をミックスしていて&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Noto Sans JP&lt;/li&gt;
&lt;li&gt;New Rodin Pro&lt;/li&gt;
&lt;li&gt;Montserrat&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;を使用しています。これまではコーポレートロゴ ver2 とかラグランパンチとか奇抜なフォントを使っていたのですが、今回は時間も長いのとカンファレンスなので、読みやすいフォントにしました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#コード部分&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;コード部分&lt;/h3&gt;
&lt;p&gt;コードを掲載する部分も結構あったのですが、これには Figma の &lt;a href=&quot;https://www.figma.com/community/plugin/938793197191698232&quot; target=&quot;_blank&quot;&gt;Code Syntax Highlighter&lt;/a&gt; プラグインを使用しています。&lt;/p&gt;
&lt;p&gt;生成されたものをちょっとだけ加工して、角丸を作ったりしています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#表紙について&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;表紙について&lt;/h3&gt;
&lt;p&gt;あと、最後にほんとどうでもいいところなのですが、表紙に載っている丸は実は点字になっています。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://ikuma.assets.newt.so/v1/10c27fca-9319-47dc-8edd-536f0bddd8aa/%E3%81%95%E3%82%80%E3%81%AD%E3%81%84%E3%82%8B.png&quot; alt=&quot;さむねいる.png&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#発表練習&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;発表練習&lt;/h2&gt;
&lt;p&gt;資料ができたのが、本番二日前の遅い時間だったので、通しでの練習を始めたのは発表の前日。そのため、1 日目は要所要所でしか発表が聞けず残念でした 🥲&lt;/p&gt;
&lt;p&gt;今回すごい当たり前のことに気がついたんですが、30 分の登壇って通しで練習すると 30 分かかるんですよ…。なので 2 回練習すると 1 時間とぶ。
なので、セクションごとに目標時間決めて各セクション単位で練習し、早口で喋ればぎりぎり時間内におわることは計測できたので、2 日目は普通に楽しみました。&lt;/p&gt;
&lt;p&gt;本番の時間オーバーだけは避けなければならなかったので、とにかく「とまるんじゃねえぞ」で早口でしゃべっていたらなんと巻きで終わりました。あらら笑&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;今回 CFP 提出にあたり、業務経験値的には話せるものはあまりないのでソフトトークに踏み切るという選択肢もありましたが、職業エンジニアになった以上、今回は絶対技術系の話をメインにしたいという思いが強くありました。&lt;/p&gt;
&lt;p&gt;「スパイス的にソフトトークを混ぜる感じにするといいかも」と CFP 考案中にレビューをいただいたので技術 9&lt;/p&gt;&lt;div&gt;&lt;/div&gt; 1 くらいの構成にしましたが、ちゃんと技術メインで話せたこと、話を構成していくその過程で業務とは直接関係ない知識をじっくり読み解いていき、それを自分の言葉に落とし込んでいく過程を締切つきでやれたのは非常によかったと思っています。&lt;p&gt;&lt;/p&gt;
&lt;p&gt;また CFP を出すこと自体も勉強になりましたし、カンファレンスで話すというのがどういう準備が必要なのかというのも今回知ることができました。&lt;/p&gt;
&lt;p&gt;一方で Olaywright のコードを書く部分で技術力的な脆さを感じたり、資料デザインも使える引き出しの数に限界を感じている部分もあったので、そこは今後の課題としてやっていこうと思います。&lt;/p&gt;
&lt;p&gt;今は仕事で Ruby を書いていないですが、今後も Ruby 関連のイベントには参加していきたいと思いますし、あとは今回カンファレンス登壇をさせていただいた経験を糧にフロントエンド関連のカンファレンスも登壇挑戦していきたいです！&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#謝辞&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;謝辞&lt;/h2&gt;
&lt;p&gt;今回 CFP を出すのも初めてだったので、チーフオーガナイザーの大倉さんには Grow.rb を通じて 2 回相談にのっていただきました。1 回目の時にはまだテーマも決まっていない状態で、2 回目の時には技術トークとソフトトークをどれくらいの割合にするかの方向性についてなど相談させていただきました。&lt;/p&gt;
&lt;p&gt;当初は自分の発表で 30 分も話すのは…と思っていたのですが、「話したいことがあるなら 30 分でもいいと思う」とアドバイスをいただけたおかげで今回の発表につなげることができました。&lt;/p&gt;
&lt;p&gt;この 1 回目の Grow.rb ではうなすけさん、ima1zumi さんに実際に RubyKaigi に提出した CFP を見せていただき、どういうふうに CFP を書いていくべきかについて非常に参考にさせていただきました。おかげさまでしっかりと CFP を書ききることができました。&lt;/p&gt;
&lt;p&gt;会社の開発チームの方も CFP 提出前にレビューいただきありがとうございました！&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;運営の皆さんも準備から当日までありがとうございました 🙇‍♂️ 来年はハイブリッド開催とのことで非常に楽しみです！ではでは！&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenges 21日目: Trim Left</title><link>https://ikuma-t.com/blog/type-challenge-trim-left/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-trim-left/</guid><description>久しぶりのチャレンジ問題https://github.com/type-challenges/type-challenges/blob/main/questions/00106-medium-trim</description><pubDate>Mon, 12 Sep 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;久しぶりのチャレンジ&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#問題&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/type-challenges/type-challenges/blob/main/questions/00106-medium-trimleft/README.md&quot; target=&quot;_blank&quot;&gt;https://github.com/type-challenges/type-challenges/blob/main/questions/00106-medium-trimleft/README.md&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;文字列を受け取り、その文字列の左側の空白を削除した新しい文字列を返す&lt;code&gt;TrimLeft&amp;lt;T&amp;gt;&lt;/code&gt;を実装する。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#解答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;解答&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#template-literal-types&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Template Literal Types&lt;/h3&gt;
&lt;p&gt;typescriptlang.org/docs/handbook/2/template-literal-types.html&lt;/p&gt;
&lt;p&gt;Template Literal TypesはJSのテンプレートリテラルと同じ記法で特定の形式を満たす文字列リテラルを型として定義することができます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#解答-1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;解答&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;space&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos; &apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;\n&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;\t&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TrimLeft&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;space&lt;/span&gt;&lt;span&gt;}${&lt;/span&gt;&lt;span&gt;infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;L&lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TrimLeft&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;L&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;</content:encoded><author>ikuma-t</author></item><item><title>ObjectSpace.#define_finalizer</title><link>https://ikuma-t.com/blog/objectspace-define-finalizer/</link><guid isPermaLink="true">https://ikuma-t.com/blog/objectspace-define-finalizer/</guid><description>ソースリーディングしているGemの中で、接続開始したタイミングでセッションをkillするスクリプトがあったのをきっかけに調べた。https://docs.ruby-lang.org/ja/latest</description><pubDate>Sun, 11 Sep 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;ソースリーディングしているGemの中で、接続開始したタイミングでセッションをkillするスクリプトがあったのをきっかけに調べた。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.ruby-lang.org/ja/latest/method/ObjectSpace/m/define_finalizer.html&quot; target=&quot;_blank&quot;&gt;https://docs.ruby-lang.org/ja/latest/method/ObjectSpace/m/define_finalizer.html&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Foo&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Foo.callback&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;proc&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;puts&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;bar&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;initialize&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ObjectSpace&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;define_finalizer&lt;/span&gt;&lt;span&gt;(self&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Foo&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;callback&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hoge&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;puts&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;hoge&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Foo&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Foo&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;hoge&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ruby&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;define_finalizer_sample.rb&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;hoge&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;bar&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;bar&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;そのオブジェクトが解放されたタイミングで実行される処理を登録することができる。読んだソースの中では、先の通りセッションを開いたタイミングで対象のpidを指定してセッションのkillを予約している構造になっていた。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Tailwind CSSのimportant</title><link>https://ikuma-t.com/blog/what-is-tailwind-important/</link><guid isPermaLink="true">https://ikuma-t.com/blog/what-is-tailwind-important/</guid><description>TailwindCSSにはimportantという属性を指定できる。module.exports={important:true,}これを指定することで、Tailwindのユーティリティクラスが!im</description><pubDate>Sun, 04 Sep 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Tailwind CSSには&lt;code&gt;important&lt;/code&gt;という属性を指定できる。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;module&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;exports&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;important&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これを指定することで、Tailwindのユーティリティクラスが&lt;code&gt;!important&lt;/code&gt;として読み込まれるようになる。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ImportantConfig&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://tailwindcss.com/docs/configuration#important&quot; target=&quot;_blank&quot;&gt;https://tailwindcss.com/docs/configuration#important&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Tailwind CSSの型定義を参照すると、値としては公式ドキュメントに記載があるbooleanの他にstringも指定できる。&lt;/p&gt;
&lt;p&gt;これも公式ドキュメントに記載があるが、&lt;code&gt;important: true&lt;/code&gt;とすると、MUIのようなインラインスタイルを要素に追加するライブラリとTailwindが競合する可能性がある。そこで&lt;code&gt;important: #app&lt;/code&gt;のように、ID Selectorを値として指定することで、importantの適用範囲を限定することができるのだそう。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://tailwindcss.com/docs/configuration#selector-strategy&quot; target=&quot;_blank&quot;&gt;https://tailwindcss.com/docs/configuration#selector-strategy&lt;/a&gt;&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>やせた（2022-08）</title><link>https://ikuma-t.com/blog/yaseta-2022-08/</link><guid isPermaLink="true">https://ikuma-t.com/blog/yaseta-2022-08/</guid><description>自分でもびっくりしたんですけど、ここ3週間で4kg痩せました。原因は食生活とリングフィットをサボっていることだと推測しています。まず食生活なのですが、季節の野菜を味噌汁でいただくスタイルが多くなりまし</description><pubDate>Tue, 23 Aug 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;自分でもびっくりしたんですけど、ここ3週間で4kg痩せました。&lt;/p&gt;
&lt;p&gt;原因は食生活とリングフィットをサボっていることだと推測しています。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;まず食生活なのですが、季節の野菜を味噌汁でいただくスタイルが多くなりました。&lt;/p&gt;
&lt;p&gt;最近鍋を変えたり、奥さんがシンプルな暮らしをしたがっていたり等々あり、このスタイルになったと記憶しています。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.vitacraft.co.jp/lineup/oregon/&quot; target=&quot;_blank&quot;&gt;https://www.vitacraft.co.jp/lineup/oregon/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ビタクラフトのおかげなのかわかりませんが、まあ味噌汁がとても美味しいこと。この前心地の良い風が吹いた日にさつまいもときのこで作った味噌汁は、秋を感じさせて最高でした。&lt;/p&gt;
&lt;p&gt;ちなみに出汁はこれを使っています。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://kuzefuku.com/?page_id=13&amp;amp;eci_product=fsh02536&quot; target=&quot;_blank&quot;&gt;https://kuzefuku.com/?page_id=13&amp;amp;eci_product=fsh02536&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;もともとめちゃくちゃな食生活はしていなかったのですが、野菜が多くなったので脂肪がつきにくくなったのかなと思ってます。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;次にリングフィットについて。こちらは転職直後は毎朝やっていたのですが、いかんせん業務外でコード読んだり勉強したり、ゲームしたりで時間がなくなったのでやめました。&lt;/p&gt;
&lt;p&gt;筋肉量が減ったので、その分の体重も落ちたと思われます。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;おわり&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>社内イベント開催を支える技術</title><link>https://ikuma-t.com/blog/how-to-hold-event/</link><guid isPermaLink="true">https://ikuma-t.com/blog/how-to-hold-event/</guid><description>社内イベントで司会をやった先日社内のイベントがあり、スタッフの一人として司会をやりました。今までオンラインのイベントを回したことがなかったので、今後自分が再度イベントの司会をやるときや他の人が参考にす</description><pubDate>Fri, 19 Aug 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#社内イベントで司会をやった&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;社内イベントで司会をやった&lt;/h2&gt;
&lt;p&gt;先日社内のイベントがあり、スタッフの一人として司会をやりました。&lt;/p&gt;
&lt;p&gt;今までオンラインのイベントを回したことがなかったので、今後自分が再度イベントの司会をやるときや他の人が参考にするときようにメモを残しておきます。
（ツールの使い方的な話で、話術の話はしないです）&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#前提&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;前提&lt;/h2&gt;
&lt;p&gt;イベントは&lt;a href=&quot;https://www.gather.town/&quot; target=&quot;_blank&quot;&gt;Gather&lt;/a&gt;で実施します。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#社内イベント開催を支える技術&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;社内イベント開催を支える技術&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#オープニングクロージングのスライド作成&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;オープニング・クロージングのスライド作成&lt;/h3&gt;
&lt;p&gt;何の変哲もないFigmaで作ったスライドをただ流しているだけだったのですが、素材の入手場所が増えたのでそこだけ。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;今回はライトなイベントだったので、アイソメトリックな画像にしようと思ったんですが、そのときに以下のサイトを利用しました。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.manypixels.co/gallery&quot; target=&quot;_blank&quot;&gt;https://www.manypixels.co/gallery&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;検索で「Types」を「Isometric」にすると色々出てきます。あとは適当にFigmaで繋げて完成です。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#gatherの会場設営技術&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Gatherの会場設営技術&lt;/h3&gt;
&lt;p&gt;今回はGatherのスペースの中で開催場所が事前に決まっていたため、ロケを敢行して障害点をチェックし排除しておきました。やったことは次の4つです。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;環境音を発生させるアイテムを事前に削除&lt;/li&gt;
&lt;li&gt;Privateスペースを拡張&lt;/li&gt;
&lt;li&gt;Spawnを指定して当日の案内を省略化&lt;/li&gt;
&lt;li&gt;看板を設置して低コストでイベント会場化&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;前提としてMapMakerの権限を持っている必要があります。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. 環境音を発生させるアイテムを事前に削除&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;Gatherには配置すると音が出るオブジェクトがいくつかあるのですが、開催場所にもこれが置いてあったため削除しました。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;設定から音量をなくすこともできるのですが、Gatherに慣れていないユーザーもいるので根本ブレイクです。
（Gatherに慣れていない時に波の音がする場所で打ち合わせしてて、マジで内容聞き取れなかったことあるマン）&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;2 ~ 4の全体像を先に示しておきます。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Privateスペースを拡張&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Gatherは通常ある程度近くにいないと音声が聞こえない仕組みで、複数人で話すにはPrivateスペースを用意する必要があります。&lt;/p&gt;
&lt;p&gt;事前に確認したところ全員が集まれるだけのスペースがなかったので、これを拡張しました。&lt;/p&gt;
&lt;p&gt;なお、先ほどの図では別のPrivateスペースと重複していますが、こうなるとそのPrivateスペースに入ってしまった場合、周りの音声が聞こえなくなるので、実際にはこれらを削除した上でイベント用のPrivateスペースを展開しています。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Spawnを指定して当日の案内を省略化&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;今回のGatherのロケーションはログインすると直接いける場所ではなかったので、Gatherに不慣れなメンバーにはややハードルが高いです。&lt;/p&gt;
&lt;p&gt;なので当日になって「ここからいけますよ」みたいな案内をしたり、迷っている人がいないかチェックしたりする必要があるのですが正直これは面倒。&lt;/p&gt;
&lt;p&gt;GatherにはSpawnという場所に対してリンクを貼る機能があり、これを使って案内を省略しました。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;あらかじめユーザーを遷移させたい場所にMapMakerの「Tile Effects」からSpawnを設置した上で、通常の画面からイベント作成を開き、このリンクをコピーします。すると、このリンクでGatherに入った場合開始位置がSpawnで設定した場所になります。
（実際にはここでイベントを作ればいいのですが、今回は別の方に事前にカレンダー登録をしていただいていたので、リンクだけコピーしました）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. 看板を設置して低コストでイベント会場化&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;画像のとおりです。仕事の合間に準備やってたので、一からマップを作る気にはならず、とりあえずオープニング用のスライドを画像化して適当に貼りました。&lt;/p&gt;
&lt;p&gt;超低コストの割に「何をやっているのかわかりやすい」という意見があり、これはいいかもと思っています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#obsによる配信技術&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;OBSによる配信技術&lt;/h3&gt;
&lt;p&gt;当日はイベント感を出すためにただ画面を共有するのではなく、ちょっと加工したものを共有していました。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;画面切り替えと司会業を同時にやるとタイムマネジメントが難しいので、逆転の発想で時計を画面に配置し、この問題を解消すると共に200%のLIVE感の演出に成功しました（当社比）。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://obsproject.com/ja/download&quot; target=&quot;_blank&quot;&gt;https://obsproject.com/ja/download&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;配信にはOBSを利用してます。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;構成&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;各種素材をシーンとしてあらかじめ構成しておき、OBSのスタジオモードで切り替えています。&lt;/p&gt;
&lt;p&gt;当日はPCとモニターの2画面で、アフタートークに備えてSlackと登壇者トークを見つつ、配信切り替えを行なっていたので全画面表示は厳しく、仕方なしに番組の方を「ウィンドウ プロジェクター（番組）」で配信しました。これで、バックグラウンドでこのウィンドウを画面共有しつつ、画面を自由に使うことができます。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;素材&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;時計に関しては以下のものを拝借しています。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://booth.pm/ja/items/2912843&quot; target=&quot;_blank&quot;&gt;https://booth.pm/ja/items/2912843&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;それ以外はOBS標準の「色ソース」や「テキスト」、ブラウザやPDFが素材です。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;シーンをあらかじめ作っておく&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;イベントの構成としてゲストトークを3本やる形式だったので、画面構成はほぼほぼ同じです。そのため、シーンは1つでテキストを都度変更するという手段を最初は考えていました。&lt;/p&gt;
&lt;p&gt;しかしながら、先の通り当日はだいぶ慌ただしいと想像できたので、ほぼ同じ画面構成でも別途シーンを作っておきました。結果としてこれは正解でした😅&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;合わせ鏡にはご注意を&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;OBSやGatherに限った話ではありませんが、共有している画面を配信してしまうと、無限に共有している画面が映り込んでしまうのでそこにだけご注意を。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#obsによる録画技術&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;OBSによる録画技術&lt;/h3&gt;
&lt;p&gt;OBSには標準で録画機能が備わっているので、先の構成で番組として配信しているものを録画することができます。&lt;/p&gt;
&lt;p&gt;画面としては大丈夫なのですが、音声側に1点問題があります。そのまま録音すると、自分の声は録音できるもののGather上で話している他の人の声が録音できません。&lt;/p&gt;
&lt;p&gt;これを回避するために、Background Musicというアプリを入れました。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/kyleneideck/BackgroundMusic&quot; target=&quot;_blank&quot;&gt;https://github.com/kyleneideck/BackgroundMusic&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Background Musicを使うことで、システム側で流れている音声を横取りすることができます。つまり&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;【Before】「システム音声（他人の声）」→「スピーカー」&lt;/li&gt;
&lt;li&gt;【After】 「システム音声（他人の声）」→「BackgroundMusic」→「スピーカー」&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;という構成に変更できるわけです。耳ではスピーカーの音声を聞きつつ、OBSには別途Background Musicをソースとして渡すことで、リアルタイムで音声を聞きつつの録音が可能になります。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;OBSでは音声ソースを複数指定することができるので、一方を自分のマイク、もう一方をBackground Musicにして対応しました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;オンラインイベントは自分からはOKに見えても、他の人は見えていなかったり聞こえていなかったりします。&lt;/p&gt;
&lt;p&gt;今回は同じ開発チームのメンバーに「事前確認したいことあったら協力するんで言ってください！」と言ってもらえたおかげで、万全の状態でオペレーションに臨めました。ありがとうございます😊&lt;/p&gt;
&lt;p&gt;いやあYoutuberとかって結構大変なんだなあと今回実感しました。なんかもう少しうまいことできる方法があったらまたブログで共有します。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>esbuildのGASテンプレート</title><link>https://ikuma-t.com/blog/gas-template-esbuild/</link><guid isPermaLink="true">https://ikuma-t.com/blog/gas-template-esbuild/</guid><description>GAS作成用のテンプレートを作成したhttps://github.com/IkumaTadokoro/esbuild-gas-template社内の業務改善とか自動化でたまにGASが出てくる場面がある</description><pubDate>Sun, 31 Jul 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#gas作成用のテンプレートを作成した&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;GAS作成用のテンプレートを作成した&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/IkumaTadokoro/esbuild-gas-template&quot; target=&quot;_blank&quot;&gt;https://github.com/IkumaTadokoro/esbuild-gas-template&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;社内の業務改善とか自動化でたまにGASが出てくる場面があるそうなんですが（自分はまだ一度も書いていない）、GASのエディタで書くとnpmが使えなかったり、TypeScriptが使えなかったりします。&lt;/p&gt;
&lt;p&gt;GASで業務効率化できるのは良いことなんですが&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;普段と異なる環境でコードを書くのはストレスが多い&lt;/li&gt;
&lt;li&gt;生JavaScriptを書く機会は業務のコードではほぼないので、GASのためだけにJSを書くのはなんだかなあ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ということで、いつもと同じように書けるようなテンプレートを作ってみました。なぜかリポジトリのREADMEを英語で書いてしまって後々使い方を忘れそうなので、ぼちぼちこの記事に追記しておきます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#よく使うやつをとりあえず入れる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;よく使うやつをとりあえず入れる&lt;/h3&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;とりあえずいつも使っているESLint、Prettier、TypeScriptは全部突っ込みました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#esbuild&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;esbuild&lt;/h3&gt;
&lt;p&gt;コンパイルとトランスパイルにはesbuildを採用しました。採用理由は「esbuildは速い」と聞いていて前から興味があったからです。結果めちゃめちゃ速いし、ビルド用の設定が1スクリプトだけで済んでいるので、小規模なGASとの相性も良さそうです。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#monorepo&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;monorepo&lt;/h3&gt;
&lt;p&gt;これをmonorepoと呼ぶのかはちょっとよくわかっていないんですが、要は複数のGASプロジェクトを1リポジトリに突っ込みます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npm run gen -name=&amp;lt;プロジェクト名&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;ってやると、&lt;code&gt;app&lt;/code&gt;配下にテンプレートが作成されて、このプロジェクトが1つのGoogleAppsScriptに対応する形になります。&lt;/p&gt;
&lt;p&gt;もともとは1リポジトリ1スクリプト構成だったんですが、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;小規模なGASのためにいちいちリポジトリたてるのもな〜&lt;/li&gt;
&lt;li&gt;パッケージを使う場合に更新忘れそうだな〜&lt;/li&gt;
&lt;li&gt;汎用的な処理は一箇所にだけ書いて他のスクリプトでも使いまわしたいな〜&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ということで、さっき変えました。TurborepoとかNxとか流行っているやつもみてみたんですが、too muchな感じだったので、とりあえずnpm workspaceにしました。ちゃんと使えているかは正直微妙です。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#今後&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;今後&lt;/h2&gt;
&lt;p&gt;適当なGAS書いてみてとりあえず機能することはわかったのですが、いかんせん本運用にはまだ載せていないので、動かしながらちょいちょい修正していきたいと思います。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>chezmoiの備忘録</title><link>https://ikuma-t.com/blog/chezmoi-note/</link><guid isPermaLink="true">https://ikuma-t.com/blog/chezmoi-note/</guid><description>ちょっと設定をいじる時にchezmoiの管理方法をいつも忘れるので書いておく。https://www.chezmoi.io/#considering-using-chezmoi編集する変更をchezm</description><pubDate>Mon, 18 Jul 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;ちょっと設定をいじる時にchezmoiの管理方法をいつも忘れるので書いておく。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.chezmoi.io/#considering-using-chezmoi&quot; target=&quot;_blank&quot;&gt;https://www.chezmoi.io/#considering-using-chezmoi&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#編集する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;編集する&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#変更をchezmoi側から追加する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;変更をchezmoi側から追加する&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;~.local/share/chezmoi&lt;/code&gt;ディレクトリ内のファイルが編集できる&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;chezmoi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;edit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;file&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;で変更を反映する。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;chezmoi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#変更を元ファイル側から追加する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;変更を元ファイル側から追加する&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;chezmoi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;file&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# or&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;chezmoi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;re-add&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;こっちの方が使いやすいかも&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#gitに反映する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Gitに反映する&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#ディレクトリ移動して普通にgit&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ディレクトリ移動して、普通にgit&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;chezmoi cd&lt;/code&gt;で chezmoiが管理しているディレクトリに移動することができる&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;chezmoi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;cd&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;git&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;git&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;commit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-m&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;commit message&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;git&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#どこからでもgitを叩く&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;どこからでもgitを叩く&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;chezmoi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;git&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;chezmoi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;git&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;commit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-m&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;commit message&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# フラグを持つ場合は、`--`で区切る必要がある&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;chezmoi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;git&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#自動で変更を反映する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;自動で変更を反映する&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;~/.config/chezmoi/chezmoi.toml&lt;/code&gt;に以下の設定を追加する&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[git]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;autoCommit &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;autoPush &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#最新の変更を反映する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;最新の変更を反映する&lt;/h2&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;chezmoi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;hr /&gt;
&lt;p&gt;忘れる時点で別のツールにした方がいいのかなと思ったりもしたり。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>herokuのOAuthトークン流出の行方まとめ</title><link>https://ikuma-t.com/blog/heroku-incident-2022/</link><guid isPermaLink="true">https://ikuma-t.com/blog/heroku-incident-2022/</guid><description>HerokuのOAuthトークン流出からしばらく経って、「あれ、これって今どういうステータスなんだ？」と思ったので、調べてみました。要約2022年4月にTravisCIのOAuthトークン流出からはじ</description><pubDate>Wed, 06 Jul 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;HerokuのOAuthトークン流出からしばらく経って、「あれ、これって今どういうステータスなんだ？」と思ったので、調べてみました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#要約&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;要約&lt;/h2&gt;
&lt;p&gt;2022年4月にTravis CIのOAuthトークン流出からはじまったHerokuのインシデントは2022年5月30日で収束し、現在はGitHubとの連携も再開している。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#時系列&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;時系列&lt;/h2&gt;





























































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;日付（UTC)&lt;/th&gt;&lt;th&gt;イベント&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;時系列不明&lt;/td&gt;&lt;td&gt;攻撃者がTravis-CIのOAuthトークンを用いた攻撃を行う&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2022-04-07&lt;/td&gt;&lt;td&gt;攻撃者がHerokuのデータベースにアクセスし、OAuth Appのトークンおよび一部ユーザーのConfig Varsをダウンロード&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2022-04-09&lt;/td&gt;&lt;td&gt;攻撃者がHerokuのOAuthトークンを用いてプライベートリポジトリをダウンロード&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2022-04-13&lt;/td&gt;&lt;td&gt;GitHubからHerokuに対して通知&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2022-04-13&lt;/td&gt;&lt;td&gt;Herokuが漏洩したOAuthトークンを無効化&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2022-04-15&lt;/td&gt;&lt;td&gt;Herokuが調査している旨を公開&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2022-04-16&lt;/td&gt;&lt;td&gt;HerokuがGitHubと統合しているOAuthトークンを無効にする旨を発表&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2022-04-17&lt;/td&gt;&lt;td&gt;HerokuがすべてのOAuthトークンの失効を完了&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2022-04-19 ~ 2022-05-03&lt;/td&gt;&lt;td&gt;Herokuが頑張っている報告が続く&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2022-05-05&lt;/td&gt;&lt;td&gt;Herokuがすべてのユーザーのパスワードをリセット開始&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2022-05-07&lt;/td&gt;&lt;td&gt;Herokuがすべてのユーザーのパスワードのリセットを完了。セキュリティベンダーとの調査で2022-04-14以降、不正アクセスはないと発表&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2022-05-25&lt;/td&gt;&lt;td&gt;HerokuがGitHubとの連携を再開&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2022-05-30&lt;/td&gt;&lt;td&gt;調査終了の報告&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;&lt;a href=&quot;#詳細&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;詳細&lt;/h2&gt;
&lt;p&gt;Heroku Statusの一件ずつ機械翻訳して追っていきます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#2022-04-15-調査開始&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;2022-04-15: 調査開始&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;At Salesforce, trust is our number one value. We’re actively investigating a report received on April 13, 2022, from GitHub that a subset of Heroku’s GitHub private repositories, including some source code, were downloaded by a threat actor on April 9, 2022. We proactively notified our Heroku customers regarding this issue and will continue to provide updates to assist them as the investigation continues. If Salesforce or GitHub becomes aware of unauthorized access to customer GitHub repositories connected to Heroku, we will notify affected customers by email without undue delay.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;セールスフォースでは、信頼が第一の価値観です。2022年4月13日にGitHubから受け取った、一部のソースコードを含むHerokuのGitHubプライベートリポジトリのサブセットが、2022年4月9日に脅威行為者によってダウンロードされたという報告について、積極的に調査を行っています。当社は、この問題についてHerokuのお客様に積極的に通知し、調査が進むにつれて、お客様を支援するための最新情報を提供し続けます。Herokuに接続されているお客様のGitHubリポジトリへの不正アクセスをSalesforceまたはGitHubが認識した場合、影響を受けるお客様に電子メールで過度の遅滞なく通知します。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;&lt;a href=&quot;#2022-04-15-概要発表oauthトークン流出&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;2022-04-15: 概要発表。OAuthトークン流出&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;On April 13, 2022, Salesforce Security was notified by GitHub that a subset of Heroku’s GitHub private repositories, including some source code, was downloaded by a threat actor on April 9, 2022. Based on Salesforce’s initial investigation, it appears that unauthorized access to Heroku’s GitHub account was the result of a compromised OAuth token. Salesforce immediately disabled the compromised user’s OAuth tokens and disabled the compromised user’s GitHub account. Additionally, GitHub reported that the threat actor was enumerating GitHub customer accounts using OAuth tokens issued to Heroku’s OAuth integration dashboard hosted on GitHub. Based on the information GitHub shared with us, we are investigating how the threat actor gained access to customer OAuth tokens. The compromised tokens could provide the threat actor access to customer GitHub repos, but not customer Heroku accounts. With the access to customer OAuth tokens, the threat actor may have read and write access to customer GitHub repositories connected to Heroku. Given the incident is still active, please review the recommended actions provided below.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;2022年4月13日、Salesforce SecurityはGitHubから、一部のソースコードを含むHerokuのGitHubプライベートリポジトリのサブセットが、2022年4月9日に脅威行為者によってダウンロードされたことを通知されました。Salesforceの初期調査によると、HerokuのGitHubアカウントへの不正アクセスは、侵害されたOAuthトークンの結果であったと思われます。Salesforceは直ちに漏洩したユーザーのOAuthトークンを無効化し、漏洩したユーザーのGitHubアカウントを無効化しました。さらに、GitHubは、脅威者がGitHubにホストされているHerokuのOAuth統合ダッシュボードに発行されたOAuthトークンを使用してGitHubの顧客アカウントを列挙していたことを報告しました。GitHubが教えてくれた情報に基づき、我々は脅威者が顧客のOAuthトークンにアクセスした方法を調査しています。漏洩したトークンは、脅威者が顧客の GitHub リポジトリにアクセスすることはできても、顧客の Heroku アカウントにはアクセスできない可能性があります。顧客OAuthトークンへのアクセスにより、脅威者はHerokuに接続された顧客GitHubリポジトリへの読み取りおよび書き込みアクセスが可能になる可能性があります。このインシデントはまだアクティブであるため、以下の推奨されるアクションを確認してください。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;このタイミングでHerokuとOAuthとの連携の切断が推奨されます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#2022-04-16-oauthトークンの無効化発表&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;2022-04-16: OAuthトークンの無効化発表&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;To mitigate impact from potentially compromised OAuth tokens, we will revoke over the next several hours all existing tokens from the Heroku GitHub integration. We are also preventing new OAuth tokens from being created until further notice. Your GitHub repositories will not be affected in any way by this action.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;OAuthトークンの漏洩による影響を軽減するため、今後数時間以内にHeroku GitHub統合の既存のトークンをすべて失効させる予定です。また、追って通知があるまで、新しいOAuthトークンの作成を禁止しています。この措置により、お客様のGitHubリポジトリが影響を受けることはありません。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;&lt;a href=&quot;#2022-04-17-すべてのoauthトークンの失効完了&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;2022-04-17: すべてのOAuthトークンの失効完了&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;At 5&lt;/p&gt;&lt;div&gt;&lt;/div&gt; p.m. PT on April 16, 2022, Salesforce completed the revocation of all OAuth tokens from the Heroku Dashboard GitHub integration.&lt;p&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;2022年4月16日午後5時（PT）、SalesforceはHeroku Dashboard GitHubインテグレーションからすべてのOAuthトークンの失効を完了しました。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;&lt;a href=&quot;#2022-05-05-すべてのパスワードリセット&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;2022-05-05: すべてのパスワードリセット&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Separately, our investigation also revealed that the same compromised token was leveraged to gain access to a database and exfiltrate the hashed and salted passwords for customers’ user accounts. For this reason, Salesforce is ensuring all Heroku user passwords are reset and potentially affected credentials are refreshed. We have rotated internal Heroku credentials and put additional detections in place. We are continuing to investigate the source of the token compromise.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;また、我々の調査により、同じ漏洩したトークンを利用してデータベースにアクセスし、お客様のユーザーアカウントのハッシュ化および塩漬けパスワードを流出させたことも判明しました。このため、Salesforce では、すべての Heroku ユーザーのパスワードをリセットし、影響を受ける可能性のある認証情報をリフレッシュするようにしています。私たちは、社内のHeroku認証情報をローテーションし、追加の検知を実施しました。トークン漏洩の原因については、引き続き調査中です。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;&lt;a href=&quot;#2022-05-07-不正アクセスの履歴はないと発表&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;2022-05-07: 不正アクセスの履歴はないと発表。&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Since our last update, we confirmed that Heroku has completed the necessary password resets. We have no evidence of any unauthorized access to Heroku systems since April 14, 2022. This analysis is based on our investigation to date, backed by a leading third-party security vendor and our extensive threat detection systems.
We also wanted to address a question regarding impact to environment variables. While we confirmed that the threat actor had access to encrypted Heroku customer secrets stored in config var, the secrets are encrypted at rest and the threat actor did not access the encryption key necessary to decrypt config var secrets.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;前回の更新以降、Herokuは必要なパスワードのリセットを完了したことを確認しました。2022年4月14日以降、Herokuのシステムに対する不正アクセスの証拠はありません。この分析は、大手サードパーティセキュリティベンダーと当社の広範な脅威検知システムに裏打ちされた、これまでの調査に基づいています。
また、環境変数への影響に関する質問にもお答えしたいと思います。脅威者は config var に格納された暗号化された Heroku の顧客秘密へのアクセスを確認しましたが、秘密は静止状態で暗号化されており、脅威者は config var の秘密を解読するのに必要な暗号化キーにアクセスしませんでした。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;&lt;a href=&quot;#2022-05-25-github連携が有効化される&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;2022-05-25: GitHub連携が有効化される&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;We are happy to report that the GitHub integration is re-enabled! You can now reconnect with GitHub and restore your Heroku pipeline functionality, including Review Apps, with newly generated tokens.
You can connect to GitHub immediately or wait for the enhanced integration as described in this blog post. To re-establish your GitHub connection now, please follow these instructions.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;GitHubとの連携が再有効化されたことをご報告します!GitHubとの再接続が可能になり、新たに生成されたトークンでReview Appsを含むHerokuパイプラインの機能を復元することができるようになりました。
すぐにGitHubに接続することもできますし、このブログポストで説明されているように統合が強化されるのを待つこともできます。今すぐGitHub接続を再確立するには、以下の手順に従ってください。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;ブログポストはこれ。色々セキュリティ向上につとめてますよ、とのこと。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OAuthで要求するスコープを見直すとか&lt;/li&gt;
&lt;li&gt;GitHub Appsへの移行とか&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tex2e.github.io/rfc-translater/html/rfc8705.html&quot; target=&quot;_blank&quot;&gt;RFC 8705 - OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens 日本語訳&lt;/a&gt;とか。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.heroku.com/github-integration-update&quot; target=&quot;_blank&quot;&gt;https://blog.heroku.com/github-integration-update&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;以下の手順はこれ。普通に再度GitHub接続すればいいみたい。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://help.heroku.com/UIUA61EH/how-do-i-reconnect-the-github-integration&quot; target=&quot;_blank&quot;&gt;https://help.heroku.com/UIUA61EH/how-do-i-reconnect-the-github-integration&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#2022-05-31-インシデント終了のお知らせ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;2022-05-31: インシデント終了のお知らせ&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Our investigation has concluded, and as previously mentioned, we restored the GitHub integration on May 25, 2022. We have no evidence of customer impact beyond what has already been reported, including no additional evidence of threat actor activity after April 14, 2022. We will publish details of the attacker’s actions on status.heroku.com the week of June 13, 2022.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;調査は終了し、前述のとおり、2022年5月25日にGitHubとの連携を復旧させました。2022年4月14日以降、脅威行為者の活動を示す追加の証拠はないなど、すでに報告されている以上のお客様への影響はありません。攻撃者の行動の詳細については、2022年6月13日の週にstatus.heroku.comで公開する予定です。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;&lt;a href=&quot;#2022-06-15-follow-up-reportが掲載&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;2022-06-15: Follow-up Reportが掲載&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Thank you for your patience and feedback throughout this incident. With the conclusion of our investigation, we are now providing our customers with an overview of the threat actor’s actions. The summary of our investigation includes mitigations and changes we are making to address the evolving threat landscape. For updates on the enhanced GitHub integration, please visit this blog post.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;この件に関しまして、お客様には大変ご迷惑をおかけいたしました。調査の終了に伴い、現在、脅威行為者の行動の概要をお客様に提供しています。調査結果の概要には、進化する脅威の状況に対応するための緩和策と変更が含まれています。GitHubとの連携強化に関する最新情報は、こちらのブログポストをご覧ください。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;ブログポストはこれ。2022-05-25のものと同じ。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.heroku.com/github-integration-update&quot; target=&quot;_blank&quot;&gt;https://blog.heroku.com/github-integration-update&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;ここからは調べごとのメモです&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#oauthトークンはなぜ盗まれると困るのか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;OAuthトークンはなぜ盗まれると困るのか？&lt;/h2&gt;
&lt;p&gt;とりあえずOAuthの理解ができていないといけません。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OAuthはRFC6749で定義されている認可のためのプロトコル。OAuth2.0はサードパーティアプリケーションによるHTTPサービスへの限定的なアクセスを可能にする認可FW。&lt;/li&gt;
&lt;li&gt;登場人物はリソースオーナー（私たち）、クライアント（Heroku、Travis CI）、リソースサーバー（GitHub）、認可サーバー（GitHub）&lt;/li&gt;
&lt;li&gt;OAuth認証はOAuthでユーザー情報のAPIを叩いて、それを使ってログインすること&lt;/li&gt;
&lt;li&gt;認可サーバはリソースオーナーが承諾した場合、リダイレクトURIを介してアクセストークン（誰のリソースがどのような権限に紐づいているか、有効かなどの情報を持つ）をクライアントに渡す&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;OAuthトークン（アクセストークン）が盗まれると、その発行元であるリソースサーバーに対して、アクセストークンの範囲内でアクセスができてしまうわけです。
HerokuとかTravis CIは大体リポジトリの読み取り権限以上のものをもっているので、privateなnpmのリポジトリのデータが不正ダウンロードされたわけですね。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#travis-ciやherokuからなぜoauthトークンが流出したのか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Travis CIやHerokuからなぜOAuthトークンが流出したのか？&lt;/h2&gt;
&lt;p&gt;調べた限りではTravis CIが漏れたのがもともとの原因で、標的型攻撃とのことだったのでそのアクセストークンを使ってHerokuへの攻撃がはじまったという感じっぽいです。&lt;/p&gt;
&lt;p&gt;とすると、なぜTravis CIから漏れたのか？なんですが、Hacker Newsに関係ありそうな調査結果がありました。&lt;/p&gt;
&lt;p&gt;Unpatched Travis CI API Bug Exposes Thousands of Secret User Access Tokens&lt;/p&gt;
&lt;p&gt;記事はクラウドセキュリティファームのAqua社がブログで出しているレポートについて紹介してます。Aqua社は初めて知ったのですが、コンテナセキュリティ製品のAquaも提供していて、日本の代理店とクラスメソッドがパートナー契約をしているので、ある程度信憑性のあるソースとみて良いかと思っています。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.aquasec.com/travis-ci-security&quot; target=&quot;_blank&quot;&gt;https://blog.aquasec.com/travis-ci-security&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;私たち Team Nautilus は、最新の調査において、誰でも過去の平文ログにアクセスできる Travis CI API を通じて、何万ものユーザートークンが公開されていることを発見しました。無料層ユーザーの7億7000万件以上のログが公開されており、そこからGitHub、AWS、Docker Hubといった人気のクラウドサービスプロバイダーに関連するトークン、秘密、その他の認証情報を簡単に抽出することが可能です。攻撃者はこの機密データを利用して、大規模なサイバー攻撃を仕掛けたり、クラウド内で横移動したりすることができます。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;どうもこの問題は過去2015年と2019年にも指摘されているみたいなんですが、それに対してTravisCIの対策は&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;API呼び出しの速度を遅くさせた&lt;/li&gt;
&lt;li&gt;昔に比べてマスクされている情報が増えたけど、それでもトークンがマスクされていないバリエーションが20種類ほどある&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;とだいぶ杜撰な感じで、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GitHubへのアクセストークン&lt;/li&gt;
&lt;li&gt;AWSへのアクセスキー&lt;/li&gt;
&lt;li&gt;MySQLやPostgreSQLなどのデータベースへのアクセスを許可する、メールやユーザー名、パスワードなどの認証情報セット&lt;/li&gt;
&lt;li&gt;Docker Hubのパスワード&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;などなどが実験してみたら取れそうとのことでした（2FAはちゃんとやろうね）。ひええ。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#参考ソース&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;参考ソース&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://status.heroku.com/incidents/2413&quot; target=&quot;_blank&quot;&gt;Incident 2413 | Heroku Status&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://zenn.dev/hiroga/articles/heroku-incident-2413-checklist&quot; target=&quot;_blank&quot;&gt;HerokuのOAuthトークン流出で、やっておくといいことリスト（コメント大歓迎）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.blog/2022-04-15-security-alert-stolen-oauth-user-tokens/&quot; target=&quot;_blank&quot;&gt;Security alert: Attack campaign involving stolen OAuth user tokens issued to two third-party integrators | The GitHub Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.travis-ci.com/2022-04-17-securitybulletin&quot; target=&quot;_blank&quot;&gt;The Travis CI Blog: SECURITY BULLETIN; Customer repositories have NOT been accessed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://thehackernews.com/2022/06/unpatched-travis-ci-api-bug-exposes.html&quot; target=&quot;_blank&quot;&gt;Unpatched Travis CI API Bug Exposes Thousands of Secret User Access Tokens&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.aquasec.com/travis-ci-security&quot; target=&quot;_blank&quot;&gt;Public Travis CI Logs (Still) Expose Users to Cyber Attacks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenges 20日目: 62-Type Lookup</title><link>https://ikuma-t.com/blog/type-challenge-type-lookup/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-type-lookup/</guid><description>問題&amp;amp;回答代数的データ型（algebraicdatatypes;ADT）を表現するユニオン型から、その属性を取得するようなLookUp型を定義する。1つ目の型引数にUnion型をとり、2つ目の</description><pubDate>Sun, 26 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#問題--回答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題 &amp;amp; 回答&lt;/h2&gt;
&lt;p&gt;代数的データ型（algebraicdatatypes;ADT）を表現するユニオン型から、その属性を取得するような&lt;code&gt;LookUp&lt;/code&gt;型を定義する。&lt;/p&gt;
&lt;p&gt;1つ目の型引数にUnion型をとり、2つ目の引数には、&lt;code&gt;type&lt;/code&gt;というプロパティに期待する属性をstringで指定する。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;LookUp&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; { type&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; } &lt;/span&gt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;never&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Conditional Typesのいつもの（never返すやつ）を利用する。問題文の指定では、取得対象の型は&lt;code&gt;type: xxx&lt;/code&gt;を必ず保持しているので、2つ目の引数&lt;code&gt;T&lt;/code&gt;で指定された値を利用した&lt;code&gt;{ type: T }&lt;/code&gt;の部分型であるinterfaceを返す。&lt;/p&gt;
&lt;p&gt;分配法則が効くので、ユニオン型の中の合致しない型はneverによって無視される。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;Conditional Typesってほんまに高度な型なんかな〜と思うくらい毎日のように出てきますね〜。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>ESLintのno-plusplusはなぜ怒られるのか</title><link>https://ikuma-t.com/blog/what-is-no-plusplus/</link><guid isPermaLink="true">https://ikuma-t.com/blog/what-is-no-plusplus/</guid><description>どうもCopilot無料にならなかった私です。先日Copilot経由でforループを書いていたら++演算子が補完されたのですが、これがESLintルールで怒られました。どうもno-plusplusだと</description><pubDate>Sat, 25 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;どうもCopilot無料にならなかった私です。先日Copilot経由でforループを書いていたら&lt;code&gt;++&lt;/code&gt;演算子が補完されたのですが、これがESLintルールで怒られました。どうも&lt;code&gt;no-plusplus&lt;/code&gt;だと。&lt;/p&gt;
&lt;p&gt;結局forEachに書き直して（最終的にはそれすらも消え）何事もなかったのですが（そのまま使うとしても&lt;code&gt;+= 1&lt;/code&gt;にするだけ）、ESLintのルールはどういう意図でこれを設けているのかわからなかったので調べてみました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#結論&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;結論&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;インクリメント演算子は前にも後ろにも置ける。&lt;/li&gt;
&lt;li&gt;JavaScriptは内部的にセミコロンが無い文にセミコロンを挿入して文を解釈する。&lt;/li&gt;
&lt;li&gt;結果として前置の&lt;code&gt;++&lt;/code&gt;が、後置の&lt;code&gt;++&lt;/code&gt;になる可能性があるので、それを禁止するルールが&lt;code&gt;no-plusplus&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#インクリメント演算子&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;インクリメント演算子&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Increment&quot; target=&quot;_blank&quot;&gt;https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Increment&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;インクリメント演算子（&lt;code&gt;++&lt;/code&gt;）は前置と後置の2種類があって、どちらもオペランドをインクリメントしますが戻り値が異なります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;前置：インクリメント前の値を返す&lt;/li&gt;
&lt;li&gt;後置：インクリメント後の値を返す&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;今回のポイントは「前にも後ろにも置ける」ということです。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#eslintのドキュメントをみてみる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ESLintのドキュメントをみてみる&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://eslint.org/docs/latest/rules/no-plusplus&quot; target=&quot;_blank&quot;&gt;https://eslint.org/docs/latest/rules/no-plusplus&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Because the unary ++ and — operators are subject to automatic semicolon insertion, differences in whitespace can change semantics of source code.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;単項演算子&lt;code&gt;++&lt;/code&gt;と&lt;code&gt;--&lt;/code&gt;は、セミコロンの自動挿入の対象になるので、ソースコードの意味が空白の違いで変わってしまうとあります。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#automatic-semicolon-insertion&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Automatic Semicolon Insertion&lt;/h2&gt;
&lt;p&gt;ここでいうセミコロンの自動挿入はASIと呼ばれるものです。&lt;/p&gt;
&lt;p&gt;ASIは「Automatic Semicolon Insertion」の略称です。
JavaScriptはセミコロンを書いても書かなくてもOKな言語ですが、内部的にはセミコロンを自動で挿入して文を区切っています。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://262.ecma-international.org/13.0/#sec-automatic-semicolon-insertion&quot; target=&quot;_blank&quot;&gt;https://262.ecma-international.org/13.0/#sec-automatic-semicolon-insertion&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Most ECMAScript statements and declarations must be terminated with a semicolon. Such semicolons may always appear explicitly in the source text. For convenience, however, such semicolons may be omitted from the source text in certain situations. These situations are described by saying that semicolons are automatically inserted into the source code token stream in those situations.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;色々とルールがあるようですが、今回のケースでは次のような解釈が発生するために問題となるようです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// i++として解釈される&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;i　&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;j&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// ++jとして解釈される&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;i&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;++&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;jj&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;1つ目はぱっと見でわかりますが、2つ目は挙動がわかりづらいですね（こんなコード書かないとは思いますが）&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#no-plusplus&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;no-plusplus&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://eslint.org/docs/latest/rules/no-plusplus&quot; target=&quot;_blank&quot;&gt;https://eslint.org/docs/latest/rules/no-plusplus&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;再びドキュメントに戻りまして、上記のような事態を抑制するのが&lt;code&gt;no-plusplus&lt;/code&gt;ルールです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;module.exports = {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;env&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;browser&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;commonjs&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;es2021&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &apos;eslint:recommended&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;parserOptions&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ecmaVersion&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;rules&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;no-plusplus&apos;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&apos;error&apos;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;このルール下では&lt;code&gt;++&lt;/code&gt;や&lt;code&gt;--&lt;/code&gt;を使うと上記の理由で怒られます。代わりに&lt;code&gt;+=&lt;/code&gt;や&lt;code&gt;-=&lt;/code&gt;を使用します。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#allowforloopafterthoughtsオプション&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;allowForLoopAfterthoughtsオプション&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; ([initialization]; [condition]; [final&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;expression])&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/for&quot; target=&quot;_blank&quot;&gt;https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/for&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;forループの&lt;code&gt;final-expression&lt;/code&gt;（ループのそれぞれの最後に評価される式）では&lt;code&gt;++&lt;/code&gt;や&lt;code&gt;--&lt;/code&gt;を許可するオプションです。&lt;/p&gt;
&lt;p&gt;Afterthougtsが&lt;code&gt;final-expression&lt;/code&gt;を指しているようです（公式なのはわかりませんが、「for loop afterthoughts」でググるとちょっとヒットした）。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;全然関係ないんですけど、ECMAScriptの仕様書のサイト結構重いですね…。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenges 19日目:20-Promise.all</title><link>https://ikuma-t.com/blog/type-challenge-promise-all/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-promise-all/</guid><description>問題&amp;amp;解答https://github.com/type-challenges/type-challenges/blob/main/questions/00020-medium-promise</description><pubDate>Wed, 22 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#問題--解答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題 &amp;amp; 解答&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/type-challenges/type-challenges/blob/main/questions/00020-medium-promise-all/README.md&quot; target=&quot;_blank&quot;&gt;https://github.com/type-challenges/type-challenges/blob/main/questions/00020-medium-promise-all/README.md&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;PromiseAll&lt;/code&gt;に型をつける。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;declare&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;PromiseAll&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]&amp;gt;(values&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;{&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;R&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;R&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;問題文にもありますが、PromiseAllの戻り値の型は&lt;code&gt;Promise&amp;lt;T&amp;gt;&lt;/code&gt;で、引数の型は配列です。&lt;code&gt;as const&lt;/code&gt;が使用されているケースがあるので、ここまでで&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;declare&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;PromiseAll&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]&amp;gt;(values&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;こういう感じです。あとはどっかの回でやった再帰的なやつにやや近いですが、TがPromiseだった場合にはそれを解除してやる必要があるので、mappedTypesと&lt;code&gt;infer&lt;/code&gt;キーワードを使って最終的にはこうなります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;declare&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;PromiseAll&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]&amp;gt;(values&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;{&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;R&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;R&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;眠いです笑&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenges 18日目：16-Pop</title><link>https://ikuma-t.com/blog/type-challenge-pop/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-pop/</guid><description>問題&amp;amp;回答https://github.com/type-challenges/type-challenges/blob/main/questions/00016-medium-pop/REA</description><pubDate>Tue, 21 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#問題--回答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題 &amp;amp; 回答&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/type-challenges/type-challenges/blob/main/questions/00016-medium-pop/README.md&quot; target=&quot;_blank&quot;&gt;https://github.com/type-challenges/type-challenges/blob/main/questions/00016-medium-pop/README.md&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;配列&lt;code&gt;T&lt;/code&gt;を受けとって、配列の最後の要素以外の型を返す&lt;code&gt;Pop&amp;lt;T&amp;gt;&lt;/code&gt;を実装する。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Pop&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;...infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Rest&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;unknown&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;&lt;span&gt;Rest&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;never&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Conditional Typesと&lt;code&gt;infer&lt;/code&gt;キーワード、Variadic Tuple Typesを用いて実装しました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;最初unknown部分をanyで書いていたのですが、回答を見ていたら、anyは怒られがちだし、どうせ使わないならunknownでよくない？みたいなコメントを見つけて、こっちに変更しました。&lt;/p&gt;
&lt;p&gt;仕事を始めたので、数日空いてしまったのですが速攻で解けたので安心しました。&lt;/p&gt;
&lt;p&gt;最近お仕事で初めてちゃんと動くTypeScriptのコードを書いたのですが（）、このtype-challengesをやったおかげで先輩の言っていることがチンプンカンプンということがないので、やっといてよかったな〜と思っています。&lt;/p&gt;
&lt;p&gt;今後も優先度は少し低くなりますが、こつこつやっていきます。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>v-modelとはなにか</title><link>https://ikuma-t.com/blog/what-is-v-model/</link><guid isPermaLink="true">https://ikuma-t.com/blog/what-is-v-model/</guid><description>バージョンによる挙動の違いやカスタムコンポーネントで使用する際に、v-modelの挙動が5秒くらいわからないときがありました。1秒以内でv-modelを利用したコードを読めるように、未来の自分に向けて</description><pubDate>Tue, 21 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;バージョンによる挙動の違いやカスタムコンポーネントで使用する際に、&lt;code&gt;v-model&lt;/code&gt;の挙動が5秒くらいわからないときがありました。&lt;/p&gt;
&lt;p&gt;1秒以内で&lt;code&gt;v-model&lt;/code&gt;を利用したコードを読めるように、未来の自分に向けて&lt;code&gt;v-model&lt;/code&gt;を説明しておきます。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#v-modelの概要&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;v-modelの概要&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;v-model&lt;/code&gt;はVuejsのディレクティブの1つで、主にフォーム入力バインディングの文脈で利用されます。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;v-bind&lt;/code&gt;ディレクティブと&lt;code&gt;v-on&lt;/code&gt;ディレクティブをまとめて書くためのシンタックスシュガーであり、&lt;code&gt;v-model=&quot;hoge&quot;&lt;/code&gt;の形式でリアクティブな変数&lt;code&gt;hoge&lt;/code&gt;にフォームの値を束縛し、入力相当のイベント（&lt;code&gt;input&lt;/code&gt;とか&lt;code&gt;change&lt;/code&gt;とか）発火時に入力値を&lt;code&gt;hoge&lt;/code&gt;に代入するという動きをします。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;v-model&lt;/code&gt;理解のためにはシンタックスシュガーを分解するのがよいのですが、Vue2とVue3で使用する変数名が異なるので、別々に解説します。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#vue-2系におけるv-model&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Vue 2系におけるv-model&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v-model&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;inputText&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これはVue2系の場合、次のシンタックスシュガーになります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;&lt;span&gt; :&lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;inputText&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;inputText &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;$event&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;target&lt;/span&gt;&lt;span&gt;.value&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;:value&lt;/code&gt;は&lt;code&gt;v-bind:value&lt;/code&gt;のショートハンド、&lt;code&gt;@input&lt;/code&gt;は&lt;code&gt;v-on:input&lt;/code&gt;のショートハンドです。&lt;/p&gt;
&lt;p&gt;読み下すと、「このフォームに&lt;code&gt;value&lt;/code&gt;という変数を束縛し、&lt;code&gt;input&lt;/code&gt;イベント時に&lt;code&gt;$event.target.value（入力値）&lt;/code&gt;を&lt;code&gt;value&lt;/code&gt;に設定する」という意味になります。&lt;/p&gt;
&lt;p&gt;Vue2系でのv-modelのデフォルト値は&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;プロパティ名：&lt;code&gt;value&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;イベント名：&lt;code&gt;input&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;となっています。これはあくまでデフォルトであって変更することもできますが、それは後述のカスタムコンポーネントの章で紹介します。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#vue-3系におけるv-model&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Vue 3系におけるv-model&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v-model&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;inputText&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これはVue3系の場合、次のシンタックスシュガーになります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;&lt;span&gt; :&lt;/span&gt;&lt;span&gt;modelValue&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;inputText&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;modelValue&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;inputText &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;$event&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;target&lt;/span&gt;&lt;span&gt;.value&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Vue2系との差分はプロパティ名とイベント名です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;プロパティ名：&lt;code&gt;modelValue&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;イベント名：&lt;code&gt;update:modelValue&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;1つのコンポーネント内でシンプルに&lt;code&gt;v-model&lt;/code&gt;を使用している場合は問題ないのですが、複数のコンポーネントで&lt;code&gt;v-model&lt;/code&gt;で定義した値をやりとりしたり、イベントで発火する処理を変更する場合はVue2と同様にすると動かないので注意が必要です。&lt;/p&gt;
&lt;p&gt;こちらもVue2同様、あくまでデフォルトの値ですが、それは後述のカスタムコンポーネントの章で紹介します。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#カスタムコンポーネントでv-modelを使用する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;カスタムコンポーネントでv-modelを使用する&lt;/h2&gt;
&lt;p&gt;ここまでは単一のコンポーネントで使用するケースを確認してきました。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v-model&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;inputText&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これだけならだいぶ理解もしやすいのですが、カスタムコンポーネントに対して&lt;code&gt;v-model&lt;/code&gt;を使用するとなると一瞬理解のスピードが落ちるのでここで解説します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// カスタムコンポーネントでは値をどうやって受け取る?&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;MyCustomComponent&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v-model&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;inputText&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;基本的な考え方は結局のところ「props down, event up」です。各バージョンごとに詳細を確認します。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#vue2系概要&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Vue2系概要&lt;/h3&gt;
&lt;p&gt;先述のようにVue2では&lt;code&gt;v-model&lt;/code&gt;は次のシンタックスシュガーです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;MyCustomComponent&lt;/span&gt;&lt;span&gt;&lt;span&gt; :&lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;inputText&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;inputText &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;$event&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;target&lt;/span&gt;&lt;span&gt;.value&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;そのため、子コンポーネント側でこの&lt;code&gt;inputText&lt;/code&gt;（親で&lt;code&gt;v-model&lt;/code&gt;に渡した値）を変更するには、次の要件を満たす必要があります。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;propsで&lt;code&gt;value&lt;/code&gt;という名前で&lt;code&gt;inputText&lt;/code&gt;を受け取る（props down）&lt;/li&gt;
&lt;li&gt;値が変更されたタイミングで、新しい値とともに、親コンポーネントの&lt;code&gt;input&lt;/code&gt;イベントを発火する（event up）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;いくつか書き方があるので、それぞれ見ていきます。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#vue2-optins-api&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Vue2: Optins API&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;愚直に受け取る&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:value&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;value&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;@input&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;$emit(&apos;input&apos;, $event.target.value)&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;MyCustomComponent&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;require&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; String&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;シンプルに&lt;code&gt;value&lt;/code&gt;をpropsとして受け取り、子コンポーネント内の&lt;code&gt;input&lt;/code&gt;イベントで親の&lt;code&gt;input&lt;/code&gt;イベントを&lt;code&gt;emit&lt;/code&gt;します。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;modelオプションを指定して受け取る&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Vue2系では&lt;code&gt;model&lt;/code&gt;オプションを指定することができます（Vue3では廃止）。これを指定することで、子コンポーネント側で&lt;code&gt;v-model&lt;/code&gt;を受け付ける際に、&lt;code&gt;v-model&lt;/code&gt;のプロパティ名とイベント名を変更することができるようになります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// プロパティ名がvalueからvalueOfModelに、イベント名がinputからvalueOfModelEventに変更される&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { prop&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;valueOfModel&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; event&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;valueOfModelEvent&apos;&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これを利用することで、先程のコードを次のように修正することができます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:value&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;valueOfModel&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;@input&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;$emit(&apos;valueOfModelEvent&apos;, $event.target.value)&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;MyCustomComponent&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { prop&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;valueOfModel&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; event&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;ValueOfModelEvent&apos;&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;valueOfModel&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;require&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; String&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;なお、この場合でも親コンポーネント側の呼び出し（&lt;code&gt;v-model=xxx&lt;/code&gt;）は変わりません。あくまでカスタムコンポーネント側で受けた&lt;code&gt;v-model&lt;/code&gt;をどう処理するかの名前を変更するだけです。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;v-modelと双方向算出プロパティで受け取る&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;算出プロパティ&lt;code&gt;computed&lt;/code&gt;を用いることで、カスタムコンポーネント内の記述でも&lt;code&gt;v-model&lt;/code&gt;を使用することができるようになります。&lt;/p&gt;
&lt;p&gt;以下の手順で説明します。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;computed&lt;/code&gt;のsetter&lt;/li&gt;
&lt;li&gt;子コンポーネントでのprops直接編集禁止&lt;/li&gt;
&lt;li&gt;v-modelと双方向算出プロパティで親のv-modelに子もv-modelでアクセスする&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;1.&lt;code&gt;computed&lt;/code&gt;のsetter&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;computed&lt;/code&gt;はプロパティ名のみを指定した場合、getter関数として定義されますが、明示することでsetterを定義することもできます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;computed&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;fullName&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;       &lt;/span&gt;&lt;span&gt;// getterの定義&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;         &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.firstName&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.lastName&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;       &lt;/span&gt;&lt;span&gt;// setterの定義&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span&gt;set&lt;/span&gt;&lt;span&gt;(newValue) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;       &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;newFirstName&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;newLastName&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;newValue&lt;/span&gt;&lt;span&gt;&lt;span&gt;.split&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos; &apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;         &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.firstName &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; newFirstName&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;         &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.lastName &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; LastName&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;この仕組みを利用すると、直接編集できないなんらかの値に対して、リアクティブ性を損なわずに参照と編集を行うことができるようになります。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2.子コンポーネントでのprops直接編集禁止&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;もともとサンプルとして出していたカスタムコンポーネントに戻りましょう。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:value&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;value&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;@input&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;$emit(&apos;input&apos;, $event.target.value)&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;MyCustomComponent&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;require&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; String&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;inputタグの部分でやっていることが&lt;code&gt;v-model&lt;/code&gt;と同じっぽいのでこれを&lt;code&gt;v-model&lt;/code&gt;に置き換えてみます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;template&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;input :value=&quot;value&quot; @input=&quot;$emit(&apos;input&apos;, $event.target.value)&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;input v-model=&quot;value&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export default {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name: &apos;MyCustomComponent&apos;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;props: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;value: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;require: true,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;type: String&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;この実装をすると一見良さそうな感じもしますが、これではVue側で「親の値を直接変更すると、再レンダリングのたびに値が上書きされる」といった警告が出てしまいます。親から貰ってきた値を子が直接編集できてしまうと、複数のコンポーネントで同じようなことをやった時に収集がつかなくなります。&lt;/p&gt;
&lt;p&gt;なので、&lt;code&gt;v-model&lt;/code&gt;のシンタックスシュガーの恩恵を受けつつ、算出プロパティを用いて間接的に値を編集します。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3.v-modelと双方向算出プロパティで親のv-modelに子もv-modelでアクセスする&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;まずは&lt;code&gt;v-model&lt;/code&gt;に直接紐づけられている親の&lt;code&gt;value&lt;/code&gt;を別の値に変更します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;template&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;input v-model=&quot;value&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;input v-model=&quot;innerValue&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export default {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name: &apos;MyCustomComponent&apos;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;props: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;value: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;require: true,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;type: String&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;このままでは定義が値の定義がされていないので、算出プロパティで「getterでは親のvalueの値を表示する、setterでは親のinputイベントを発火する」ように定義します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;template&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;input v-model=&quot;innerValue&quot;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export default {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name: &apos;MyCustomComponent&apos;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;props: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;value: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;require: true,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;type: String&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;computed: {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;innerValue: {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;get() {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span&gt;return this.value&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;set(newValue) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span&gt;this.$emit(&apos;input&apos;, newValue)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これによりこのコンポーネントの&lt;code&gt;innerValue&lt;/code&gt;は次のように動作するようになります。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;（親の）&lt;code&gt;v-model&lt;/code&gt;で定義した値が&lt;code&gt;props&lt;/code&gt;として子に渡る&lt;/li&gt;
&lt;li&gt;&lt;code&gt;innerValue&lt;/code&gt;の&lt;code&gt;getter&lt;/code&gt;で親の&lt;code&gt;value&lt;/code&gt;を表示する&lt;/li&gt;
&lt;li&gt;&lt;code&gt;input&lt;/code&gt;タグに値を入力すると、&lt;code&gt;innerValue&lt;/code&gt;の&lt;code&gt;setter&lt;/code&gt;で&lt;code&gt;newValue&lt;/code&gt;を引数に親の&lt;code&gt;input&lt;/code&gt;イベントが発火する&lt;/li&gt;
&lt;li&gt;親コンポーネントの&lt;code&gt;v-model&lt;/code&gt;で定義した値が変更される&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;… 1に戻る&lt;/p&gt;
&lt;p&gt;もちろんVue2系であれば、この方法の中でもmodelオプションを利用することもできます。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#vue2-composition-api&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Vue2: Composition API&lt;/h4&gt;
&lt;p&gt;CompositionAPIの場合も同じです。modelオプションを使用することもできます。一例として算出プロパティを利用する例をComposition APIに書き換えてみます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;text&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v-model&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;innerValue&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { computed } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;@vue/composition-api&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;MyInputComposition&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { prop&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;modelValue&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; event&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;update:modelUpdate&apos;&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;label&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;require&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; String&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;modelValue&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;require&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; String&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;setup&lt;/span&gt;&lt;span&gt; (props&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; { emit }) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;innerValue&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;computed&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt;.modelValue&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;set&lt;/span&gt;&lt;span&gt;(newValue) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;emit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;update:modelUpdate&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; newValue)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;innerValue&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#vue3系概要&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Vue3系概要&lt;/h3&gt;
&lt;p&gt;Vue3では&lt;code&gt;v-model&lt;/code&gt;は次のシンタックスシュガーです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;MyCustomComponent&lt;/span&gt;&lt;span&gt;&lt;span&gt; :&lt;/span&gt;&lt;span&gt;modelValue&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;inputText&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;modelValue&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;inputText &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;$event&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;target&lt;/span&gt;&lt;span&gt;.value&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;そのため、子コンポーネント側でこの&lt;code&gt;inputText&lt;/code&gt;（親で&lt;code&gt;v-model&lt;/code&gt;に渡した値）を変更するには、次の要件を満たす必要があります。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;propsで&lt;code&gt;modelValue&lt;/code&gt;という名前でinputTextを受け取る（props down）&lt;/li&gt;
&lt;li&gt;値が変更されたタイミングで、新しい値とともに、親コンポーネントの&lt;code&gt;update:ModelValue&lt;/code&gt;イベントを発火する（event up）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;またVue2との変更点として、modelオプションが廃止されました。その代わりにv-modelに引数を取ることができます。&lt;/p&gt;
&lt;p&gt;例えばカスタムコンポーネントの呼び出し側で&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;MyCustomComponent&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v-model&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;inputText&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt; &amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;とした場合、これは次と同じ意味になります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;MyCustomComponent&lt;/span&gt;&lt;span&gt;&lt;span&gt; :&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;inputText&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;inputText&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt; &amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;ちょうどデフォルト値の&lt;code&gt;modelValue&lt;/code&gt;の部分が指定した引数に置き換わるような形です。&lt;/p&gt;
&lt;p&gt;次に各APIでのカスタムコンポーネントの書き方を見ていきます。簡略化のため、引数は用いずにデフォルト値で実装します。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#vue3-options-api&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Vue3: Options API&lt;/h4&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;text&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;options&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v-model&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;innerValue&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;MyInputOptions&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;modelValue&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; String&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;computed&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;innerValue&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.modelValue&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;set&lt;/span&gt;&lt;span&gt;(newValue) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;&lt;span&gt;.$emit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;update:modelValue&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; newValue)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;算出プロパティを使用した形式ですが、Vue2で使用していた他の形式も使用できます（ただしmodelオプションは使えません）。&lt;/p&gt;
&lt;p&gt;差分としては先述のプロパティ名とイベント名です。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#vue3-composition-api&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Vue3: Composition API&lt;/h4&gt;
&lt;p&gt;Vue3.2.26からは&lt;code&gt;script setup&lt;/code&gt;構文が使えて、基本的にはこれが推奨されているので、その形式で書き直してみます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;text&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v-model&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;innerValue&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;setup&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;lang&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;ts&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { computed&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; defineEmits&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; defineProps } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;vue&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Props&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;modelValue&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Emits&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;(e&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;update:modelValue&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;defineProps&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Props&lt;/span&gt;&lt;span&gt;&amp;gt;()&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;emit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;defineEmits&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emits&lt;/span&gt;&lt;span&gt;&amp;gt;()&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;innerValue&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;computed&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt;.modelValue&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;set&lt;/span&gt;&lt;span&gt;(newValue&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;emit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;update:modelValue&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; newValue)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;一部tsが入ったことでPropsとEmitsの型が追加されましたが、冗長なreturn文が消えてスッキリしました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#v-modelの修飾子&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;v-modelの修飾子&lt;/h2&gt;
&lt;p&gt;v-modelでは&lt;code&gt;v-model.modifier&lt;/code&gt;の形式で修飾子を補うことで、v-modelにbindしている値を任意の形式に変換することができます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#vue-2系&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Vue 2系&lt;/h3&gt;
&lt;p&gt;Vue2では組み込みの修飾子3種類のみが定義されています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.trim&lt;/code&gt;：入力から空白を取り除く&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.number&lt;/code&gt;：入力をnumberへ型キャストする。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.lazy&lt;/code&gt;：inputイベントではなく、changeイベントでイベントを発火する&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#vue-3系&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Vue 3系&lt;/h3&gt;
&lt;p&gt;Vue3では上記の3種類の組み込み修飾子に加えて、カスタム修飾子を定義することもできるようになりました。&lt;/p&gt;
&lt;p&gt;公式のサンプルにもある、最初の一文字を大文字にする&lt;code&gt;capitalize&lt;/code&gt;修飾子を実装します。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;親コンポーネント&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;setup&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;lang&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;ts&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { ref } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;vue&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; MyVModelModifier &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;./components/MyVModelModifier.vue&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;text&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ref&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;MyVModelModifier&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v-model.capitalize&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;text&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;MyVModelModifier&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{{ text }}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;子コンポーネント&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;text&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:value&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;modelValue&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;@input&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emitValue&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;setup&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;defineProps&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;modelValue&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; String&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;modelModifiers&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; ({}) }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;emit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;defineEmits&lt;/span&gt;&lt;span&gt;([&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;update:modelValue&apos;&lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;emitValue&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (e) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; value &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;target&lt;/span&gt;&lt;span&gt;.value&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;modelModifiers&lt;/span&gt;&lt;span&gt;.capitalize) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;value &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;&lt;span&gt;.charAt&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;.toUpperCase&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;&lt;span&gt;.slice&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;emit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;update:modelValue&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; value)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;v-model.modifier&lt;/code&gt;の形式で記述すると、&lt;code&gt;modelModifiers&lt;/code&gt;というpropが使用できるようになります。例えば、`capitalize“をmodifierの位置に指定すると、&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;modelModifiers &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;capitalize&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;という具合にtrueを値に持つプロパティが作成されます。Vue側が提供するのはこのフラグ的な機能のみで、これを利用して実際にv-modelに紐づいたイベントで期待する処理（ここでは大文字にする処理）を実装する形式になります。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;ちょっと前までずっと&lt;code&gt;script setup&lt;/code&gt;で書いていたので、久しぶりにOptionsAPIだったり3.2.26以下のCompositionを触る機会でちょっと頭がこんがらがりました（「あれ、これVue3から使えるのか？CompositionAPIだから使えるのか？3.2.26以上で使えるのか？」など）。&lt;/p&gt;
&lt;p&gt;今回整理したので、これでしばらくは大丈夫でしょう！&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenges 17日目: 15-last-of-array</title><link>https://ikuma-t.com/blog/type-challenge-last-of-array/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-last-of-array/</guid><description>問題&amp;amp;解答https://github.com/type-challenges/type-challenges/blob/main/questions/00015-medium-last/RE</description><pubDate>Mon, 13 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#問題--解答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題 &amp;amp; 解答&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/type-challenges/type-challenges/blob/main/questions/00015-medium-last/README.md&quot; target=&quot;_blank&quot;&gt;https://github.com/type-challenges/type-challenges/blob/main/questions/00015-medium-last/README.md&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;配列&lt;code&gt;T&lt;/code&gt;をとって、最後の要素の型を返す&lt;code&gt;Last&amp;lt;T&amp;gt;&lt;/code&gt;を実装する。&lt;/p&gt;
&lt;p&gt;Variadic Tuple Typesが要素の最後でなくても使えるのがポイント。最後以外の要素を&lt;code&gt;_Rest&lt;/code&gt;として受けて、最後の要素を&lt;code&gt;Last&lt;/code&gt;で参照する。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Last&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;...infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;_Rest&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Last&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Last&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;never&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;類似の問題はこれ。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.work/posts/type-challenge-first-of-array&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.work/posts/type-challenge-first-of-array&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;別に参照する必要がないのであれば、&lt;code&gt;infer&lt;/code&gt;にする必要もない&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Last&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Last&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Last&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;never&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;そのうち、&lt;code&gt;Last&lt;/code&gt;を書くのも煩わしくなるくらいに慣れてきたら、これくらいが妥当なのかもしれない。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Last&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;L&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;L&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;never&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;類似の問題とはいえ、久しぶりに解く問題でもスラスラと解けるようになっているので、これをやっている意味はあると思われる。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenges 16日目: 12-Chainable Options</title><link>https://ikuma-t.com/blog/type-challenge-chainable-options/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-chainable-options/</guid><description>問題&amp;amp;解答https://github.com/type-challenges/type-challenges/blob/main/questions/00012-medium-chainab</description><pubDate>Sun, 12 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#問題--解答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題 &amp;amp; 解答&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/type-challenges/type-challenges/blob/main/questions/00012-medium-chainable-options/README.md&quot; target=&quot;_blank&quot;&gt;https://github.com/type-challenges/type-challenges/blob/main/questions/00012-medium-chainable-options/README.md&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;option(key, value)&lt;/code&gt;を任意の数チェインして、最終的な結果を&lt;code&gt;get()&lt;/code&gt;で呼び出すような 2 つの関数を提供する型を定義する。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Chainable&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Options&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {}&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;option&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;V&lt;/span&gt;&lt;span&gt;&amp;gt;(&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;V&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Chainable&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Options&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;&lt;span&gt; { [&lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;V&lt;/span&gt;&lt;span&gt; }&amp;gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Options&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;hr /&gt;
&lt;p&gt;全然わからなくて答えをみたので、解析していく。まず、単純に&lt;code&gt;option&lt;/code&gt;メソッドを持つオブジェクトを考える。&lt;/p&gt;
&lt;p&gt;このメソッドの要件は&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;引数は&lt;code&gt;key&lt;/code&gt;と&lt;code&gt;value&lt;/code&gt;で、&lt;code&gt;key&lt;/code&gt;に&lt;code&gt;string&lt;/code&gt;、&lt;code&gt;value&lt;/code&gt;に任意の型を受ける&lt;/li&gt;
&lt;li&gt;戻り値はここまで追加された option（オブジェクト）と、今回メソッドに渡された key と value で生成された option（オブジェクト）が合わさったもの。&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// ここまでに定義されたOptionをチェーンする。何もOptionがなければ`{}`が初期値として設定される&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Chainable&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Options&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {}&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;option&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;V&lt;/span&gt;&lt;span&gt;&amp;gt;(&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;V&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Chainable&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Options&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;&lt;span&gt; { [&lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;V&lt;/span&gt;&lt;span&gt; }&amp;gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;declare&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;base&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Chainable&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// Chainable&amp;lt;{}&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Optionsは初期値`{}`&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Chainable&amp;lt;{} &amp;amp; { &quot;require&quot;: boolean }&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Chainable&amp;lt;{ require: boolean }&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;requireOptionAdded&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;base&lt;/span&gt;&lt;span&gt;&lt;span&gt;.option&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;require&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// optionで返されているOptionsは`{ require: boolean }`&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Chainable&amp;lt;{ require: boolean } &amp;amp; { old: boolean }&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Chainable&amp;lt;{ require: boolean,  old: boolean; }&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;oldOptionAdded&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;requireOptionAdded&lt;/span&gt;&lt;span&gt;&lt;span&gt;.option&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;old&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;あとは現在保持している Options を返すように&lt;code&gt;get&lt;/code&gt;を実装する。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type Chainable&amp;lt;Options = {}&amp;gt; = {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;option&amp;lt;K extends string, V&amp;gt;(key: K, value: V): Chainable&amp;lt;Options &amp;amp; { [S in K]: V }&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;get(): Options;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#調べたこと&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;調べたこと&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#アンビエント宣言declare&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;アンビエント宣言（&lt;code&gt;declare&lt;/code&gt;）&lt;/h3&gt;
&lt;p&gt;JavaScript コードを生成せずに、型推論のためだけの情報を渡すのに使用する。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;declare&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; number;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;再帰とはまた違った形式だけれど、地味に汎用性の高い型定義だと思うので覚えておこう&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenges 15日目: Tuple to Union</title><link>https://ikuma-t.com/blog/type-challenge-tuple-to-union/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-tuple-to-union/</guid><description>問題&amp;amp;解答タプル型を受け取って、その要素からなるユニオン型を返すTupleToUnion&amp;lt;T&amp;gt;を実装する。typeArr=[&apos;1&apos;,&apos;2&apos;,&apos;3&apos;]typeTest=TupleTo</description><pubDate>Sat, 11 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#問題--解答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題 &amp;amp; 解答&lt;/h2&gt;
&lt;p&gt;タプル型を受け取って、その要素からなるユニオン型を返す&lt;code&gt;TupleToUnion&amp;lt;T&amp;gt;&lt;/code&gt;を実装する。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Arr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&apos;1&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;2&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;3&apos;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Test&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TupleToUnion&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Arr&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// expected to be &apos;1&apos; | &apos;2&apos; | &apos;3&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;ルックアップ型を利用して、配列の要素の型を取得します。&lt;code&gt;number&lt;/code&gt;で取得すると配列の要素すべての型がユニオン型で返ります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TupleToUnion&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;関連：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.work/posts/type-challenge-tuple-to-object&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.work/posts/type-challenge-tuple-to-object&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;TupleToObjectよりも簡単（Mapped Types使ってないし）と思ったんですけど、どうなんだろう。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenges 14日目: Deep Readonly</title><link>https://ikuma-t.com/blog/type-challenge-deep-readonly/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-deep-readonly/</guid><description>問題&amp;amp;解答https://github.com/type-challenges/type-challenges/blob/main/questions/00009-medium-deep-re</description><pubDate>Fri, 10 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#問題--解答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題 &amp;amp; 解答&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/type-challenges/type-challenges/blob/main/questions/00009-medium-deep-readonly/README.md&quot; target=&quot;_blank&quot;&gt;https://github.com/type-challenges/type-challenges/blob/main/questions/00009-medium-deep-readonly/README.md&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;オブジェクトの各プロパティを再帰的に&lt;code&gt;readonly&lt;/code&gt;にする&lt;code&gt;DeepReadonly&amp;lt;T&amp;gt;&lt;/code&gt;を実装する。&lt;/p&gt;
&lt;p&gt;前提：オブジェクトのみが渡される前提（クラスや配列、関数は考慮しなくてよい）&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;思考過程&lt;/p&gt;
&lt;p&gt;単純にReadonlyにするのであれば、&lt;code&gt;Mapped Types&lt;/code&gt;で定義すれば良い。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Readonly&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;] }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;再帰的にこの定義を実装していくので、&lt;code&gt;Recursive Conditional Types&lt;/code&gt;も使う。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;DeepReadonly&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;がオブジェクト&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;DeepReadonly&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;]&amp;gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;]   }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;T[P]がオブジェクトであるかどうかってどうやって判断するんだっけ？
ここでいうオブジェクトには関数とか配列は含まなくて、単純な&lt;code&gt;{ key: value }&lt;/code&gt;構造
インデックスシグネチャを利用する？ブル本には推奨されていなかったけど、一旦これでやってみる。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;DeepReadonly&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; { [key&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;unknown&lt;/span&gt;&lt;span&gt; } &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;DeepReadonly&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;]&amp;gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;] }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;一応代入しようとすると、&lt;code&gt;readonly&lt;/code&gt;になっているんだけど、型定義を確認すると&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Expected&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; b&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;　&lt;/span&gt;&lt;span&gt;// DeepReadonlyは適用されているものの、展開されていない&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;DeepReadonly&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;d&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// 略&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;となっていて、厳密な一致にはなっていない模様。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;…というところでもうわからんとなったので、他の方の回答をみました。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;DeepReadonly&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;never&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;k&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;DeepReadonly&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;k&lt;/span&gt;&lt;span&gt;]&amp;gt; }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/type-challenges/type-challenges/issues/187&quot; target=&quot;_blank&quot;&gt;https://github.com/type-challenges/type-challenges/issues/187&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;base caseを&lt;code&gt;keyof T extends never&lt;/code&gt;で拾って、recursive caseで&lt;code&gt;DeepReadonly&amp;lt;T&amp;gt;&lt;/code&gt;を呼び出しています。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;Objectの中でRecursive Conditional Typesを使うとなぜだめなのかがわかりませんでした。&lt;/p&gt;
&lt;p&gt;ちゃんと代入しようとすると&lt;code&gt;readonly&lt;/code&gt;になっているのに…。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenges 13日目: 8-Readonly 2</title><link>https://ikuma-t.com/blog/type-challenge-readonly-2/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-readonly-2/</guid><description>問題&amp;amp;解答https://github.com/type-challenges/type-challenges/blob/main/questions/00008-medium-readonl</description><pubDate>Thu, 09 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#問題--解答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題 &amp;amp; 解答&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/type-challenges/type-challenges/blob/main/questions/00008-medium-readonly-2/README.md&quot; target=&quot;_blank&quot;&gt;https://github.com/type-challenges/type-challenges/blob/main/questions/00008-medium-readonly-2/README.md&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;二つの引数&lt;code&gt;T&lt;/code&gt;、&lt;code&gt;K&lt;/code&gt;をとり、&lt;code&gt;K&lt;/code&gt;が指定されていれば&lt;code&gt;T&lt;/code&gt;のそのプロパティを、指定されていなければすべての&lt;code&gt;T&lt;/code&gt;のプロパティを読み取り専用に変換する&lt;code&gt;MyReadonly&amp;lt;T, K&amp;gt;&lt;/code&gt;を実装する。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyReadonly2&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;] } &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Omit&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;hr /&gt;
&lt;p&gt;「&lt;code&gt;readonly&lt;/code&gt;な&lt;code&gt;K&lt;/code&gt;で指定されているプロパティ &amp;amp; &lt;code&gt;T&lt;/code&gt;に含まれる&lt;code&gt;K&lt;/code&gt;以外のプロパティ」を目指して作っていきます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#1-readonlyなkで指定されているプロパティを作る&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;1. &lt;code&gt;readonly&lt;/code&gt;な&lt;code&gt;K&lt;/code&gt;で指定されているプロパティを作る&lt;/h3&gt;
&lt;p&gt;これが通常のReadonlyの実装です。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyReadonly2&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;] }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;このままだと&lt;code&gt;K&lt;/code&gt;の値が&lt;code&gt;readonly&lt;/code&gt;にならないので、mapped typesでぐるぐるするところを変えます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type MyReadonly2&amp;lt;T, K extends keyof T&amp;gt; = {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly [P in T]: T[P]&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly [P in K]: T[P]&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これにより&lt;code&gt;K&lt;/code&gt;に渡されたプロパティは&lt;code&gt;readonly&lt;/code&gt;になります。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#2-tに含まれるk以外のプロパティ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;2. &lt;code&gt;T&lt;/code&gt;に含まれる&lt;code&gt;K&lt;/code&gt;以外のプロパティ&lt;/h3&gt;
&lt;p&gt;これだけだと&lt;code&gt;K&lt;/code&gt;に含まれるプロパティしか含まれていません。そのため、&lt;code&gt;K&lt;/code&gt;に渡されなかったプロパティの型を取得する必要があります。これは&lt;code&gt;T&lt;/code&gt;の中から&lt;code&gt;K&lt;/code&gt;に該当するプロパティを除いたものです。&lt;/p&gt;
&lt;p&gt;例えば以下のような&lt;code&gt;T&lt;/code&gt;と&lt;code&gt;K&lt;/code&gt;を渡すことを考えます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// こっちがT&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Music&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;artist&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;releaseYear&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// こっちがK&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ReadonlyRequiredParams&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;artist&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;releaseYear&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;最終的に&lt;code&gt;MyReadonly2&lt;/code&gt;に期待するのは次のような形式なので、&lt;code&gt;name: string&lt;/code&gt;を取り出せれば良いはずです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Expected&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// TODO: これから取得したい&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; artist&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// { readonly [P in K]: T[P] } で表現される&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; releaseYear&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// { readonly [P in K]: T[P] } で表現される&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これは昨日出てきた&lt;code&gt;Omit&lt;/code&gt;（組み込みの型の方です）を使用して、&lt;code&gt;Omit&amp;lt;T, K&amp;gt;&lt;/code&gt;の形式で取り出すことができます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Music2&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Omit&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Music&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ReadonlyRequiredParams&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// type Music2 = { name: string; }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#3-1と2を合体&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;3. 1と2を合体&lt;/h3&gt;
&lt;p&gt;これらをインターセクション型で繋ぎこむと、解答を得ることができます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyReadonly2&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;] } &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Omit&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#4-kのデフォルト値を設定する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;4. &lt;code&gt;K&lt;/code&gt;のデフォルト値を設定する&lt;/h3&gt;
&lt;p&gt;…と思ったらまだエラーが出ています。この型は&lt;code&gt;K&lt;/code&gt;を省略可能なのでそこでひっかります。&lt;code&gt;K&lt;/code&gt;は参照されるので何かしらの値を入れておく必要があります。&lt;/p&gt;
&lt;p&gt;TypeScriptは型引数にデフォルト値を取ることができます。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://typescriptbook.jp/reference/generics/default-type-parameter&quot; target=&quot;_blank&quot;&gt;https://typescriptbook.jp/reference/generics/default-type-parameter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;今回は「&lt;code&gt;K&lt;/code&gt;を指定しなかった場合、すべてのプロパティが&lt;code&gt;readonly&lt;/code&gt;になる」ので、&lt;code&gt;K&lt;/code&gt;には「&lt;code&gt;T&lt;/code&gt;のプロパティすべて」を設定します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type MyReadonly2&amp;lt;T,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;K extends keyof T&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;K extends keyof T = keyof T&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;hr /&gt;
&lt;p&gt;他の人の解答を見ていたら、&lt;code&gt;Omit&amp;lt;T, K&amp;gt;&lt;/code&gt;の部分を&lt;code&gt;&amp;amp; T&lt;/code&gt;で繋ぎ込んでいる解答もあったのですが、これではだめでした。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Todo1&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;completed&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Todo2&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; title&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;completed&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TodoX&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Todo1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Todo2&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;todoX&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TodoX&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;JavaScriptを勉強する&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;completed&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;todoX&lt;/span&gt;&lt;span&gt;.title &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;TypeScript&quot;&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// titleはreadonlyではない。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;う〜ん、最後のインターセクション型の挙動についてはドキュメントをざっと読んだのですが、期待する記述は見つけられませんでした。&lt;code&gt;readonly&lt;/code&gt;だけならいいんですが、他にも自分が理解できていない部分があると怖いです。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenges 12日目: 3-Omit</title><link>https://ikuma-t.com/blog/type-challenge-omit/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-omit/</guid><description>問題&amp;amp;解答組み込みのOmit&amp;lt;T,K&amp;gt;を実装する。Tのプロパティから、Kを除いた型を返す。typeMyExclude&amp;lt;T,U&amp;gt;=TextendsU?never:T;ty</description><pubDate>Wed, 08 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#問題--解答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題 &amp;amp; 解答&lt;/h2&gt;
&lt;p&gt;組み込みの&lt;code&gt;Omit&amp;lt;T, K&amp;gt;&lt;/code&gt;を実装する。&lt;code&gt;T&lt;/code&gt;のプロパティから、&lt;code&gt;K&lt;/code&gt;を除いた型を返す。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyExclude&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;never&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyOmit&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; { [&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyExclude&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt;&amp;gt;]&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;] }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;別解（こっちの方がナウい）&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyOmit&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; { [&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Exclude&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt;&amp;gt;]&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;]  }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#調べたこと&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;調べたこと&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#key-remapping-in-mapped-types&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Key Remapping in Mapped Types&lt;/h3&gt;
&lt;p&gt;Mapped Typesで使えるプロパティ名（キー）の再定義方法。&lt;/p&gt;
&lt;p&gt;一例としてすべてのプロパティを&lt;code&gt;readonly&lt;/code&gt;にするような型を書いてみます。
（組み込み型として&lt;code&gt;Readonly&lt;/code&gt;がありますが、理解のためにあえて再実装します）&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Mapped Typesを使って、各プロパティをreadonlyにする&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyReadonly&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;] }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// 以下はサンプル&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Book&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;author&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;book&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Book&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;ABC殺人事件&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;author&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;アガサ・クリスティ&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;readonlyBook&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyReadonly&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Book&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;銀河鉄道の夜&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;author&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;宮沢賢治&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;book&lt;/span&gt;&lt;span&gt;.name &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;オリエント急行の殺人&quot;&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;// OK&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Mapped Typesによってreadonlyになっているので、変更が禁止されている。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;readonlyBook&lt;/span&gt;&lt;span&gt;.name &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;注文の多い料理店&quot;&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;// TS2540: Cannot assign to &apos;name&apos; because it is a read-only property.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;このMapped Typesの使用法では、プロパティの属性は変わっていますが（指定なし→&lt;code&gt;readonly&lt;/code&gt;）、プロパティ名自体は変わっていません（&lt;code&gt;name&lt;/code&gt;は&lt;code&gt;name&lt;/code&gt;のまま、&lt;code&gt;author&lt;/code&gt;は&lt;code&gt;author&lt;/code&gt;のまま）。&lt;/p&gt;
&lt;p&gt;TypeScript 4.1 以降で導入されたMapped Typesで使用できる&lt;code&gt;as&lt;/code&gt;キーワードを使用すると、プロパティ名を変更することができるようになります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// as キーワードを利用して、`keyof T`で取得される「name」「author」をそれぞれ「specialName」「specialAuthor」に変換する&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MySpecial&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; { [&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;`special&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;&lt;span&gt;Capitalize&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;] }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// プロパティ名が変換されている&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;specialBook&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MySpecial&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Book&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;specialName&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;SPY FAMILY&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;specialAuthor&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;遠藤達哉&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;console&lt;/span&gt;&lt;span&gt;&lt;span&gt;.log&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;specialBook&lt;/span&gt;&lt;span&gt;.name); &lt;/span&gt;&lt;span&gt;// TS2339: Property &apos;name&apos; does not exist on type &apos;My Special&quot;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;as&lt;/code&gt;の後ろに変換後の名前を指定します。今回はTemplate Literal Typesを利用して、動的にプロパティを組み立てています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;`special&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;Capitalize&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;string &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// &quot;specialXxxxx...&quot;に変換&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;p&gt;&lt;code&gt;Capitalize&lt;/code&gt;については、TypeScriptのコンパイラに組み込まれている型でその名の通り1文字目を大文字にして返します。
定義としては&lt;code&gt;Capitalize&amp;lt;string&amp;gt;&lt;/code&gt;になりますが、&lt;code&gt;keyof&lt;/code&gt;で取得しているのはオブジェクトのプロパティなので&lt;code&gt;string | symbol | number&lt;/code&gt;の可能性があるため、参照したプロパティ名をそのまま使用してしまうとエラーになります。&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;`special&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;Capitalize&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;//TS2344: Type &apos;P&apos; does not satisfy the constraint &apos;string&apos;. Type &apos;keyof T&apos; is not assignable to type &apos;string&apos;.Type &apos;string | number | symbol&apos; is not assignable to type &apos;string&apos;.Type &apos;number&apos; is not assignable to type &apos;string&apos;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;そのため、インターセクション型を利用して、&lt;code&gt;string&lt;/code&gt;に絞り込んでいます。&lt;/p&gt;&lt;/div&gt;
&lt;hr /&gt;
&lt;p&gt;ここまでの例では単純にプロパティ名を変換しているだけでしたが、&lt;code&gt;as&lt;/code&gt;は&lt;code&gt;never&lt;/code&gt;を返した場合にそのプロパティを除外することもできます。これが今回の問題の別解です。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Conditional Typesでそのまま実装した形式&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyOmit&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; { [&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;never&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;] }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// 組み込みのExcludeを使用する&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyOmit&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; { [&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Exclude&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt;&amp;gt;]&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;] }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;参考&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/2/mapped-types.html#key-remapping-via-as&quot; target=&quot;_blank&quot;&gt;https://www.typescriptlang.org/docs/handbook/2/mapped-types.html#key-remapping-via-as&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html&quot; target=&quot;_blank&quot;&gt;https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;組み込みのExcludeを使っていいのかどうかわからなくて再実装しました。Excludeは過去回で登場しています。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.work/posts/type-challenge-exclude&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.work/posts/type-challenge-exclude&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;解いた後にantfuさんの解答のスレッドをみて&lt;code&gt;as&lt;/code&gt;が使えることを知って色々と調べました。ワカラナイコトマダマダタクサンネ・・・。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>デスクを変えたのでモニターアームが使えるようになった</title><link>https://ikuma-t.com/blog/setup-desk-2022-06/</link><guid isPermaLink="true">https://ikuma-t.com/blog/setup-desk-2022-06/</guid><description>月1で「Fika」をやっている最近「Fika」と称して家族会議的なものを月1でやっています。これは月に1度ただカフェに行って夫婦間で「そういえばこれ変えたいんだけど」とか「本当はこういう暮らしがしたい</description><pubDate>Tue, 07 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#月1でfikaをやっている&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;月1で「Fika」をやっている&lt;/h2&gt;
&lt;p&gt;最近「Fika」と称して家族会議的なものを月1でやっています。&lt;/p&gt;
&lt;p&gt;これは月に1度ただカフェに行って夫婦間で「そういえばこれ変えたいんだけど」とか「本当はこういう暮らしがしたい」みたいなことをただ言っていく試みです。
「Fika」という名前はスウェーデン語のコーヒーブレイク的な意味で、「短い名前だと予定入れやすいし、可愛い名前だとテンション上がるよね」ということで命名しています。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A3%E3%83%BC%E3%82%AB&quot; target=&quot;_blank&quot;&gt;https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A3%E3%83%BC%E3%82%AB&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;もともとこういう夫婦感の課題解決みたいなところはだいぶ前から挑戦していて、TrelloやNotionにタスクを積んだりしていたのですが、如何せんそういうのが好きなのは私だけでして、妻はまったく見ず、何も解決に向かわないことからがっつり時間を設けてその中で発散し、アクションを決めていくスタイルに移行しました。This is Fikaです。&lt;/p&gt;
&lt;p&gt;一応議事録の役割と話のフレームみたいなものがあった方が課題を見つけやすいので、Transnoを利用して1枚のマインドマップを毎回その場で更新しながら話をしています。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;
&lt;em&gt;transnoで作成しているマインドマップ&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Transnoについてはこちらの記事で紹介しています。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ikmbear.hatenablog.com/entry/20211215/1639551694&quot; target=&quot;_blank&quot;&gt;https://ikmbear.hatenablog.com/entry/20211215/1639551694&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;今日のテーマは「家」から派生して「ものを減らす」だったので、アクションとしてあがったものを色々と整理した上でそのついでにリビングの机と作業用のデスクを入れ替えました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#デスク入れ替えでモニターアームが使えるように&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;デスク入れ替えでモニターアームが使えるように&lt;/h2&gt;
&lt;p&gt;もともと横長のそこそこ大きいデスクを使っていたんですが、机の各辺に12cmくらいの返しがあったため、モニターアームを購入しておきながら使えていませんでした（2年くらい倉庫に眠っていた）。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;もともとの机は写真のデスクの2倍の長さがあったので、「モニターアームが使えるようになるのはいいけど、メモリが狭くなるのはいたしかたなしか〜」とややネガティブに捉えていたのですが、入れ替えてみると全然問題なし。&lt;/p&gt;
&lt;p&gt;むしろ広いスペースにものがおけなくなったことで、本当に必要なものだけがおけるようになりました。これはパーキンソンの第N法則に掲げていいかと。&lt;/p&gt;
&lt;p&gt;モニターアームを導入したことでモニター配下にクラムシェルのMacが配置できるようになったので、とても良い感じです。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;来週から新しいお仕事が始まる予定なので、今回のデスク含めて現状の作業環境で使用しているものを近日中にまとめておいて、定点観測で何が不要で逆に何が必要だったかまとめたいと思います。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenges 11日目: 2-Get Return Type</title><link>https://ikuma-t.com/blog/type-challenge-get-return-type/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-get-return-type/</guid><description>問題&amp;amp;解答組み込みのReturnType&amp;lt;T&amp;gt;を実装する。inferで戻り値の型を取得して、あとはいつものUorneverです。typeMyReturnType&amp;lt;Texten</description><pubDate>Tue, 07 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#問題--解答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題 &amp;amp; 解答&lt;/h2&gt;
&lt;p&gt;組み込みの&lt;code&gt;ReturnType&amp;lt;T&amp;gt;&lt;/code&gt;を実装する。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;infer&lt;/code&gt;で戻り値の型を取得して、あとはいつものU or neverです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyReturnType&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;never&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#調べたこと&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;調べたこと&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#returntype&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;code&gt;ReturnType&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/utility-types.html#returntypetype&quot; target=&quot;_blank&quot;&gt;https://www.typescriptlang.org/docs/handbook/utility-types.html#returntypetype&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;関数&lt;code&gt;F&lt;/code&gt;を渡すと、その戻り値の型を返す。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ReturnType&lt;/span&gt;&lt;span&gt;&amp;lt;() &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// type T0 = string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;昨日の問題の変化系ですね。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.work/posts/type-challenge-parameters&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.work/posts/type-challenge-parameters&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;任意の関数を示すのに、&lt;code&gt;(...args: any[]) =&amp;gt; any&lt;/code&gt;がさらっと出てくるようになったのは成長の証です。&lt;/p&gt;
&lt;p&gt;ところでMediumの問題とEasyの境目はなんなのでしょうか…。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Reactのchildrenとはなにか</title><link>https://ikuma-t.com/blog/what-is-react-children/</link><guid isPermaLink="true">https://ikuma-t.com/blog/what-is-react-children/</guid><description>要約Reactのchildrenはpropsが保持しているプロパティです。親コンポーネントのタグに入れられた要素を参照します。ReactナニモワカラナイいままでVueとVanilaJSしか触ってこなか</description><pubDate>Tue, 07 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#要約&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;要約&lt;/h2&gt;
&lt;p&gt;Reactの&lt;code&gt;children&lt;/code&gt;は&lt;code&gt;props&lt;/code&gt;が保持しているプロパティです。親コンポーネントのタグに入れられた要素を参照します。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#reactナニモワカラナイ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Reactナニモワカラナイ&lt;/h2&gt;
&lt;p&gt;いままでVueとVanila JSしか触ってこなかったので、現在TypeScriptとReactのキャッチアップをしているのですが、まずはTypeScriptに時間を割いているためReactはちょっと後回し気味です（のわりにDenoやってるやんけワレ）。一応チュートリアルくらいはやっています。&lt;/p&gt;
&lt;p&gt;いやでもReact と TSが目につくようにこのブログはNext.js + TypeScriptで作成しているのですが、カスタマイズにあたってReactの初歩的な知識でつまづいたのでまとめます。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#reactのchildren&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Reactのchildren&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#対象バージョン&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;対象バージョン&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;React v18.0&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#意味&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;意味&lt;/h3&gt;
&lt;p&gt;Reactの&lt;code&gt;children&lt;/code&gt;は&lt;code&gt;props&lt;/code&gt;が保持しているプロパティです。親コンポーネントのタグに入れられた要素を参照します。&lt;/p&gt;
&lt;p&gt;例えばこのブログでは共通レイアウトを&lt;code&gt;Layout&lt;/code&gt;コンポーネントで定義しています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Props&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;children&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;React&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ReactNode&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Layout&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; ({ children }&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Props&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Meta &lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;div className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;min-h-screen flex flex-col&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;main className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;flex-1&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;{children}&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Footer &lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&amp;lt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;Layout&lt;/code&gt;コンポーネントは各所で使用されており、一例としてブログのトップページを示す&lt;code&gt;pages/index.tsx&lt;/code&gt;では次のように呼び出されています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Index&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; ({ allPosts }&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Props&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;morePosts&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; allPosts&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Layout&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Head&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;&amp;gt;ikuma&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;Head&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Container&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Intro &lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&amp;lt;MoreStories posts&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{morePosts} &lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;Container&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;Layout&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&amp;lt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;この時、&lt;code&gt;&amp;lt;Layout&amp;gt;&lt;/code&gt; ~ &lt;code&gt;&amp;lt;/Layout&amp;gt;&lt;/code&gt;の間の部分が&lt;code&gt;children&lt;/code&gt;となります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Head&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;&amp;gt;ikuma&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;Head&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Container&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Intro &lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;MoreStories posts&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{morePosts} &lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;Container&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;Layout&lt;/code&gt;コンポーネントでは最終的に次のような内容が描画されます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Meta &lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;div className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;min-h-screen flex flex-col&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;main className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;flex-1&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;// ここからchildrenの内容が描画されている}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Head&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;&amp;gt;ikuma&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;Head&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Container&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Intro &lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;MoreStories posts&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{morePosts} &lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;Container&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;// ここまでchildrenの内容が描画されている}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Footer &lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#childrenの型&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;childrenの型&lt;/h3&gt;
&lt;p&gt;先のサンプルコードの通り、&lt;code&gt;children&lt;/code&gt;の型は&lt;code&gt;React.ReactNode&lt;/code&gt;です。
どうもv18から仕様が変わったようで、明示的に型を指定していない状態で&lt;code&gt;props.children&lt;/code&gt;を使用すると、エラーになるようになったそうです。&lt;/p&gt;
&lt;p&gt;参考：&lt;a href=&quot;https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html#updates-to-typescript-definitions&quot; target=&quot;_blank&quot;&gt;https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html#updates-to-typescript-definitions&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;おわり&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenges easyを解きおえた</title><link>https://ikuma-t.com/blog/type-challenge-easy/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-easy/</guid><description>https://github.com/type-challenges/type-challengestype-challenges、easy問題の全13問を解き終えたので、一旦振り返りたいと思います。</description><pubDate>Mon, 06 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://github.com/type-challenges/type-challenges&quot; target=&quot;_blank&quot;&gt;https://github.com/type-challenges/type-challenges&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;type-challenges、easy問題の全13問を解き終えたので、一旦振り返りたいと思います。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#各問題の振り返り&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;各問題の振り返り&lt;/h2&gt;
&lt;p&gt;一言書こうと思ったのですが、終盤にいくにつれて特筆事項がなくなったので、ただの羅列です😅&lt;/p&gt;
&lt;p&gt;:::details 各問題へのリンク&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.work/posts/type-challenge-pick&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.work/posts/type-challenge-pick&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyPick&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; { [&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;] }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;キーワード：&lt;code&gt;keyof&lt;/code&gt;、&lt;code&gt;Indexed Access Type&lt;/code&gt;、&lt;code&gt;Mapped Types&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;初見で無事ギブアップした回。最初は全くもって意味不明な記号でしたが今は見慣れました。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.work/posts/type-challenge-readonly&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.work/posts/type-challenge-readonly&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyReadonly&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;] }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;キーワード：&lt;code&gt;Mapped types&lt;/code&gt;、&lt;code&gt;readonly&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;当日も自力で解けたと言っています。今回も解けました。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.work/posts/type-challenge-tuple-to-object&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.work/posts/type-challenge-tuple-to-object&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TupleToObject&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;[]&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; { [&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;キーワード：&lt;code&gt;Tuple&lt;/code&gt;、&lt;code&gt;Indexed Access Type&lt;/code&gt;、`Mapped Types&lt;/p&gt;
&lt;p&gt;ここらへんで&lt;code&gt;Mapped Types&lt;/code&gt;に慣れてきました。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.work/posts/type-challenge-first-of-array&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.work/posts/type-challenge-first-of-array&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;First&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; [] &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;never&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;First&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;...infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Rest&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;never&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;キーワード：&lt;code&gt;infer&lt;/code&gt;、&lt;code&gt;Conditional Types&lt;/code&gt;, &lt;code&gt;Indexed Access Types&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;infer&lt;/code&gt;キーワード初出。これも今はだいぶ見慣れてきました。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.work/posts/type-challenge-length-of-tuple&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.work/posts/type-challenge-length-of-tuple&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Length&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;length&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;キーワード：&lt;code&gt;Indexed Access Types&lt;/code&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.work/posts/type-challenge-exclude&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.work/posts/type-challenge-exclude&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Exclude&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt; T extends U ? never : T&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;キーワード：&lt;code&gt;Conditional Types&lt;/code&gt;、&lt;code&gt;Union Types&lt;/code&gt;、&lt;code&gt;Distributive&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;分配法則初登場回&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.work/posts/type-challenge-awaited&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.work/posts/type-challenge-awaited&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyAwaited&lt;/span&gt;&lt;span&gt;&amp;lt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;extend&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyAwaited&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;never&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;キーワード：&lt;code&gt;infer&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;再起的な型推論&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.work/posts/type-challenge-if&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.work/posts/type-challenge-if&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;If&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;C&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;F&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;C&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;キーワード: &lt;code&gt;Conditional Types&lt;/code&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.work/posts/type-challenge-concat&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.work/posts/type-challenge-concat&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Concat&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;キーワード: &lt;code&gt;Variadic Tuple Types&lt;/code&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.work/posts/type-challenge-includes&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.work/posts/type-challenge-includes&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// この回はわからなかったのでコピペしました。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Includes&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;unknown&lt;/span&gt;&lt;span&gt;[]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;First&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;...infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Rest&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Equal&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;First&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Includes&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Rest&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;キーワード: &lt;code&gt;Conditional Types&lt;/code&gt;、&lt;code&gt;infer&lt;/code&gt;、 &lt;code&gt;Variadic Tuple Types&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;めちゃくちゃ難しかった回です。厳密な等価評価の部分は今でもよくわかっていません。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.work/posts/type-challenge-push&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.work/posts/type-challenge-push&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Push&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;キーワード: &lt;code&gt;Variadic Tuple Types&lt;/code&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.work/posts/type-challenge-unshift&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.work/posts/type-challenge-unshift&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Unshift&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;キーワード: &lt;code&gt;Variadic Tuple Types&lt;/code&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.work/posts/type-challenge-parameters&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.work/posts/type-challenge-parameters&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyParameters&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;never&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;キーワード： &lt;code&gt;infer&lt;/code&gt;、&lt;code&gt;Conditional Types&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;:::&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;出てきたキーワードで重複しているものは&lt;code&gt;Conditional Types&lt;/code&gt;、&lt;code&gt;infer&lt;/code&gt;、&lt;code&gt;Variadic Tuple Types&lt;/code&gt;、&lt;code&gt;Mapped Types&lt;/code&gt;、&lt;code&gt;Indexed Access Types&lt;/code&gt;、&lt;code&gt;keyof&lt;/code&gt;って感じですかね。&lt;/p&gt;
&lt;p&gt;自分はプリミティブ型とそこそこの用語だけオライリーの本で覚えて、あとはエイやでTypeScriptの世界にきてしまったので、いわゆる「高度な型」を実際に学ぶことができているのはとても良いなあと思います。&lt;/p&gt;
&lt;p&gt;もともとTypeScriptを勉強しようとしたきっかけは、自作サービスを作っている時に、各ライブラリのドキュメントとかソースが軒並みTS化していて、「これTypeScriptがわからないと、単位時間あたりで取得できる情報量めちゃくちゃしょぼいんじゃね」と思ったのがきっかけでした。&lt;/p&gt;
&lt;p&gt;自分で練習で書いているコードではeasyの問題に出てくるようなコードもまだそこまで書いていませんが、本来の目的であるライブラリのソースを理解するという点では非常に役に立っていると思います。&lt;/p&gt;
&lt;p&gt;というわけで明日からはmedium編に突入です。これまでの延長で解けるのか、はたまた撃沈するかわかりませんが、毎日1問解いていきます！&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenge 10日目(その2): 3312-Parameters</title><link>https://ikuma-t.com/blog/type-challenge-parameters/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-parameters/</guid><description>問題&amp;amp;解答https://github.com/type-challenges/type-challenges/blob/main/questions/03312-easy-parameter</description><pubDate>Mon, 06 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#問題--解答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題 &amp;amp; 解答&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/type-challenges/type-challenges/blob/main/questions/03312-easy-parameters/README.md&quot; target=&quot;_blank&quot;&gt;https://github.com/type-challenges/type-challenges/blob/main/questions/03312-easy-parameters/README.md&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;組み込みの型Parametersを実装する&lt;/p&gt;
&lt;p&gt;やりたいことは、関数&lt;code&gt;T&lt;/code&gt;の引数の型を動的に取得することなので、&lt;code&gt;infer&lt;/code&gt;を使用する。参照したらいつものパターン&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyParameters&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;never&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#調べたこと&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;調べたこと&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#parameters型&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Parameters型&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/utility-types.html#parameterstype&quot; target=&quot;_blank&quot;&gt;https://www.typescriptlang.org/docs/handbook/utility-types.html#parameterstype&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Parametes&amp;lt;T&amp;gt;&lt;/code&gt;の形式で、関数&lt;code&gt;T&lt;/code&gt;の引数の型のタプル型を生成する。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenge 10日目: 3060-Unshift</title><link>https://ikuma-t.com/blog/type-challenge-unshift/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-unshift/</guid><description>問題&amp;amp;解答Array.prototype.unshiftを型で実装する。あれ、これ昨日とほぼ同じでは？typeUnshift&amp;lt;Textendsany[],U&amp;gt;=[U,...T]Va</description><pubDate>Mon, 06 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#問題--解答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題 &amp;amp; 解答&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Array.prototype.unshift&lt;/code&gt;を型で実装する。&lt;/p&gt;
&lt;p&gt;あれ、これ昨日とほぼ同じでは？&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Unshift&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Variadic Tuple Typeで解くことができました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;Unshiftを先にやってからPushをやった方がよかったかもしれないです（Variadic Tuple Type)の位置が最後でなくても使えるというはっけんがあるから）&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>ブログ用のコマンド試作その4</title><link>https://ikuma-t.com/blog/create-blog-command-4/</link><guid isPermaLink="true">https://ikuma-t.com/blog/create-blog-command-4/</guid><description>https://ikuma-t.work/posts/create-blog-command-3前回の時点ではただファイルを生成するシェルスクリプトでしたが、今回思い切って一気に色々機能を追加しました</description><pubDate>Sun, 05 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://ikuma-t.work/posts/create-blog-command-3&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.work/posts/create-blog-command-3&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;前回の時点ではただファイルを生成するシェルスクリプトでしたが、今回思い切って一気に色々機能を追加しました。&lt;/p&gt;
&lt;p&gt;というわけでできたものがこちら。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/IkumaTadokoro/blog-cli&quot; target=&quot;_blank&quot;&gt;https://github.com/IkumaTadokoro/blog-cli&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;もともとRubyで書いていてThor gemで作ろうと思っていたのですが、インタラクティブなものを作るのが大変そうだったのと、2日前くらいから「Denoってなんかいいな」と思い始めたので、途中からDenoに切り替えて実装しました。
各機能を順番に紹介していきます。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#実装&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;実装&lt;/h2&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;❯&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;deno&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--version&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;deno&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;1.22.2&lt;/span&gt;&lt;span&gt; (release, &lt;/span&gt;&lt;span&gt;x86_64-apple-darwin&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;v8&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;10.3.174.6&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;typescript&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;4.6.2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Third PartyにはcliffyというCLI用のフレームワークを使用しているのみです。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://cliffy.io/&quot; target=&quot;_blank&quot;&gt;https://cliffy.io/&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;p&gt;追記: 嘘をつきました。&lt;a href=&quot;https://deno.land/x/frontmatter@v0.1.4/mod.ts&quot; target=&quot;_blank&quot;&gt;frontmatter@v0.1.4 | Deno&lt;/a&gt;も使っていました。&lt;/p&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#機能一覧&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;機能一覧&lt;/h2&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;❯&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;blog&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-h&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Usage:&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;blog&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Version:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0.1.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Description:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;✍️&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;CLI&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tool&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;my&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;blog:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;https://ikuma-t.work&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Options:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-h,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--help&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Show&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;help.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-V,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--version&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Show&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;the&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;program.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Commands:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;completions&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Generate&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;shell&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;completions.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;list&lt;/span&gt;&lt;span&gt;         &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;List&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;the&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;last&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;articles&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;open&lt;/span&gt;&lt;span&gt;         &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Open&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;blog&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;browser&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;config&lt;/span&gt;&lt;span&gt;       &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Config&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;BLOG_PATH&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Create&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;article&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;edit&lt;/span&gt;&lt;span&gt;         &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Edit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;article&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;editor.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#各機能紹介&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;各機能紹介&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#設定-config&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;設定: &lt;code&gt;config&lt;/code&gt;&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;❯&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;blog&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;config&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;記事の格納ディレクトリを指定してください&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;設定が完了しました&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;❯&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;blog&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;config&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-h&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Usage:&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;blog&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;config&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Version:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0.1.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Description:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Config&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;BLOG_PATH&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Options:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-h,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--help&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Show&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;help.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;設定用のコマンドです。ブログ記事のあるパスを雑にJSONファイルにして保存しています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#補完completions&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;補完：&lt;code&gt;completions&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;❯&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;blog&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;completions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-h&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Usage:&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;blog&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;completions&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Version:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0.1.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Description:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Generate&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;shell&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;completions.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;To&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;enable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;shell&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;completions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;program&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;the&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;following&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;line&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;your&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/.bashrc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;or&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;similar:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;source&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;(&lt;/span&gt;&lt;span&gt;blog&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;completions&lt;/span&gt;&lt;span&gt; [shell])&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;For&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;more&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;information&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;blog&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;completions&lt;/span&gt;&lt;span&gt; [shell] --help&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Options:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-h,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--help&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Show&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;help.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Commands:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;bash&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Generate&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;shell&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;completions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;bash.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;fish&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Generate&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;shell&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;completions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fish.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;zsh&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Generate&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;shell&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;completions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;zsh.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;cliffyのビルトインコマンドの1つで、各シェルの補完機能を提供します。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://cliffy.io/docs@v0.24.2/command/build-in-commands#completions-command&quot; target=&quot;_blank&quot;&gt;https://cliffy.io/docs@v0.24.2/command/build-in-commands#completions-command&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;私の場合はzshを使っているので、&lt;code&gt;.zshrc&lt;/code&gt;あたりに&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;source&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;(&lt;/span&gt;&lt;span&gt;blog&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;completions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;zsh&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;と書いてあげることで、自動的に補完が使用できるようになります。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#ブログを開く-open&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ブログを開く： &lt;code&gt;open&lt;/code&gt;&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;❯&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;blog&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;open&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-h&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Usage:&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;blog&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;open&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Version:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0.1.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Description:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Open&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;blog&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;browser&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Options:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-h,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--help&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Show&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;help.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;ブラウザでブログを開きます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#一覧-list&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;一覧: &lt;code&gt;list&lt;/code&gt;&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;❯&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;blog&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;list&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-h&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Usage:&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;blog&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;list&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Version:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0.1.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Description:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;List&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;the&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;last&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;articles&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Options:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-h,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--help&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Show&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;help.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-a,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--all&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;List&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;all&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;articles&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;instead&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;of&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;the&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;last&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;articles&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;デフォルトでは最新の記事5件を取得します。&lt;code&gt;-a&lt;/code&gt;オプション指定時には全て取得します。&lt;/p&gt;
&lt;p&gt;表示するのは左から、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ファイル名&lt;/li&gt;
&lt;li&gt;記事名（YAMLフロントマターから取得）&lt;/li&gt;
&lt;li&gt;投稿日（YAMLフロントマターから取得）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;です。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;┌─────────────────────────────┬─────────────────────────────────────┬─────────────────────┐&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;                        &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;                               &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;published_at&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;├─────────────────────────────┼─────────────────────────────────────┼─────────────────────┤&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;join-mdn-translate-event.md&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MDNドキュメントの翻訳に参加&lt;/span&gt;&lt;span&gt;                 &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2022-06-18&lt;/span&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;├─────────────────────────────┼─────────────────────────────────────┼─────────────────────┤&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;sample.md&lt;/span&gt;&lt;span&gt;                   &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;サンプルの記事&lt;/span&gt;&lt;span&gt;                           &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2022-06-05&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;22:06:58&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;├─────────────────────────────┼─────────────────────────────────────┼─────────────────────┤&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;create-blog-command-4.md&lt;/span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ブログ用のコマンド試作その4&lt;/span&gt;&lt;span&gt;                   &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2022-06-05&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;21:06:49&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;├─────────────────────────────┼─────────────────────────────────────┼─────────────────────┤&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;type-challenge-push.md&lt;/span&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type-challenge&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;9日目:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3057-Push&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2022-06-05&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;15:06:43&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;├─────────────────────────────┼─────────────────────────────────────┼─────────────────────┤&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;type-challenge-unshift.md&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type-challenge&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10日目:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3060-Unshift&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2022-06-05&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;15:06:11&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;└─────────────────────────────┴─────────────────────────────────────┴─────────────────────┘&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;出力はcliffyのTableを使用しています。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://cliffy.io/docs@v0.24.2/table&quot; target=&quot;_blank&quot;&gt;https://cliffy.io/docs@v0.24.2/table&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;日本語が全体的にダメで、ちょっとずれてしまっているんですが、実害がないので無視しています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#新規作成-new&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;新規作成: &lt;code&gt;new&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;❯&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;blog&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-h&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Usage:&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;blog&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Version:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0.1.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Description:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Create&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;article&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Options:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-h,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--help&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Show&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;help.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;タイトルとファイル名を指定して記事を作成します。&lt;/p&gt;
&lt;p&gt;cliffyのInput promptにはlocal storageもしくは配列を使用して入力値をサジェストできる機能があります。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://cliffy.io/docs@v0.24.2/prompt/types/input#auto-suggestions&quot; target=&quot;_blank&quot;&gt;https://cliffy.io/docs@v0.24.2/prompt/types/input#auto-suggestions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;シリーズものの記事を書く際に、以前の回の記事名などを参照することがあるので、過去記事を配列につっこんでカーソルキーで候補が出るようになっています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#編集-edit&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;編集: &lt;code&gt;edit&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;❯&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;blog&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;edit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-h&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Usage:&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;blog&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;edit&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Version:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0.1.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Description:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Edit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;article&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;editor.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Options:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-h,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--help&lt;/span&gt;&lt;span&gt;              &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Show&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;help.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-e,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--editor&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&amp;lt;editor&amp;gt;&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Choose&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;your&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;editor.&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Default&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;is&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;vim&lt;/span&gt;&lt;span&gt;  (Default: &lt;/span&gt;&lt;span&gt;&quot;vim&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;ファイルを指定して編集します。エディタはオプションで指定できるのですが、デフォルトはvimです（たまに&lt;code&gt;mi&lt;/code&gt;で登録しているRubyMineで編集することがあります）。&lt;/p&gt;
&lt;p&gt;cliffyのSelect promptにファイル名を投げて選択しているのですが、便利なのが&lt;code&gt;enable-search-input&lt;/code&gt;です。&lt;code&gt;search: true&lt;/code&gt;を指定することで、インクリメンタル検索ができるようになります。これはとても嬉しい…!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://cliffy.io/docs@v0.24.2/prompt/types/select#enable-search-input&quot; target=&quot;_blank&quot;&gt;https://cliffy.io/docs@v0.24.2/prompt/types/select#enable-search-input&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;とりあえず作ってみたんですが、候補から選択できるのがかなり便利ですね。
これを作成する前は、似たような記事を一度別で開いてコピーして…みたいなことをやっていたので、生産性めちゃくちゃ上がりました。&lt;/p&gt;
&lt;p&gt;Denoはこれの前に練習として、deno-jpsumという、ダミー文作成メーカーLorem JpsumをCLI化したものを作っていましたが。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/IkumaTadokoro/deno-jpsum&quot; target=&quot;_blank&quot;&gt;https://github.com/IkumaTadokoro/deno-jpsum&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;が、まだ仕様があまり頭に入っていないのと、そもそもTypeScript自体を最近始めたので、全体的にコードがお粗末です…。&lt;/p&gt;
&lt;p&gt;とはいえ、Denoは標準でFormatterやLinterを提供しているし、TypeScriptも設定なしで使えるし、cliffyは多機能だし、CLIツールの開発体験としては非常によかったです。&lt;/p&gt;
&lt;p&gt;今後もDenoやっていくぞ！&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenge 9日目: 3057-Push</title><link>https://ikuma-t.com/blog/type-challenge-push/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-push/</guid><description>問題&amp;amp;解答https://github.com/type-challenges/type-challenges/blob/main/questions/03057-easy-push/READ</description><pubDate>Sun, 05 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#問題--解答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題 &amp;amp; 解答&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/type-challenges/type-challenges/blob/main/questions/03057-easy-push/README.md&quot; target=&quot;_blank&quot;&gt;https://github.com/type-challenges/type-challenges/blob/main/questions/03057-easy-push/README.md&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ジェネリクス版の&lt;code&gt;Array.prototype.push&lt;/code&gt;を実装する。&lt;/p&gt;
&lt;p&gt;これはえ〜と、Variadic Tuple Typesですね。Tの型を展開することができます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Push&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;ブルーベリー本を買ったので、Variadic Tuple Typesについてもみてみました。「6.7.3 可変長タプル型」に載っていました。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.work/posts/type-challenge-concat&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.work/posts/type-challenge-concat&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;この回でも書いたのですが「&lt;code&gt;...&lt;/code&gt;で展開される型は&lt;code&gt;extends readonly any[]&lt;/code&gt;ようです。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;any[]&lt;/code&gt;はまあいいんですけど、ただの配列だったら&lt;code&gt;readonly&lt;/code&gt;はいらないのかな〜。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenge 8日目: 898-Includes</title><link>https://ikuma-t.com/blog/type-challenge-includes/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-includes/</guid><description>問題&amp;amp;解答https://github.com/type-challenges/type-challenges/blob/main/questions/00898-easy-includes/</description><pubDate>Sat, 04 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#問題--解答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題 &amp;amp; 解答&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/type-challenges/type-challenges/blob/main/questions/00898-easy-includes/README.md&quot; target=&quot;_blank&quot;&gt;https://github.com/type-challenges/type-challenges/blob/main/questions/00898-easy-includes/README.md&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;JavaScriptの&lt;code&gt;Array.includes&lt;/code&gt;を型で実装する。&lt;/p&gt;
&lt;p&gt;はじめはこういう回答を考えました。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Includes&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;が、全然ダメでした…。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// 全部落ちているテストケースです&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Expect&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Equal&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Includes&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;[{}]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; { a&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;A&apos;&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Expect&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Equal&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Includes&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;[boolean&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Expect&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Equal&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Includes&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Expect&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Equal&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Includes&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;[{ a&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;A&apos;&lt;/span&gt;&lt;span&gt; }]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; { readonly a&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;A&apos;&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Expect&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Equal&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Includes&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;[{ readonly a&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;A&apos;&lt;/span&gt;&lt;span&gt; }]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; { a&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;A&apos;&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Expect&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Equal&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Includes&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Expect&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Equal&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Includes&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;全然わからなかったので、今回は答えを見ました。見つけた回答がこちら&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Includes&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;unknown&lt;/span&gt;&lt;span&gt;[]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;First&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;...infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Rest&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Equal&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;First&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Includes&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Rest&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/type-challenges/type-challenges/issues/1568&quot; target=&quot;_blank&quot;&gt;https://github.com/type-challenges/type-challenges/issues/1568&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;順番に読み下していきます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Includes&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;unknown&lt;/span&gt;&lt;span&gt;[]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;型&lt;code&gt;Includes&lt;/code&gt;は第1引数（配列）、第2引数を受けます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; extends [infer First&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;infer Rest]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;inferキーワードとVariadic Tuple Typesを利用して、配列Tの最初の要素の型情報を&lt;code&gt;First&lt;/code&gt;として、以降の要素がある場合にそれらの型情報を&lt;code&gt;Rest&lt;/code&gt;として推論します。&lt;/p&gt;
&lt;p&gt;以下はそれぞれinferとVariadic Tuple Typesが出た回です。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.work/posts/type-challenge-first-of-array&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.work/posts/type-challenge-first-of-array&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.work/posts/type-challenge-concat&quot; target=&quot;_blank&quot;&gt;https://ikuma-t.work/posts/type-challenge-concat&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; extends [infer First&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;infer Rest] &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; @ &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Conditional Typesの一つ目の分岐で一旦脳をセーブします。ここの部分で、なんらかの配列であれば&lt;code&gt;true&lt;/code&gt;、そうでなければ&lt;code&gt;false&lt;/code&gt;を返す型になります。 ここから始まるRecursiveな型探索のbase caseです。&lt;/p&gt;
&lt;p&gt;では次に進みます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Equal&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;First&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; extends &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Equal型はtype-challengeがutilityとして定義している独自の型で、次のように定義されています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Equal&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;X&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Y&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; (&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt;() &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;X&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt;() &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Y&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;ちょっとここを読むのは時間がかかりそうなので、一旦は「XとYの型が同じかどうかを判定する」と認識しておきます。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://zenn.dev/razokulover/articles/890102685d5ea2&quot; target=&quot;_blank&quot;&gt;https://zenn.dev/razokulover/articles/890102685d5ea2&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/microsoft/TypeScript/issues/27024&quot; target=&quot;_blank&quot;&gt;https://github.com/microsoft/TypeScript/issues/27024&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://stackoverflow.com/questions/68961864/how-does-the-equals-work-in-typescript&quot; target=&quot;_blank&quot;&gt;https://stackoverflow.com/questions/68961864/how-does-the-equals-work-in-typescript&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;話を戻します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Equal&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;First&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; extends true &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Includes&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Rest&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;先程&lt;code&gt;infer&lt;/code&gt;で推論された&lt;code&gt;First&lt;/code&gt;と、ジェネリクス&lt;code&gt;U&lt;/code&gt;が等しいかをチェックし、同じであれば&lt;code&gt;true&lt;/code&gt;、そうでなければ残りのパラメータを使用して同じ処理を実施します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Includes&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;unknown&lt;/span&gt;&lt;span&gt;[]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;First&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;...infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Rest&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Equal&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;First&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Includes&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Rest&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;一致する型が存在するまで要素を探索し、見つからなかった場合には&lt;code&gt;false&lt;/code&gt;が返るという仕組みでした。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#調べたこと&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;調べたこと&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#arrayprototypeincludes&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;code&gt;Array.prototype.includes&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;特定の要素が配列に含まれているかどうかをbooleanで返すメソッド。
第2引数で検索を開始するインデックスを指定することができる（省略可能）。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fruits&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&apos;apple&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;banana&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;orange&apos;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// searchElementのみを指定する&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;fruits&lt;/span&gt;&lt;span&gt;&lt;span&gt;.includes&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;cherry&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;fruits&lt;/span&gt;&lt;span&gt;&lt;span&gt;.includes&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;apple&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// fromIndexを指定する&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;fruits&lt;/span&gt;&lt;span&gt;&lt;span&gt;.includes&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;apple&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;fruits&lt;/span&gt;&lt;span&gt;&lt;span&gt;.includes&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;apple&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;今日はめちゃくちゃ難しかったです…。type-challengeでユーティリティとして提供されている型&lt;code&gt;Equals&lt;/code&gt;を使っていましたが、実質2個定義しないと解けなかった訳ですね。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Equals&lt;/code&gt;のところを、シンプルに&lt;code&gt;First extends U&lt;/code&gt;とか&lt;code&gt;[First, U] extends [U, First]&lt;/code&gt;とか試してみたんですが、&lt;code&gt;readonly&lt;/code&gt;を抜けられなかったり、&lt;code&gt;boolean&lt;/code&gt;に&lt;code&gt;false&lt;/code&gt;が通ってしまったりと、意外と抜け漏れがあり、これはTypeScriptの内部的な比較を知らないと解けないなあと思いました。
TypeScriptなにもわからん…。&lt;/p&gt;
&lt;p&gt;あと問題に載っているサンプルがなぜかジョジョだったのですが、作者の方は日本人の方でした。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;isPillarMen&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Includes&lt;/span&gt;&lt;span&gt;&amp;lt;[&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;Kars&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;Esidisi&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;Wamuu&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;Santana&apos;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;Dio&apos;&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;// expected to be `false`&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenge 7日目（その2）: 533-Concat</title><link>https://ikuma-t.com/blog/type-challenge-concat/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-concat/</guid><description>問題&amp;amp;解答JavaScriptのArray.concatを型システムで構成する。VariadicTupleTypesを使って次のように定義するtypeConcat&amp;lt;Textendsany</description><pubDate>Fri, 03 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#問題--解答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題 &amp;amp; 解答&lt;/h2&gt;
&lt;p&gt;JavaScriptの&lt;code&gt;Array.concat&lt;/code&gt;を型システムで構成する。&lt;/p&gt;
&lt;p&gt;Variadic Tuple Typesを使って次のように定義する&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Concat&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#調べたこと&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;調べたこと&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#variadic-tuple-types&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Variadic Tuple Types&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;タプル型の中でに&lt;code&gt;...T&lt;/code&gt;と書ける機能&lt;/li&gt;
&lt;li&gt;&lt;code&gt;...&lt;/code&gt;で展開される方は&lt;code&gt;extends readonly any[]&lt;/code&gt;を満たす必要がある。&lt;/li&gt;
&lt;li&gt;ちなみにVariadicは「可変長引数」&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html&quot; target=&quot;_blank&quot;&gt;TypeScript: Documentation - TypeScript 4.0&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;Variadic Tuple Typesという名前がわからないまま、「こんな感じにできそうかな」と思ったら通ってしまいました。
TypeScript難しい…&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenge 7日目: 268-If</title><link>https://ikuma-t.com/blog/type-challenge-if/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-if/</guid><description>問題&amp;amp;解答https://github.com/type-challenges/type-challenges/blob/main/questions/00268-easy-if/README</description><pubDate>Fri, 03 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#問題--解答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題 &amp;amp; 解答&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/type-challenges/type-challenges/blob/main/questions/00268-easy-if/README.md&quot; target=&quot;_blank&quot;&gt;https://github.com/type-challenges/type-challenges/blob/main/questions/00268-easy-if/README.md&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;条件&lt;code&gt;C&lt;/code&gt;がtruthyであれば&lt;code&gt;T&lt;/code&gt;を、falsyであれば&lt;code&gt;F&lt;/code&gt;を返す&lt;code&gt;If&lt;/code&gt;を実装する。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;If&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;C&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;F&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;C&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;さすがにConditional Typesは慣れてきました。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenges 6日目: 189-Awaited</title><link>https://ikuma-t.com/blog/type-challenge-awaited/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-awaited/</guid><description>問題&amp;amp;解答Promise風な型が持っている型を取得する方法を考える。typeX=Promise&amp;lt;string&amp;gt;;//stringを取り出す。typeY=Promise&amp;lt;{fi</description><pubDate>Thu, 02 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#問題--解答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題 &amp;amp; 解答&lt;/h2&gt;
&lt;p&gt;Promise 風な型が持っている型を取得する方法を考える。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;X&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;&amp;gt;; &lt;/span&gt;&lt;span&gt;// stringを取り出す。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Y&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;{ field&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt; }&amp;gt;; &lt;/span&gt;&lt;span&gt;// { filed: number } を取り出す&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Z&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;; &lt;/span&gt;&lt;span&gt;// string | numberを取り出す&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;最初はこういうことかなと思って、ConditionalTypes の中で infer を利用するような形で解いてみたのですが、&lt;code&gt;Promise&amp;lt;Promise&amp;lt;string | number&amp;gt;&amp;gt;&lt;/code&gt;のように Promise がネストしている場合に引っ掛かりました。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyAwaited&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;never&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;というわけで再帰的に中を掘っていくやつです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyAwaited&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyAwaited&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;never&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;今回の問題は&lt;code&gt;infer&lt;/code&gt;にちゃんとたどり着けるかどうかが肝だなと思いました。&lt;/p&gt;
&lt;p&gt;ConditionalTypes でネストする場合って、どこで改行するのが正解なんだろうというのは少し疑問です。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenges 5日目: 43-Exclude</title><link>https://ikuma-t.com/blog/type-challenge-exclude/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-exclude/</guid><description>問題&amp;amp;解答組み込みのExclude&amp;lt;T,U&amp;gt;を自前で実装するConditionalTypesの分配法則を用いて、次のように記述する。typeMyExclude&amp;lt;T,U&amp;gt;</description><pubDate>Wed, 01 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#問題--解答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題 &amp;amp; 解答&lt;/h2&gt;
&lt;p&gt;組み込みの&lt;code&gt;Exclude&amp;lt;T, U&amp;gt;&lt;/code&gt;を自前で実装する&lt;/p&gt;
&lt;p&gt;Conditional Typesの分配法則を用いて、次のように記述する。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyExclude&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;U&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;never&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;例えば&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;T&lt;/code&gt;：&lt;code&gt;&quot;a&quot; | &quot;b&quot; | &quot;c&quot; | &quot;d&quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;U&lt;/code&gt;：&lt;code&gt;&quot;c&quot; | &quot;d&quot; | &quot;e&quot; | &quot;f&quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;であるとき、まず&lt;code&gt;&quot;a&quot;&lt;/code&gt;は&lt;code&gt;U&lt;/code&gt;のサブセットではないので、&lt;code&gt;T&lt;/code&gt;つまり&lt;code&gt;&quot;a&quot;&lt;/code&gt;が返る。
一つ飛ばして&lt;code&gt;&quot;c&quot;&lt;/code&gt;は&lt;code&gt;U&lt;/code&gt;のサブセットなので、&lt;code&gt;never&lt;/code&gt;が返る。&lt;/p&gt;
&lt;p&gt;分配法則によりこれらの結果を結合したものが返るので&lt;code&gt;MyExclude&amp;lt;&quot;a&quot; | &quot;b&quot; | &quot;c&quot; | &quot;d&quot;, &quot;c&quot; | &quot;d&quot; | &quot;e&quot; | &quot;f&quot;&amp;gt;&lt;/code&gt;は&lt;code&gt;&quot;a&quot; | &quot;b&quot;&lt;/code&gt;をあらわす&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#調べたこと&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;調べたこと&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#exclude型&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Exclude型&lt;/h3&gt;
&lt;p&gt;差集合を表す型&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Exclude&amp;lt;UnionType, ExcludedMembers&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// (a, b, c)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Exclude&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;a&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;b&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;c&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;a&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// type T0 = &quot;b&quot; | &quot;c&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Exclude&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;a&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;b&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;c&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;d&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;c&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;d&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;e&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;f&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// type T1 = &quot;a&quot; | &quot;b&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/utility-types.html#excludeuniontype-excludedmembers&quot; target=&quot;_blank&quot;&gt;TypeScript: Documentation - Utility Types&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#conditional-typesとdistributive分配法則&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Conditional TypesとDistributive（分配法則）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Conditional types がGeneric型である時、Union型が渡された場合は、分配法則に従う。&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// 各Tがanyでを満たせば`T[]`を返す&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ToArray&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;never&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StrArrOrNumArr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ToArray&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;&amp;gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;StrArrOrNumArr&lt;/code&gt;では、&lt;code&gt;T&lt;/code&gt;としてUnion型の&lt;code&gt;string | number&lt;/code&gt;が与えられている。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// StrArrOrNumArrの右辺は次のようになる(ちょっと表現としては変だけど）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;(string &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; number) extends any &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; never&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// 分配法則により次のように読み下せる&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;(string extends any &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; string[] &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; never) &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; (number extends any &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; number[] &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; never)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// anyはすべてを満たすので`StrArrOrNumArr`はこうなる&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;string[] &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; number[]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenges 4日目: 14-First of Array</title><link>https://ikuma-t.com/blog/type-challenge-first-of-array/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-first-of-array/</guid><description>問題&amp;amp;解答type-challenges/README.mdatmain·type-challenges/type-challenges配列Tを受け取って、その配列の最初の要素の型をとるような</description><pubDate>Tue, 31 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#問題--解答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題 &amp;amp; 解答&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/type-challenges/type-challenges/blob/main/questions/00014-easy-first/README.md&quot; target=&quot;_blank&quot;&gt;type-challenges/README.md at main · type-challenges/type-challenges&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;配列&lt;code&gt;T&lt;/code&gt;を受け取って、その配列の最初の要素の型をとるようなジェネリクス&lt;code&gt;First&amp;lt;T&amp;gt;&lt;/code&gt;を実装する。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;arr1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&apos;a&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;b&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;c&apos;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;arr2&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;head1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;First&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;arr1&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// expected to be &apos;a&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;head2&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;First&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;arr2&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// expected to be 3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Conditional Typesを利用して、要素がある場合には1番目の要素の型を返すようにする&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;First&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; [] &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;never&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;別解を見ていたら、inferを使っているケースもありました&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;First&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;...infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;_Rest&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;never&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;infer&lt;/code&gt;キーワードを使って&lt;code&gt;first&lt;/code&gt;という名前で配列の1番目の要素の型を推論している。&lt;code&gt;...infer _Rest&lt;/code&gt;の部分はrest parametersを使って、配列の残りの要素の方を&lt;code&gt;_Rest&lt;/code&gt;に押し込んでいる。といっても今回は使用しない型なので&lt;code&gt;_&lt;/code&gt;始まりにしているっぽいです。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#調べたこと&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;調べたこと&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#conditional-types条件型&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Conditional Types（条件型）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;条件に応じて動的に型を定義する方法&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;IsString&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#inferキーワード&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;inferキーワード&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;条件の一部としてジェネリック型を宣言できる機能。conditional typesのextendsの条件部分に限定して使用することができる&lt;/li&gt;
&lt;li&gt;&lt;code&gt;infer U&lt;/code&gt;の形式で推論した型情報を&lt;code&gt;U&lt;/code&gt;として扱うことができるようになる。&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SecondArg&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;F&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;F&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; (a&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; b&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;infer&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;B&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;B&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;never&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;このサンプルでは、渡された関数&lt;code&gt;F&lt;/code&gt;が、&lt;code&gt;number&lt;/code&gt;型の第1引数と何かしらの第2引数を持ち、stringを返す関数である場合、第2引数の型をinferで推論して返すというもの。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#never型&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;never型&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;neverは決して戻ることのない関数の型。無限ループや単純に例外をthrowするような関数の戻り値&lt;/li&gt;
&lt;li&gt;他の全ての型のサブタイプであるbottom型：値を持たない型&lt;/li&gt;
&lt;li&gt;どんな変数も入れることができない | どんな方にも入れることができる&lt;/li&gt;
&lt;li&gt;無限ループや&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#index-accessed-types&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Index Accessed Types&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Lookup Typesと同じ。&lt;a href=&quot;https://ikuma-t.work/posts/type-challenge-tuple-to-object&quot; target=&quot;_blank&quot;&gt;type-challenges 3日目: 11-Tuple to Object | ikuma-t&lt;/a&gt;に書いてある「配列の要素の型を取得する」と同じ&lt;/li&gt;
&lt;li&gt;公式：&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/2/indexed-access-types.html#handbook-content&quot; target=&quot;_blank&quot;&gt;TypeScript: Documentation - Indexed Access Types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Lookup Typesと同じであることのソース：&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/release-notes/overview.html#keyof-and-lookup-types&quot; target=&quot;_blank&quot;&gt;TypeScript: Documentation - Overview&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;blockquote&gt;
&lt;p&gt;indexed access types, also called lookup types&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;今日は条件分岐型を覚えました。1週間前くらいまではジェネリクス型見たら「うわっ」って感じだったんですけど、だいぶ慣れてきました。（感覚としてはギター始めたての頃のBm7-5に近い）&lt;/p&gt;
&lt;p&gt;手元にオライリーのプログラミングTypeScriptをおいてリファレンス的に使っているんですが、第4版が2021年発行なので、ちょっと情報が古いかもと思い始めています。
もう一冊くらい手元においておいてもよいかなあ。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenges 4日目（その2）: 18-Length of Tuple</title><link>https://ikuma-t.com/blog/type-challenge-length-of-tuple/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-length-of-tuple/</guid><description>問題&amp;amp;解答type-challenges/README.mdatmain·type-challenges/type-challengestype-challenges/README.mdatm</description><pubDate>Tue, 31 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#問題--解答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題 &amp;amp; 解答&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/type-challenges/type-challenges/blob/main/questions/00018-easy-tuple-length/README.md&quot; target=&quot;_blank&quot;&gt;type-challenges/README.md at main · type-challenges/type-challenges&lt;/a&gt;&lt;a href=&quot;https://github.com/type-challenges/type-challenges/blob/main/questions/00018-easy-tuple-length/README.md&quot; target=&quot;_blank&quot;&gt;type-challenges/README.md at main · type-challenges/type-challenges&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;タプルが与えられるので、その長さを型とする&lt;code&gt;Length&lt;/code&gt;を実装する&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tesla&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&apos;tesla&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;model 3&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;model X&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;model Y&apos;&lt;/span&gt;&lt;span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;spaceX&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&apos;FALCON 9&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;FALCON HEAVY&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;DRAGON&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;STARSHIP&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;HUMAN SPACEFLIGHT&apos;&lt;/span&gt;&lt;span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;teslaLength&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Length&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;tesla&lt;/span&gt;&lt;span&gt;&amp;gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// expected 4&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;spaceXLength&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Length&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;spaceX&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// expected 5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;constアサーションが適用されているので、&lt;code&gt;readonly&lt;/code&gt;な配列&lt;code&gt;T&lt;/code&gt;を定義する。
&lt;code&gt;Array.prototype&lt;/code&gt;のインスタンスプロパティ&lt;code&gt;length&lt;/code&gt;を指定して、長さを取得する。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Length&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt;[]&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;length&apos;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#調べたこと&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;調べたこと&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#arrayprototypelength&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Array.prototype.length&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/length&quot; target=&quot;_blank&quot;&gt;Array.length - JavaScript | MDN&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;length は Array 型のインスタンスであるオブジェクトのプロパティで、配列の要素の数を設定または取得します&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;今回はIndex Accessed Typesとプロトタイプチェーンの復習でした。&lt;/p&gt;
&lt;p&gt;最初にPickを解いた時は「これでeasyかよ！」と思ったりしていましたが、だんだん妥当に感じるようになってきました。
でもeasyで高度な型がでているってことは、mediumはえげつないのかな。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>IkumaScriptと37進数</title><link>https://ikuma-t.com/blog/ikumascript/</link><guid isPermaLink="true">https://ikuma-t.com/blog/ikumascript/</guid><description>ikuma,akuma,xkuma,ukuma…JSやTSのサンプルコードで、よく自分の名前ikumaを一文字変えて使っているのだけれど、毎回入力するのも面倒なので、スニペット化しました。ikumaを</description><pubDate>Mon, 30 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#ikuma-akuma-xkuma-ukuma&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ikuma, akuma, xkuma, ukuma…&lt;/h2&gt;
&lt;p&gt;JSやTSのサンプルコードで、よく自分の名前&lt;code&gt;ikuma&lt;/code&gt;を一文字変えて使っているのだけれど、毎回入力するのも面倒なので、スニペット化しました。&lt;code&gt;ikuma&lt;/code&gt;を複製するので、ECMAScriptを文字ってIkumaScriptです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;&lt;span&gt;Array&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;26&lt;/span&gt;&lt;span&gt;&lt;span&gt;)]&lt;/span&gt;&lt;span&gt;.map&lt;/span&gt;&lt;span&gt;((_&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; index) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;(index &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;.toString&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;36&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;kuma`&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// [ &apos;akuma&apos;, &apos;bkuma&apos;, &apos;ckuma&apos;, &apos;dkuma&apos;, &apos;ekuma&apos;, &apos;fkuma&apos;, &apos;gkuma&apos;, &apos;hkuma&apos;, &apos;ikuma&apos;, &apos;jkuma&apos;, &apos;kkuma&apos;, &apos;lkuma&apos;, &apos;mkuma&apos;, &apos;nkuma&apos;, &apos;okuma&apos;, &apos;pkuma&apos;, &apos;qkuma&apos;, &apos;rkuma&apos;, &apos;skuma&apos;, &apos;tkuma&apos;, &apos;ukuma&apos;, &apos;vkuma&apos;, &apos;wkuma&apos;, &apos;xkuma&apos;, &apos;ykuma&apos;, &apos;zkuma&apos; ]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;親の顔よりよくみた連番作成処理を行います。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;&lt;span&gt;Array&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;26&lt;/span&gt;&lt;span&gt;&lt;span&gt;)]&lt;/span&gt;&lt;span&gt;.map&lt;/span&gt;&lt;span&gt;((_&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; index) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; index)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// [ 0,  1,  2,  3,  4,  5,  6,  7, 8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 ]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;実際には&lt;code&gt;+ 10&lt;/code&gt;しているので&lt;code&gt;10 ~ 35&lt;/code&gt;までの値を含む配列が取得できます。&lt;/p&gt;
&lt;p&gt;ここからN進数を利用してアルファベットに変換を行っていきます。文字としての数字は0から9までの10種類しかないので、36進数に変換すると、10 ~ 35がそれぞれa ~ zに相当することになります（36 - 10 = 26個のアルファベットが必要になる）&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#37進数にはどの記号が採用されるのか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;37進数にはどの記号が採用されるのか&lt;/h2&gt;
&lt;p&gt;ここでふと疑問に思うのが、37進数以降の場合、アルファベットで賄えない部分はどうなるのかということです。実際にやってみました。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;36&lt;/span&gt;&lt;span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;.toString&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;37&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Uncaught RangeError: toString() radix argument must be between 2 and 36&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;at &lt;/span&gt;&lt;span&gt;Number&lt;/span&gt;&lt;span&gt;&lt;span&gt;.toString&lt;/span&gt;&lt;span&gt; (&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;anonymous&lt;/span&gt;&lt;span&gt;&amp;gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Number/toString#%E4%BE%8B%E5%A4%96&quot; target=&quot;_blank&quot;&gt;Number.prototype.toString() - JavaScript | MDN&lt;/a&gt;にも記載がありましたが、37以上はエラーになるようですね。&lt;/p&gt;
&lt;p&gt;Rubyでも試してみます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;36&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;to_s&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;37&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# =&amp;gt; (irb):3:in `to_s&apos;: invalid radix 37 (ArgumentError)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.ruby-lang.org/ja/latest/method/Integer/i/inspect.html&quot; target=&quot;_blank&quot;&gt;Integer#inspect (Ruby 3.1 リファレンスマニュアル)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;こちらもリファレンスに記載がありましたが、37以上を指定するとエラーになるようです。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;ikumaという名前が名付けられた経緯には色々な意味があるのですが、時代背景的に&lt;a href=&quot;https://ja.wikipedia.org/wiki/%E6%82%AA%E9%AD%94%E3%81%A1%E3%82%83%E3%82%93%E5%91%BD%E5%90%8D%E9%A8%92%E5%8B%95&quot; target=&quot;_blank&quot;&gt;悪魔ちゃん命名騒動 - Wikipedia&lt;/a&gt;があったこともあり、あえて一文字ずらして「ikuma」になったみたいな理由もあると以前母から聞きました。&lt;/p&gt;
&lt;p&gt;1文字どころかたくさんずらして遊んでます。 — 息子より&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenges 3日目: 11-Tuple to Object</title><link>https://ikuma-t.com/blog/type-challenge-tuple-to-object/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-tuple-to-object/</guid><description>問題&amp;amp;解答type-challenges/README.mdatmain·type-challenges/type-challengesタプルを受け取り、その各値のkey/valueを持つオブ</description><pubDate>Mon, 30 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#問題--解答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題 &amp;amp; 解答&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/type-challenges/type-challenges/blob/main/questions/00011-easy-tuple-to-object/README.md&quot; target=&quot;_blank&quot;&gt;type-challenges/README.md at main · type-challenges/type-challenges&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;タプルを受け取り、その各値のkey/valueを持つオブジェクトの型に変換する型を実装する&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tuple&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&apos;tesla&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;model 3&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;model X&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;model Y&apos;&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TupleToObject&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;typeof&lt;/span&gt;&lt;span&gt; tuple&amp;gt; &lt;/span&gt;&lt;span&gt;// expected { tesla: &apos;tesla&apos;, &apos;model 3&apos;: &apos;model 3&apos;, &apos;model X&apos;: &apos;model X&apos;, &apos;model Y&apos;: &apos;model Y&apos;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;文字列型の配列を受け取り、各要素をキーと値に持つオブジェクトとしてマッピングする。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TupleToObject&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;[]&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; { [&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// このテストケース特有なら以下の方がいいかもしれない&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TupleToObject&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;]&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; { [&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#調べたこと&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;調べたこと&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#tuple型&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Tuple型&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;タプルは配列のサブタイプで、固定長の配列を片付けするための特別な方法&lt;/li&gt;
&lt;li&gt;配列の各インデックスでの値は特定の既知の型を持つ&lt;/li&gt;
&lt;li&gt;タプルと配列の構文は同じであり、またTypeScriptは配列に対して型推論するためのルールを持っているため、タプルを宣言する際には明示的に型を宣言する必要がある。&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; b&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&apos;ikuma&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;takuma&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;参考：&lt;a href=&quot;https://www.oreilly.co.jp/books/9784873119045/&quot; target=&quot;_blank&quot;&gt;O’Reilly Japan - プログラミングTypeScript&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#const-assertion&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;const assertion&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;as const&lt;code&gt;を末尾に記述することで、再帰的に&lt;/code&gt;readonly`にする仕組み&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;参考：&lt;a href=&quot;https://typescriptbook.jp/reference/values-types-variables/const-assertion&quot; target=&quot;_blank&quot;&gt;constアサーション「as const」 (const assertion) | TypeScript入門『サバイバルTypeScript』&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#インデックスシグネチャ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;インデックスシグネチャ&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;{ [key: T]: U }&lt;/code&gt;：このオブジェクトの型Tのすべてのキーは型Uの値を持たなければならない&lt;/li&gt;
&lt;li&gt;オブジェクトのキーを抽象的に定義する方法。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#配列の要素の型を取得する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;配列の要素の型を取得する&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;number&lt;/code&gt;型の添字を使うと配列から要素の型を取得することができる。&lt;/li&gt;
&lt;li&gt;タプルの場合は、0、1またはアクセスしたいインデックスを表す数値リテラル型を使う&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#readonlyな配列&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;readonlyな配列&lt;/h3&gt;
&lt;p&gt;いくつかの定義方法がある&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// readonly T[]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;names&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&apos;akuma&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;bkuma&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;ckuma&apos;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// ReadonlyT[]&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;names&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Readonly&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;[]&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&apos;akuma&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;bkuma&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;ckuma&apos;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// ReadonlyArray&amp;lt;T&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;names&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ReadonlyArray&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&apos;akuma&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;bkuma&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;ckuma&apos;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;タプルの場合は次のように定義する&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// readonly&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;names&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&apos;akuma&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;bkuma&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;ckuma&apos;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Readonly&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;names&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Readonly&lt;/span&gt;&lt;span&gt;&amp;lt;[&lt;/span&gt;&lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;]&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&apos;akuma&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;bkuma&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;ckuma&apos;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;解いた後に回答をみたら、&lt;code&gt;any[]&lt;/code&gt;で受け取っている人もいたり、&lt;code&gt;string[]&lt;/code&gt;で受け取っている人もいたり、何がいいんだろうと思いました。自分はもともと「タプルなんだから、&lt;code&gt;[string, string, string, string]&lt;/code&gt;で受け取るだろう」と思ってやっていたのですが、そういう感じでもないんですかね。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Next.jsで作成したブログにRSS機能を追加する</title><link>https://ikuma-t.com/blog/generate-rss-feed/</link><guid isPermaLink="true">https://ikuma-t.com/blog/generate-rss-feed/</guid><description>このブログにRSS機能を実装したので、メモを残しておきます。RSSについてRSSの概要具体的な実装の前にRSSそのもの仕組みを確認していきます。RSSとは、“RichSiteSummary”の略で、サ</description><pubDate>Sun, 29 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;このブログにRSS機能を実装したので、メモを残しておきます。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#rssについて&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;RSSについて&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#rssの概要&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;RSSの概要&lt;/h3&gt;
&lt;p&gt;具体的な実装の前にRSSそのもの仕組みを確認していきます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;RSSとは、“Rich Site Summary”の略で、サイトの概要を記述する為のXML形式の文書のこと&lt;/li&gt;
&lt;li&gt;提供されたRSSのことをRSSフィードという&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#rssの拡張子&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;RSSの拡張子&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;以下の2種類がある
&lt;ul&gt;
&lt;li&gt;RDF：&lt;a href=&quot;https://ja.wikipedia.org/wiki/Resource_Description_Framework&quot; target=&quot;_blank&quot;&gt;Resource Description Framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;XML&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#rssの歴史&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;RSSの歴史&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;RSS 0.9：NexScape社が自社のポータルサイトで使用したのが始まり。元々はRDFを使用していたので、「RDF site summary」と呼ばれていた&lt;/li&gt;
&lt;li&gt;RSS 0.91：XMLで記述される。より多くの情報が配信できるようになったため、「rich site summary」と呼ばれるようになる&lt;/li&gt;
&lt;li&gt;RSS 1.0：NetScape社がRSS開発から撤退したことにより、「RSS-DEV Working Group」と「Dave WinnerとUserLand Software社」の二派に分かれる。1.0は前者により実装されたもので、RDFで実装されている&lt;/li&gt;
&lt;li&gt;RSS 2.0：RSS1.0の実装方針（拡張子、名前空間の複雑化）は一部層から不満があるものであったため、UserLand Software社はRSS 0.91からの派生（≠RSS 1.0の後継）としてRSS 0.92~0.94をXMLで実装した。2003年にDave Winnerが移籍したことにより、この流れを汲むRSS 2.0系はハーバード大学へ移管された。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;&lt;a href=&quot;#atom&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Atom&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Atomも配信形式の一つである&lt;/li&gt;
&lt;li&gt;RSSは上記のような論争があるため、しがらみのないところで始めたいという動悸もあってAtomが生まれた。&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://datatracker.ietf.org/doc/html/rfc4287&quot; target=&quot;_blank&quot;&gt;RFC 4287 - The Atom Syndication Format&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#参考&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;参考&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://ja.wikipedia.org/wiki/RSS&quot; target=&quot;_blank&quot;&gt;RSS - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ja.wikipedia.org/wiki/Resource_Description_Framework&quot; target=&quot;_blank&quot;&gt;Resource Description Framework - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#rss機能の実装&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;RSS機能の実装&lt;/h2&gt;
&lt;p&gt;このブログはSSGを利用しているため、&lt;code&gt;getStaticProps&lt;/code&gt;の中でfeedを作成するように追加します。 実際に行った変更は以下の部分です。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/IkumaTadokoro/blog/pull/1/files&quot; target=&quot;_blank&quot;&gt;https://github.com/IkumaTadokoro/blog/pull/1/files&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;タスクとしてはこんな感じです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;RSSフィードを生成する処理を作成する（&lt;code&gt;generateRssFeed&lt;/code&gt;）
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.npmjs.com/package/feed&quot; target=&quot;_blank&quot;&gt;feed - npm&lt;/a&gt;を導入する&lt;/li&gt;
&lt;li&gt;FeedクラスをnewしてRSSフィードの基本設定をする&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Feed#addItem&lt;/code&gt;で記事のRSSフィードを登録する&lt;/li&gt;
&lt;li&gt;&lt;code&gt;public/rss&lt;/code&gt;配下に各仕様ごとのRSSフィードを出力する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;getStaticProps&lt;/code&gt;の中で&lt;code&gt;generateRssFeed&lt;/code&gt;を呼び出す&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;RSS自体の仕様がよく分からなくてとりあえずで作ってみたら、リーダーの中でコンテンツが表示されず、&lt;a href=&quot;https://www.futomi.com/lecture/japanese/rss20.html&quot; target=&quot;_blank&quot;&gt;RSS 2.0 Specification 日本語訳 - futomi’s CGI Cafe&lt;/a&gt;を参考にして値を設定し直しました。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;そのため、Feedlyに一度コンテンツがないRSSフィードが載っかってしまったのですが、どうもFeedlyは一度載っかったフィードはFeedly側でキャッシュされてしまうらしく、今もFeedly上の最初の数本の記事のコンテンツはなくなったままです…。
どこか別のところで試せばよかった…。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenges 2日目: 7-Readonly</title><link>https://ikuma-t.com/blog/type-challenge-readonly/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-readonly/</guid><description>問題&amp;amp;回答type-challenges/README.mdatmain·type-challenges/type-challenges組み込みのユーティリティ型Readonlyを使用しないで</description><pubDate>Sun, 29 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#問題--回答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題 &amp;amp; 回答&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/type-challenges/type-challenges/blob/main/questions/00007-easy-readonly/README.md&quot; target=&quot;_blank&quot;&gt;type-challenges/README.md at main · type-challenges/type-challenges&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;組み込みのユーティリティ型&lt;code&gt;Readonly&lt;/code&gt;を使用しないで、&lt;code&gt;T&lt;/code&gt;のすべてのプロパティを読み取り専用にする&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Todo&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;todo&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyReadonly&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Todo&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Hey&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;foobar&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;todo&lt;/span&gt;&lt;span&gt;.title &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Hello&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;// Error: cannot reassign a readonly property&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;todo&lt;/span&gt;&lt;span&gt;.description &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;barFoo&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;// Error: cannot reassign a readonly property&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;mapped type&lt;/code&gt;を利用して、&lt;code&gt;T&lt;/code&gt;をすべて読み取り専用にします。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyReadonly&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt;] }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#調べたこと&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;調べたこと&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#readonly修飾子&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;readonly修飾子&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;オブジェクトのフィールドを読み取り専用に指定するための修飾子&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#readonly型&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Readonly型&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Readonly&amp;lt;T&amp;gt;&lt;/code&gt;は、オブジェクト型Tのプロパティをすべて読み取り専用にするユーティリティ型。挙動は今回実装した&lt;code&gt;MyReadonly&amp;lt;T&amp;gt;&lt;/code&gt;と同じ&lt;/li&gt;
&lt;li&gt;参考：&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/utility-types.html#readonlytype&quot; target=&quot;_blank&quot;&gt;TypeScript: Documentation - Utility Types&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;今日は昨日の発展系だったので、自力で解けました！
TypeScript初めて数日の身からすると、まずは型の見た目に拒絶反応を起こさないようにすることが大切なので、このtypechallengesはいいですね〜。明日も頑張ります。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>「今日のesa」という自分用のChrome拡張を作ってみた</title><link>https://ikuma-t.com/blog/chrome-extension-kyo-no-esa/</link><guid isPermaLink="true">https://ikuma-t.com/blog/chrome-extension-kyo-no-esa/</guid><description>FJORDBOOTCAMPを卒業したことにより日報の提出先がなくなってしまったので、自分でesaに登録するようにしていたのですが、今日の分の日報を作るのが面倒&amp;amp;結構頻繁に別のページに飛んでしま</description><pubDate>Sat, 28 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;FJORD BOOT CAMPを卒業したことにより日報の提出先がなくなってしまったので、自分でesaに登録するようにしていたのですが、今日の分の日報を作るのが面倒 &amp;amp; 結構頻繁に別のページに飛んでしまって、今日の日報ページに戻るのが面倒だったので、とても雑にChrome拡張を作りました。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/IkumaTadokoro/kyo-no-esa&quot; target=&quot;_blank&quot;&gt;IkumaTadokoro/kyo-no-esa: (Chrome Extension) Add kyo-no-esa button in the sidebar of esa.io that opens or create today’s diary&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;GitHubはREADMEすら治してません…自分用なので。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#使い方&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;使い方&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;上記PJをcloneして、&lt;code&gt;npm run build&lt;/code&gt;でdistフォルダに出力します。&lt;/li&gt;
&lt;li&gt;Chrome側で「パッケージ化されていない拡張機能を読み込む」でdistフォルダを指定します。&lt;/li&gt;
&lt;li&gt;「拡張機能のオプション」からオプションページを開き、諸々設定します。&lt;/li&gt;
&lt;li&gt;esaのページのサイドバーに「今日のesa」がでてくるのでクリックします。今日の日報があればそれを、なければ新規作成画面に移ります（テンプレートがある前提）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;「Chrome拡張作ってみたいな」と前々から思っていたので、Vite + TypeScript + Vueで作ってみました。&lt;/p&gt;
&lt;p&gt;これくらいの規模の拡張機能なら割とあっさりできるんですが、結構ゴリ押しで進めてしまったので、次はもう少ししっかり設計を練ってから挑みたいです。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>RubyとJavaScriptにおける正規表現</title><link>https://ikuma-t.com/blog/regexp-ruby-and-js/</link><guid isPermaLink="true">https://ikuma-t.com/blog/regexp-ruby-and-js/</guid><description>正規表現系のメソッドがいつもごちゃごちゃになって、その場その場でリファレンスを見ているので、このタイミングでまとめてみます。正規表現に対するメソッド体系用途RubyJavaScript正規表現のパター</description><pubDate>Sat, 28 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;正規表現系のメソッドがいつもごちゃごちゃになって、その場その場でリファレンスを見ているので、このタイミングでまとめてみます。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#正規表現に対するメソッド体系&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;正規表現に対するメソッド体系&lt;/h2&gt;








































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;用途&lt;/th&gt;&lt;th&gt;Ruby&lt;/th&gt;&lt;th&gt;JavaScript&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;正規表現のパターンにマッチした最初の部分を文字列に置換する&lt;/td&gt;&lt;td&gt;String#sub&lt;/td&gt;&lt;td&gt;String.prototype.replace&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;正規表現のパターンにマッチしたすべての部分を文字列に置換する&lt;/td&gt;&lt;td&gt;String#gsub&lt;/td&gt;&lt;td&gt;String.prototype.replaceAll&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;正規表現のパターンにマッチする文字のインデックスを返す&lt;/td&gt;&lt;td&gt;String#=~&lt;/td&gt;&lt;td&gt;String.prototype.search&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;正規表現のパターンにマッチする文字列を返す&lt;/td&gt;&lt;td&gt;String#match or Regexp#match&lt;/td&gt;&lt;td&gt;String.prototype.match&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;正規表現のパターンにマッチするかどうかをbooleanで返す&lt;/td&gt;&lt;td&gt;String#match? or Regexp#match?&lt;/td&gt;&lt;td&gt;RegExp.prototype.test&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;正規表現のパターンにマッチする文字列すべてを返す&lt;/td&gt;&lt;td&gt;String#scan&lt;/td&gt;&lt;td&gt;String.prototype.matchAll&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;&lt;a href=&quot;#ちょっと試してみた&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ちょっと試してみた&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#正規表現のパターンにマッチした最初の部分を文字列に置換する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;正規表現のパターンにマッチした最初の部分を文字列に置換する&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&apos;ikuma-t, yamada-d, tanaka-p, okurag, tarou-d&apos;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;sub&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;/-/&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;~&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;#=&amp;gt; &quot;ikuma~t, yamada-d, tanaka-p, okurag, tarou-d&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&apos;ikuma-t, yamada-d, tanaka-p, okurag, tarou-d&apos;&lt;/span&gt;&lt;span&gt;&lt;span&gt;.replace&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;/-/&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;~&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// &apos;ikuma~t, yamada-d, tanaka-p, okurag, tarou-d&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.ruby-lang.org/ja/latest/method/String/i/sub.html&quot; target=&quot;_blank&quot;&gt;String#sub (Ruby 3.1 リファレンスマニュアル)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/replace&quot; target=&quot;_blank&quot;&gt;String.prototype.replace() - JavaScript | MDN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#正規表現のパターンにマッチしたすべての部分を文字列に置換する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;正規表現のパターンにマッチしたすべての部分を文字列に置換する&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&apos;ikuma-t, yamada-d, tanaka-p, okurag, tarou-d&apos;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;gsub&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;/-/&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;~&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;#=&amp;gt; &quot;ikuma~t, yamada~d, tanaka~p, okurag, tarou~d&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&apos;ikuma-t, yamada-d, tanaka-p, okurag, tarou-d&apos;&lt;/span&gt;&lt;span&gt;&lt;span&gt;.replaceAll&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;/-/&lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;~&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;//  &apos;ikuma~t, yamada~d, tanaka~p, okurag, tarou~d&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;JavaScriptのString.prototype.replaceAllを使用する際には、グローバルフラグを持つRegExpオブジェクトを指定する必要がある。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.ruby-lang.org/ja/latest/method/String/i/gsub.html&quot; target=&quot;_blank&quot;&gt;String#gsub (Ruby 3.1 リファレンスマニュアル)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll&quot; target=&quot;_blank&quot;&gt;String.prototype.replaceAll() - JavaScript | MDN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#正規表現のパターンにマッチする文字のインデックスを返す&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;正規表現のパターンにマッチする文字のインデックスを返す&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&apos;ikuma-t&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=~&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/.*-./&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# =&amp;gt; 0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&apos;ikumat&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=~&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/.*-./&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# =&amp;gt; nil&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&apos;ikuma-t&apos;&lt;/span&gt;&lt;span&gt;&lt;span&gt;.search&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;/.&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;-./&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// 0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&apos;ikumat&apos;&lt;/span&gt;&lt;span&gt;&lt;span&gt;.search&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;/.&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;-./&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// -1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.ruby-lang.org/ja/latest/method/String/i/=3d=7e.html&quot; target=&quot;_blank&quot;&gt;String#=~ (Ruby 3.1 リファレンスマニュアル)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/search&quot; target=&quot;_blank&quot;&gt;String.prototype.search() - JavaScript | MDN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#正規表現のパターンにマッチする文字列を返す&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;正規表現のパターンにマッチする文字列を返す&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Regexp#matchの方を使っています&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/.*-./&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;match&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;ikuma-t&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# =&amp;gt; #&amp;lt;MatchData &quot;ikuma-t&quot;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/.*-./&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;match&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;ikumat&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# =&amp;gt; nil&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&apos;ikuma-t&apos;&lt;/span&gt;&lt;span&gt;&lt;span&gt;.match&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;/.&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;-./&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// [ &apos;ikuma-t&apos;, index: 0, input: &apos;ikuma-t&apos;, groups: undefined ]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&apos;ikumat&apos;&lt;/span&gt;&lt;span&gt;&lt;span&gt;.match&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;/.&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;-./&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.ruby-lang.org/ja/latest/method/Regexp/i/match.html&quot; target=&quot;_blank&quot;&gt;Regexp#match (Ruby 3.1 リファレンスマニュアル)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/match&quot; target=&quot;_blank&quot;&gt;String.prototype.match() - JavaScript | MDN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#正規表現のパターンにマッチするかどうかをbooleanで返す&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;正規表現のパターンにマッチするかどうかをbooleanで返す&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/.*-./&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;match?&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;ikuma-t&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# =&amp;gt; true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/.*-./&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;match?&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;ikumat&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# =&amp;gt; false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/.&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;-./&lt;/span&gt;&lt;span&gt;&lt;span&gt;.test&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;ikuma-t&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/.&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;-./&lt;/span&gt;&lt;span&gt;&lt;span&gt;.test&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;ikumat&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.ruby-lang.org/ja/latest/method/Regexp/i/match=3f.html&quot; target=&quot;_blank&quot;&gt;Regexp#match? (Ruby 3.1 リファレンスマニュアル)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test&quot; target=&quot;_blank&quot;&gt;RegExp.prototype.test() - JavaScript | MDN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#正規表現のパターンにマッチする文字列すべてを返す正規表現のパターンにマッチする文字列すべてを返す&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;正規表現のパターンにマッチする文字列すべてを返す正規表現のパターンにマッチする文字列すべてを返す&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&apos;ikuma-t&apos;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;scan&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;/[aiueo]/&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# =&amp;gt; [&quot;i&quot;, &quot;u&quot;, &quot;a&quot;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&apos;ikuma-t&apos;&lt;/span&gt;&lt;span&gt;&lt;span&gt;.matchAll&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;/[aiueo]/&lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;)]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// [ [ &apos;i&apos;, index: 0, input: &apos;ikuma-t&apos;, groups: undefined ], [ &apos;u&apos;, index: 2, input: &apos;ikuma-t&apos;, groups: undefined ], [ &apos;a&apos;, index: 4, input: &apos;ikuma-t&apos;, groups: undefined ] ]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;JavaScriptのString.prototype.matchAllを使用する際には、グローバルフラグを持つRegExpオブジェクトを指定する必要がある。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.ruby-lang.org/ja/latest/method/String/i/scan.html&quot; target=&quot;_blank&quot;&gt;String#scan (Ruby 3.1 リファレンスマニュアル)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/matchAll&quot; target=&quot;_blank&quot;&gt;String.prototype.matchAll() - JavaScript | MDN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>ikuma-t</author></item><item><title>remarkでtableのMarkdownを解釈できるようにする</title><link>https://ikuma-t.com/blog/support-table-markdown-in-remark/</link><guid isPermaLink="true">https://ikuma-t.com/blog/support-table-markdown-in-remark/</guid><description>tableはCommonMarkdownではないこのブログはremarkを使用してMarkdownをパースしているわけですが、tableを投稿してみたところ原文のまま表示されてしまいました。なんでかな</description><pubDate>Sat, 28 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#tableはcommonmarkdownではない&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;tableはCommonMarkdownではない&lt;/h2&gt;
&lt;p&gt;このブログはremarkを使用してMarkdownをパースしているわけですが、tableを投稿してみたところ原文のまま表示されてしまいました。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;なんでかな〜と思って調べてみると、&lt;a href=&quot;https://unifiedjs.com/learn/recipe/remark-table/&quot; target=&quot;_blank&quot;&gt;unifiedjsのドキュメント&lt;/a&gt;に&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Tables are a non-standard feature in markdown: they are not defined in CommonMark and will not work everywhere.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;という記述を見つけました。tableのスタイルってGitHub Flavored Markdownなんですね〜。というわけでGitHub Flavored Markdownもパースできるように改修していきます。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#remark-gfmを適用する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;remark-gfmを適用する&lt;/h2&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;yarn&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;remark-gfm&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { remark } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;remark&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; html &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;remark-html&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; prism &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;remark-prism&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// remarkGfmを追加する&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; remarkGfm &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;remark-gfm&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;markdownToHtml&lt;/span&gt;&lt;span&gt;(markdown&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;remark&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;.use&lt;/span&gt;&lt;span&gt;(html&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; { sanitize&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;&lt;span&gt; })&lt;/span&gt;&lt;span&gt;.use&lt;/span&gt;&lt;span&gt;(prism)&lt;/span&gt;&lt;span&gt;.use&lt;/span&gt;&lt;span&gt;(remarkGfm)&lt;/span&gt;&lt;span&gt;.process&lt;/span&gt;&lt;span&gt;(markdown)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt;&lt;span&gt;.toString&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;ここまでで、tableタグとして解釈されるようになりました。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#スタイルを適用する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;スタイルを適用する&lt;/h2&gt;
&lt;p&gt;シンプルに&lt;code&gt;table&lt;/code&gt;関連タグが適用されているだけなので、それに従ってスタイルを適用します。このブログではTailwind CSSを利用しているので、次のような感じです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;w-full&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;text-sm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;text-left&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;text-gray-&lt;/span&gt;&lt;span&gt;500 &lt;/span&gt;&lt;span&gt;overflow-x-auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;shadow-md&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sm&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;rounded-lg&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;thead&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;text-sm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;text-gray-&lt;/span&gt;&lt;span&gt;700 &lt;/span&gt;&lt;span&gt;bg-gray-&lt;/span&gt;&lt;span&gt;50;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;th&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;px-&lt;/span&gt;&lt;span&gt;6 &lt;/span&gt;&lt;span&gt;py-&lt;/span&gt;&lt;span&gt;3;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;tr&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;border-b&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;td&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;px-&lt;/span&gt;&lt;span&gt;6 &lt;/span&gt;&lt;span&gt;py-&lt;/span&gt;&lt;span&gt;3;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これでいい感じにテーブルが表示されるようになりました。&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>type-challenges 1日目: 4-Pick</title><link>https://ikuma-t.com/blog/type-challenge-pick/</link><guid isPermaLink="true">https://ikuma-t.com/blog/type-challenge-pick/</guid><description>問題&amp;amp;回答type-challenges/README.ja.mdatmain·type-challenges/type-challengesPick&amp;lt;T,K&amp;gt;：UtilityTy</description><pubDate>Sat, 28 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#問題--回答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題 &amp;amp; 回答&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/type-challenges/type-challenges/blob/main/questions/00004-easy-pick/README.ja.md&quot; target=&quot;_blank&quot;&gt;type-challenges/README.ja.md at main · type-challenges/type-challenges&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Pick&amp;lt;T, K&amp;gt;&lt;/code&gt;：Utility Typesの一つ。既に存在する&lt;code&gt;T&lt;/code&gt;型の中から&lt;code&gt;K&lt;/code&gt;で選択した一部のプロパティのみを含んだ新たな型を構築する。&lt;/li&gt;
&lt;li&gt;これを独自に実装すると次のような形式になる&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyPick&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; { [&lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;span&gt;] }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#調べたこと&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;調べたこと&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#ルックアップ型&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ルックアップ型&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;定義済みの型[&quot;キー&quot;]&lt;/code&gt;とすることで、指定したキーに対応する型を取り出すことができる。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Todo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;comment&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// キー`id`の型`number`を取得する&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Id&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Todo&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;id&apos;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Id&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;1&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;// TS2322: Type &apos;string&apos; is not assignable to type &apos;number&apos;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#keyof演算子&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;code&gt;keyof&lt;/code&gt;演算子&lt;/h3&gt;
&lt;p&gt;オブジェクトの全てのキーを、文字列リテラル型のUnion型として取得する。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Todo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;comment&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TodoKeys&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Todo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// type TodoKeys = &quot;id&quot; | &quot;title&quot; | &quot;comment&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#マップ型mapped-type&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;マップ型（&lt;code&gt;mapped type&lt;/code&gt;）&lt;/h3&gt;
&lt;p&gt;オブジェクトのキーの型と値の型をマッピングするための方法。
どの値の型がどのキーの名前に対応するかを制約できる&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// P：Parameter（引数型）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// K：Constraint（制約型）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// T：Template（テンプレート型）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{  [&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt;]: &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;ここまでの内容を踏まえると次のようになる。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Todo&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;completed&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyPick&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; { [&lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;span&gt;] }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// { &apos;title&apos;: string, &apos;completed&apos;: boolean }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// keyofを使用しているので、`contents`とかTodoにないキーを指定するとエラーになる&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TodoPreview&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyPick&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Todo&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;title&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;completed&apos;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;todo&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TodoPreview&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;Clean room&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;completed&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;初日から全然とけなかったんですが…。型を理解するためにこれを始めたので、根気強くやっていきたいと思います！&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Gemfileにある`require: false`ってなんでしたっけ？</title><link>https://ikuma-t.com/blog/what-is-require-false-in-gemfile/</link><guid isPermaLink="true">https://ikuma-t.com/blog/what-is-require-false-in-gemfile/</guid><description>Gemfileで度々でてくるrequire:false。ざっくり理解はしているけど、ちゃんと公式ドキュメントを読んでいなかったので、思い出しついでに読んでいく。まずrequire:falseのそもそも</description><pubDate>Sat, 28 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Gemfileで度々でてくる&lt;code&gt;require: false&lt;/code&gt;。ざっくり理解はしているけど、ちゃんと公式ドキュメントを読んでいなかったので、思い出しついでに読んでいく。&lt;/p&gt;
&lt;p&gt;まず&lt;code&gt;require: false&lt;/code&gt;のそもそもの意味は&lt;a href=&quot;https://bundler.io/man/gemfile.5.html#REQUIRE-AS&quot; target=&quot;_blank&quot;&gt;Bundler: gemfile&lt;/a&gt;に記載があって、&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;false to prevent any file from being autorequired.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;つまり、自動でrequiredしないようにするには、&lt;code&gt;require: false&lt;/code&gt;と書くことになる。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Bundlerを使用していない場合、通常&lt;code&gt;require&lt;/code&gt;を各ファイルで各gemに対して書く必要があるが、Bundlerにはロードを行うパスの解決を行う&lt;code&gt;Bundler.setup&lt;/code&gt;とそこで指定されたGemを自動的にrequireする&lt;code&gt;Bundler.require&lt;/code&gt;という機能があり、これによりGemfile記載のgemは全て自動でrequireされる。&lt;/p&gt;
&lt;p&gt;これを無効にするのが&lt;code&gt;require: false&lt;/code&gt;である（デフォルトがtrue）&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;どういう場面で使用するかというと、「依存関係は管理したいが、アプリでは使用しない」といったケースで使用する。
例えばRakeタスクで自動的にデータを取得するのに使用しているけれども、アプリで使うのはデータであって、そのgem自体は使用しない、みたいな場合に&lt;code&gt;require: false&lt;/code&gt;を指定してあげるといった例がある。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;「&lt;code&gt;Bundler.setup&lt;/code&gt;とか&lt;code&gt;Bundler.require&lt;/code&gt;とかあまり使ったことないんだけど…」となるものそのはずで、Railsの場合はフレームワーク側でそれが組み込まれているので普段は意識しない。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Bundker.setup&lt;/code&gt;は&lt;code&gt;config/boot.rb&lt;/code&gt;に記載されている。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ENV&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&quot;BUNDLE_GEMFILE&quot;&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;||=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;File&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;expand_path&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;../Gemfile&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;__dir__&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;require&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;bundler/setup&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# Set up gems listed in the Gemfile.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;Bundler.require&lt;/code&gt;は&lt;code&gt;config/application.rb&lt;/code&gt;に記載されている。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;require_relative&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;boot&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;require&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;rails/all&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Require the gems listed in Gemfile, including any gems&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# you&apos;ve limited to :test, :development, or :production.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Bundler&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;require&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;Rails&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;groups&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;</content:encoded><author>ikuma-t</author></item><item><title>ブログ用のコマンド試作その1</title><link>https://ikuma-t.com/blog/create-blog-command/</link><guid isPermaLink="true">https://ikuma-t.com/blog/create-blog-command/</guid><description>雑に投稿するためのコマンドを作ってみた。ファイルがなければmarkdownファイルと画像格納用のディレクトリを作成し、ファイルがあればmarkdownファイルを開く。#!/bin/bashif[-e~</description><pubDate>Fri, 27 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;雑に投稿するためのコマンドを作ってみた。ファイルがなければmarkdownファイルと画像格納用のディレクトリを作成し、ファイルがあればmarkdownファイルを開く。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;#!/bin/bash&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; [ &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~&lt;/span&gt;&lt;span&gt;/blog/_posts/$1.md ]; &lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;vim&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/blog/_posts/&lt;/span&gt;&lt;span&gt;$1&lt;/span&gt;&lt;span&gt;.md&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;else&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;cp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/bin/template.md&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/blog/_posts/&lt;/span&gt;&lt;span&gt;$1&lt;/span&gt;&lt;span&gt;.md&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;mkdir&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/blog/public/blog/&lt;/span&gt;&lt;span&gt;$1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;fi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;あまりにも雑すぎるけど、これでどこにいてもターミナル上でささっとブログがかける。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://gihyo.jp/book/2021/978-4-297-12267-6&quot; target=&quot;_blank&quot;&gt;1日1問、半年以内に習得 シェル・ワンライナー160本ノック：書籍案内｜技術評論社&lt;/a&gt;をみてシェルスクリプトに親しむか、もはやzxを使ってTypeScriptで書いた方がよさそう。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>ブログ用のコマンド試作その3</title><link>https://ikuma-t.com/blog/create-blog-command-3/</link><guid isPermaLink="true">https://ikuma-t.com/blog/create-blog-command-3/</guid><description>初回作成時に2回コマンドを叩くのはめんどいだろうということで、if文を変えた。#!/bin/bashif[!-e~/blog/_posts/$1.md];thencp~/bin/template.md</description><pubDate>Fri, 27 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;初回作成時に2回コマンドを叩くのはめんどいだろうということで、if文を変えた。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;#!/bin/bash&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; [ &lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~&lt;/span&gt;&lt;span&gt;/blog/_posts/$1.md ]; &lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;cp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/bin/template.md&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/blog/_posts/&lt;/span&gt;&lt;span&gt;$1&lt;/span&gt;&lt;span&gt;.md&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;mkdir&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/blog/public/blog/&lt;/span&gt;&lt;span&gt;$1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;fi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;vim&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;~/blog/_posts/&lt;/span&gt;&lt;span&gt;$1&lt;/span&gt;&lt;span&gt;.md&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;cd&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;~/blog&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;git&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/blog/_posts/&lt;/span&gt;&lt;span&gt;$1&lt;/span&gt;&lt;span&gt;.md&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;git&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;commit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-m&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;feat: update post&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;git&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;cd&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これで&lt;code&gt;blog hoge&lt;/code&gt;とすれば、その瞬間に記事を書くことができる。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>ブログ用のコマンド試作その2</title><link>https://ikuma-t.com/blog/create-blog-command-2/</link><guid isPermaLink="true">https://ikuma-t.com/blog/create-blog-command-2/</guid><description>ブログ用のコマンド試作の続き。もはや保存した瞬間にデプロイしてしまって良いのではと思ったので、ただただgitpushするまでのコマンドを組み込んだ#!/bin/bashif[-e~/blog/_pos</description><pubDate>Fri, 27 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;ブログ用のコマンド試作の続き。もはや保存した瞬間にデプロイしてしまって良いのではと思ったので、ただただgit pushするまでのコマンドを組み込んだ&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;#!/bin/bash&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; [ &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~&lt;/span&gt;&lt;span&gt;/blog/_posts/$1.md ]; &lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;vim&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/blog/_posts/&lt;/span&gt;&lt;span&gt;$1&lt;/span&gt;&lt;span&gt;.md&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;cd&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/blog&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;git&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/blog/_posts/&lt;/span&gt;&lt;span&gt;$1&lt;/span&gt;&lt;span&gt;.md&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;git&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;commit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-m&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;feat: update post&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;git&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;cd&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;else&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;cp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/bin/template.md&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/blog/_posts/&lt;/span&gt;&lt;span&gt;$1&lt;/span&gt;&lt;span&gt;.md&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;mkdir&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/blog/public/blog/&lt;/span&gt;&lt;span&gt;$1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;fi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;画像とかを入れていきたい場合は微妙な感じがするけど、そういう場合はエディタちゃんと開いてやるし、ターミナルでささっと学習メモをあげるにはこれで十分なのでは？と思っていたりする。
しばらくこれで運用してみます。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>ブログをNext.jsで作りました</title><link>https://ikuma-t.com/blog/create-new-blog/</link><guid isPermaLink="true">https://ikuma-t.com/blog/create-new-blog/</guid><description>はてなブログのエディタをわざわざ開いて書いていくのが非常に面倒で、TypeScript→React→Nextの順で学んでNext.jsでブログを作ろうと思っていたけど、だいぶ時間がかかるので、ささっと</description><pubDate>Thu, 26 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;はてなブログのエディタをわざわざ開いて書いていくのが非常に面倒で、TypeScript→React→Nextの順で学んでNext.jsでブログを作ろうと思っていたけど、
だいぶ時間がかかるので、ささっとtemplateを使って作りました（レイアウトだけ少し整えた）&lt;/p&gt;
&lt;p&gt;Markdownをおいたら公開されるようにはなっているんですが、最小工数で記事公開まで持って行けるようにしたいので、コマンド一発で作業できるといいなあと思っています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# これでmarkdownファイルと画像用のディレクトリが作成されて、適当にフロントマターを入れてくれる感じにしたい&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;blog&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sample-title&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;</content:encoded><author>ikuma-t</author></item><item><title>Google Meetで相手の画面やプレゼンテーションが見えないときの対処法</title><link>https://ikuma-t.com/blog/202204181650274863/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202204181650274863/</guid><description>Tableofcontents相手が見えない…結論詳細バージョン設定：受信時の解像度（最高）終わりに相手が見えない…先日GoogleMeetでお話をする機会があったのですが、相手のプレゼンテーションや</description><pubDate>Mon, 18 Apr 2022 18:41:03 GMT</pubDate><content:encoded>&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#table-of-contents&quot;&gt;Table of contents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E7%9B%B8%E6%89%8B%E3%81%8C%E8%A6%8B%E3%81%88%E3%81%AA%E3%81%84&quot;&gt;相手が見えない…&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E7%B5%90%E8%AB%96&quot;&gt;結論&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E8%A9%B3%E7%B4%B0&quot;&gt;詳細&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3&quot;&gt;バージョン&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E8%A8%AD%E5%AE%9A%E5%8F%97%E4%BF%A1%E6%99%82%E3%81%AE%E8%A7%A3%E5%83%8F%E5%BA%A6%E6%9C%80%E9%AB%98&quot;&gt;設定：受信時の解像度（最高）&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E7%B5%82%E3%82%8F%E3%82%8A%E3%81%AB&quot;&gt;終わりに&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#相手が見えない&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;相手が見えない…&lt;/h2&gt;
&lt;p&gt;先日Google Meetでお話をする機会があったのですが、相手のプレゼンテーションやお顔がまったくみえないという事象に出くわしました…。&lt;/p&gt;
&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220418/20220418180719.png&quot; height=&quot;608&quot; width=&quot;1200&quot; /&gt;
&lt;p&gt;お相手の別の端末で会議に参加していただいたところ、すべて映っていたところから「これは自分側に問題があるぞ」と切り分けまでできたのですが、その時間では解決できず1時間音声+テキストで会話を続けました😅&lt;/p&gt;
&lt;p&gt;終わってみて色々試してみたところ原因がわかったので、メモしておきます。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#結論&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;結論&lt;/h2&gt;
&lt;p&gt;設定 &amp;gt; 動画 &amp;gt; 受信時の解像度（最高）が「音声のみ」になっていると相手の動画全般が見えない。&lt;br /&gt;
「音声のみ」以外の選択肢に変更する&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#詳細&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;詳細&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#バージョン&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;バージョン&lt;/h3&gt;
&lt;p&gt;確認したバージョンは以下の通りです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OS：macOS Monetery バージョン 12.1&lt;/li&gt;
&lt;li&gt;Chrome：100.0.4896.88（Official Build） （x86_64）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#設定受信時の解像度最高&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;設定：受信時の解像度（最高）&lt;/h3&gt;
&lt;p&gt;原因はGoogle Meetの受信時の設定にありました。設定 &amp;gt; 動画 &amp;gt; 受信時の解像度（最高）を確認します。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220418/20220418183322.png&quot; height=&quot;491&quot; width=&quot;539&quot; /&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220418/20220418183417.png&quot; height=&quot;683&quot; width=&quot;835&quot; /&gt;&lt;/p&gt;
&lt;p&gt;相手の画面やカメラが見えていない時は、ここの設定が「音声のみ」になっていました。これにより音声しか受信しなくなるので、相手の動画はすべて見えないというカ$1リでした。&lt;/p&gt;
&lt;p&gt;この設定は次回以降も保存されるそうなので、なにかの拍子にここを「音声のみ」にしてしまっていて、それが今回も引き継がれていたということになります。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#終わりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;終わりに&lt;/h2&gt;
&lt;p&gt;過去に「送信時の解像度（最高）」を高画質にしようとしたけど、カクツキすぎるので自動に戻したということがあって、おそらくその際に手が滑ったのでしょう…。&lt;/p&gt;
&lt;p&gt;ネット上には「発信している側起因で見えない」ケースが結構転がっていますが、「受信する側起因で見えない」ケースはあまりなかったので、どなたかの参考になれば幸いです。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Vue3のReactivity TransformをJestでもコンパイルできるようにする</title><link>https://ikuma-t.com/blog/202203151647341633/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202203151647341633/</guid><description>要約ReactivityTransformを使った$1をテストしていて、それが原因でJestが落ちるときは、@vue/vue-jest@27.0.0-alpha.3以上を導入しよう！yarnadd-D</description><pubDate>Tue, 15 Mar 2022 19:53:53 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#要約&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;要約&lt;/h2&gt;
&lt;p&gt;Reactivity Transformを使った$1をテストしていて、それが原因でJestが落ちるときは、&lt;code&gt;@vue/vue-jest@27.0.0-alpha.3&lt;/code&gt;以上を導入しよう！&lt;/p&gt;
&lt;p&gt;&lt;code&gt;yarn add -D @vue/vue3-jest@latest&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#環境&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;環境&lt;/h2&gt;
&lt;p&gt;※この記事は2022/03/15書いたものです。執筆時点ではReactivity Transform自体がExperimentalかつ、vue-jestのアルファ版でしか対応していないため下記のような対応が必要になりますが、しばらくすればここらへんは意識しなくても良くなるはずです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Vue：3.2.26&lt;/li&gt;
&lt;li&gt;Jest：27.5.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#前提reactivity-transformとは&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;前提：Reactivity Transformとは&lt;/h2&gt;
&lt;p&gt;Vue 3.2.25からExperimentalとして追加された$1ーマクロで、Vueが提供しているReactiveな値を&lt;code&gt;.value&lt;/code&gt;を経由せずに取得することができるようになります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// 通常のrefimport { ref } from &apos;vue&apos;const counter = ref(0)console.log(counter.value) // 0// Reactivity Transformconst counter = $ref(0)console.log(counter) // 0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;公式ドキュメントでは以下の章で紹介されていて、refだけでなく、computedも$computedとして使用することができます。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://vuejs.org/guide/extras/reactivity-transform.html#refs-vs-reactive-variables&quot; target=&quot;_blank&quot;&gt;vuejs.org&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;&lt;a href=&quot;#問題jestがreactivity-transformを解釈できない&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題：JestがReactivity Transformを解釈できない&lt;/h2&gt;
&lt;p&gt;今開発しているアプリはWebpackを利用しているので（正確にはWebpacker…殺せっ！）、ドキュメントの通り、明示的に設定に追記することでこの機能を有効化することができます。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://vuejs.org/guide/extras/reactivity-transform.html#plain-webpack-vue-loader&quot; target=&quot;_blank&quot;&gt;vuejs.org&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;module.exports = {  test: /\.vue$/,  loader: &apos;vue-loader&apos;,  options: {    reactivityTransform: true  }}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これでアプリ実行時はうまくいくのですが、$1に使用しているJestではWebpackは関係ないため、この構文の解釈ができずにエラーになります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;node:internal/process/promises:265            triggerUncaughtException(err, true /* fromPromise */);            ^[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason &quot;ReferenceError: $computed is not defined&quot;.] {  code: &apos;ERR_UNHANDLED_REJECTION&apos;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;今回はこれを解消します。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#対処vuevue3-jest2700-alpha3以上を導入する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;対処：@vue/vue3-jest@27.0.0-alpha.3以上を導入する&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;yarn add -D @vue/vue3-jest@27.0.0-alpha.4&lt;/code&gt;もしくは&lt;code&gt;@vue/vue3-jest@latest&lt;/code&gt;を実行します。&lt;/p&gt;
&lt;p&gt;2022/03/15時点ではalpha4が最新版なので、こう書いていますが27.0.0-alpha.3以上を導入すればOKです。&lt;/p&gt;
&lt;p&gt;これによりテスト実行時のログに、webpackで実行したときと同じようにexperimentalに対するログが出るようになり、Reactivity Transformが正しく解釈されるようになります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[@vue/ref-transform] Reactivity transform is an experimental feature.Experimental features may change behavior between patch versions.It is recommended to pin your vue dependencies to exact versions to avoid breakage.You can follow the proposal&apos;s status at https://github.com/vuejs/rfcs/discussions/369.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#解説&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;解説&lt;/h2&gt;
&lt;p&gt;Reactivity Transformのみならず、Vueの仕様についてはGitHub Discussionsにて議論されています。&lt;/p&gt;
&lt;p&gt;この中でJestへの対応に関する質問がありました。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/vuejs/rfcs/discussions/369#discussioncomment-1742554&quot; target=&quot;_blank&quot;&gt;github.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;VueとAngularのコントリビュータであるCédricさんが「vue3-jest」に新しいオプションを加えたよという話をしています。それがこのPRです。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/vuejs/vue-jest/pull/412&quot; target=&quot;_blank&quot;&gt;github.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;READMEにも同様の内容が書いてあるのですが、27.0.0-alpha3以降は以下のオプションでReactivity Transformを解釈できるようになります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;globals: {  &apos;vue-jest&apos;: {    compilerOptions: {      refTransform: false    }  }}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;デフォルトではこれがtrueだそうで、先に述べた通りalpha3以上を導入すれば自動的にReactivity Transformが解釈できるようになるわけです。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;これを解消したはいいんですけど、まだ私のJestはエラーを出力しています。やばいですねっ！&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>【Rails】collection_selectで表示するテキストには、Procを指定できる</title><link>https://ikuma-t.com/blog/202203031646265181/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202203031646265181/</guid><description>事の発端自分で作ったGem「jp_local_gov」を使って、自作サービスを実装しています。実装にあたって、市区町村名のセレクトボックスが必要でした。jp_local_govではViewTempla</description><pubDate>Thu, 03 Mar 2022 08:53:01 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#事の発端&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;事の発端&lt;/h2&gt;
&lt;p&gt;自分で作ったGem「jp_local_gov」を使って、自作サービスを実装しています。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220303/20220303082449.png&quot; alt=&quot;f:id:ikmbear:20220303082449p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;実装にあたって、市区町村名のセレクトボックスが必要でした。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;jp_local_gov&lt;/code&gt;では&lt;a href=&quot;https://github.com/IkumaTadokoro/jp_local_gov#view-template&quot; target=&quot;_blank&quot;&gt;View Template&lt;/a&gt;に記載の通り、&lt;code&gt;collection_select&lt;/code&gt;で使用する候補を返すことを目的の一つとした&lt;code&gt;JpLocalGov.all&lt;/code&gt;というAPIを実装しているので、一見以下の形式で目的は達成できそうです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;f.collection_select :local_gov_code, JpLocalGov.all, :code, :city&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;たしかにこれでも動作としては問題ないのですが、&lt;code&gt;city&lt;/code&gt;としか指定していないので、「市区町村名」しか表示されません。&lt;/p&gt;
&lt;p&gt;日本には「$1府県は異なるけど、市区町村名が同じ市区町村」がそこそこ存在します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;JpLocalGov.all.group_by(&amp;amp;:city).select { |k, v| v.size &amp;gt; 1 }.map { |k, v| { k =&amp;gt; v.map(&amp;amp;:prefecture) }}=&amp;gt;[{&quot;伊達市&quot;=&amp;gt;[&quot;北海道&quot;, &quot;福島県&quot;]}, {&quot;松前町&quot;=&amp;gt;[&quot;北海道&quot;, &quot;愛媛県&quot;]}, {&quot;森町&quot;=&amp;gt;[&quot;北海道&quot;, &quot;静岡県&quot;]},...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;そのため、$1府県と市区町村を合わせてテキストに表示したかったので、雑に以下のようにやってみたのですが動かず。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;f.collection_select :local_gov_code, JpLocalGov.all, :code, &quot;#{prefecture}#{:city}&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#collection_selectで表示するvalueとtextにはprocを指定できる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;collection_selectで表示するvalueとtextにはProcを指定できる&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-collection_select&quot; target=&quot;_blank&quot;&gt;api.rubyonrails.org&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;困った時のAPI Dockというわけでチェックしてみると、&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The &lt;/p&gt;&lt;div&gt;&lt;/div&gt;_method and &lt;div&gt;&lt;/div&gt; parameters are methods to be called on each member of collection. The return values are used as the value attribute and contents of each tag, respectively. They can also be any object that responds to call, such as a proc, that will be called for each member of the collection to retrieve the value/text.&lt;p&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;要はcollection_selectの第1引数に指定したオブジェクトが対応できるメソッドを呼び出すことができ、それゆえにProcも呼び出せるようです。&lt;/p&gt;
&lt;p&gt;結果として、&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;f.collection_select :local_gov_code, JpLocalGov.all, :code, -&amp;gt;(lg) { &quot;#{lg.prefecture} #{lg.city}&quot; }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;こんな感じにProcを渡してあげると、&lt;code&gt;JpLocaGov.all&lt;/code&gt;で取得されたすべての市区町村がイテレーションされて&lt;code&gt;lg&lt;/code&gt;にわたり、それぞれの「都道府県名 市区町村名」として表示できるわけです。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220303/20220303085115.png&quot; alt=&quot;f:id:ikmbear:20220303085115p&quot; /&gt;&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Formオブジェクトのロケールファイルの定義方法（i18n）</title><link>https://ikuma-t.com/blog/202202231645578000/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202202231645578000/</guid><description>Formオブジェクトを利用した場合の翻訳キーはどれ？要約前提対象バージョンサンプルケースRailsがModelのi18nを探索する手順バリデーションメッセージカラム（画面表示項目）Formオブジェクト</description><pubDate>Wed, 23 Feb 2022 10:00:00 GMT</pubDate><content:encoded>&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#Form%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%92%E5%88%A9%E7%94%A8%E3%81%97%E3%81%9F%E5%A0%B4%E5%90%88%E3%81%AE%E7%BF%BB%E8%A8%B3%E3%82%AD%E3%83%BC%E3%81%AF%E3%81%A9%E3%82%8C&quot;&gt;Formオブジェクトを利用した場合の翻訳キーはどれ？&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E8%A6%81%E7%B4%84&quot;&gt;要約&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%89%8D%E6%8F%90&quot;&gt;前提&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%AF%BE%E8%B1%A1%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3&quot;&gt;対象バージョン&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%82%B1%E3%83%BC%E3%82%B9&quot;&gt;サンプルケース&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#Rails%E3%81%8CModel%E3%81%AEi18n%E3%82%92%E6%8E%A2%E7%B4%A2%E3%81%99%E3%82%8B%E6%89%8B%E9%A0%86&quot;&gt;RailsがModelのi18nを探索する手順&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8&quot;&gt;バリデーションメッセージ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%82%AB%E3%83%A9%E3%83%A0%E7%94%BB%E9%9D%A2%E8%A1%A8%E7%A4%BA%E9%A0%85%E7%9B%AE&quot;&gt;カラム（画面表示項目）&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#formオブジェクトを利用した場合の翻訳キーはどれ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Formオブジェクトを利用した場合の翻訳キーはどれ？&lt;/h2&gt;
&lt;p&gt;通常DBに紐づくモデル、つまり&lt;code&gt;ActiveRecord::Base&lt;/code&gt;を継承したクラスに対応するフォームを作成する場合、次のような$1ファイルを作成することで、バリデーションメッセージや表示される項目を多$1することができます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ja:  activerecord: # activerecordをキーにする    attributes:      user:        name: 名前        password: パスワード&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;一方DBへの保存だけではなく、複雑な$1を実装する場合にはFormオブジェクトを作って対処します。例えばフォームから入力されたデータを用いて、メール送信を行うような場合です。&lt;/p&gt;
&lt;p&gt;Formオブジェクトは複数のモデルを扱ったり、DB以外の操作が伴うため、基本的には&lt;code&gt;ActiveModel::Model&lt;/code&gt;をincludeした形で実装します。&lt;/p&gt;
&lt;p&gt;また、form_withからの$1判定を行うために、to_modelをオーバーライドし、メインとなるModelクラスに向けることもあります。&lt;/p&gt;
&lt;p&gt;…こうなってくると、i18n用のi18nファイルをどうやって書いたらいいのかよくわからなくなってきたので、Railsがどのようにi18nファイルを解釈しているのか調べました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#要約&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;要約&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;ActiveModelとActiveRecordはそれぞれ&lt;code&gt;i18n_scope&lt;/code&gt;を実装していて、これによりActiveRecordファイルのトッActiveRecordルの探索キーが決まる。&lt;/li&gt;
&lt;li&gt;Formオブジェクト側で行っている処理（例：バリデーション）は&lt;code&gt;activemodel&lt;/code&gt;をキーにする&lt;/li&gt;
&lt;li&gt;to_modelをオーバーライドしてActiveRecord::Baseを継承したモデルを参照している場合、それらの表示に対する翻訳は&lt;code&gt;activerecord&lt;/code&gt;をキーにする&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#前提&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;前提&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#対象バージョン&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;対象バージョン&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;ActiveRecord：~&amp;gt; 7.0.0&lt;/li&gt;
&lt;li&gt;ActiveModel：~&amp;gt; 7.0.0&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#サンプルケース&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;サンプルケース&lt;/h3&gt;
&lt;p&gt;モデル：User&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;class User &amp;lt; ApplicationRecordend&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;フォームオブジェクト：UserForm&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;class UserForm    include ActiveModel::Model  include ActiveModel::Attributes  attr_reader :user  def initialize(user = User.new, **attributes)    @user = user    attributes = default_attributes if attributes.empty?    super(attributes)  end  validates :name, presence: true  # バリデーションがいっぱい  attribute :name, :string  # カラム定義も様々  def save    # 実際の処理  end  def to_model    user  endend&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#railsがmodelのi18nを探索する手順&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;RailsがModelのi18nを探索する手順&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#バリデーションメッセージ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;バリデーションメッセージ&lt;/h3&gt;
&lt;p&gt;バリデーション用のエラーメッセージの組み立ては、&lt;code&gt;ActiveModel::Error.generata_message&lt;/code&gt;で行われています。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/rails/rails/blob/main/activemodel/lib/active_model/error.rb#L64&quot; target=&quot;_blank&quot;&gt;https://github.com/rails/rails/blob/main/activemodel/lib/active_model/error.rb#L64&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;def self.generate_message(attribute, type, base, options) # :nodoc:      type = options.delete(:message) if options[:message].is_a?(Symbol)      value = (attribute != :base ? base.read_attribute_for_validation(attribute) : nil)      options = {        model: base.model_name.human,        attribute: base.class.human_attribute_name(attribute, { base: base }),        value: value,        object: base      }.merge!(options)      if base.class.respond_to?(:i18n_scope)        i18n_scope = base.class.i18n_scope.to_s        attribute = attribute.to_s.remove(/\[\d+\]/)        defaults = base.class.lookup_ancestors.flat_map do |klass|          [ :&quot;#{i18n_scope}.errors.models.#{klass.model_name.i18n_key}.attributes.#{attribute}.#{type}&quot;,            :&quot;#{i18n_scope}.errors.models.#{klass.model_name.i18n_key}.#{type}&quot; ]        end        defaults &amp;lt;&amp;lt; :&quot;#{i18n_scope}.errors.messages.#{type}&quot;        catch(:exception) do          translation = I18n.translate(defaults.first, **options.merge(default: defaults.drop(1), throw: true))          return translation unless translation.nil?        end unless options[:message]      else        defaults = []      end      defaults &amp;lt;&amp;lt; :&quot;errors.attributes.#{attribute}.#{type}&quot;      defaults &amp;lt;&amp;lt; :&quot;errors.messages.#{type}&quot;      key = defaults.shift      defaults = options.delete(:message) if options[:message]      options[:default] = defaults      I18n.translate(key, **options)    end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://api.rubyonrails.org/classes/ActiveModel/Errors.html#method-i-generate_message&quot; target=&quot;_blank&quot;&gt;https://api.rubyonrails.org/classes/ActiveModel/Errors.html#method-i-generate_message&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;抜粋するとこんな感じです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;def self.generate_message(attribute, type, base, options) # :nodoc:    # 1： 対象のクラスについて、i18n_scopeを実行し、キーを取得する。  if base.class.respond_to?(:i18n_scope)    i18n_scope = base.class.i18n_scope.to_s    attribute = attribute.to_s.remove(/\[\d+\]/)    defaults = base.class.lookup_ancestors.flat_map do |klass|      [ :&quot;#{i18n_scope}.errors.models.#{klass.model_name.i18n_key}.attributes.#{attribute}.#{type}&quot;,        :&quot;#{i18n_scope}.errors.models.#{klass.model_name.i18n_key}.#{type}&quot; ]    end    # 省略  end  # 2. 取得できた情報でデータを翻訳文を作成し、つっこむ  key = defaults.shift  defaults = options.delete(:message) if options[:message]  options[:default] = defaults  # 3. 2で作成されたデータで翻訳処理を行う（ロケールに応じたファイルを選択する）  I18n.translate(key, **options)end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;ここで肝になるのは&lt;code&gt;i18n_scope&lt;/code&gt;というメソッドです。このメソッドにより、&lt;code&gt;activerecord&lt;/code&gt;を見にいくのか、&lt;code&gt;activemodel&lt;/code&gt;を見にいくのかが決まります。&lt;/p&gt;
&lt;p&gt;ではその実装はどうなっているのかというと、ActiveModelの場合、次のようになっています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Returns the +i18n_scope+ for the class. Override if you want custom lookup.def i18n_scope  :activemodelend&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/rails/rails/blob/75a9e1be75769ae633a938d81d51e06852a69ea3/activemodel/lib/active_model/translation.rb#L26&quot; target=&quot;_blank&quot;&gt;https://github.com/rails/rails/blob/75a9e1be75769ae633a938d81d51e06852a69ea3/activemodel/lib/active_model/translation.rb#L26&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;一方で、ActiveRecordでも同じメソッドがオーバーライドされており、次のように実装されています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Set the i18n scope to override ActiveModel.def i18n_scope # :nodoc:  :activerecordend&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/rails/rails/blob/75a9e1be75769ae633a938d81d51e06852a69ea3/activerecord/lib/active_record/translation.rb#L20&quot; target=&quot;_blank&quot;&gt;https://github.com/rails/rails/blob/75a9e1be75769ae633a938d81d51e06852a69ea3/activerecord/lib/active_record/translation.rb#L20&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これにより、翻訳対象のクラスが&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ActiveModelの場合は、&lt;code&gt;activemodel&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;ActiveRecordの場合は、&lt;code&gt;activerecord&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;が翻訳キーとして採用されることになります。&lt;/p&gt;
&lt;p&gt;ここで、バリデーションメッセージについては、Formオブジェクト、つまりActiveModelで実装されたものです。そのため、エラーメッセージの翻訳キーは&lt;code&gt;activemodel&lt;/code&gt;始まりになります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ja:    activemodel:        user_form:            name: 名前            password: パスワード&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#カラム画面表示項目&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;カラム（画面表示項目）&lt;/h3&gt;
&lt;p&gt;カラム（画面表示項目）の翻訳についても先のi18n_scopeで説明がつきます。&lt;/p&gt;
&lt;p&gt;form_withでフォームを作成する際に、to_modelによって、ActiveRecordであるUser側にクラス判定が向くため、ActiveRecordのi18n_scopeが採用されます。&lt;/p&gt;
&lt;p&gt;そのため、以下のような$1ファイルを記述します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ja:    activerecord:        user:            name: 名前            password: パスワード&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;なおUserモデルに含まれない項目をFormオブジェクトに定義した場合も、翻訳ファイルはactiverecord下に記述することに注意が必要です。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;以上Formオブジェクトでの翻訳キーの参照先についての調査でした。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Slapdashを使って、瞬間で Notionにアイデアを追加する</title><link>https://ikuma-t.com/blog/202202171645061400/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202202171645061400/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217080548.pngNotionは情報を</description><pubDate>Thu, 17 Feb 2022 10:30:00 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217080548.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217080548.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217080548.png&quot; alt=&quot;f:id:ikmbear:20220217080548p&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#notionは情報を貯めるには便利だけど開くのは面倒&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Notionは情報を貯めるには便利だけど、開くのは面倒&lt;/h2&gt;
&lt;p&gt;Notionも「辛い」と言われるくらいに普及してきましたね。英語版だけだったり、無料ユーザーはブロック数に制限があったりした時代が懐かしいです。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217073348.png&quot; alt=&quot;f:id:ikmbear:20220217073348p&quot; /&gt; やっぱり1つの情報を複数の表示形式で閲覧することができるのは非常に画期的で、自分もブログネタを管理するのに使用しています（同じDBをボードとカレンダーで表示して、コンテンツの状況と締切を一覧している）。&lt;/p&gt;
&lt;p&gt;こうやって溜まった情報を閲覧するにはすごい便利なんですが、問題はちょっとリッチ &amp;amp; ゆるすぎて、新しい情報を登録するためにわざわざNotionを開くのが面倒くさいんですよね。&lt;/p&gt;
&lt;p&gt;特にブログ記事みたいなア$1は、他の作業をしている時にふっと思いつくものなので、Notionを開くことによる$1が発生するのがネックでした。&lt;/p&gt;
&lt;p&gt;そこでSlapdashというコマンドランチャーの機能を使い、Notionへの登録を簡略化したのですが、これが結構よかったのでご紹介したいと思います。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#slapdashの使い方&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Slapdashの使い方&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#slapdashとは&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Slapdashとは&lt;/h3&gt;
&lt;p&gt;Slapdashは各種Webアプリを統合し、まとめて操作できるランチャーアプリです。&lt;/p&gt;
&lt;p&gt;TrelloやAsanaといったプロジェクト管理ツールから、GitHub、Figmaといったクリエイティブツールまで、このアプリから一括で検索、追加、編集を行うことができます（※：アプリによって、操作できる範囲は異なります）。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://slapdash.com/&quot; target=&quot;_blank&quot;&gt;slapdash.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217073457.gif&quot; alt=&quot;f:id:ikmbear:20220217073457g&quot; /&gt;&lt;/p&gt;
&lt;p&gt;例えばGitHubを連携した場合、GIFのようにどこからでもコマンドパレットを立ち上げ、自分が関与しているGitHubのIssueを横断して検索することができます（ここからIssueを選択し、登録・編集操作が可能です）。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217073556.png&quot; alt=&quot;f:id:ikmbear:20220217073556p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;価格についてはBasic、Pro、Teamsの3つのプランがありますが、今回紹介する範囲はBasic、すなわち無料で使える範囲での機能紹介になります（私もBasic会員です）。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217073617.gif&quot; alt=&quot;f:id:ikmbear:20220217073617g&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ランチャー画面とは別に起動画面があり、ここからアプリを連携したり、Spaceと呼ばれる空間にリンクを突っ込んだり、自分専用のコマンドを作成することができます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#notionと連携する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Notionと連携する&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217073649.png&quot; alt=&quot;f:id:ikmbear:20220217073649p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;SlapdashはNotionにも対応しており、操作としては&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ページの新規作成（Not DB）&lt;/li&gt;
&lt;li&gt;DBに新たにページを追加&lt;/li&gt;
&lt;li&gt;既存のページに対してコンテンツを追加&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;の3つに対応しています。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217073713.png&quot; alt=&quot;f:id:ikmbear:20220217073713p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Notionを連携する場合は、Slapdashを起動してから「Apps」を選択し、&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217073728.png&quot; alt=&quot;f:id:ikmbear:20220217073728p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;「App Store」からNotionを選択します（私の場合は接続済になっているので表示が異なりますが、新規接続の場合はConnectというボタンが表示されているので、それを選択します）。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217073743.png&quot; alt=&quot;f:id:ikmbear:20220217073743p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;この接続を行った時点で存在するNotionのページやDBに対して、Slapdashへと編集の許可が降りるようになっています。そのため、接続後に新しくNotionページやDBを追加し、それらに対してSlapdashから操作を行いたい場合は、Notion側でAPIを許容する必要があります（Notion右上のShare → SlapdashをInviteする）。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#slapdashから実行できるnotionの操作&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Slapdashから実行できるNotionの操作&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#notion内の検索を行う&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Notion内の検索を行う&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217073814.gif&quot; alt=&quot;f:id:ikmbear:20220217073814g&quot; /&gt;&lt;/p&gt;
&lt;p&gt;「Notion」と入力し、「Filter by Notion」を選択することで、Notionのページを横断的に検索することができます。また「Notion」と入力しなくても検索ワードを直接入力してもページやDBにたどり着くことができます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#slapdashからnotionのページを作成する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;SlapdashからNotionのページを作成する&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217073856.png&quot; alt=&quot;f:id:ikmbear:20220217073856p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;「Notion」→「Create New Notion Page」と進むことで、単一のページを作成することができます。作成する際には作成場所となる親のページを指定します。&lt;/p&gt;
&lt;p&gt;作成する際にページタイトルやコンテンツは指定できません。あくまでページを作成するのみです。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#slapdashからnotionのデータベースにページを追加する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;SlapdashからNotionのデータベースにページを追加する&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217073919.png&quot; alt=&quot;f:id:ikmbear:20220217073919p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;「Notion」→「Add to Notion Database」と進み、対象のDBを指定することで、そのDBに新しくページを追加することができます。&lt;/p&gt;
&lt;p&gt;紙芝居でイメージをご紹介しましょう🐵🦀&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217073934.png&quot; alt=&quot;f:id:ikmbear:20220217073934p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;例えば私の場合だと、このようなプロパティを持ったブログネタ管理用のDBがあります。ここに新しくページを追加します。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217080735.png&quot; alt=&quot;f:id:ikmbear:20220217080735p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;対象のDBとして「ブログ」にカーソルを合わせTab or Enterキーを押します。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217075722.png&quot; alt=&quot;f:id:ikmbear:20220217075722p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;するとこのDBのプロパティとコンテンツを入力するためのフォームが出てきます。各プロパティには、Notionであらかじめ指定しておいたフォーマットに合わせて入力を行うことができます（リストやカレンダーなど）。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217075130.png&quot; alt=&quot;f:id:ikmbear:20220217075130p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;「Add」を押すと、作成した記事に対するアクションを指定することができます。今回は「Open in Notion」で作成した情報をチェックしてみましょう。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217075145.png&quot; alt=&quot;f:id:ikmbear:20220217075145p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;先程入力した内容がNotionに追加されました。Markdownも正しく反映されています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#追加したnotionのページにコンテンツを追加する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;追加したNotionのページにコンテンツを追加する&lt;/h3&gt;
&lt;p&gt;先ほどはNotionにページを追加する操作でしたが、追加したページに内容を追記することもできます。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217080935.png&quot; alt=&quot;f:id:ikmbear:20220217080935p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;「Notion」→「Add to Notion Page」と進み、ページを指定することでコンテンツを追加することができます。こちらも紙芝居で動作をみていきましょう。先程追加した「新しいブログ記事」に対して追加を行っていきます。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217075228.png&quot; alt=&quot;f:id:ikmbear:20220217075228p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ページを選択すると、コンテンツの入力フォームが表示されます。こちらもMarkdownで内容を記述することができます。&lt;/p&gt;
&lt;p&gt;内容を追記したら「Add」を選択し、先程と同じように「Open in Notion」で作成した情報をチェックしてみます。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217075241.png&quot; alt=&quot;f:id:ikmbear:20220217075241p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ページの最下部に今追加し内容が追記されました！&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#tipstemplateを作成する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Tips：templateを作成する&lt;/h2&gt;
&lt;p&gt;「このDBにテーブルを追加することがほとんど」「新規作成時はこのステータスで登録する」といった具合に、具体的なケースがある場合はSlapdashのテンプレート機能を利用して効率化することができます。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217080843.png&quot; alt=&quot;f:id:ikmbear:20220217080843p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Slapdashから「Create Command」→「Template」と進みます。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217075309.png&quot; alt=&quot;f:id:ikmbear:20220217075309p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;テンプレートは連携しているサービスに対してそれぞれ作成できるのですが、今回はNotionへのDB追加のテンプレートを作成するため、「Add to Notion Database」を指定します。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217075328.png&quot; alt=&quot;f:id:ikmbear:20220217075328p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;まずはNotionのテンプレートを指定します。ここで指定した項目がSlapdashからの登録時のデフォルト値になります。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217075350.png&quot; alt=&quot;f:id:ikmbear:20220217075350p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Notion側の設定を終えたら、ページをスクロールしテンプレート自体の設定を行います。&lt;/p&gt;
&lt;p&gt;Nameにはテンプレートの名前を、その他アイコンや説明を追記します。$1を設定しておくと、Slapdashのコマンドパレットにその$1を入力することで、テンプレートを呼び出すことができます。&lt;/p&gt;
&lt;p&gt;設定が完了したら「Create Command」を押して、実際に試してみましょう！今回はwtという$1を貼ったので、これをキーに呼び出してみます。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220217/20220217075428.gif&quot; alt=&quot;f:id:ikmbear:20220217075428g&quot; /&gt;&lt;/p&gt;
&lt;p&gt;呼び出した入力画面に、あらかじめ設定した内容が反映されていることが確認できました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;というわけでSlapdashを使ったNotionの更新フローの紹介でした。&lt;/p&gt;
&lt;p&gt;私はこれを使って、冒頭にも述べた通りブログネタを登録して思いついた時にア$1を追記したり、やりたいことリストを追加したりしています。&lt;/p&gt;
&lt;p&gt;思いついた時に登録することでア$1を漏らさず、かつどこからでも登録できることで現在のタスクから大きく$1をすることもなく、快適に生活できています。&lt;/p&gt;
&lt;p&gt;SlapdashはNotion以外のツールにも対応していますので、ぜひ試してみてください。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Appraisalを使っている状態でもRubyMineのGUIでRSpecを実行する</title><link>https://ikuma-t.com/blog/202202091644368400/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202202091644368400/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220209/20220209071635.pngきっかけTL;前提の</description><pubDate>Wed, 09 Feb 2022 10:00:00 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220209/20220209071635.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220209/20220209071635.png&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%81%8D%E3%81%A3%E3%81%8B%E3%81%91&quot;&gt;きっかけ&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#TLDR&quot;&gt;TL&lt;/a&gt;&lt;/p&gt;&lt;div&gt;&lt;/div&gt;&lt;a href=&quot;#TLDR&quot;&gt;;&lt;/a&gt;&lt;p&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%89%8D%E6%8F%90%E3%81%AE%E3%81%8A%E3%81%95%E3%82%89%E3%81%84&quot;&gt;前提のおさらい&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#Appraisal&quot;&gt;Appraisal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#RubyMine%E3%81%A7%E3%81%AERSpec%E5%AE%9F%E8%A1%8C&quot;&gt;RubyMineでのRSpec実行&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%95%8F%E9%A1%8C%E7%82%B9&quot;&gt;問題点&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%AF%BE%E5%BF%9C%E7%AD%96&quot;&gt;対応策&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#script%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B&quot;&gt;scriptを作成する&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#RubyMine%E3%81%ABscript%E3%82%92%E8%AA%8D%E8%AD%98%E3%81%95%E3%81%9B%E3%82%8B&quot;&gt;RubyMineにscriptを認識させる&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%AE%9F%E8%A1%8C%E7%B5%90%E6%9E%9C&quot;&gt;実行結果&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E6%84%9F%E6%83%B3&quot;&gt;感想&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#きっかけ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;きっかけ&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/IkumaTadokoro/jp_local_gov/blob/main/Appraisals&quot; target=&quot;_blank&quot;&gt;github.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;先日開発したGemはActiveRecordへの対応を仕様として盛り込んでいるため、Appraisalを使って、複数verのActiveRecordでテストができるようにしています。&lt;/p&gt;
&lt;p&gt;それはそれでいいんですが、この状態でいつものようにRubyMine上からテストを実行しようとすると、Appraisalで指定しているはずのGem（ActiveRecord）がないためにテストが落ちるようになってしまいました（ActiveRecordからAppraisal経由でテストをすれば問題なくとおる）。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Testing started at 7:13 ...An error occurred while loading spec_helper. - Did you mean?                    rspec ./spec/spec_helper.rbFailure/Error: require &quot;active_record&quot;LoadError:  cannot load such file -- active_record# ./spec/spec_helper.rb:6:in `require&apos;# ./spec/spec_helper.rb:6:in `&amp;lt;top (required)&amp;gt;&apos;Run options: include {:full_description=&amp;gt;/JpLocalGov\.find/}All examples were filtered out&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;というわけで今回はAppraisalを経由しても、RubyMine上でテストを実行できるようにしていきます。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#tl&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;TL&lt;div&gt;&lt;/div&gt;;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Apppraisalを導入する場合、各種コマンドは&lt;code&gt;bundle exec appraisal&lt;/code&gt;の形式で呼び出す必要がある。&lt;/li&gt;
&lt;li&gt;RubyMine標準のRSpec実行は&lt;code&gt;bundle exec rspec ….&lt;/code&gt; であるため、Appraisalが導入されていて、そこでインストールされたGemに依存する実装・テストを書いている場合、RubyMine経由でRSpecが実行できなくなる。&lt;/li&gt;
&lt;li&gt;AppraisalのCLIを経由するscriptを作成し、RubyMineに設定することで、RubyMine経由でもRSpecを個別に実行できるようになる。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#前提のおさらい&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;前提のおさらい&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#appraisal&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Appraisal&lt;/h3&gt;
&lt;p&gt;Appraisalはthoutbot社が管理している、複数のバージョンでのテストを同時に行うためのGemです。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/thoughtbot/appraisal&quot; target=&quot;_blank&quot;&gt;github.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;公式READMEからの拝借になりますが、以下のように指定することで、Railsの3と4の双方の環境でテストを実行することができます。通常のGemfileでは1つのGemに対して、1つのバージョンしか指定できないため、複数環境に対応したい場合に重宝します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;appraise &quot;rails-3&quot; do  gem &quot;rails&quot;, &quot;3.2.14&quot;endappraise &quot;rails-4&quot; do  gem &quot;rails&quot;, &quot;4.0.0&quot;end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Appraisalを使用する場合、各種コマンドは次のように実行することになります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;bundle exec appraisal {実行対象の環境} &amp;lt;実行したいコマンド&amp;gt;# 上記例で、rails-3のかんきょうでテストしたい場合、bundle exec appraisal rails-3 rspec&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#rubymineでのrspec実行&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;RubyMineでのRSpec実行&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220209/20220209071635.png&quot; alt=&quot;f:id:ikmbear:20220209071635p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;RubyMineではテスティングGUIに関係なく、GUI上でテストの実行ができます。&lt;/p&gt;
&lt;p&gt;一括実行と個別実行の双方を行うことができます。&lt;/p&gt;
&lt;p&gt;内部的には、各テスティング$1のexampleやname指定のオプションなどを付与しながら、&lt;code&gt;bundle exec rspec&lt;/code&gt;を実行しているだけです。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#問題点&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題点&lt;/h2&gt;
&lt;p&gt;上記の通り、Apppraisalは&lt;code&gt;bundle exec appraisal&lt;/code&gt;の形式で各コマンドを呼び出すことで、指定した環境のGemfileでコマンドを実行することができます。&lt;/p&gt;
&lt;p&gt;逆にいえばAppraisalを経由しないと、Appraisalで指定したGemfileは認識されません。冒頭に述べた通り、Appraisalは複数のバージョンでのテストを可能にするためのGemなので、Appraisalを経由しない = テストが実行できない ということです。&lt;/p&gt;
&lt;p&gt;RubyMineでのテスト実行はAppraisalを経由しない形式になっているので、結果としてAppraisalを利用すると、テストが実行できないということになります。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#対応策&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;対応策&lt;/h2&gt;
&lt;p&gt;以下の2ステップで対応します。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Appraisal経由でテストを実行するscriptを作成する&lt;/li&gt;
&lt;li&gt;1のscriptをRubyMineに認識させる。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;&lt;a href=&quot;#scriptを作成する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;scriptを作成する&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/thoughtbot/appraisal/issues/123&quot; target=&quot;_blank&quot;&gt;github.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;require &apos;rubygems&apos;require &apos;bundler/setup&apos;require &apos;appraisal&apos;require &apos;appraisal/cli&apos;begin appraisal_name = &apos;&apos;rails-5.0&quot; # this is just an example, use the appraisal that you have installed  cmd = [appraisal_name, &apos;rspec&apos;] + ARGV  Appraisal::CLI.start(cmd)rescue Appraisal::AppraisalsNotFound =&amp;gt; e  puts e.message  exit 127end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;AppraisalのIssueを確認していると、同じような問題が起票されていました。&lt;/p&gt;
&lt;p&gt;AppraisalにCLIがあるので、それを間接的に呼び出すようです。このコードでは特定のAppraisal環境をしていするようになっていますが、とりあえずすべてのAppraisal環境で実行するように少し修正しました。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;require &quot;rubygems&quot;require &quot;bundler/setup&quot;require &quot;appraisal&quot;require &quot;appraisal/cli&quot;begin  `bundle exec appraisal list`.split(/\R/) do |appraisal_name|    cmd = [appraisal_name, &quot;rspec&quot;] + ARGV    Appraisal::CLI.start(cmd)  endrescue Appraisal::AppraisalsNotFound =&amp;gt; e  puts e.message  exit 127end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#rubymineにscriptを認識させる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;RubyMineにscriptを認識させる&lt;/h2&gt;
&lt;p&gt;RubyMineのGUI実行は、それぞれ実行の構成を指定することができます。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://zenn.dev/ikuma/books/how-to-use-redimine/viewer/run-source#%E5%AE%9F%E8%A1%8C%E3%81%AE%E6%A7%8B%E6%88%90%EF%BC%9Aedit-configurations&quot; target=&quot;_blank&quot;&gt;zenn.dev&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220209/20220209071725.png&quot; alt=&quot;f:id:ikmbear:20220209071725p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;複数の構成に対して、まとめて設定を行うためには「Edit configuration templates…」を選択します。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220209/20220209071741.png&quot; alt=&quot;f:id:ikmbear:20220209071741p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;左側のサイドバーからRSpecを選択し、「Use cutom RSpec runner script」に、1で作成したscriptを設定します。scriptはどこにおいてもいいですが、Appraisalはプロジェクト固有のものだと思うので、私はプロジェクトのbinフォルダにおいています。&lt;/p&gt;
&lt;p&gt;これにより、RubyMineがRSpecを実行するときは、このコマンドを実行するようになります。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#実行結果&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;実行結果&lt;/h2&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;BUNDLE_GEMFILE=/Users/tadokoroikuma/RubymineProjects/jp_local_gov/gemfiles/rails61.gemfile bundle exec rspec&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これらの設定でRSpec実行時にAppraisalのCLIが走るようになり、Gemfileを指定した状態でテストが実行できるようになりました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;Appraisalで作成した環境に対してCLI実行する分にはこのCLIでいいんですが、「ある特定のテストを特定の環境でのみ実行したい」というケースは対応できないので、対応できるようにしておきたいです（CLIの引数処理→Appraisal CLIの引数処理の部分だけクリアできれば、ちゃちゃっとできると思うので）。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Conventional CommitでGemのCHANGELOGをコミットから自動作成する</title><link>https://ikuma-t.com/blog/202202081644282000/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202202081644282000/</guid><description>ConventionalCommitとは概要Gitのコミット粒度はまずConventionalCommitsで種類が混ざりにくいようにしつつ、「小さいコミットを後からくっつけたり並べ替えたりする方が、</description><pubDate>Tue, 08 Feb 2022 10:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#conventional-commitとは&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Conventional Commitとは&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#概要&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;概要&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Gitのコミット粒度はまずConventional Commitsで種類が混ざりにくいようにしつつ、「小さいコミットを後からくっつけたり並べ替えたりする方が、大きいコミットを後から分割するよりもずっと簡単なので、迷ったら細かくコミットして後から見直せばいいよ」とよく言っています&lt;a href=&quot;https://t.co/ySrZSP2xQ7&quot; target=&quot;_blank&quot;&gt;https://t.co/ySrZSP2xQ7&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;— Takuto Wada (@t_wada) &lt;a href=&quot;https://twitter.com/t_wada/status/1466610043756101634?ref_src=twsrc%5Etfw&quot; target=&quot;_blank&quot;&gt;2021年12月3日&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;t_wadaさんが以前Twitterで言及されているのを見かけて、Conventional Commitなるものがあることを知りました。&lt;/p&gt;
&lt;p&gt;Conventional Commitとは、以下のようなコミットメッセージの規約を指します。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Conventional Commits の仕様はコミットメッセージのための軽量の規約です。 明示的なコミット履歴を作成するための簡単なルールを提供します。この規則に従うことで自動化ツールの導入を簡単にします。 コミットメッセージで機能追加・修正・破壊的変更などを説明することで、この規約は **&lt;a href=&quot;http://semver.org/&quot; target=&quot;_blank&quot;&gt;SemVer&lt;/a&gt;**と協調動作します。&lt;/p&gt;
&lt;p&gt;引用元：&lt;a href=&quot;https://www.conventionalcommits.org/ja/v1.0.0/&quot; target=&quot;_blank&quot;&gt;https://www.conventionalcommits.org/ja/v1.0.0/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;&lt;a href=&quot;#形式&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;形式&lt;/h3&gt;
&lt;p&gt;Conventional Commitは以下の形式を取ります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;型&amp;gt;[任意 スコープ]: &amp;lt;タイトル&amp;gt;[任意 本文][任意 フッター]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;型は&lt;code&gt;feat&lt;/code&gt;や&lt;code&gt;fix&lt;/code&gt;、&lt;code&gt;docs&lt;/code&gt;など、変更を端的に表した単語です。具体的には次のようになります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;feat(subscribe): メール購読解約時のログインを不要にしたユーザーのストレス軽減のため（適当）Closes: #79&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#rubymineでのサポート&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;RubyMineでのサポート&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://www.conventionalcommits.org/en/about/#tooling-for-conventional-commits&quot; target=&quot;_blank&quot;&gt;www.conventionalcommits.org&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;にもある通り、Conventional Commitをサポートするためのツールはかなりたくさんあります。所詮はコミットメッセージなので、人力で入力してもConventional Commitにはできるのですが、型やフッターを選択肢から選べたり、枠が決まっているので形式を意識せずにメッセージを作れたりするので、あった方が何かと便利です。&lt;/p&gt;
&lt;p&gt;このページにもInteliJ用のツールは掲載されているのですが、私は別途「Conventional Commit」というツールを使っています（RubyMineのPluginストアで評価が高いのを選んだだけ）。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://plugins.jetbrains.com/plugin/13389-conventional-commit&quot; target=&quot;_blank&quot;&gt;plugins.jetbrains.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;&lt;a href=&quot;#conventional-commitでchangelogを作る&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Conventional CommitでCHANGELOGを作る&lt;/h2&gt;
&lt;p&gt;で、ここからが今回の本題で、Conventional CommitからCHANGELOGを作成します。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.conventionalcommits.org/ja/v1.0.0/#%E4%BD%95%E6%95%85-conventional-commits-%E3%82%92%E4%BD%BF%E3%81%86%E3%81%AE%E3%81%8B&quot; target=&quot;_blank&quot;&gt;何故-conventional-commits-を使うのか&lt;/a&gt; には、理由の1つに&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;• 変更履歴 (CHANGELOG) を自動的に生成できます。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;とあって、どうやって自動生成できるのかなと思ったんですが、コミットメッセージが規約に則っていることで、別途ツールを使用すればCHANGELOGにCHANGELOGが作成できるということのようです。&lt;/p&gt;
&lt;p&gt;今回は以前リリースしたGemのCHANGELOGを作成してみることにしました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#conventional-changelog&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;conventional-changelog&lt;/h3&gt;
&lt;p&gt;Conventional Commitから色々やるためのツールが、conventional-changelogとしてまとまっています。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/conventional-changelog/conventional-changelog&quot; target=&quot;_blank&quot;&gt;github.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;この中のconventional-changelog-cliを使用してCHANGELOGを作成します。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-cli&quot; target=&quot;_blank&quot;&gt;github.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;&lt;a href=&quot;#インストール&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;インストール&lt;/h3&gt;
&lt;p&gt;conventional-changelog-cliはnpmなので、まずはインストールします。&lt;/p&gt;
&lt;p&gt;リリースのためだけに$1を汚したくないので、グローバルインストールします（グローバルを汚すのはいいんかい）。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$ npm i -g conventional-changelog-cli&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#コマンド&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;コマンド&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;conventional-changelog&lt;/code&gt; コマンドで実行します。helpを見ると分かる通り、結構色々なオプションがあります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$ conventional-changelog --help  Generate a changelog from git metadata  Usage    conventional-changelog  Example    conventional-changelog -i CHANGELOG.md --same-file  Options    -i, --infile              Read the CHANGELOG from this file    -o, --outfile             Write the CHANGELOG to this file                              If unspecified, it prints to stdout    -s, --same-file           Outputting to the infile so you don&apos;t need to specify the same file as outfile    -p, --preset              Name of the preset you want to use. Must be one of the following:                              angular, atom, codemirror, conventionalcommits, ember, eslint, express, jquery or jshint    -k, --pkg                 A filepath of where your package.json is located                              Default is the closest package.json from cwd    -a, --append              Should the newer release be appended to the older release                              Default: false    -r, --release-count       How many releases to be generated from the latest                              If 0, the whole changelog will be regenerated and the outfile will be overwritten                              Default: 1    --skip-unstable           If given, unstable tags will be skipped, e.g., x.x.x-alpha.1, x.x.x-rc.2    -u, --output-unreleased   Output unreleased changelog    -v, --verbose             Verbose output. Use this for debugging                              Default: false    -n, --config              A filepath of your config script                              Example of a config script: https://github.com/conventional-changelog/conventional-changelog/blob/master/packages/conventional-changelog-cli/test/fixtures/config.js    -c, --context             A filepath of a json that is used to define template variables    -l, --lerna-package       Generate a changelog for a specific lerna package (:pkg-name@1.0.0)    -t, --tag-prefix          Tag prefix to consider when reading the tags    --commit-path             Generate a changelog scoped to a specific directory&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#実際に作ってみる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;実際に作ってみる&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;conventional-changelog -p eslint -i CHANGELOG.md -s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;今回はESLint形式で、CHANGELOG.mdに対して追記をしていきます（なんでESLintにしたかというと、ESLintが一番よく知っているパッケージだからというだけです、すみません😅）。&lt;/p&gt;
&lt;p&gt;このコマンドを実行してできたCHANGELOGがコチラになります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# [](https://github.com/IkumaTadokoro/jp_local_gov/compare/v0.1.0...v0.) (2022-01-14)### chore* Add RSpec Runner for JetBrains IDE ([83d8c86](https://github.com/IkumaTadokoro/jp_local_gov/commit/83d8c8649f69506c9a08acf275960480316eb988))* Make JpLocalGov::Data::Importer#prefecture_capital? to return true/false ([82daafd](https://github.com/IkumaTadokoro/jp_local_gov/commit/82daafd19b47e52ff2c1c341a243aef7e5dffae4))### ci* Add spell checking GitHub Actions Workflow ([fc23bd1](https://github.com/IkumaTadokoro/jp_local_gov/commit/fc23bd1a3c10cc49f8aaf4e869c0062b50255f03))### docs* 💅 ([61c6d66](https://github.com/IkumaTadokoro/jp_local_gov/commit/61c6d66a43b75339036656a1b110dec97156177e))* Add how to use JpLocalGov.valid_code? ([2e14d71](https://github.com/IkumaTadokoro/jp_local_gov/commit/2e14d71c146d823e4bc3fa268da2e3a0c5f7ebe1))* Add issue template ([9f416a3](https://github.com/IkumaTadokoro/jp_local_gov/commit/9f416a335247c3be5c52e450b914bd73c380092d)), closes [#47](https://github.com/IkumaTadokoro/jp_local_gov/issues/47)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword&quot; target=&quot;_blank&quot;&gt;Closing Keyword&lt;/a&gt; を使ってIssueをクローズしていると、参照先のIssueも表示されるみたいです。これは結構便利ですね。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#prをもらった場合にどうするか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;PRをもらった場合にどうするか？&lt;/h3&gt;
&lt;p&gt;そのOSSにコミットする人がみんなConventional Commitを使うかというとOSSの場合はそうもいかないと思います。&lt;/p&gt;
&lt;p&gt;私も実際にそのケースに出くわしたのですが、「今回は特例で手動でCHANGELOGを追加するか」ということで、特に調べず終わってしまいました。&lt;/p&gt;
&lt;p&gt;で、この記事を執筆する過程で調べてみたところ、以下の記述が見つかりました。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://www.conventionalcommits.org/ja/v1.0.0/#%E8%B2%A2%E7%8C%AE%E8%80%85%E5%85%A8%E5%93%A1%E3%81%8C-conventional-commits-%E3%81%AE%E4%BB%95%E6%A7%98%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B%E5%BF%85%E8%A6%81%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%81%8B&quot; target=&quot;_blank&quot;&gt;www.conventionalcommits.org&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;いいえ！ Git で squash ベースのワークフローを使用する場合は、主要メンテナがマージ時にコミットメッセージをクリーンアップすることができるため、臨時のコミッタには作業負荷がかかりません。 また、これをするための一般的な方法としては、プルリク$1トからのコミットを git システムが自動的に squash し、主要メンテナによるマージ時に適切な git コミットメッセージを入力するためのフォームを表示するというものです。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Conventional Commit側の主張は、「メンテナが都度直せばいいじゃん」とのことでした…。他のRailsとかどうしているんだろう？それこそRailsのような大きなRailsだとなかなか難しいと思うんですが。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;というわけでConventional Commitで自動的にCHANGELOGを作る方法でした。&lt;/p&gt;
&lt;p&gt;個人的にはコマンド1つでCHANGELOGが完成するので、気楽にupdate作業をできていい感じです。&lt;/p&gt;
&lt;p&gt;PRのマージコミットメッセージの件も含めて、他のOSSがどんな感じにCHANGELOGを書いているのかがすごい気になったのですが、残念ながら作成する過程は見えないので、地域rbとかで聞けたら聞いてみようと思います。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#余談もう少しコミットは細かく積もうかな&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;余談：もう少しコミットは細かく積もうかな&lt;/h2&gt;
&lt;p&gt;少しずれるのですが、最近ちょっと前に以下の動画を見た影響もあって、「できるだけコミットはsquashしておこう」と強く意識しすぎていました。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=VfnWlNbzbkA&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://img.youtube.com/vi/VfnWlNbzbkA/0.jpg&quot; alt=&quot;Embedded YouTube video&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=VfnWlNbzbkA&quot; target=&quot;_blank&quot;&gt;www.youtube.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;そうすると、なかなかコミットが打てなくて作業的には辛いので、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;作業時はconventional commitでこまめにコミットを打つ&lt;/li&gt;
&lt;li&gt;Pushするときにsquashする&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;みたいなフローにしたほうがいいなと記事を書いていて思いました。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>スマホ中毒改善のために空き箱でスマホケースを作る</title><link>https://ikuma-t.com/blog/202202051644031800/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202202051644031800/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220205/20220205090821.jpg$1をついつい触って</description><pubDate>Sat, 05 Feb 2022 12:30:00 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220205/20220205090821.jpg&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220205/20220205090821.jpg&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#1をついつい触ってしまう&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;$1をついつい触ってしまう…&lt;/h2&gt;
&lt;p&gt;勉強中もそうなんですが、ベッドにも$1を持ち込んでしまって、色々と質を落としているのが最近の問題点でした。&lt;/p&gt;
&lt;p&gt;毎週1回、個人のGKPTを振り返っていて、この問題に対しては以下のような議論がなされました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;$1を金庫に入れれば良いのでは？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;休憩中にすぐ見られない。&lt;/li&gt;
&lt;li&gt;しまうのと出すのが億劫になって結局継続できなさそう&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$1を触らない、持っていかないという鉄の意志を持つ&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;意志の力に頼るのは根本的解決にならない&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$1の定位置を机の上にもうけるのはどうだろう？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;見える位置にあると結局触る&lt;/li&gt;
&lt;li&gt;視覚的に見えない位置に収納すると良いのでは？&lt;/li&gt;
&lt;li&gt;あまり遠い場所に置くと、$1をなくす問題が発生する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;机の近くで、かつ見えにくい位置にシュッとしまえるケースがあれば捗りそう&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;捗りそう…！？&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#でプロトタイプ作ってみた&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;で、プロトタイプ作ってみた&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220205/20220205090821.jpg&quot; alt=&quot;f:id:ikmbear:20220205090821j&quot; /&gt;&lt;/p&gt;
&lt;p&gt;というわけでプロトタイプ作成です。イメージ図はこんな感じ。&lt;/p&gt;
&lt;p&gt;右利き &amp;amp; モニターの右側にMacを置いているので、机の左側面にMacケースを作れると、「離着席時にはMacがよく見え、作業時には視界に入らない」という感じにできそう、っていう魂胆です。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220205/20220205090831.jpg&quot; alt=&quot;f:id:ikmbear:20220205090831j&quot; /&gt;&lt;/p&gt;
&lt;p&gt;次は材料探し。プロトタイプってことで家にある材料を探したら、FILCOのキーキャップの空き箱がありました。これを使います。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220205/20220205090840.jpg&quot; alt=&quot;f:id:ikmbear:20220205090840j&quot; /&gt;&lt;/p&gt;
&lt;p&gt;開いてほしい方向と、実際に箱が開く方向があべこべだったので、カッターで無理やりくり抜きました。不器用なんで辛かった…。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220205/20220205090849.jpg&quot; alt=&quot;f:id:ikmbear:20220205090849j&quot; /&gt;&lt;/p&gt;
&lt;p&gt;机に接着して完成です。両面テープも家にはなかったんで、ビニールテープでHOT LIMITにしています。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#いざ装填&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;いざ装填！&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220205/20220205090858.jpg&quot; alt=&quot;f:id:ikmbear:20220205090858j&quot; /&gt;&lt;/p&gt;
&lt;p&gt;設計通り、$1がシュッと入りました！&lt;/p&gt;
&lt;p&gt;目論見通り、作業中は左側に全然意識が向かず、$1を触る時間が格段に減りました。びっくりするほどに睡眠の質もめちゃくちゃ上がりました！$1恐るべし…。&lt;/p&gt;
&lt;p&gt;一つ難点があるとすれば、貼り付けがあまりにも適当すぎるので、定期的に押さえつける必要があることくらいでしょうか。&lt;/p&gt;
&lt;p&gt;やっぱり人間ってのは定位置が決まっていると、うまく整理・整頓できるもんですね。$1の片付けが言っている「姿置き」ってやつですね。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.co.jp/dp/404600049X?tag=hatena-22&amp;amp;linkCode=osi&amp;amp;th=1&amp;amp;psc=1&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://m.media-amazon.com/images/I/5154DgQbjTL._SL500_.jpg&quot; alt=&quot;[図解]トヨタの片づけ&quot; title=&quot;[図解]トヨタの片づけ&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.co.jp/dp/404600049X?tag=hatena-22&amp;amp;linkCode=osi&amp;amp;th=1&amp;amp;psc=1&quot; target=&quot;_blank&quot;&gt;[図解]トヨタの片づけ&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;作者:$1&lt;/li&gt;
&lt;li&gt;$1&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.co.jp/dp/404600049X?tag=hatena-22&amp;amp;linkCode=osi&amp;amp;th=1&amp;amp;psc=1&quot; target=&quot;_blank&quot;&gt;Amazon&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;このプロトタイプでしばらく持ちそうですが、HOT LIMITが解放されてしまったら、ちゃんとしたの作ろうと思います。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Steepで使えるコマンドを見てみよう</title><link>https://ikuma-t.com/blog/202202041643936692/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202202041643936692/</guid><description>資料はこちらspeakerdeck.com昨日omotesando.rb#71で話したネタです。元々はRails7から追加されたActiveModel::APIの話をしようと思っていたんですが、資料作</description><pubDate>Fri, 04 Feb 2022 10:04:52 GMT</pubDate><content:encoded>&lt;p&gt;資料はこちら&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://speakerdeck.com/ikumatadokoro/steepdeshi-erukomandowojian-temiyou&quot; target=&quot;_blank&quot;&gt;speakerdeck.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;昨日omotesando.rb#71で話したネタです。元々はRails7から追加されたActiveModel::APIの話をしようと思っていたんですが、資料作ろうと思った翌日にTechRachoで紹介されていたのでやめました。&lt;/p&gt;
&lt;p&gt;資料にも書いたのですが、RubyMineでLSPがうまく起動できませんでした…。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/soutaro/steep/pull/79&quot; target=&quot;_blank&quot;&gt;github.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;一応ここに書いてある方法でやっているんですけど、なんかがうまくいっていないみたいなので、継続調査していきたいと思います。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>わたしがRubyMineを使う理由</title><link>https://ikuma-t.com/blog/202202031643850000/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202202031643850000/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220203/20220203082003.png「RubyMineの</description><pubDate>Thu, 03 Feb 2022 10:00:00 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220203/20220203082003.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220203/20220203082003.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220203/20220203082003.png&quot; alt=&quot;f:id:ikmbear:20220203082003p&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#rubymineの何がいいのかという問い&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;「RubyMineの何がいいのか？」という問い&lt;/h2&gt;
&lt;p&gt;みなさんRubyMine使っていますか？昨今のエディタシェアでは、やはりVSCodeが一番大きなパイを占めているような感じですが、私はRubyMineが好きなのでずっとRubyMineを使っています（一部例外で、LiveShareを使いたいとか、Slidevのスライドを作る時だけVSCodeを使っています）。&lt;/p&gt;
&lt;p&gt;そんな中、FJORD BOOT CAMPで「みんながおすすめするのでRubyMine使ってみたけど、他のエディタに比べて何がいいんだろう」という質問が出てきました。&lt;/p&gt;
&lt;p&gt;というわけで今回は一利用者として「私がRubyMineを使う理由」を述べてみました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#世界中の開発者体験が機能として実装されている&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;世界中の開発者体験が機能として実装されている&lt;/h2&gt;
&lt;p&gt;VSCodeもかなり便利ですよね。VSCodeを追加していけば「RubyMineではこんなことできるよ」の大多数はVSCodeでもできると思います。これはVimやEmacsを使った場合でも同じで、つまりフルパワー状態の単純な機能比較によっては、普段使用していて馴染んでいるエディタにRubyMineが勝る点はあまりないかもしれません。&lt;/p&gt;
&lt;p&gt;ではRubyMineを使用するメリットは何かというと &lt;strong&gt;「世界中の開発者体験が、あらかじめ機能として実装されていること」&lt;/strong&gt; です。&lt;/p&gt;
&lt;p&gt;たしかにVSCodeにVSCodeを追加すれば、RubyMine相当の機能を動かせるかもしれませんが、それはその機能にあなたが &lt;strong&gt;「気がついた」&lt;/strong&gt; 場合です。使えたら便利だけど読むには細かいGitコマンドのオプションや、DBの操作方法の全てに気がつくことができるでしょうか？少なくとも私には難しそうです。&lt;/p&gt;
&lt;p&gt;RubyMineを運営するJetBrains社は毎年&lt;a href=&quot;https://www.jetbrains.com/ja-jp/lp/devecosystem-2021/&quot; target=&quot;_blank&quot;&gt;開発者に対して調査&lt;/a&gt;を実施し、&lt;a href=&quot;https://www.jetbrains.com/ja-jp/lp/dogfooding/&quot; target=&quot;_blank&quot;&gt;製品開発のためにJetBrains製のエディタのドッグフーディング&lt;/a&gt;を行なっています。これによりRubyMineには、世界中の開発者が「これは開発によく使うし、あると便利」と思っている機能が最初から、つまり &lt;strong&gt;「気がつかなくても」&lt;/strong&gt; 使えるようになっているわけです。&lt;/p&gt;
&lt;p&gt;1人で学習を進めているいまだからこそ、私は世界中の開発者の動きを学習の補助輪とするために、RubyMineを使用しています。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#コマンド操作が全部見えるから&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;コマンド操作が全部「見える」から&lt;/h2&gt;
&lt;p&gt;RubyMineの操作は基本的にすべてGUI上で実行されます。&lt;/p&gt;
&lt;p&gt;そのため、コマンドで実行すると複雑な操作も、実際にどういうことをやっているのかイメージがつきやすいです。&lt;/p&gt;
&lt;p&gt;例えばGitの&lt;code&gt;rebase&lt;/code&gt; は最たる例で、よくわからないけど必要だから…と$1上でやると、「なんかよくわかんない…」「変な感じで取り込まれてしまった…」となりがちです。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s3-us-west-2.amazonaws.com/secure.notion-static.com/280efeef-03ae-4bff-ae5f-620539700455/Untitled.png&quot; alt=&quot;Untitled&quot; /&gt; &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220203/20220203071125.png&quot; alt=&quot;f:id:ikmbear:20220203071125p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;これをRubyMine上でやると、すべてを画面操作として実行できるので、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;実際にどういう作業ができるのか&lt;/li&gt;
&lt;li&gt;今自分が行った操作はどのような結果になるのか&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;が画面上で確認できるため、そのコマンドでできること、自分がやっていることのイメージがしやすくなります。いわばRubyMineが各コマンドの「図解！〇〇」的な役割を担うわけですね。&lt;/p&gt;
&lt;p&gt;もちろんGUI→CUIへの変換は必要になりますが、コマンドの実行イメージがあるおかげで、CUIで実行する際にも意図通りに実行しやすくなり、実行への恐怖感も薄れます。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#はじめこそちゃんと整備された道具を使ったほうがいい&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;はじめこそ、ちゃんと整備された道具を使ったほうがいい&lt;/h2&gt;
&lt;p&gt;私は高校時代に初めてギターにさわり、パン作りを始めました。&lt;/p&gt;
&lt;p&gt;ギターの方は安いアコギを買ってしまったがために、弦高が高くてしばらくバレーコードが弾けなかったのですが、友達の高いギターはとても弾きやすくて、それを借りて練習しているうちに、安い方のアコギでもバレーコードが弾けるようになりました。&lt;/p&gt;
&lt;p&gt;パン作りの方はずっと独学でやっていたのですが、大学時代にアルバイトで実際に製パンをやらせてもらえることになり、そのときに初めて整備された環境でパンを作ったことで、一気にパン作りのコツを掴むことができました。4年分の成長が3日で追い越されるくらいのブレイクスルーでした。&lt;/p&gt;
&lt;p&gt;双方の話に通じるのは、「初めから整備された環境でやっていれば、もっと早く成長できたのに」ということです。何も最高級の環境を整えろというわけではありませんが、最初のうちは**「どんな道具が必要か」**がわからず「&lt;strong&gt;正しい型&lt;/strong&gt;」もわかっていない状態です。&lt;/p&gt;
&lt;p&gt;そんな状態だからこそ、はじめのうちこそRubyのためのフルマネージドなIDEであるRubyMineを使うのがいいんじゃないかなと思っています。&lt;/p&gt;
&lt;p&gt;「弘法筆を選ばず」と言いますが、そもそも弘法って達人の域の話なので、個人的には「初めのうちは筆を選んでいけ」という気持ちです。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;というわけで今回は「私がRubyMineを使う理由」をお届けしました。&lt;/p&gt;
&lt;p&gt;私自身も初学者であるがゆえに、全体的に初学者向けの内容になってしまいました（ある程度プログラミングできる人は、自分の欲しい機能とか開発スタイルでエディタを選ぶ気がするんだ…）。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://speakerdeck.com/ikumatadokoro/chu-xin-zhe-koso-rubyminedeshi-meyou&quot; target=&quot;_blank&quot;&gt;speakerdeck.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;以前FJORD BOOT CAMPの中で行われたLT会でも「初心者こそ！RubyMineで始めよう！」という話をさせていただきましたが、やはり最適化された開発フローをエディタを通じて学べるからこそ、自分のようなエンジニア未経験者でもお金を払ってRubyMineを使用する価値はあると思っています。&lt;/p&gt;
&lt;p&gt;とはいえ、エディタってやっぱりエンジニアの道具の中で一番大きい部分なので、最後は「自分が使いたいエディタ」で楽しく開発するのがいいんじゃないですかね、と雑にしめて終わりにしたいと思います。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#宣伝rubymine入門は無料で読めます&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;宣伝：RubyMine入門は無料で読めます！&lt;/h2&gt;
&lt;p&gt;この記事を読んで、「RubyMine使ってみようかな…でも使いこなせるか不安…」と思った方、ZennでRubyMine入門という無料で読める$1を出しています！&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://zenn.dev/ikuma/books/how-to-use-redimine&quot; target=&quot;_blank&quot;&gt;zenn.dev&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;基本的な操作からGit、エディタの見た目変更まで、RubyMine初心者に必要な内容を詰め込んだ一冊になっているので、ぜひに！&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>OSS gateにビギナーとして参加しました！</title><link>https://ikuma-t.com/blog/202201301643509805/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202201301643509805/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220130/20220130112941.png昨日OSSGateオ</description><pubDate>Sun, 30 Jan 2022 11:30:05 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220130/20220130112941.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220130/20220130112941.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220130/20220130112941.png&quot; alt=&quot;f:id:ikmbear:20220130112941p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;昨日 &lt;a href=&quot;https://oss-gate.doorkeeper.jp/events/125414&quot; target=&quot;_blank&quot;&gt;OSS Gateオンラインワークショップ&lt;/a&gt; にビギナーとして参加してきました！&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#oss-gateとは引用&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;OSS Gateとは？（引用）&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;「OSS Gate」とはOSS開発に参加していない人が参加する人に変わる「入り口」を提供する取り組みです。&lt;/p&gt;
&lt;p&gt;OSS開発に未参加の人向けに参加方法を伝える場を継続的に提供することにより、OSS開発に参加する人を増やすことができるのではないか。それを実現することが「OSS Gate」という取り組みの目的です。&lt;/p&gt;
&lt;p&gt;参考：&lt;a href=&quot;http://oss-gate.github.io/announce/update/2015/12/17/welcome-to-oss-gate.html&quot; target=&quot;_blank&quot;&gt;OSS Gateへようこそ！&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://oss-gate.doorkeeper.jp/&quot; target=&quot;_blank&quot;&gt;oss-gate.doorkeeper.jp&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;&lt;a href=&quot;#参加した理由&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;参加した理由&lt;/h2&gt;
&lt;p&gt;OSS Gateのアンケートには一つだけ書いたんですが、よくよく考えると3つくらいありました。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;いつもOSSにお世話になっているので、自分もそこに貢献したいと思ったから&lt;/li&gt;
&lt;li&gt;2020年にCOVID-19のサイトがOSSとして作成された時に、自分はIT業界で働いているのに何もできなくて、ちゃんと勉強して社会の役に立ちたいと思ったことが原点の一つとしてあるから&lt;/li&gt;
&lt;li&gt;（OSSに限らず）不満に対して文句を言うんじゃなくて、それを改善できるように生きていきたいと思っている。そのための手段としてプログラミングを学び始めたから&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;というような思いが常々あって、でもやっぱり見ず知らずの人にパッチとかIssueを送るのはちょっと気がひけるので、背中を押してもらうために参加しました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#作業内容&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;作業内容&lt;/h2&gt;
&lt;p&gt;イベント自体は10&lt;/p&gt;&lt;div&gt;&lt;/div&gt;〜17&lt;div&gt;&lt;/div&gt;、そのうち手を動かしている時間は11&lt;div&gt;&lt;/div&gt;~15&lt;div&gt;&lt;/div&gt;（途中で休憩あり）。&lt;p&gt;&lt;/p&gt;
&lt;p&gt;今回はオンライン開催だったので、Discord上で作業を進めました。作業ログを見て適宜サポーターさんから$1 &amp;amp; 後述の作業ログのコメントで「いいですね〜」「こういうところを見てみるのもいいかも」みたいなサポートをもらいつつ進める感じです。&lt;/p&gt;
&lt;p&gt;作業内容としては、貢献したいOSSを選んで、それを公式のドキュメントに則って動かす中で改善した方がいいこと、エラーになったことを投げるという形式だったので、私は最近利用したMarkdownを使ってスライドが作れるツールのSlidevを対象にすることにしました。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/slidevjs/slidev&quot; target=&quot;_blank&quot;&gt;github.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;OSS Gateの特徴として、作業中は常に作業ログを取っていきます。実際に私が取った作業ログはこんな感じです。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/oss-gate/workshop/issues/1538&quot; target=&quot;_blank&quot;&gt;github.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;以前、「ログ駆動開発」というテーマでLTを行ったことがあって、自分も普段から作業時は全部ログを書いているんですが、これに似ているかな〜とか思いました。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://ikmbear.hatenablog.com/entry/20211219/1639875600_1&quot; target=&quot;_blank&quot;&gt;ikmbear.hatenablog.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;&lt;a href=&quot;#成果物&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;成果物&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#作成したissue&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;作成したIssue&lt;/h3&gt;
&lt;p&gt;というわけで実際に投げたIssueがこちらになります！&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220130/20220130111402.png&quot; alt=&quot;f:id:ikmbear:20220130111402p&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/slidevjs/slidev/issues/469&quot; target=&quot;_blank&quot;&gt;github.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Slidevには作成したスライドのExport機能があって、これが&lt;code&gt;playwright-chromium&lt;/code&gt;というパッケージに依存しています。&lt;/p&gt;
&lt;p&gt;これがない場合には、コマンド側は&lt;code&gt;npm i playwright-chromium&lt;/code&gt;をするように例外を投げるのですが、一方でドキュメントには&lt;code&gt;npm i -D playwright-chromium&lt;/code&gt;、つまりdevDependenciesとして追加をするように推奨していて齟齬があり、ここを統一した方がいいのでは？というIssueを立てました。&lt;/p&gt;
&lt;p&gt;サポーターさんにも👍をいただいたポイントなのですが、この2つの文言が追加された経緯をGit Blameで辿っていけたのがよかったです。&lt;/p&gt;
&lt;p&gt;遡っていくと、これらの文言は全く同じコミットで追加されていることがわかり、「書き間違いというか表記揺れかな？」と思えたことが主張の安心材料になりました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#気づき&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;気づき&lt;/h3&gt;
&lt;p&gt;午前中にさわっていた時は「エラーにはなったけど、別にログを見ればわかるからここはフィードバックポイントじゃないかな〜」と思っていたんですけど、サポーターのDaipomさんとPiroさんが書いていただいたコメントから、間接的にですが「あれ？案内している文言が違うかも」と気がつくことができました。自分でやるときはちょっとでも「ん？」と思ったところは一旦視点を変えて見つめ直すのがいいかな〜と思いました！&lt;/p&gt;
&lt;p&gt;あとはIssueの下書きが出来上がった際に、「やっていないことを書いてみると文意が伝わりやすくなるかも」「こういう返答も想定されるので、自分のお気持ちも書いておくといいかも」といったアド$1をもらうことができました。前にkoicさんの動画でみたと思うんですが、「なぜそれを取り込む必要があるのか」「そのための判断材料」を意識して書いていくのがやっぱり大切なんだと、自分でやってみて感じました✍️&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#前提知識として何が必要か&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;前提知識として何が必要か？&lt;/h2&gt;
&lt;p&gt;「OSSを動かした際のポイントをフィードバックする」というプログラムなので、そのOSSに対してめちゃくちゃ詳しくないといけないということはないかな〜という印象です。&lt;/p&gt;
&lt;p&gt;技術的な前提としては&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Git / GitHubが使える&lt;/li&gt;
&lt;li&gt;黒い画面が使える&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ってところですかね。実際私も、ブラウザでドキュメント読む→ターミナルでインストールする→ブラウザ上でIssueを立てるって感じでした。&lt;/p&gt;
&lt;p&gt;あとは対象となるOSSを自分で決める必要があるので、最近使ったアプリをちょっと思い出しておくといいかもです（私は当日ふと頭に出たのでSlidevにしましたが、Gemとかでもよかったかも）。なおOSSかどうか、Issueをたてるポイントがありそうかは、プログラムの中で確認するので事前チェックは不要です。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;参加する前は「本当にこの時間内でIssueを立てられるのかな？」と内心不安だったんですが、本当に立てることができて、驚き &amp;amp; とても嬉しかったです！&lt;/p&gt;
&lt;p&gt;OSS Gateの目的として「自分1人でもOSSに参加できるようになる（気持ちになる）」という点があるのですが、今回実際にIssueを立てることでこれからもやっていけそうだな！と感じました。&lt;/p&gt;
&lt;p&gt;（…実際にOSS Gate終了後に今回扱ったSlidevの別件の対応の準備を始めました💪）&lt;/p&gt;
&lt;p&gt;OSS貢献へのあと一歩が踏み出せなかった理由に「こんなんで大丈夫なのかな？」という気持ちがきっとあったのですが、今回サポーターの皆さんに自分のやっていることを「承認」してもらえたり、「客観視」した上でアドOSSをもらえたことで、自分1人の中に沈み込んでいた不安が大きく開けた気持になりました！&lt;/p&gt;
&lt;p&gt;今回の挑戦をステップに、どんどんOSSの世界を楽しみたいと思えるイベントでした！サポートいただいた皆さん、ありがとうございました！！！！😊&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;余談&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;…当日Piroさんに言えなかったんですけど、「シス管系女子全部持ってます！初めてLinuxの勉強する時に買いました！」とここに書き残しておきます😅&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220130/20220130111448.png&quot; alt=&quot;f:id:ikmbear:20220130111448p&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに次回oss-gateのご案内と気になる方へ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに：次回OSS Gateのご案内と気になる方へ&lt;/h2&gt;
&lt;p&gt;OSS Gateは定期的に開催されていて次回は3/8みたいです。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://oss-gate.doorkeeper.jp/events/129871&quot; target=&quot;_blank&quot;&gt;oss-gate.doorkeeper.jp&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;参加できるサポーター枠によって、ビギナーとして参加できる方の数も変わってくるのですが、ビギナーには「サポーターを1人以上連れてくるビギナー」枠があります。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;「サポーターを1人以上連れてくるビギナー」枠&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;今回のワークショップに「サポーター」で参加する人を見つけ、自分は「ビギナー」で参加する枠です。&lt;/li&gt;
&lt;li&gt;実際に「サポーター」の登録者が1人増えたら繰り上がります。&lt;/li&gt;
&lt;li&gt;どの「サポーター」がどの「サポーターを1人以上連れてくるビギナー」に対応しているかはわからないので一番最初に登録していた「サポーターを1人以上連れてくるビギナー」が繰り上がります。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;もし「OSS Gate興味あるけど、枠もいっぱいだし…」という方がいたら、次回開催に限らず、お声がけいただければサポーターとして参加しようと思うので、コメント欄でもTwitterでもお気軽にご連絡ください！&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>⚡️K-Rubyと銀座Railsで自作Gemの話をしました！⚡️</title><link>https://ikuma-t.com/blog/202201281643338800/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202201281643338800/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220128/20220128104136.png自作Gemの話をして</description><pubDate>Fri, 28 Jan 2022 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220128/20220128104136.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220128/20220128104136.png&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E8%87%AA%E4%BD%9CGem%E3%81%AE%E8%A9%B1%E3%82%92%E3%81%97%E3%81%A6%E3%81%8D%E3%81%BE%E3%81%97%E3%81%9F&quot;&gt;自作Gemの話をしてきました！&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%83%97%E3%83%AD%E3%83%A2%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E6%B4%BB%E5%8B%95%E3%81%AE%E6%88%90%E6%9E%9C&quot;&gt;プロモーション活動の成果&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E7%99%BB%E5%A3%87%E3%81%97%E3%81%A6%E3%81%BF%E3%81%A6%E6%84%9F%E3%81%98%E3%81%9F%E3%81%93%E3%81%A8&quot;&gt;登壇してみて感じたこと&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E8%87%AA%E5%88%86%E3%81%AE%E4%B8%AD%E3%81%AE%E7%99%BA%E8%A1%A8%E3%81%AB%E9%96%A2%E3%81%99%E3%82%8BQA&quot;&gt;自分の中の発表に関するQ&amp;amp;A&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E8%87%AA%E5%B7%B1PR%E3%81%AF%E3%81%82%E3%81%95%E3%81%BE%E3%81%97%E3%81%84%E3%81%8B&quot;&gt;自己PRはあさましいか？&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%88%9D%E5%BF%83%E8%80%85%E3%81%8C%E8%A9%B1%E3%81%97%E3%81%A6%E8%BF%B7%E6%83%91%E3%81%98%E3%82%83%E3%81%AA%E3%81%84%E3%81%8B&quot;&gt;初心者が話して迷惑じゃないか？&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%90%8C%E3%81%98%E3%81%93%E3%81%A8%E3%82%92%E4%BD%95%E5%BA%A6%E3%82%82%E8%A8%80%E3%81%86%E3%81%AE%E3%81%AF%E7%94%B3%E3%81%97%E8%A8%B3%E3%81%AA%E3%81%84%E3%81%8B&quot;&gt;同じことを何度も言うのは申し訳ないか？&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%83%81%E3%83%A3%E3%83%B3%E3%82%B9%E3%82%92%E6%8E%B4%E3%82%80%E6%8F%A1%E5%8A%9B%E3%82%82%E6%89%8D%E8%83%BD%E3%81%A3%E3%81%A6%E6%9D%89%E6%B1%9F%E3%81%95%E3%82%93%E3%81%8C%E8%A8%80%E3%81%A3%E3%81%A6%E3%82%8B&quot;&gt;チャンスを掴む握力も才能って杉江さんが言ってる&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E9%8A%80%E5%BA%A7Rails%E3%82%82K-Ruby%E3%82%82LT%E6%9E%A0%E5%8B%9F%E9%9B%86%E4%B8%AD%E3%81%BF%E3%81%9F%E3%81%84%E3%81%A7%E3%81%99&quot;&gt;銀座RailsもK-RubyもLT枠募集中みたいです！&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB&quot;&gt;おわりに&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#自作gemの話をしてきました&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;自作Gemの話をしてきました！&lt;/h2&gt;
&lt;p&gt;K-Rubyと銀座Railsで先日作成した自作Gemの話をしてきました！&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://ikmbear.hatenablog.com/entry/20220118/1642490708&quot; target=&quot;_blank&quot;&gt;ikmbear.hatenablog.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://ginza-rails.connpass.com/event/234304/&quot; target=&quot;_blank&quot;&gt;ginza-rails.connpass.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://k-ruby.connpass.com/event/234964/&quot; target=&quot;_blank&quot;&gt;k-ruby.connpass.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;登壇資料はこちらです。Rails青緑みたいになってます（そこは赤じゃないのかよ：銀座Railsの赤にしようと思ったけど、全面赤は目に良くないのでやめた）&lt;/p&gt;
&lt;p&gt;こっちがK-Ruby&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://speakerdeck.com/ikumatadokoro/di-fang-gong-gong-tuan-ti-kotowobian-li-nixi-utamefalsegemwozuo-tuta&quot; target=&quot;_blank&quot;&gt;speakerdeck.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;こっちが銀座Rails&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://speakerdeck.com/ikumatadokoro/chu-xin-zhe-gadi-fang-gong-gong-tuan-ti-kodowoxi-utamefalsegemwozuo-tutahua&quot; target=&quot;_blank&quot;&gt;speakerdeck.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;同じことを話しているので、ベースは同じなんですが、ちょっとだけまとめの方向性が違います。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;K-Rubyの方は過去のイベントの登壇資料の感じから「自分の学習成果を発表する」っていうところに重点を置いていると感じたので、感想はあっさり目に、自分が工夫したところを多めに話しています。&lt;/li&gt;
&lt;li&gt;銀座Railsの方は初のLT枠募集で、初心者の自分が貢献できるのは「エンジニア未満の人でも気軽にLT登壇していいんだ」という気持ちにプッシュするというところだと思ったので、「初心者の気持ち」に重点を置いてまとめています。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#プロモーション活動の成果&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;プロモーション活動の成果&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/IkumaTadokoro/jp_local_gov&quot; target=&quot;_blank&quot;&gt;github.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;気持ち的には「こういうところでの発表もチャレンジしよう！（そして登壇者特典のパーカーもらおう）」というライトな気持ちで参加したのですが、Gemの方に実利的なフィードバックもあったので、さっくりご紹介しようと思います。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$1のStarが2個増えました（ありがとうございますありがとうございます🙇‍♂️）&lt;/li&gt;
&lt;li&gt;修正のPRをいただけました！Ruby 3.0以降をサポートしていたのですが、2.7からサポートできるようになりました（リリースはまだです）&lt;/li&gt;
&lt;li&gt;yasulabさんから&lt;a href=&quot;https://twitter.com/yasulab/status/1485930716559196164&quot; target=&quot;_blank&quot;&gt;地方公共団体コードを実際に使っている事例&lt;/a&gt;を教えていただけました！継続メンテのモチベーションにすごい繋がりました！&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#登壇してみて感じたこと&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;登壇してみて感じたこと&lt;/h2&gt;
&lt;p&gt;いろいろな方に発表そのものとGemについてフィードバックをもらえたのが嬉しかったです！やっぱり言わないと伝わらないな〜とあらためて感じました！&lt;/p&gt;
&lt;p&gt;あとは銀座Railsの懇親会に初めて参加できたのも嬉しかったです！&lt;/p&gt;
&lt;p&gt;今までは「懇親会って緊張するし、パスかな」と思って参加したことがなかったのですが、「発表した」っていうある種の免罪符的なものがあったので、参加することができました。&lt;/p&gt;
&lt;p&gt;懇親会ではRubyの書き方でワイワイできたり、Railsガイドの裏側の話とかが聞けてすごく楽しかったです。発表内容と被りますけど、Rubyっていう言語を介してつながりが広がっていく感じがとても心地よかったです！&lt;/p&gt;
&lt;p&gt;…あとアンケートは毎回ちゃんと書こうと思いました😅&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#自分の中の発表に関するqa&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;自分の中の発表に関するQ&amp;amp;A&lt;/h2&gt;
&lt;p&gt;今回発表するときにはもうあんまり感じていなかったのですが、今まで、LTという短い枠とはいえ登壇にあたって色々と気にしていたことを3点書きます。「登壇したいけど…」と思っている方の参考になれば…！&lt;/p&gt;
&lt;p&gt;※あくまで一個人の意見です。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#自己prはあさましいか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;自己PRはあさましいか？&lt;/h3&gt;
&lt;p&gt;発表すること自体に「エゴ感強くない？」と感じるかどうかって話ですけど、全然そんなことないと思います。&lt;/p&gt;
&lt;p&gt;私の場合、前職では部署内で数少ない若手であるがゆえに、自己PRをしていなくても、能力の如何にもかかわらず、勝手に注目されたんですよね。だからなのかちょっと自己PRをわざわざすることに少し抵抗がありました。&lt;/p&gt;
&lt;p&gt;でも、自分はこれからエンジニアとして再スタートを切ろうとしているわけだし、突出した能力があるわけでもないので、新卒はおろか、それより前からプログラミングをやっていた人に対しては大幅にハンディキャップがあるわけですよね。&lt;/p&gt;
&lt;p&gt;そんな状態で、企業側に「なんかいい感じに頑張れるから雇ってくれよ」ってのも無理があるし、そもそも見つけてももらえないと思っているので、最近では「外に発信することが礼儀」くらいの感じで個人としては捉えています。&lt;/p&gt;
&lt;p&gt;…みたいな話をもっとちゃんと書いている有名な記事を貼っておきます✍️&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.jnito.com/entry/2018/12/05/071235&quot; target=&quot;_blank&quot;&gt;blog.jnito.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;&lt;a href=&quot;#初心者が話して迷惑じゃないか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;初心者が話して迷惑じゃないか？&lt;/h3&gt;
&lt;p&gt;いろんな人が聞いている場ほど、「自分なんかの発表で時間とってしまって申し訳ない」と思ってしまいがちですが、そんなことはないと思います。とりあえずそういう気持ちがあればちゃんと練習とか資料とか考えると思いますし。&lt;/p&gt;
&lt;p&gt;「経験者」の人には「初心者」の意見は新鮮だと思いますし、同じ「初心者」の人には共感がもらえると思います。&lt;/p&gt;
&lt;p&gt;また「初心者」って一口に言っても、Rubyは同一ではないので、同じことをやってもその人だけの切り口があります（今回の発表だと、仮に同じようにGemを作った話だとしても、心理学者のRubyと「たのしい開発スタートアップRuby」が同時に出てくる発表がカブる確立は限りなく低いはずです）。&lt;/p&gt;
&lt;p&gt;あとはRubyコミュニティはやっぱり優しいので、初心者でも大丈夫って感じでしょうか。&lt;/p&gt;
&lt;p&gt;私は気にしいなので、「初心者だけど優しく受け入れてくれ」っていう無償の優しさを求めるだけなのは抵抗があって、最近はRubyistHotlinks読んだり、Rubyistの人の古い本買ったりして読んで勉強させてもらってます（なので発表に「たのしい開発スタートアップRuby」が出てくるわけですが😅）。そういう気持ちのやわらげ方もありかもです。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#同じことを何度も言うのは申し訳ないか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;同じことを何度も言うのは申し訳ないか？&lt;/h3&gt;
&lt;p&gt;今回のGemの発表は短期間に2つの場所でLTをやっていて、さらにFJORD BOOT CAMP内の自作サービス進捗報告会でもちょいちょい言っているので、なんとな〜く心のどっかで「みんな知っている話をするのは申し訳ない感じするな〜」と思っていました。&lt;/p&gt;
&lt;p&gt;実際に聞いている方がどう思われているかは別として、個人としては&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;発表者$1たらずっとその内容を考えていて、その流れの一つに発表があるけど、聞いている人的には別に発表の瞬間しかその内容に触れないので、重複感はそこまでないのでは？&lt;/li&gt;
&lt;li&gt;人は結構覚えていないものなので、大事なことは何度も言った方がいい（何度も言わないと伝わらない）&lt;/li&gt;
&lt;li&gt;プレゼンは「誰に」「何を」伝えたいかってのが骨子にあると思っていて、客層が変われば「誰に」が変わるので、そこらへんを意識して話し方とか情報の濃淡に手を加えると自分でも安心感が出るのでは？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;とか考えて別にいいんじゃないかな〜と思うようにしました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#チャンスを掴む握力も才能って杉江さんが言ってる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;チャンスを掴む握力も才能って杉江さんが言ってる&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220128/20220128104136.png&quot; alt=&quot;f:id:ikmbear:20220128104136p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;SHIROBAKOっていう人生のバイブルみたいなアニメがあるんですが、その中で杉江さんがこんな言葉を言っています。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;僕は才能っていうのはなによりまずチャンスをつかむ握力と失敗から学べる冷静さだと思う。絵の上手い下手はその次だ。僕は僕より上手い人間がわずかな自意識過剰やつまらない遠慮のせいでチャンスをとりこぼしてきたのを何度も見た。惜しいと思うよ。未だにね。———SHIROBAKO #22 ノアは下着です！より&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;「チャンス」の定義は難しいですけど、個人的には「いつかやってみたい」と思ったことをやる機会があるなら、それはまさしく「チャンス」だと思います。&lt;/p&gt;
&lt;p&gt;私はアウトプット文化が好きということもあって、こういう発表をやってみたいと常々感じていたので、今回のチャンスを掴めたのはとてもよかったです！！&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#銀座railsもk-rubyもlt枠募集中みたいです&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;銀座RailsもK-RubyもLT枠募集中みたいです！&lt;/h2&gt;
&lt;p&gt;ちょっと硬いことも書いちゃいましたが、LTはコミュニティでのコミュニケーションのきっかけにもなるし、そこからいろんな人とRubyのこと、それ以外のことも含めて話せるのは楽しいので、この記事が読んでいただいた方のLT参加モチベーションアップに繋がると嬉しいです！&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://k-ruby.connpass.com/event/237132/&quot; target=&quot;_blank&quot;&gt;k-ruby.connpass.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://ginza-rails.connpass.com/event/237582/&quot; target=&quot;_blank&quot;&gt;ginza-rails.connpass.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;次回の銀座RailsもK-RubyもまだLT枠を募集しているみたいなのでリンク貼っておきます！&lt;/p&gt;
&lt;p&gt;…あと最近はまたコロナが復活してきてオンライン開催が多いですが、オンラインで発表すると、100人に話しても5人に話しても感覚的に変わらないので、いいかもしれません。&lt;/p&gt;
&lt;p&gt;（Youtubeにあがっている過去のRuby関連のオフラインイベント見てると、リアルタイムでリアクションがあっていいなあと思ったりしますが）&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;というわけでLT登壇レポでした。&lt;/p&gt;
&lt;p&gt;LT自体は初めてではなくて、FJORD BOOT CAMP内でやっている「初めてのLT会」で2回、練習の機会をいただいていました。その時の参加レポはこちら&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://ikmbear.hatenablog.com/entry/2020/10/25/130327&quot; target=&quot;_blank&quot;&gt;ikmbear.hatenablog.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://ikmbear.hatenablog.com/entry/20211219/1639875600_1&quot; target=&quot;_blank&quot;&gt;ikmbear.hatenablog.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;こちらの記事でも書きましたが、初めての『初めてのLT会』に参加する際には、FJORD BOOT CAMP内のいろんな人に勇気をもらいました。あらためて感謝感謝です🙏&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://ikmbear.hatenablog.com/entry/2020/12/18/064703&quot; target=&quot;_blank&quot;&gt;ikmbear.hatenablog.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;今後も「出ない神本より出るクソ本」の精神でアウトプットの敷居を下げつつ、もっと意欲的に学習して、技術的にも、聞いていただけるみなさんのプラスになるような登壇ができるように頑張っていきたいと思います！&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>日本の地方公共団体コードをパースするGemをリリースしました</title><link>https://ikuma-t.com/blog/202201181642490708/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202201181642490708/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220118/20220118162141.png作ったものjp_lo</description><pubDate>Tue, 18 Jan 2022 16:25:08 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220118/20220118162141.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220118/20220118162141.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220118/20220118162141.png&quot; alt=&quot;f:id:ikmbear:20220118162141p&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#作ったもの&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;作ったもの&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220118/20220118162056.png&quot; alt=&quot;f:id:ikmbear:20220118162056p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;jp_local_govという日本の$1コードを市区町村の情報にパースしてくれるGemを作りました。人生初Gemリリースです🎉&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/IkumaTadokoro/jp_local_gov&quot; target=&quot;_blank&quot;&gt;github.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://rubygems.org/gems/jp_local_gov&quot; target=&quot;_blank&quot;&gt;rubygems.org&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;「そもそも$1コードってなんやねん」方も多いと思いますが、&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;$1&lt;/strong&gt;（ぜんこくちほうこうきょうだんたいコード）&lt;a href=&quot;https://ja.wikipedia.org/wiki/%E5%85%A8%E5%9B%BD%E5%9C%B0%E6%96%B9%E5%85%AC%E5%85%B1%E5%9B%A3%E4%BD%93%E3%82%B3%E3%83%BC%E3%83%89#cite_note-2&quot; target=&quot;_blank&quot;&gt;[注釈 1]&lt;/a&gt;は、&lt;a href=&quot;https://ja.wikipedia.org/wiki/%E6%97%A5%E6%9C%AC&quot; target=&quot;_blank&quot;&gt;日本&lt;/a&gt;の&lt;a href=&quot;https://ja.wikipedia.org/wiki/%E5%9C%B0%E6%96%B9%E5%85%AC%E5%85%B1%E5%9B%A3%E4%BD%93&quot; target=&quot;_blank&quot;&gt;地方公共団体&lt;/a&gt;につけられた、数字3&lt;a href=&quot;https://ja.wikipedia.org/wiki/%E6%A1%81&quot; target=&quot;_blank&quot;&gt;桁&lt;/a&gt;または5桁または6桁の符号（コード）で ある。コードが与えられる$1とは、&lt;a href=&quot;https://ja.wikipedia.org/wiki/%E9%83%BD%E9%81%93%E5%BA%9C%E7%9C%8C&quot; target=&quot;_blank&quot;&gt;都道府県&lt;/a&gt;・&lt;a href=&quot;https://ja.wikipedia.org/wiki/%E5%B8%82%E7%94%BA%E6%9D%91&quot; target=&quot;_blank&quot;&gt;市町村&lt;/a&gt;・&lt;a href=&quot;https://ja.wikipedia.org/wiki/%E7%89%B9%E5%88%A5%E5%8C%BA&quot; target=&quot;_blank&quot;&gt;特別区&lt;/a&gt;、&lt;a href=&quot;https://ja.wikipedia.org/wiki/%E4%B8%80%E9%83%A8%E4%BA%8B%E5%8B%99%E7%B5%84%E5%90%88&quot; target=&quot;_blank&quot;&gt;一部事務組合&lt;/a&gt;・&lt;a href=&quot;https://ja.wikipedia.org/wiki/%E5%9C%B0%E6%96%B9%E9%96%8B%E7%99%BA%E4%BA%8B%E6%A5%AD%E5%9B%A3&quot; target=&quot;_blank&quot;&gt;地方開発事業団&lt;/a&gt;・&lt;a href=&quot;https://ja.wikipedia.org/wiki/%E5%BA%83%E5%9F%9F%E9%80%A3%E5%90%88&quot; target=&quot;_blank&quot;&gt;広域連合&lt;/a&gt;、加えて、$1ではないが&lt;a href=&quot;https://ja.wikipedia.org/wiki/%E8%A1%8C%E6%94%BF%E5%8C%BA&quot; target=&quot;_blank&quot;&gt;行政区&lt;/a&gt;・&lt;a href=&quot;https://ja.wikipedia.org/wiki/%E6%9D%B1%E4%BA%AC%E9%83%BD%E5%8C%BA%E9%83%A8&quot; target=&quot;_blank&quot;&gt;東京都区部&lt;/a&gt;である。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ja.wikipedia.org/wiki/%E5%85%A8%E5%9B%BD%E5%9C%B0%E6%96%B9%E5%85%AC%E5%85%B1%E5%9B%A3%E4%BD%93%E3%82%B3%E3%83%BC%E3%83%89&quot; target=&quot;_blank&quot;&gt;全国地方公共団体コード - Wikipedia&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;というものです。JIS規格にも指定されています。&lt;/p&gt;
&lt;p&gt;3桁、5桁、6桁とありますが、ルール的には&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;上2桁が$1府県、&lt;/li&gt;
&lt;li&gt;続く3桁が市区町村&lt;/li&gt;
&lt;li&gt;残りの1桁がチェックディジット&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;になっているので、このGemでは6桁フルの状態をパースできるようになっています。&lt;/p&gt;
&lt;p&gt;READMEにも書いているのですが、jp_prefectureのア$1に多大に影響を受けています。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/chocoby/jp_prefecture&quot; target=&quot;_blank&quot;&gt;github.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;&lt;a href=&quot;#作った背景&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;作った背景&lt;/h2&gt;
&lt;p&gt;今作っているサービスで必要だったからです。&lt;/p&gt;
&lt;p&gt;ざっくりいうと公共料金を計算するサービスで、その計算のための料率が市区町村ごとに違うために、市区町村ごとにレコードを持つ必要がありました。&lt;/p&gt;
&lt;p&gt;で、市区町村だけのテーブルをもつのもなんだか微妙だし、市区町村のための管理画面をもつのも面倒だったので、「Gemでできないかな〜」と思っていたのですが、似たようなア$1のGemは更新が数年前…。&lt;/p&gt;
&lt;p&gt;…みたいなことを、FJORD BOOT CAMP内で日報に書いたら、メンターさんから「作ってみては」とアド$1が。&lt;/p&gt;
&lt;p&gt;「ちょっと難しいかも…」と思いつつも、内心「作ってみたい、MY FIRST GEM」という思いが心の中に溢れてきたので、作ることにしました！&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#使い方&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;使い方&lt;/h2&gt;
&lt;p&gt;だいたいREADMEに書いてある通りなんですが、英語なので日本語でも書きます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#インストール&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;インストール&lt;/h3&gt;
&lt;p&gt;一応Ruby3.0.0以上が対象です。&lt;/p&gt;
&lt;p&gt;普通にインストールするか&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;gem install jp_local_gov&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Gemfileを使ってインストールします&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Gemfilegem &apos;jp_local_gov&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;bundle install&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;必要に応じて&lt;code&gt;require&lt;/code&gt; します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;require &apos;jp_local_gov&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#id指定の検索jplocalgovfind-&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;id指定の検索（&lt;code&gt;JpLocalGov.find&lt;/code&gt; ）&lt;/h3&gt;
&lt;p&gt;$1コード（String）を指定することで、$1の情報を取得することができます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;chiyodaku = JpLocalGov.find(&quot;131016&quot;)# =&amp;gt; #&amp;lt;JpLocalGov::LocalGov:0x00007fe706a8f148 @code=&quot;131016&quot;, @prefecture_code=&quot;13&quot;, @prefecture=&quot;東京都&quot;, @prefecture_kana=&quot;トウキョウト&quot;, @city=&quot;千代田区&quot;, @city_kana=&quot;チヨダク&quot;, @prefecture_capital=false&amp;gt;chiyodaku.code# =&amp;gt; &quot;131016&quot;chiyodaku.prefecture_code# =&amp;gt; &quot;13&quot;chiyodaku.prefecture# =&amp;gt; &quot;東京都&quot;chiyodaku.prefecture_kana# =&amp;gt; &quot;トウキョウト&quot;chiyodaku.city# =&amp;gt; &quot;千代田区&quot;chiyodaku.city_kana# =&amp;gt; &quot;チヨダク&quot;chiyodaku.prefecture_capital# =&amp;gt; false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;この後のメソッドでも共通ですが、取得できる情報は&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$1コード&lt;/li&gt;
&lt;li&gt;$1府県コード&lt;/li&gt;
&lt;li&gt;$1府県（漢字）&lt;/li&gt;
&lt;li&gt;$1府県（カタカナ）&lt;/li&gt;
&lt;li&gt;市区町村（漢字）&lt;/li&gt;
&lt;li&gt;市区町村（カタカナ）&lt;/li&gt;
&lt;li&gt;$1所在地かどうか&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;です。&lt;/p&gt;
&lt;p&gt;ひらがなとか英字とかも追加するのは苦ではないんですが、$1が出している元データは漢字とカタカナだけなのと、あんまり$1が見つからなかったので、一旦出していません。&lt;/p&gt;
&lt;p&gt;あと東京都の都庁所在地は一応「東京」って習ったと思うんですが、「新宿」として登録しています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#条件指定での検索jplocalgovwhere&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;条件指定での検索（&lt;code&gt;JpLocalGov.where&lt;/code&gt;）&lt;/h3&gt;
&lt;p&gt;上記の取得できる情報をキーとして、ハッシュを渡すことで、指定した条件に合致する市区町村の情報が配列で返ってきます。&lt;/p&gt;
&lt;p&gt;なお複数の条件を指定した場合はAND検索になります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;misato = JpLocalGov.where(city: &quot;美郷町&quot;)# =&amp;gt; [#&amp;lt;JpLocalGov::LocalGov:0x00007fb1c594cb08 @code=&quot;054348&quot;, @prefecture_code=&quot;05&quot;, @prefecture=&quot;秋田県&quot;, @prefecture_kana=&quot;アキタケン&quot;, @city=&quot;美郷町&quot;, @city_kana=&quot;ミサトチョウ&quot;, @prefecture_capital=false&amp;gt;, #&amp;lt;JpLocalGov::LocalGov:8 @code=&quot;324485&quot;, @prefecture_code=&quot;32&quot;, @prefecture=&quot;島根県&quot;, @prefecture_kana=&quot;シマネケン&quot;, @city=&quot;美郷町&quot;, @city_kana=&quot;ミサトチョウ&quot;, @prefecture_capital=false&amp;gt;, #&amp;lt;JpLocalGov::LocalGov:0x00007fb1c1a3ce40 @code=&quot;454311&quot;, @prefecture=&quot;宮崎県&quot;, @prefecture_kana=&quot;ミヤザキケン&quot;, @city=&quot;美郷町&quot;, @city_kana=&quot;ミサトチョウ&quot;, @prefecture_capital=false&amp;gt;]misato.map { &quot;#{_1.prefecture}:#{_1.city}&quot; }# =&amp;gt; [&quot;秋田県:美郷町&quot;, &quot;島根県:美郷町&quot;, &quot;宮崎県:美郷町&quot;]JpLocalGov.where(prefecture: &quot;東京都&quot;, prefecture_capital: true)# =&amp;gt; [#&amp;lt;JpLocalGov::LocalGov:0x00007fb1c219e418 @code=&quot;131041&quot;, @prefecture_code=&quot;13&quot;, @prefecture=&quot;東京都&quot;, @prefecture_kana=&quot;トウキョウト&quot;, @city=&quot;新宿区&quot;, @city_kana=&quot;シンジュクク&quot;, @prefecture_capital=true&amp;gt;]JpLocalGov.where(prefecture: &quot;東京&quot;)# =&amp;gt; nil# Exact match search. You should specified &quot;東京都&quot; instead of &quot;東京&quot;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#全件検索jplocalgovall&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;全件検索（&lt;code&gt;JpLocalGov.all&lt;/code&gt;）&lt;/h3&gt;
&lt;p&gt;すべての$1の情報を取得したい場合に使用します。戻り値は配列です。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;JpLocalGov.all# =&amp;gt;  [#&amp;lt;JpLocalGov::LocalGov:0x00007fdf3a9c6758 @code=&quot;011002&quot;, @prefecture_code=&quot;01&quot;, @prefecture=&quot;北海道&quot;, @prefecture_kana=&quot;ホッカイドウ&quot;, @city=&quot;札幌市na=&quot;サッポロシ&quot;, @prefecture_capital=true&amp;gt;, #&amp;lt;JpLocalGov::LocalGov:0x00007fdf3a9c6730 @code=&quot;011011&quot;,...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Railsだと、&lt;code&gt;collection_select&lt;/code&gt; を使用することで、すべての市区町村のコンボボックスを簡単に作ることができます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#ランダムな1情報の生成jplocalgovrandom&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ランダムな$1情報の生成（&lt;code&gt;JpLocalGov::Random&lt;/code&gt;）&lt;/h3&gt;
&lt;p&gt;ランダムな$1情報から、指定したプロパティを返します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;JpLocalGov::Random.code# =&amp;gt; &quot;281077&quot;JpLocalGov::Random.city# =&amp;gt; &quot;大島町&quot;JpLocalGov::Random.city_kana# =&amp;gt; &quot;チュウオウシ&quot;JpLocalGov::Random.prefecture# =&amp;gt; &quot;青森県&quot;JpLocalGov::Random.prefecture_code# =&amp;gt; &quot;46&quot;JpLocalGov::Random.prefecture_kana# =&amp;gt; &quot;ヒョウゴケン&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;一応想定するケースとしては、FactoryBotで$1コードを指定する際に、決めうちではんく探索的なテストデータを作成しておきたいという場合を想定しています。&lt;/p&gt;
&lt;p&gt;後述しますが、Railsで使用する場合はDBに保持するカラムは&lt;code&gt;local_gov_code&lt;/code&gt; だけなので、その他のプロパティのメソッドはあまり使い所がないかもしれません笑&lt;/p&gt;
&lt;p&gt;補足として、あくまでプロパティ単位でしかランダムな値を生成しないので、ランダムな$1の$1を作成する場合は、&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;JpLocalGov.find(JpLocalGov::Random.code)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;という具合に呼んでやる必要があります。需要があれば、&lt;code&gt;JpLocalGov::Random.new&lt;/code&gt; みたいなのを作るかもです。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#railsでの使用基本&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Railsでの使用（基本）&lt;/h3&gt;
&lt;p&gt;このGemをModelクラスに&lt;code&gt;include&lt;/code&gt;することで、そのモデル内で&lt;code&gt;local_govenment&lt;/code&gt; というメソッドが使えるようになります。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;jp_local_gov :&amp;lt;地方公共団体コードを保存したカラム名&amp;gt;&lt;/code&gt; とすることで、そのカラム（$1コード）から、$1府県名や市区町村の情報を展開することができるようになります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# app/models/insurance_fee.rb:class InsuranceFee &amp;lt; ActiveRecord::Base  # local_gov_code:String  include JpLocalGov  jp_local_gov :local_gov_codeend&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;insurance_fee = InsuranceFee.newinsurance_fee.local_gov_code = &quot;131016&quot;insurance_fee.local_government.city# =&amp;gt; &quot;千代田区&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;なおカラム「$1コード」の作成時、型はStringにする必要があります。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#railsでの使用バリデーションjplocalgovvalid_code-&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Railsでの使用（バリデーション）（&lt;code&gt;JpLocalGov.valid_code?&lt;/code&gt; ）&lt;/h3&gt;
&lt;p&gt;$1コードのチェックのためのメソッドを設けているので、これをカスタムバリデーションに組み込むことで、$1コードのチェックができます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;class InsuranceFee &amp;lt; ApplicationRecord  include JpLocalGov  jp_local_gov :local_gov_code  ## カスタムバリデーションで利用する  validate :valid_code?  def valid_code?    unless JpLocalGov.valid_code?(local_gov_code)      errors.add(:local_gov_code, &quot;is not valid code&quot;)    end  endend&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;実施しているチェックは&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;コードが文字列かどうか&lt;/li&gt;
&lt;li&gt;コードが正しい長さか（6文字）&lt;/li&gt;
&lt;li&gt;チェックディジットを満たしているか&lt;/li&gt;
&lt;li&gt;正しい$1府県コードを持っているか&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;です。&lt;/p&gt;
&lt;p&gt;チェックディジットについては、$1コードの仕様に記載があります。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220118/20220118162309.png&quot; alt=&quot;f:id:ikmbear:20220118162309p&quot; /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;11 検査数字&lt;/p&gt;
&lt;p&gt;$1における検査数字は、電算処理にあたって、不正なコードが使われないよう第6桁目をチェック用としたもので、次の方式により算出した数字とする。(方式)第1桁から第5桁までの数字に、それぞれ6.5.4.3.2を乗じて算出した積の和を求め、その和を11で除し、商と剰余(以下「余り数字」という。)を求めて、11と余り数字との差の下1桁の数字を検査数字とする。ただし、積の和が11より小なるときは、検査数字は、11から積の和を控除した数字とする。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;出典：&lt;a href=&quot;https://www.soumu.go.jp/main_content/000137948.pdf&quot; target=&quot;_blank&quot;&gt;https://www.soumu.go.jp/main_content/000137948.pdf&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;実装としてはこんな感じです。ボリューム的にもプログラミングのちょうどいい問題だと感じていて、結構好きな仕様です。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;CHECK_DIGITS_INDEX = 5CHECK_BASE = 11sub_total = code.chars                .take(CHECK_DIGITS_INDEX)                .map.with_index { |digit, index| digit.to_i * (CHECK_DIGITS_INDEX - index + 1) }                .sumcandidate = (CHECK_BASE - sub_total % CHECK_BASE) % 10check_digits = sub_total &amp;gt; CHECK_BASE ? candidate : CHECK_BASE - sub_totalcode[CHECK_DIGITS_INDEX] == check_digits.to_s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;なお最初はチェックディジットだけのチェックでいいかなと思っていたんですが、チェックディジットを満たしていても、$1府県コードがイレギュラーになるケースに後から気がつきました。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&apos;481238&apos; # 都道府県は47までなので、こんな市区町村はない# 第1桁から第5桁までの数字に、それぞれ6.5.4.3.2を乗じて算出した積の和を求める80# その和を11で除し、商と剰余(以下「余り数字」という。)を求めて、11と余り数字との差の下1桁の数字を検査数字とする。8　　# 存在しない市区町村だけど、チェックディジットを満たす&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;なので、$1府県コード（&lt;code&gt;1..47&lt;/code&gt;）のチェックも入っています。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#仕組み&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;仕組み&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20220118/20220118161859.png&quot; alt=&quot;f:id:ikmbear:20220118161859p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;そこまで複雑なGemではないのですが、一応こういう仕組みです。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.soumu.go.jp/denshijiti/code.html&quot; target=&quot;_blank&quot;&gt;総務省｜地方行政のデジタル化｜全国地方公共団体コード&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;情報の元は$1のこのページです。手順的には以下のような感じです。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;元データ（PDF）をGem：pdf-readerで読み取る&lt;/li&gt;
&lt;li&gt;sqliteにぶん投げる&lt;/li&gt;
&lt;li&gt;sqlite内でソートを行う&lt;/li&gt;
&lt;li&gt;JSON府県ごとにSELECTしてJSONに出力する&lt;/li&gt;
&lt;li&gt;出力されたJSONを使ってJSONコードをパースする&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;このGemはGitHubコードの情報が命なので、この処理自体をRakeタスクとして登録して、GitHub Actionsで1ヶ月に1回、自動でPRを作成する形式にしています。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#今後の展望&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;今後の展望&lt;/h2&gt;
&lt;p&gt;まだIssueにも登録していませんが、ここらへんはやりたいなと思っています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#jplocalgovall-で1の行政区を除外する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;code&gt;JpLocalGov.all&lt;/code&gt; で$1の行政区を除外する&lt;/h3&gt;
&lt;p&gt;「区」って東京のイメージが強いですが、実は各$1府県の$1には区があります。例えば札幌市には$1や東区があります。&lt;/p&gt;
&lt;p&gt;市区町村を選択するのに、ここら辺を選択したい場合もあれば、「札幌市」という市区町村の単位だけがあればいいケースもあると思っています（私のアプリもそうです）。&lt;/p&gt;
&lt;p&gt;なので、これをオプションで除外できるようにしたいです。一応、$1府県コードに続く3桁の決まりでなんとか除外できそうなので、近いうちに入ると思います。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#yardでドキュメントを書く&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;YARDでドキュメントを書く&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;@params&lt;/code&gt; とかかいてあるあれです。&lt;/p&gt;
&lt;p&gt;このGemはRBSを使っているので、それが半分ドキュメントの役割を果たしている感じもしますが、まだまだ普及率も高くないことと、自分自身が書いてみたいので、これも時間ができたらやる予定です。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#各rubyバージョンでのテストのciを実行する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;各RubyバージョンでのテストのCIを実行する&lt;/h3&gt;
&lt;p&gt;強いGemのCIで走っているあれです。&lt;/p&gt;
&lt;p&gt;今はrubyにruby-versionをおいて、それをGitHub Actionsで参照するようにしているのですが、これを各Rubyバージョンで実行できるようにしたいです。&lt;/p&gt;
&lt;p&gt;どうやってやるのかわからんですが。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#曖昧検索一つのプロパティに対して複数条件検索or検索&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;曖昧検索、一つのプロパティに対して複数条件検索、OR検索&lt;/h3&gt;
&lt;p&gt;今実装している&lt;code&gt;where&lt;/code&gt; は完全一致検索かつAND検索で、一つのプロパティに対して一つの条件しか指定できないんですが、ここら辺をもうちょっと柔軟にしたいです。&lt;/p&gt;
&lt;p&gt;あんまり使う機会ないんですけど、なんかできたら良さそうな感じするじゃないですか。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#変更差分の1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;変更差分の$1&lt;/h3&gt;
&lt;p&gt;リリースしてからまだ時間が立ってないので、$1コードの変更は起こっていないんですが、変更が発生した場合になんかいい感じに見せられないかな〜とぼんやり思っています。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#終わりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;終わりに&lt;/h2&gt;
&lt;p&gt;というわけで、$1コードをパースしてくれるGem「jp_local_gov」をリリースしたというお話でした。&lt;/p&gt;
&lt;p&gt;前にもnpmを作ったことはあったのですが、今回はちゃんと実践的に使えるものを作ったので、いろいろと学びも多かったし、楽しかったです😄&lt;/p&gt;
&lt;p&gt;（npmの話はこちら）&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://ikmbear.hatenablog.com/entry/20211017/1634472193&quot; target=&quot;_blank&quot;&gt;ikmbear.hatenablog.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;市区町村まで必要になるケースってそんなに多くないかもですが、もしこのGemを作っていただける方がいるなら嬉しいです！バグや要望はIssueにお気軽に登録してください！&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/IkumaTadokoro/jp_local_gov/issues&quot; target=&quot;_blank&quot;&gt;github.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded><author>ikuma-t</author></item><item><title>最近のScrapboxの使い方（2021/12）</title><link>https://ikuma-t.com/blog/202112191639875600/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202112191639875600/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211015/20211015135059.pngikmbear.ha</description><pubDate>Sun, 19 Dec 2021 10:00:00 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211015/20211015135059.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211015/20211015135059.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211015/20211015135059.png&quot; alt=&quot;f:id:ikmbear:20211015135059p&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://ikmbear.hatenablog.com/entry/20211015/1634273489&quot; target=&quot;_blank&quot;&gt;ikmbear.hatenablog.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;2ヶ月前にこんな記事を書きましたが、微妙に進化している &amp;amp; LT会でScrapboxについてお話ししたので、現状のカスタマイズをScrapboxと合わせてご紹介します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#UserScript%E3%81%A8UserCSS&quot;&gt;UserScriptとUserCSS&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#UserScript&quot;&gt;UserScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#UserCSS&quot;&gt;UserCSS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#UserScript-1&quot;&gt;UserScript&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88&quot;&gt;テンプレート&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E4%BB%95%E7%B5%84%E3%81%BF&quot;&gt;仕組み&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E6%97%A5%E5%A0%B1%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88&quot;&gt;日報テンプレート&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%81%98%E3%81%B6%E3%82%93Release-Notes%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88&quot;&gt;じぶんRelease Notesテンプレート&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E4%BB%8A%E6%97%A5%E3%81%AE%E3%83%9A%E3%83%BC%E3%82%B8%E3%81%AB%E7%A7%BB%E5%8B%95%E3%81%99%E3%82%8B%E3%83%9C%E3%82%BF%E3%83%B3&quot;&gt;今日のページに移動するボタン&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E3%83%9C%E3%83%83%E3%82%AF%E3%82%B9%E3%81%AA%E3%81%A9%E3%82%92%E8%A1%A8%E7%A4%BA%E3%81%99%E3%82%8B&quot;&gt;チェックボックスなどを表示する&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#UserCSS-1&quot;&gt;UserCSS&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%83%94%E3%83%B3%E7%95%99%E3%82%81%E3%81%95%E3%82%8C%E3%81%9F%E3%83%9A%E3%83%BC%E3%82%B8%E3%82%92%E5%88%A5%E3%81%AE%E6%AE%B5%E3%81%A8%E3%81%97%E3%81%A6%E8%A1%A8%E7%A4%BA%E3%81%99%E3%82%8B&quot;&gt;ピン留めされたページを別の段として表示する&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%82%BB%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E7%94%A8%E3%81%AE%E8%A6%8B%E5%87%BA%E3%81%97CSS&quot;&gt;セクション用の見出しCSS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E9%81%8B%E7%94%A8%E6%96%B9%E6%B3%95&quot;&gt;運用方法&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E6%A6%82%E8%A6%81&quot;&gt;概要&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E6%97%A5%E5%A0%B1--%E3%83%A9%E3%82%A4%E3%83%95%E3%83%AD%E3%82%B0&quot;&gt;日報 &amp;amp; ライフログ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%81%98%E3%81%B6%E3%82%93ReleaseNotes%E9%80%B1%E5%A0%B1&quot;&gt;じぶんReleaseNotes（週報）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E6%9C%88%E6%AC%A1%E3%83%9A%E3%83%BC%E3%82%B8&quot;&gt;月次ページ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#Scrapbox%E7%94%A8%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88&quot;&gt;Scrapbox用クライアント&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#userscriptとusercss&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;UserScriptとUserCSS&lt;/h2&gt;
&lt;p&gt;この記事に記載してあるカスタマイズ内容には、ScrapboxのUserScriptとUserCSSを使っています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#userscript&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;UserScript&lt;/h3&gt;
&lt;p&gt;JavaScriptを使ってページを動的にカスタマイズできる機能です。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218223348.gif&quot; alt=&quot;f:id:ikmbear:20211218223348g&quot; /&gt; UserScriptの有効化&lt;/p&gt;
&lt;p&gt;有効化：TOP &amp;gt; User settings &amp;gt; Extensions &amp;gt; User Script「Enabled」をオンにする&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218223615.png&quot; alt=&quot;f:id:ikmbear:20211218223615p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;自分のユーザーページ（ユーザー名と同じタイトルのページ）に&lt;code&gt;code:script.js&lt;/code&gt;という形式でコードを定義することで、そのJavaScriptを有効にすることができます（コード変更直後は、一度トップページに戻って、表示されている「再読み込み」的なボタンをクリックする必要があります）。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://scrapbox.io/help-jp/UserScript&quot; target=&quot;_blank&quot;&gt;scrapbox.io&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;&lt;a href=&quot;#usercss&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;UserCSS&lt;/h3&gt;
&lt;p&gt;CSSを使って見た目をカスタマイズできる機能です。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;settings&lt;/code&gt;というページを作って、&lt;code&gt;code:style.css&lt;/code&gt;というCSSを書くことで、そのプロジェクトでのみ有効なCSSを定義することができます。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218233446.png&quot; alt=&quot;f:id:ikmbear:20211218233446p&quot; /&gt; UserCSSの設定例&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://scrapbox.io/help-jp/UserCSS&quot; target=&quot;_blank&quot;&gt;scrapbox.io&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;&lt;a href=&quot;#userscript-1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;UserScript&lt;/h2&gt;
&lt;p&gt;UserScriptでカスタマイズしている機能を紹介します。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#テンプレート&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;テンプレート&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218233939.gif&quot; alt=&quot;f:id:ikmbear:20211218233939g&quot; /&gt;&lt;/p&gt;
&lt;p&gt;各種テンプレートをボタンクリックで挿入する$1です。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#仕組み&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;仕組み&lt;/h4&gt;
&lt;p&gt;テンプレート機能は次の3つから構成されます。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;テンプレートボタンを追加する機能（UserScript）&lt;/li&gt;
&lt;li&gt;テンプレートボタンの見た目を編集する機能（UserCSS）&lt;/li&gt;
&lt;li&gt;挿入するテンプレート（ただのページ）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;テンプレートボタンを追加する機能&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218235145.png&quot; alt=&quot;f:id:ikmbear:20211218235145p&quot; /&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// UserScriptとしてユーザーページに追加するaddTemplateItemsToPageMenu()  function addTemplateItemsToPageMenu() {    // テンプレートメニューの定義ここから ----------   const __templates = [     { title: &apos;🥞today&apos;, url: &apos;/api/code/ikuma-t/template/today.js&apos; },     { title: &apos;🥞tomorrow&apos;, url: &apos;/api/code/ikuma-t/template/tomorrow.js&apos; },     { title: &apos;🚀release&apos;, url: &apos;/api/code/ikuma-t/template/release.js&apos; }     // メニューを追加する場合は、同じように行を追加する。     // titleにはテンプレートメニューに表示する名前を、urlはそのテンプレートがあるスクリプトのURLを指定する     // `api/code/{自分のユーザー名}/{テンプレートファイルを置いているページ名}/{テンプレート名}.js   ]   // テンプレートメニューの定義ここまで ----------      const __templateMenuTitle = &apos;Templates&apos;   scrapbox.PageMenu.addMenu({ title: __templateMenuTitle, image: &apos;/assets/img/logo.png&apos;, onClick: () =&amp;gt; { } })   __templates.forEach((template) =&amp;gt; {       scrapbox.PageMenu(__templateMenuTitle).addItem({            title: template.title,           onClick: () =&amp;gt; { __loadTemplate(template.url) }})   })      const __loadTemplate = templateUrl =&amp;gt; {     if (scrapbox.Page.lines &amp;amp;&amp;amp; scrapbox.Page.lines.length == 1) {       const line = document.getElementById(&apos;L&apos; + scrapbox.Page.lines[0].id)       const lastChar = line.querySelector(&apos;span.char-index:last-of-type&apos;)       const textarea = document.getElementById(&apos;text-input&apos;)       lastChar.dispatchEvent(new MouseEvent(&apos;click&apos;, {bubbles: true, cancelable: true}))       textarea.dispatchEvent(new KeyboardEvent(&apos;keydown&apos;, {bubbles: true, cancelable: true, keyCode: 35}))       // テンプレートを読み込む       $(&apos;#text-input&apos;).load(templateUrl, function (response, status, xhr) {         if (status == &quot;success&quot;) {           try {             // 読み込んだテンプレートをテキストエリアにセット             textarea.value = /\.js$/.test(templateUrl) ? eval(response) : response             // テキストエリアのinputイベント             textarea.dispatchEvent(new InputEvent(&apos;input&apos;, {bubbles: true, cancelable: true}))             console.log(&quot;できました&quot;)           } catch (ex) {             console.log(&quot;だめでした&amp;gt;&amp;lt; \n&quot; + ex)           }         } else {           console.log(&quot;だめでした&amp;gt;&amp;lt; \n&quot; + status)         }       })     }   } }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;テンプレートボタンの見た目を編集する機能&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218234758.png&quot; alt=&quot;f:id:ikmbear:20211218234758p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;こんな感じにFontAwesomeを使っていい感じのアイコンにします&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/* UserCSSとしてSettingsページに追加する */a#Templates.tool-btn:hover { text-decoration: none }a#Templates.tool-btn::before { position: absolute; content: &apos;\f067&apos;; font: 900 21px/46px &apos;Font Awesome 5 Free&apos; }a#Templates.tool-btn img { opacity: 0 }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;挿入するテンプレート&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218234852.png&quot; alt=&quot;f:id:ikmbear:20211218234852p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;これは適当なページを作って、そこにテンプレートをコードブロックとして定義するだけです。&lt;br /&gt;
なおJavaScriptで書く必要があります。&lt;/p&gt;
&lt;p&gt;ただし、「テンプレートボタンを追加する機能」からアクセスするので、ちゃんとテンプレートごとに別々の名前で定義しておく必要があります。&lt;/p&gt;
&lt;p&gt;ページ名についてはなんでも良いのですが、管理がしやすいので「template」というページに設置しています。&lt;/p&gt;
&lt;p&gt;以下に自分が作成しているテンプレートのコード例を示します。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#日報テンプレート&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;日報テンプレート&lt;/h4&gt;
&lt;p&gt;毎日の日報ページを作成するためのテンプレートです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// today.js (function() {  const today = new Date()  const year = today.getFullYear()  const month = (&quot;0&quot;+(today.getMonth() + 1)).slice(-2)  const date = (&quot;0&quot;+today.getDate()).slice(-2)  const yesterdayDate = (&quot;0&quot;+(today.getDate()-1)).slice(-2)  const tomorrowDate = (&quot;0&quot;+(today.getDate()+1)).slice(-2)   return `　←[${year}/${month}/${yesterdayDate}]：[${year}/${month}/${tomorrowDate}]→　　[{ 日報] [*** 👍やったこと]  [_]  [*** 🎓学習したこと] [** 【わかったこと】] [** 【わからなかったこと】]  [*** 🥷次にやること]  [*** 🍘感想・余談] 　[{ ライフログ]` })()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;私は毎日明日分の日記を作ってから1日を始めるので、明日分のテンプレートも作っています（ほぼほぼ同じです）。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// tomorrow.js (function() {  const today = new Date()  const year = today.getFullYear()  const month = (&quot;0&quot;+(today.getMonth() + 1)).slice(-2)  const date = (&quot;0&quot;+(today.getDate()+1)).slice(-2)  const yesterdayDate = (&quot;0&quot;+(today.getDate())).slice(-2)  const tomorrowDate = (&quot;0&quot;+(today.getDate()+2)).slice(-2)   return `　←[${year}/${month}/${yesterdayDate}]：[${year}/${month}/${tomorrowDate}]→　　[{ 日報] [*** 👍やったこと]  [_]  [*** 🎓学習したこと] [** 【わかったこと】] [** 【わからなかったこと】]  [*** 🥷次にやること]  [*** 🍘感想・余談] 　[{ ライフログ]` })()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h4&gt;&lt;a href=&quot;#じぶんrelease-notesテンプレート&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;じぶんRelease Notesテンプレート&lt;/h4&gt;
&lt;p&gt;週/1ペースで書いているじぶんRelease Notesのテンプレートです。&lt;br /&gt;
最近作ったばかりなので、ちょっと荒削りです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// release.js  (function() {   const today = new Date()   const year = today.getFullYear()   const month = (&quot;0&quot;+(today.getMonth() + 1)).slice(-2)   const date = (&quot;0&quot;+(today.getDate()+1)).slice(-2)   const thisWeek = Math.floor(date / 7) + 1   const lastWeek = thisWeek - 1   const nextWeek = thisWeek + 1      const birthDayYear = 1995      const age = year - birthDayYear     return ` 前：[じぶん Release Notes（ver 0.${age}.${month}.${lastWeek}）] 次：[じぶん Release Notes（ver 0.${age}.${month}.${nextWeek}）]  本日[${year}/${month}]/${date}、ikuma-t（ver 0.${age}.${month}.${thisWeek}）がリリースされました  [** 今週の日記]  [*** 📆振り返り（KPT）] [** KEEP]  [** PROBLEM]  [** TRY]  [*** 🍳感想] 　`  })()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#今日のページに移動するボタン&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;今日のページに移動するボタン&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218235744.gif&quot; alt=&quot;f:id:ikmbear:20211218235744g&quot; /&gt;&lt;/p&gt;
&lt;p&gt;別のページを開いているときに、ふと自分の日報ページにメモを残したくなることがあります。そのためのボタンです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;const today = new Date()  const year = today.getFullYear()  const month = (&quot;0&quot;+(today.getMonth() + 1)).slice(-2)  const date = (&quot;0&quot;+today.getDate()).slice(-2)  const formatToday = encodeURIComponent(`${year}/${month}/${date}`)  const menuTitle = &apos;Daily&apos;   scrapbox.PageMenu.addMenu({    title: menuTitle,    image: &apos;https://twitter.com/favicon.ico&apos;,    onClick: () =&amp;gt; window.location.href = `https://scrapbox.io/ikuma-t/${formatToday}`  })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;こちらも見た目をFontAwesomeにするために、UserCSSを書いています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;a#Daily.tool-btn:hover { text-decoration: none } a#Daily.tool-btn::before { position: absolute; content: &apos;\f783&apos;; font: 900 21px/46px &apos;Font Awesome 5 Free&apos; } a#Daily.tool-btn img { opacity: 0 }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#1などを表示する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;$1などを表示する&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211219/20211219000106.png&quot; alt=&quot;f:id:ikmbear:20211219000106p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ログを書くための拡張表現をJavaScriptで描画する機能です。どっかから拾ってきたんですけど、どこから拾ったか忘れました。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;const tagIconStyles = {    &quot;!&quot; : &quot;{ content: &apos;\\f06a&apos;; color: #F6AE2D }&quot;,   /* ひらめき */   &quot;?&quot; : &quot;{ content: &apos;\\f059&apos;; color: #758E4F }&quot;,   /* 疑問、要調査 */   &quot;*&quot; : &quot;{ content: &apos;\\f069&apos;; color: #F26419 }&quot;,   /* 重要 */      &quot; &quot; : &quot;{ content: &apos;\\f0c8&apos;; color: #08BDBD }&quot;,   /* タスク */   &quot;x&quot; : &quot;{ content: &apos;\\f14a&apos;; color: #2489C5 }&quot;,   /* 完了タスク */   &quot;&amp;gt;&quot; : &quot;{ content: &apos;\\f14d&apos;; color: lightgrey }&quot;, /* 先送りしたタスク */   &quot;&amp;lt;&quot; : &quot;{ content: &apos;\\f274&apos;; color: lightgrey }&quot;, /* 日付を決めたタスク */   &quot;e&quot; : &quot;{ content: &apos;\\f192&apos;; color: #F26419 }&quot;,   /* イベント */      &quot;good&quot; : &quot;{ content: &apos;\\f164&apos; }&quot;,   &quot;bad&quot; : &quot;{ content: &apos;\\f165&apos; }&quot;, };  (function(m){   let charSelectors = [], afterLinkSelectors = [], iconStyle = &quot;&quot;   const linkSelFmt = &quot;.line:not(.cursor-line) a[href=&apos;./#&apos;]:not(.icon)&quot;   const charStyle = &quot;{display:inline-block;width:0;text-indent:-9999px}&quot;   const afterLinkStyle = &quot;{display:inline-block;min-width:1.15em;padding-left:1px;font: 900 110%/normal &apos;Font Awesome 5 Free&apos;;text-align:center}&quot;   const a = &quot;::after&quot;, f = &quot; span&quot;   const enc = [&apos;@$&amp;amp;+=:;&quot;, &apos;,&apos;@$&amp;amp;+=:;&quot;,_&apos;]   const encode = tag =&amp;gt; Array.from(tag).map(c =&amp;gt; {      const i = enc[0].indexOf(c)     return -1 &amp;lt; i &amp;amp;&amp;amp; enc[1][i] ? enc[1][i] : encodeURIComponent(c) }).join(&quot;&quot;);   for (var k in m) {     const href = encode(k)     charSelectors.push(linkSelFmt.replace(/#/, href) + f)     afterLinkSelectors.push(linkSelFmt.replace(/#/, href) + a)     iconStyle += linkSelFmt.replace(/#/, href) + a + m[k]   }   let style = document.createElement(&apos;style&apos;)   style.appendChild(document.createTextNode(charSelectors.join(&quot;,&quot;) + charStyle))   style.appendChild(document.createTextNode(afterLinkSelectors.join(&quot;,&quot;) + afterLinkStyle))   style.appendChild(document.createTextNode(iconStyle))   document.head.appendChild(style) })(tagIconStyles)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#usercss-1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;UserCSS&lt;/h2&gt;
&lt;p&gt;UserCSSでカスタマイズしている機能を紹介します&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#ピン留めされたページを別の段として表示する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ピン留めされたページを別の段として表示する&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211219/20211219000528.png&quot; alt=&quot;f:id:ikmbear:20211219000528p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Scrapboxではページをピン留めすることで、トップページの最上段に貼り付けられます。&lt;br /&gt;
このCSSはピンされたページだけ別の段として表示するものです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.page-list-item.pin + .page-list-item:not(.pin) {    clear: both; }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#セクション用の見出しcss&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;セクション用の見出しCSS&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211219/20211219001027.png&quot; alt=&quot;f:id:ikmbear:20211219001027p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;日報に使っているセクション用の見出しを作るCSSです。&lt;code&gt;[{ 文字 ]&lt;/code&gt;とすることで、見た目が変わります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.deco-\{, .deco-\} {     font-size: 0.9em;     color: #fff;     background-color: #FB7476;     padding: 0 0.5em 0 0.5em;     margin-bottom: 0.4em;     border-radius: 0.2em;     display: inline-block;     max-width: calc(100% - 100px);     vertical-align: top;   }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#運用方法&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;運用方法&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#概要&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;概要&lt;/h3&gt;
&lt;p&gt;個別のメモページはそのままページを作っていますが、それ以外のページは以下の4種類です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;日報 &amp;amp; $1（毎日）&lt;/li&gt;
&lt;li&gt;じぶんRelease Notes（毎週）&lt;/li&gt;
&lt;li&gt;月次ページ（毎月作って、毎日更新）&lt;/li&gt;
&lt;li&gt;年間ページ（毎年作って、毎月更新）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#日報--1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;日報 &amp;amp; $1&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211219/20211219001408.png&quot; alt=&quot;f:id:ikmbear:20211219001408p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;毎日作るページです。&lt;/p&gt;
&lt;p&gt;基本的に1日のはじめに「今日やったこと」にやることをタスク形式で書き込みます（UserCSSにより&lt;code&gt;[_]&lt;/code&gt;と書くことでUserCSSが、&lt;code&gt;[x]&lt;/code&gt;とすることで完了のUserCSSが、それぞれ描画できます）。&lt;/p&gt;
&lt;p&gt;だいたい前日の「次にやること」をコピペしています。&lt;/p&gt;
&lt;p&gt;あとはすべての作業を$1以下に書き込んでいき、1日の終わりにこれを日報の各セクションに振り分けて、FJORD BOOT CAMPに提出します。&lt;/p&gt;
&lt;p&gt;ScrapboxはMarkdown形式ではないので、変換が必要ですが、これは後述のsbeというアプリで行っています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#じぶんreleasenotes週報&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;じぶんReleaseNotes（週報）&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211219/20211219002218.png&quot; alt=&quot;f:id:ikmbear:20211219002218p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;週の振り返りです。毎週金曜日に書いています。金曜日書く理由は働いている時は土日が最も時間がとれたので、土日をスタートにすると週の計画がうまくいきやすかったからです。&lt;/p&gt;
&lt;p&gt;内容は単純なKPTと感想です。あまり無理しないように書いています。また今週の日記を貼り付けて見直す時間にもしています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#月次ページ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;月次ページ&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211219/20211219002548.png&quot; alt=&quot;f:id:ikmbear:20211219002548p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;月の日記をまとめたページです。今月の目標と達成確認も簡単に書いています。&lt;/p&gt;
&lt;p&gt;11月の途中からですが、日付の横にはその日の気分の絵文字とタイトルを載せています。（これはKPTで提案されたものです）&lt;/p&gt;
&lt;p&gt;ここの部分もテンプレート作れるんですが、1ヶ月に一回しかやらないのと、ブラウザのコンソールですぐに作れてしまうので、毎回for文を書いてリンクを作成しています。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#scrapbox用クライアント&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Scrapbox用クライアント&lt;/h2&gt;
&lt;p&gt;ブラウザでも見られるのですが、&lt;a href=&quot;https://github.com/kondoumh/sbe&quot; target=&quot;_blank&quot;&gt;sbe: An unofficial Scrapbox desktop app&lt;/a&gt;というScrapbox用のクライアントを使っています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;タブが使える&lt;/li&gt;
&lt;li&gt;見出し（&lt;code&gt;[* ]&lt;/code&gt;など）を&lt;code&gt;⌘&lt;/code&gt; + &lt;code&gt;1&lt;/code&gt;（数字）で挿入できる&lt;/li&gt;
&lt;li&gt;右クリックメニューから、Markdownとしてコピーできる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;という理由で使っています。他にも色々できるのですが、今のところちゃんと使っているのは上記3つです。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;以上、最近のScrapboxの使い方（2021/12）でした〜！何かご質問があればTwitterまたはコメントでお願いたします！&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>⚡️初めてのLT会 Vol.10で登壇しました！！</title><link>https://ikuma-t.com/blog/202112191639875600_1/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202112191639875600_1/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218205648.png⚡️初めてのLT会V</description><pubDate>Sun, 19 Dec 2021 10:00:00 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218205648.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218205648.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218205648.png&quot; alt=&quot;f:id:ikmbear:20211218205648p&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#️初めてのlt会-vol10に参加しました&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;⚡️初めてのLT会 Vol.10に参加しました！&lt;/h2&gt;
&lt;p&gt;昨日&lt;a href=&quot;https://bootcamp.fjord.jp/&quot; target=&quot;_blank&quot;&gt;FJORD BOOT CAMP&lt;/a&gt;で開催された、ライトニング$1初心者のための発表会、「⚡️初めてのLT会 Vol.10」に参加しました！&lt;/p&gt;
&lt;p&gt;今回のテーマは「一年間で得た学びと気づき」ということで、私は「作業するときにログを書いていくと、進捗が捗るよ〜」という話をさせていただきました。&lt;/p&gt;

&lt;p&gt;この記事では、主に発表した内容の補足と今回のスライド作成で使ったツールなどを説明したいと思います。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%EF%B8%8F%E5%88%9D%E3%82%81%E3%81%A6%E3%81%AELT%E4%BC%9A-Vol10%E3%81%AB%E5%8F%82%E5%8A%A0%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F&quot;&gt;⚡️初めてのLT会 Vol.10に参加しました！&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%8F%82%E5%8A%A0%E3%81%AE%E7%B5%8C%E7%B7%AF&quot;&gt;参加の経緯&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%83%86%E3%83%BC%E3%83%9E%E3%83%AD%E3%82%B0%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA&quot;&gt;テーマ：ログ駆動開発&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E8%87%AA%E5%88%86%E3%81%AE%E4%BD%9C%E6%A5%AD%E3%81%AE%E9%80%B2%E3%82%81%E6%96%B9%E5%86%85%E5%AE%B9%E8%A3%9C%E8%B6%B3&quot;&gt;自分の作業の進め方（内容補足）&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%81%A9%E3%81%93%E3%81%AB%E3%83%AD%E3%82%B0%E3%82%92%E6%9B%B8%E3%81%84%E3%81%A6%E3%81%84%E3%82%8B%E3%81%8B&quot;&gt;どこにログを書いているか&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%81%A9%E3%81%86%E3%81%84%E3%81%86%E9%A2%A8%E3%81%AB%E3%83%AD%E3%82%B0%E3%82%92%E6%9B%B8%E3%81%84%E3%81%A6%E3%81%84%E3%82%8B%E3%81%8B%E3%83%AB%E3%83%BC%E3%83%AB&quot;&gt;どういう風にログを書いているか（ルール）&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E6%97%A5%E4%BB%98%E3%81%A8%E6%99%82%E5%88%BB%E3%81%AE%E5%85%A5%E5%8A%9B&quot;&gt;日付と時刻の入力&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%88%A5%E3%81%AE%E3%83%9A%E3%83%BC%E3%82%B8%E3%81%B8%E3%81%AE%E5%88%87%E3%82%8A%E5%87%BA%E3%81%97&quot;&gt;別のページへの切り出し&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%81%A8%E3%82%8A%E3%81%82%E3%81%88%E3%81%9A%E3%83%AA%E3%83%B3%E3%82%AF%E3%81%AB%E3%81%97%E3%81%A6%E3%81%8A%E3%81%8F&quot;&gt;とりあえずリンクにしておく&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%81%A9%E3%81%86%E3%81%84%E3%81%86%E9%A2%A8%E3%81%AB%E3%83%AD%E3%82%B0%E3%82%92%E6%9B%B8%E3%81%84%E3%81%A6%E3%81%84%E3%82%8B%E3%81%8B%E5%AE%9F%E4%BE%8B&quot;&gt;どういう風にログを書いているか（実例）&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E6%B0%97%E6%8C%81%E3%81%A1%E3%81%AE%E6%95%B4%E7%90%86&quot;&gt;気持ちの整理&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E6%99%AE%E9%80%9A%E3%81%AE%E3%83%AD%E3%82%B0&quot;&gt;普通のログ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E8%B3%87%E6%96%99%E3%81%AE%E4%BD%9C%E6%88%90%E6%96%B9%E6%B3%95Figma&quot;&gt;資料の作成方法（Figma）&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E8%B3%87%E6%96%99%E3%81%AFFigma&quot;&gt;資料はFigma&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E4%BB%8A%E5%9B%9E%E3%81%AE%E3%83%86%E3%83%BC%E3%83%9E%E3%81%A8%E8%89%B2%E9%81%B8%E5%AE%9A%E7%94%A8%E3%83%84%E3%83%BC%E3%83%AB&quot;&gt;今回のテーマと色選定用ツール&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E7%94%BB%E5%83%8F%E3%81%AE%E5%BC%95%E7%94%A8%E5%85%83&quot;&gt;画像の引用元&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E6%BC%AB%E7%94%BB%E9%A2%A8%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3&quot;&gt;漫画風デザイン&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E8%A1%A8%E7%B4%99%E3%81%AE%E3%82%A4%E3%83%A9%E3%82%B9%E3%83%88&quot;&gt;表紙のイラスト&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%82%A2%E3%83%8B%E3%83%A1%E3%81%AE%E7%94%BB%E5%83%8F&quot;&gt;アニメの画像&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E7%B5%B5%E6%96%87%E5%AD%97%E3%81%A3%E3%81%BD%E3%81%84%E3%81%AE&quot;&gt;絵文字っぽいの&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E7%B7%B4%E7%BF%92%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AB%E4%BD%BF%E3%81%A3%E3%81%9F%E3%83%84%E3%83%BC%E3%83%ABCleanShot-X&quot;&gt;練習のために使ったツール：CleanShot X&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E6%84%9F%E6%83%B3&quot;&gt;感想&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#参加の経緯&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;参加の経緯&lt;/h2&gt;
&lt;p&gt;初めてのLT会自体は、以前にも登壇者として参加したことがありました。&lt;/p&gt;
&lt;p&gt;その時の記事はこちら↓&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://ikmbear.hatenablog.com/entry/2020/10/25/130327&quot; target=&quot;_blank&quot;&gt;ikmbear.hatenablog.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;前回登壇した時から1年以上経っていたので「そろそろ登壇しておかなければ」と思い、今回手を上げさせていただきました。主催者の&lt;a href=&quot;https://twitter.com/Paru871&quot; target=&quot;_blank&quot;&gt;paru&lt;/a&gt;さん、ありがとうございます！&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#テーマログ駆動開発&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;テーマ：ログ駆動開発&lt;/h2&gt;
&lt;p&gt;「ログ駆動開発」ってちょっと言葉としては大袈裟ですね笑。ビジネス本として出したら叩かれそうですが、LTという短い尺だったので、コンパクトにタイトルつけさせていただきました。&lt;/p&gt;
&lt;p&gt;もともとは「寄り道レトロスペクティブ」というタイトルで、今年はRailsとかGemのソースにいろいろと寄り道してきた話をしようと思ったのですが、ボリュームが大きすぎたので、その話の中で「どうやって難しい内容に対しても安定して進捗を出していくか」というセクションだけ切り出した内容が今回の話になります。&lt;/p&gt;
&lt;p&gt;話している内容的には、以下の記事と多少オーバーラップするところがあるので、気になる方はこちらも読んでいただければ&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://ikmbear.hatenablog.com/entry/2020/12/18/064703&quot; target=&quot;_blank&quot;&gt;ikmbear.hatenablog.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;p&gt;ここからツールの話多めです&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#自分の作業の進め方内容補足&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;自分の作業の進め方（内容補足）&lt;/h2&gt;
&lt;p&gt;LT会での質問で&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;どこにログを書いているか&lt;/li&gt;
&lt;li&gt;どんな内容を書いているかみてみたい&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;という内容がありました。LT会中も話した部分はありますが、このブログで一連の作業ルーティンを補足として説明させてもらればと思います。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#どこにログを書いているか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;どこにログを書いているか&lt;/h3&gt;
&lt;p&gt;ログはすべてScrapboxに書いています。やり方としては1日ごとにページを作成して、その中に書いていくようなイメージです。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://ikmbear.hatenablog.com/entry/20211015/1634273489&quot; target=&quot;_blank&quot;&gt;ikmbear.hatenablog.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;この記事で書いた内容と変わっていないのですが、次のように日報作成ボタンをJavaScriptでカスタムしているので、それを使って今日のページを作成します。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218192942.gif&quot; alt=&quot;f:id:ikmbear:20211218192942g&quot; /&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;←[2021/12/17]：[2021/12/19]→[{ 日報][*** 👍やったこと] [_][*** 🎓学習したこと][** 【わかったこと】][** 【わからなかったこと】][*** 🥷次にやること][*** 🍘感想・余談][{ ライフログ]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;CSSや「日報」の見た目はCSSで拡張してわかりやすいように表示しています。（長くなるのでコードは割愛します。どっか別の記事で書くと思います）。&lt;/p&gt;
&lt;p&gt;「日報」のセクションは、そのままFJORD BOOT CAMPで提出するための日報テンプレートになっています。&lt;/p&gt;
&lt;p&gt;で、「$1」のセクションが今回のLT会でお話ししたログを書く場所です。ここにログを記載していきます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#どういう風にログを書いているかルール&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;どういう風にログを書いているか（ルール）&lt;/h3&gt;
&lt;p&gt;ルールはあまりありませんが、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;日付と時刻を入力する&lt;/li&gt;
&lt;li&gt;内容が後から参照できそうなら別のページに切り出す&lt;/li&gt;
&lt;li&gt;あとでページになりそうな内容は、とりあえずリンクにしておく&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;という感じでやっています。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#日付と時刻の入力&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;日付と時刻の入力&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218193735.gif&quot; alt=&quot;f:id:ikmbear:20211218193735g&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Scrapboxでは&lt;code&gt;⌃&lt;/code&gt; + &lt;code&gt;T&lt;/code&gt;で日付を入力することができます。3つのフォーマットがあるのですが、3回押した際に出てくる時刻入りのフォーマットを使って、ログの入力を開始します。&lt;/p&gt;
&lt;p&gt;時刻を入力するタイミングは厳密には決めていませんが、時間が経っていたり、内容が変わるときには大体日付を入力し直すようにしています。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#別のページへの切り出し&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;別のページへの切り出し&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218194033.gif&quot; alt=&quot;f:id:ikmbear:20211218194033g&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ログを書いている中で、「これまた見返しそうだな」と思ったり、独立した内容になっていたら、その部分を選択して「New Page」を選択することで別ページに切り出しています。&lt;/p&gt;
&lt;p&gt;こうすることで後から参照しやすくなります。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#とりあえずリンクにしておく&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;とりあえずリンクにしておく&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218201827.png&quot; alt=&quot;f:id:ikmbear:20211218201827p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ログを書いていると、「この単語後からまとめたいけど、今は時間ないな」「こういう概念でまとめておいたら、自分の考えがまとまりそう」みたいな要素に出会うことが多々あります。&lt;/p&gt;
&lt;p&gt;そういう時は文中で、積極的にリンク（&lt;code&gt;[リンクにしたい単語]&lt;/code&gt;）を利用していきます。たとえその時点でメモを作らなくても、あとでメモを見返したときに「あ、ここ追記しておこう」という感じで、過去のログから知識が進化する余地を残せます。&lt;/p&gt;
&lt;p&gt;タグの機能も使えますが、基本的にはコンテキストの中で自然に残せる内容はリンクとして雑に定義する方針を取っています（こうしておくと自分のメモ見返すの楽しいんですよ）。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#どういう風にログを書いているか実例&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;どういう風にログを書いているか（実例）&lt;/h3&gt;
&lt;p&gt;Scrapboxの中に個人的な内容も書いているので、ある時からScrapboxをprivateにしてしまいました。なので抜粋してお届けします。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#気持ちの整理&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;気持ちの整理&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218194831.png&quot; alt=&quot;f:id:ikmbear:20211218194831p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;本来であればタスクを整理→作業開始、くらいの感じだと思うんですが、やる気が出なかったようなのでタスク整理する前に気持ちを整理しているメモです。&lt;/p&gt;
&lt;p&gt;自分で自分を鼓舞していること、今自分の身に起きていることをとにかく書き出していることがポイントです。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218195344.png&quot; alt=&quot;f:id:ikmbear:20211218195344p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;レビューしてもらった内容があまりいいものではなくて、気持ちが落ち込んでしまった時のログです。なんだかモヤモヤしてしまって、「明日作業するのだるいな〜」と思っていたので、その日のうちに頭の中にあることをとにかく書き出しました（この後めちゃくちゃ寝て、翌日朝から快調に作業ができました）。&lt;/p&gt;
&lt;p&gt;「悔しい！劣等感だ！いつだって上がり調子でいたい」「でもこの劣等感はずっと味わっていなかった感情だ！！！うれしくもあるぞ」&lt;/p&gt;
&lt;p&gt;見返すと恥ずかしいですが、当時の自分はこうやって吐き出せたことで、悩んでいた時間は5分くらいだった模様です。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#普通のログ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;普通のログ&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218200454.png&quot; alt=&quot;f:id:ikmbear:20211218200454p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;普通のログは結構やった作業を全部書いていることが多いです。&lt;/p&gt;
&lt;p&gt;一番最後に「気になることを書き出してみよう」と書いていますが、このパターンは結構使っていて、実装中もできるだけ頭の中は空っぽにして、今やっていることだけにフォーカスするのに役立っています。&lt;/p&gt;
&lt;p&gt;だいたいこのパターンの後に「よしじゃあひとつずつ見ていこうか」「全然わからんな」「本当？今自分が知っていることは何？」みたいな常套句が続きます。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218201241.png&quot; alt=&quot;f:id:ikmbear:20211218201241p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;これはリファクタされたメモの例で、ログを振り返ると全然書いていないように見えるんですが、例えば「$1・$1・住民税の計算方法」は次のように別のページとして成立した内容になっています。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218201342.png&quot; alt=&quot;f:id:ikmbear:20211218201342p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;これは技術全然関係ないですが、例えば「PostgreSQLでエラーになった」とか「Railsで例外発生」みたいな事象にあったときには、とことんログを書きながら調べていって、後から別ページに切り出すと、検索性も高くなってとても良きです。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;その他のScrapboxの使い方（Scrapbox用のクライアント、各種Scrapbox）については別の記事で紹介したいと思います（長いんで）。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#資料の作成方法figma&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;資料の作成方法（Figma）&lt;/h2&gt;
&lt;p&gt;発表中、資料内のイラスト等にも質問をいただきましたのでここに書いていければと思います。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#資料はfigma&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;資料はFigma&lt;/h3&gt;

&lt;p&gt;今回の資料はFigmaで作成しました。結局Keynote使ったの前回の一回だけだった笑&lt;/p&gt;
&lt;p&gt;Figmaを使う理由は&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;色やフォントをストックしておける&lt;/li&gt;
&lt;li&gt;$1を使える&lt;/li&gt;
&lt;li&gt;スライドを一覧しやすい&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;という理由です。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#今回のテーマと色選定用ツール&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;今回のテーマと色選定用ツール&lt;/h3&gt;
&lt;p&gt;今回は「ログ」についてのお話でした。ログの語源って「ログブック」つまりは「航海日誌」なんですよね。なので、スライドのテーマになっているのは船です。&lt;/p&gt;
&lt;p&gt;季節的には冬だったので、冬の夜の暗い海とそこに灯る赤い船のライトをイメージしたカラーにしたらいいかな〜と思っていました。&lt;/p&gt;
&lt;p&gt;以前ブログで紹介したPalettableも利用しているのですが、今回はAIで色を提案してくれるHueMintというサービスを使って配色のベースを選択しました（結構ライト目な内容だと最近よくこのサービス使っています）。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://huemint.com/&quot; target=&quot;_blank&quot;&gt;huemint.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;ここでベースの黒と文字のグレーを決めて、あとは感覚で合いそうな色をパレットとして作成し、スライドを作成しました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#画像の引用元&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;画像の引用元&lt;/h3&gt;
&lt;h4&gt;&lt;a href=&quot;#漫画風デザイン&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;漫画風デザイン&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218203127.png&quot; alt=&quot;f:id:ikmbear:20211218203127p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;この画像はどこから？という質問があったのですが、これはOpen Peepsという素材を使っています。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://pablostanley.gumroad.com/l/openpeeps?wanted=true&quot; target=&quot;_blank&quot;&gt;pablostanley.gumroad.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218203250.png&quot; alt=&quot;f:id:ikmbear:20211218203250p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;素材の中にこういう漫画っぽいイラストがあったので、コマ割りと中に出てくるキャFigmaターをFigmaで編集しました。&lt;/p&gt;
&lt;p&gt;それだけでもよかったんですが、漫画といえば集中線とか$1、$1があった方がいいでしょ、ということでマンガパーツSTOCKというサイトから素材を拾ってきて合成し、今回のスライドの完成です。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://mangasozai.com/&quot; target=&quot;_blank&quot;&gt;mangasozai.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;正直今回のスライドで一番時間がかかった部分でした笑&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#表紙のイラスト&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;表紙のイラスト&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218203539.png&quot; alt=&quot;f:id:ikmbear:20211218203539p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;表紙にはログ→航海日誌→船の連想から、船の画像をのせています。これはLoose Drawingというサイトから拾ってきたものです。何かイラストが必要な時は、ソコストかLoose Drawingで拾ってくることが多いです。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://loosedrawing.com/&quot; target=&quot;_blank&quot;&gt;loosedrawing.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;&lt;a href=&quot;#アニメの画像&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;アニメの画像&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218203749.png&quot; alt=&quot;f:id:ikmbear:20211218203749p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;これは私が持っているSHIROBAKOのBluray-Diskをスクショしただけです。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.co.jp/dp/B081VL3N76?tag=hatena-22&amp;amp;linkCode=ogi&amp;amp;th=1&amp;amp;psc=1&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://m.media-amazon.com/images/I/51PE1dOL4tL._SL500_.jpg&quot; alt=&quot;SHIROBAKO Blu-ray BOX 1 スタンダード エディション (3枚組)&quot; title=&quot;SHIROBAKO Blu-ray BOX 1 スタンダード エディション (3枚組)&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.co.jp/dp/B081VL3N76?tag=hatena-22&amp;amp;linkCode=ogi&amp;amp;th=1&amp;amp;psc=1&quot; target=&quot;_blank&quot;&gt;SHIROBAKO Blu-ray BOX 1 スタンダード エディション (3枚組)&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$1&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.co.jp/dp/B081VL3N76?tag=hatena-22&amp;amp;linkCode=ogi&amp;amp;th=1&amp;amp;psc=1&quot; target=&quot;_blank&quot;&gt;Amazon&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#絵文字っぽいの&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;絵文字っぽいの&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218203909.png&quot; alt=&quot;f:id:ikmbear:20211218203909p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;FigmaではFontAwesomeを利用することができるので、図解にFigmaを使いたい時はFontAwesomeを使っています。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#練習のために使ったツールcleanshot-x&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;練習のために使ったツール：CleanShot X&lt;/h2&gt;
&lt;p&gt;今回はFigmaでスライドをつくったのですが、そうすると録画機能がないために練習をどうしようか迷いました（録音するので）。&lt;/p&gt;
&lt;p&gt;で、最近購入したCleanShot Xは$1だけではなく、GIFや動画も撮影できることがわかったので、今回はこれを使って録画練習をしました。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://cleanshot.com/&quot; target=&quot;_blank&quot;&gt;cleanshot.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211218/20211218204350.png&quot; alt=&quot;f:id:ikmbear:20211218204350p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;しかも録画するときにワイプで自分の画像もうつせることに気がついたので、もっぱらこのスタイルで録画をしての練習でした。&lt;/p&gt;
&lt;p&gt;ここらへんも長くなるので、CleanShot Xについては別記事で書きます（と思います）。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;登壇をやるのはそれなりに大変だけど、その分自分の考えをいろんな人に知ってもらえて、やってよかったな〜と改めて思いました！&lt;/p&gt;
&lt;p&gt;今回はFJORD BOOT CAMP内でしたが、来年は今作っているGemの内容で外部のLT会にも登壇しにいきたいと思っています！&lt;/p&gt;
&lt;p&gt;ではでは〜！&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>【アウトライナー】transnoというアプリがすごくフィットしている</title><link>https://ikuma-t.com/blog/202112151639551694/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202112151639551694/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211215/20211215152126.pngア$1をまとめるとき</description><pubDate>Wed, 15 Dec 2021 16:01:34 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211215/20211215152126.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211215/20211215152126.png&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#ア1をまとめるときには1を使っている&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ア$1をまとめるときには$1を使っている&lt;/h2&gt;
&lt;p&gt;私は何か文章を書いたり、図を作ったりする際には$1を使って整理しています。&lt;/p&gt;
&lt;p&gt;$1とは以下のように$1状になった箇条書きリストのことです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;タイトル&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Chapter1&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;内容&lt;/li&gt;
&lt;li&gt;内容&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Chapter2&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;内容&lt;/li&gt;
&lt;li&gt;内容&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;もともとはNotionを$1として使っていたのですが、最近Transnoというアプリに切り替えてだいぶいい感じなのでご紹介したいと思います。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#transnoとは&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Transnoとは&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#概要&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;概要&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211215/20211215152126.png&quot; alt=&quot;f:id:ikmbear:20211215152126p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://transno.com/&quot; target=&quot;_blank&quot;&gt;Transno - Outlines, Notes, Mind Map&lt;/a&gt;は、オンラインで使用できるアウトライン兼$1です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;シンプルかつフレキシブルなリスト&lt;/li&gt;
&lt;li&gt;ワンタッチでアウトラインを$1に切り替え可能&lt;/li&gt;
&lt;li&gt;$1で共有し、チームで編集できる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;といった特徴があります。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;PCからはWebアプリとして、$1・$1からはアプリとして使用することができます。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211215/20211215152425.png&quot; alt=&quot;f:id:ikmbear:20211215152425p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;価格は無料です。…というか、Proという機能があるんですが、料金が書いておらず、今のところ課金もされていないんですよね笑&lt;/p&gt;
&lt;p&gt;ある程度ユーザー数が伸びるまではPRのためにProを解放しているのかもしれません。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#機能紹介アウトライン編&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;機能紹介：アウトライン編&lt;/h2&gt;
&lt;p&gt;$1なので、メインはアウトライン機能です。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#アウトライン作成&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;アウトライン作成&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211215/20211215153005.gif&quot; alt=&quot;f:id:ikmbear:20211215153005g&quot; /&gt;&lt;/p&gt;
&lt;p&gt;TransnoではTransnoteという単位でアウトラインを作成することができます。&lt;br /&gt;
一般的な$1同様にEnterでリスト追加、Tabでリストの構造切り替えを行うことができます。&lt;/p&gt;
&lt;p&gt;アウトラインには文字だけでなく画像も含めることができます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#フォーカスイン&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;フォーカスイン&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211215/20211215153817.gif&quot; alt=&quot;f:id:ikmbear:20211215153817g&quot; /&gt;&lt;/p&gt;
&lt;p&gt;アウトラインの一つ一つのリストをクリックすると、クリックした要素を親とする階層にジャンプすことができます。&lt;/p&gt;
&lt;p&gt;Notionではリストは俯瞰でしかみられなかったので、これは便利！&lt;br /&gt;
結構リストが長くなってくると、だんだん見辛くなってきたり、他の部分に気を取られてしまうので、これを使いながら一つ一つの要素を書いています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#折りたたみ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;折りたたみ&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211215/20211215154453.gif&quot; alt=&quot;f:id:ikmbear:20211215154453g&quot; /&gt;&lt;/p&gt;
&lt;p&gt;一つ一つのリストを折りたたむことができます。&lt;br /&gt;
同じ階層にあるリストの粒度を確認したい時に便利です。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#アウトラインへのアクションメモチェック&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;アウトラインへのアクション（メモ、チェック）&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211215/20211215154558.gif&quot; alt=&quot;f:id:ikmbear:20211215154558g&quot; /&gt;&lt;/p&gt;
&lt;p&gt;アウトラインのリスト自体にメモをしたり、チェックをすることができます。&lt;/p&gt;
&lt;p&gt;ア$1以外の部分で、例えば「ここはあの本を参照する」みたいなメモを残しておきたいケースが多々あるので、メモは非常に重宝しています。なお、クリックしなくてもメモはリストに対して&lt;code&gt;Shift&lt;/code&gt; + &lt;code&gt;Enter&lt;/code&gt;で登録することができます。&lt;/p&gt;
&lt;p&gt;チェック機能の方はあまり使うことはないですが、買い物リストみたいな使い方する時には便利なのかも。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#エクスポート&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;エクスポート&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211215/20211215153544.png&quot; alt=&quot;f:id:ikmbear:20211215153544p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;作成したアウトラインはWord、PDF、画像、HTML、OPML形式で出力できます。&lt;br /&gt;
なおエクスポートはエディタ上で見えているのとほぼ同じ形式で出力されます。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#機能紹介1編&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;機能紹介：$1編&lt;/h2&gt;
&lt;p&gt;私がTransnoを気に入っているのは、$1に切り替えられるからです。&lt;/p&gt;
&lt;p&gt;アウトラインってどうしても長くなると全体が俯瞰しにくくなるので、「使いにくいな〜」と思っていたのですが、Transnoであれば途中で$1に切り替えることができるのでその問題が解消できました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#1への切り替え&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;$1への切り替え&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211215/20211215155423.gif&quot; alt=&quot;f:id:ikmbear:20211215155423g&quot; /&gt;&lt;/p&gt;
&lt;p&gt;アウトラインを開いた状態で、$1のアイコンをクリックすると、$1へ切り替えることができます（もう一度押すと元に戻ります）。&lt;/p&gt;
&lt;p&gt;$1の形式はいくつかあるテンプレートから選ぶことができます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#1で使える機能は1でも使える&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;$1で使える機能は$1でも使える&lt;/h3&gt;
&lt;p&gt;リストを折り畳んだり、メモを残すという$1として紹介した機能は$1上でも使用することができます。&lt;/p&gt;
&lt;p&gt;こういうことをやるためにわざわざアウトラインに戻らなくていいのもポイント高いですね〜。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;というわけで簡単にですが$1「Transno」をご紹介しました。&lt;/p&gt;
&lt;p&gt;途中でも述べましたが、なぜか今はProが無料で使えるので、ぜひ今のうちに試してみてはいかがでしょうか。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>【ツール】リストをコピーすると、Scrapbox用のリンク/リストに変換してくれるAlfredWorkflowを作る</title><link>https://ikuma-t.com/blog/202112121639280723/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202112121639280723/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211212/20211212124414.pngなんで作ったかQii</description><pubDate>Sun, 12 Dec 2021 12:45:23 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211212/20211212124414.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211212/20211212124414.png&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#なんで作ったか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;なんで作ったか&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211212/20211212121719.gif&quot; alt=&quot;f:id:ikmbear:20211212121719g&quot; /&gt;&lt;/p&gt;
&lt;p&gt;QiitaとかZennに投稿されている記事で、「お、このリストいいな。自分のメモにコピペして一つずつ深掘りしていこう！」と思う時があります（「レビュー依頼をする前に見るリスト」とか「転職で聞かれる質問リスト」とか）。&lt;/p&gt;
&lt;p&gt;私はメモにScrapboxを使っているのですが、そのままコピペしてしまうと、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;そもそもリストにならない&lt;/li&gt;
&lt;li&gt;各リストごとにページ内リンクとして作成したいが、プレーンテキストにしかならない&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;という問題があります。&lt;/p&gt;
&lt;p&gt;そこで今回は、Alfred Workflowを利用して「リストをコピーすると、Scrapboxのリンク/リストを作成してくれるツール」を作ってみました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#今回作ったもの&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;今回作ったもの&lt;/h2&gt;
&lt;p&gt;LiLink：リストを渡すと、Scrapboxのリンクリストを作成してくれるAlfred Workflow&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211212/20211212122305.gif&quot; alt=&quot;f:id:ikmbear:20211212122305g&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Alfredのメニューから「lilink」と入力することで呼び出せます。スペースを開けてコピーしたリンクを貼り付けると、Scrapboxのリンクかつリスト形式に変換したものをScrapboxに出力します。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211212/20211212122510.png&quot; alt=&quot;f:id:ikmbear:20211212122510p&quot; /&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;プラグインについて：以下のプラグインを導入するために、プラグインについて学びます学習を支えるプラグイン：学習を支える3つのプラグインを紹介しますRubyMineのウィンドウ：RubyMineを開いた時に見える各ウィンドウの名称を整理します↓（変換） [プラグインについて：以下のプラグインを導入するために、プラグインについて学びます] [学習を支えるプラグイン：学習を支える3つのプラグインを紹介します] [RubyMineのウィンドウ：RubyMineを開いた時に見える各ウィンドウの名称を整理します]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#作成過程&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;作成過程&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#ツールの名前を決める&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ツールの名前を決める&lt;/h3&gt;
&lt;p&gt;なんでもいいんですが、今後ツールを増やしていくことを考えると、ある程度わかりやすいものがいいです。今回は、ListとLinkを作ってくれるので、「LiLink」にしました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#ドット絵を描く&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ドット絵を描く&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211212/20211212122930.jpg&quot; alt=&quot;f:id:ikmbear:20211212122930j&quot; /&gt;&lt;/p&gt;
&lt;p&gt;AlfredはWorkflowに対して、任意の画像を設定することができます。&lt;/p&gt;
&lt;p&gt;私はドット絵が趣味なので、ドット絵でリストの中黒とリンクのアイコンを合わせたアイコンを作成しました。&lt;/p&gt;
&lt;p&gt;ちなみにドット絵はiPadの&lt;a href=&quot;https://dotpict.net/&quot; target=&quot;_blank&quot;&gt;dotpict&lt;/a&gt;というアプリで描いています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#workflowを作る&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Workflowを作る&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211212/20211212123405.png&quot; alt=&quot;f:id:ikmbear:20211212123405p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;大した$1も書かないので、今回はBlank Workflowに対して一から作成しました。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211212/20211212123525.png&quot; alt=&quot;f:id:ikmbear:20211212123525p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;基本的な情報を設定して、&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211212/20211212123602.png&quot; alt=&quot;f:id:ikmbear:20211212123602p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;引数つきでキーワード「lilink」を受け取るように設定&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211212/20211212123635.png&quot; alt=&quot;f:id:ikmbear:20211212123635p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;rubyrubyを書いていきます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# 前段の入力をARGVとして受け取る（`with input as argv`）設定なので、これを処理するquery = ARGV[0].split(&quot;\n&quot;).map { |line| &quot; [#{line}]&quot; }.join(&quot;\n&quot;)# 次の処理に渡すために、`query`という名前で出力するprint query&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211212/20211212123832.png&quot; alt=&quot;f:id:ikmbear:20211212123832p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;$1へのコピーアクションを設定し&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211212/20211212123924.png&quot; alt=&quot;f:id:ikmbear:20211212123924p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;あとは全部がっちゃんこして完成🎉&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;これくらいのRubyRubyなら、適当に作ってコマンド置き場に設置してもいいんですが、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;標準入出力をAlfredが担ってくれるので、ロジックだけ書けばいい&lt;/li&gt;
&lt;li&gt;アイコンや説明がつくので、コマンドを実行する時に思い出しやすい&lt;/li&gt;
&lt;li&gt;ターミナルを開かなくていい&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;という利点があるので、AlfredWorkflowとして作るのもありだな〜と思いました。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>AWS SAA試験に合格しました🎉</title><link>https://ikuma-t.com/blog/202112061638787285/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202112061638787285/</guid><description>本日AWSソリューションアーキテクト-アソシエイト試験を受験し、合格しました🎉せっかくなので、当日ルポから受けた経緯等々を綴ってみたいと思います。（なおこの記事の95%は試験を受ける前に書かれたもの</description><pubDate>Mon, 06 Dec 2021 19:41:25 GMT</pubDate><content:encoded>&lt;p&gt;本日AWS ソリューションアーキテクト-アソシエイト試験を受験し、合格しました🎉せっかくなので、当日ルポから受けた経緯等々を綴ってみたいと思います。（なおこの記事の95%は試験を受ける前に書かれたものです。合格してよかったね笑）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E8%A9%A6%E9%A8%93%E5%BD%93%E6%97%A5%E3%83%AB%E3%83%9D&quot;&gt;試験当日ルポ&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E7%8F%BE%E5%9C%B0%E5%85%A5%E3%82%8A&quot;&gt;現地入り&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E9%A8%93%E6%8B%85%E3%81%8E%E3%81%A7Burger-King%E3%82%92%E9%A3%9F%E3%81%B9%E3%82%8B&quot;&gt;験担ぎでBurger Kingを食べる&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%81%84%E3%81%96%E8%A9%A6%E9%A8%93%E4%BC%9A%E5%A0%B4%E5%85%A5%E3%82%8A&quot;&gt;いざ試験会場入り&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%90%88%E6%A0%BC%E3%81%A3%E3%81%A6%E3%82%B3%E3%83%88&quot;&gt;合格…ってコト？&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%81%AA%E3%81%9C%E8%A9%A6%E9%A8%93%E3%82%92%E5%8F%97%E3%81%91%E3%82%88%E3%81%86%E3%81%A8%E6%80%9D%E3%81%A3%E3%81%9F%E3%81%8B&quot;&gt;なぜ試験を受けようと思ったか&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%81%A8%E3%81%97%E3%81%A6%E5%83%8D%E3%81%8F%E4%B8%8A%E3%81%A7%E7%9F%A5%E8%AD%98%E3%81%A8%E3%81%97%E3%81%A6%E6%8C%81%E3%81%A3%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84%E3%81%A8%E6%80%9D%E3%81%A3%E3%81%9F%E3%81%8B%E3%82%89&quot;&gt;プログラマとして働く上で、知識として持っておきたいと思ったから&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%83%97%E3%83%A9%E3%82%AF%E3%83%86%E3%82%A3%E3%82%B7%E3%83%A7%E3%83%8A%E3%83%BC%E3%81%A7%E3%81%AF%E7%89%A9%E8%B6%B3%E3%82%8A%E3%81%AA%E3%81%84%E3%81%A8%E6%80%9D%E3%81%A3%E3%81%9F%E3%81%8B%E3%82%89&quot;&gt;クラウドプラクティショナーでは物足りないと思ったから&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%AD%A6%E7%BF%92%E6%99%82%E9%96%93%E3%81%AF&quot;&gt;学習時間は？&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E7%B4%AF%E8%A8%8846%E6%99%82%E9%96%9320%E5%88%86&quot;&gt;累計：46時間20分&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%89%8D%E6%8F%90&quot;&gt;前提&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%81%A9%E3%81%86%E3%82%84%E3%81%A3%E3%81%A6%E5%AD%A6%E7%BF%92%E3%81%97%E3%81%9F&quot;&gt;どうやって学習した？&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E6%94%B9%E8%A8%82%E6%96%B0%E7%89%88-%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5-AWS%E8%AA%8D%E5%AE%9A-%E3%82%BD%E3%83%AA%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%88--%E3%82%A2%E3%82%BD%E3%82%B7%E3%82%A8%E3%82%A4%E3%83%88%E6%95%99%E7%A7%91%E6%9B%B8SAA-C02&quot;&gt;改訂新版 徹底攻略 AWS認定 ソリューションアーキテクト − アソシエイト教科書［SAA-C02］&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%81%93%E3%82%8C%E3%81%A0%E3%81%91%E3%81%A7OK-AWS-%E8%AA%8D%E5%AE%9A%E3%82%BD%E3%83%AA%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%88--%E3%82%A2%E3%82%BD%E3%82%B7%E3%82%A8%E3%82%A4%E3%83%88%E8%A9%A6%E9%A8%93%E7%AA%81%E7%A0%B4%E8%AC%9B%E5%BA%A7SAA-C02%E8%A9%A6%E9%A8%93%E5%AF%BE%E5%BF%9C%E7%89%88&quot;&gt;これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座（SAA-C02試験対応版）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#SAA-C02%E7%89%88AWS-%E8%AA%8D%E5%AE%9A%E3%82%BD%E3%83%AA%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%88-%E3%82%A2%E3%82%BD%E3%82%B7%E3%82%A8%E3%82%A4%E3%83%88%E6%A8%A1%E6%93%AC%E8%A9%A6%E9%A8%93%E5%95%8F%E9%A1%8C%E9%9B%866%E5%9B%9E%E5%88%86390%E5%95%8F&quot;&gt;【SAA-C02版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#CloudTech&quot;&gt;CloudTech&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E8%A9%A6%E9%A8%93%E3%82%92%E5%8F%97%E3%81%91%E3%81%A6%E3%81%BF%E3%81%A6%E3%81%AE%E6%84%9F%E6%83%B3&quot;&gt;試験を受けてみての感想&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E7%B7%B4%E7%BF%92%E5%95%8F%E9%A1%8C%E3%81%A8%E3%81%AE%E3%83%AC%E3%83%99%E3%83%AB%E6%84%9F&quot;&gt;練習問題とのレベル感&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%8F%97%E3%81%8B%E3%81%A3%E3%81%A6%E3%82%88%E3%81%8B%E3%81%A3%E3%81%9F%E3%81%AD&quot;&gt;受かってよかったね&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#試験当日ルポ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;試験当日ルポ&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#現地入り&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;現地入り&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211206/20211206193452.png&quot; alt=&quot;f:id:ikmbear:20211206193452p&quot; /&gt; 14&lt;/p&gt;&lt;div&gt;&lt;/div&gt;、12&lt;div&gt;&lt;/div&gt;$1にINしました。基本的に会場INは早めなタイプです。合宿とかあると、集合時間2時間前に集合しているタイプです。&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#験担ぎでburger-kingを食べる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;験担ぎでBurger Kingを食べる&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211206/20211206193508.png&quot; alt=&quot;f:id:ikmbear:20211206193508p&quot; /&gt; 資格試験のときは、いつも$1$1口にあるBurger Kingで昼食をとりながら最後まで復習しています。基本的にお腹弱いんですが、なぜか$1ーだけは試験前に食べてもお腹壊さないので…。（逆にカフェに行って、カフェラテとか飲むと100%お腹壊す）&lt;/p&gt;
&lt;p&gt;全然関係ないですが、$1スーツを着た就活生がめちゃめちゃ多かったです。冬季$1の時期ですかね？&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#いざ試験会場入り&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;いざ試験会場入り&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211206/20211206193520.png&quot; alt=&quot;f:id:ikmbear:20211206193520p&quot; /&gt; いざ試験へ！自宅からは少し距離があるのですが、これまで5資格をここで合格してきた実績がある &amp;amp; 勝手のわかっている会場なので、ここで受験しています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#合格ってコト&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;合格…ってコト？&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211206/20211206193531.png&quot; alt=&quot;f:id:ikmbear:20211206193531p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;わ〜い、合格できました🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉（合格から3時間後にレポート出ました）&lt;/p&gt;
&lt;p&gt;試験中は予定通り30分程度で一周解き終えたあとに、見直しを行いました。&lt;/p&gt;
&lt;p&gt;私はいつも配布されるメモ用紙に全問題分のマス目を用意して、そこに各問題の回答の自信度を「○」「△」「×」で記入しています。&lt;/p&gt;
&lt;p&gt;見直し時には「○」の中でも自信があるものを「◎」に、「△」を検証してほぼあっていると思うものを「○」に格上げするというチェックを行い、「◎」「○」の合計が合格ボーダーに乗っかるくらい、「△」も含めるとボーダーを5問以上オーバーするくらいでテスト終了します（試験時間140分なので、大体時間が余ります）。AWS SAAは72%が合格ラインです。&lt;/p&gt;
&lt;p&gt;今回は試験中自己採点は「73%」でしたが、実際の結果は画像の通り、「80%」でした。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#なぜ試験を受けようと思ったか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;なぜ試験を受けようと思ったか&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#1として働く上で知識として持っておきたいと思ったから&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;$1として働く上で、知識として持っておきたいと思ったから&lt;/h3&gt;
&lt;p&gt;私は現在$1を目指して勉強中です。かなり広く取ると、アプリケーションエンジニアを目指しています。&lt;/p&gt;
&lt;p&gt;AWSといえば「インフラ」みたいなイメージもありますが、S3のようなストレージサービスや、Step Functionsのようなジョブ実行サービスなど、いわゆる低レイヤーに留まらない、さまざまなサービスも含まれます。また大規模なネットワーク構築、例えばDirect Connectを使ったオンプレ環境との接続や、DRサイトのためのAWS構築などは（それこそ情シスとかインフラエンジニアの）専任の領域になるかもしれませんが、自分たちが使っているサーバやコンテナの管理くらいはアプリケーションエンジニアにも求められる知識だろうと思っています。&lt;/p&gt;
&lt;p&gt;そのため、AWSの各種サービスを理解することは必要であろうと考えて、この試験を通じて知識を習得しようと考えました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#1プ1ティショナーでは物足りないと思ったから&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;$1プ$1ティショナーでは物足りないと思ったから&lt;/h3&gt;
&lt;p&gt;今年（2021年）の1月に$1プ$1ティショナーを受験し合格しました。&lt;/p&gt;
&lt;p&gt;もともとAWSプAWSティショナーを受験しようと思ったのは、当時の職場で部内のプロジェクト別AWS環境を構築する必要があったためです。人がいなかったので立候補したはいいんですが、知識がまったくなかったので資格試験を通じて知識を習得しながら、社内の環境構築をしました。&lt;/p&gt;
&lt;p&gt;で、そのときにいろいろと調べたり、他の人でもメンテできるようにドキュメントに整理したりと頑張ったんですが、それはあくまでその会社の中の話なので、対外的にも「基礎的なところはわかっているのかな、AWS」と思ってもらえるものがあると嬉しいなと思いました。&lt;/p&gt;
&lt;p&gt;そう考えた時に$1プ$1ティショナーはちょっと初級すぎるかもと思って、「SAAとるか〜」となった次第です🙂&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#学習時間は&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;学習時間は？&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#累計46時間20分&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;累計：46時間20分&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211206/20211206193605.png&quot; alt=&quot;f:id:ikmbear:20211206193605p&quot; /&gt; 46時間でした。隙間時間、メインの学習時間全部を漏らさず集計していましたので、リアルな時間です。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#前提&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;前提&lt;/h3&gt;
&lt;p&gt;結構AWS試験のルポって「未経験者が2週間で…」みたいな触れ込みの記事が多くある印象があると思うんですが、AWSの経験にかかわらず、いろんな知識が前提知識として有利に働く試験なので、なんとも言えないなあという気持ちです。&lt;/p&gt;
&lt;p&gt;というわけで、参考までに私の前提を晒しておきます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$1プ$1ティショナーを持っています&lt;/li&gt;
&lt;li&gt;$1・$1を持っています&lt;/li&gt;
&lt;li&gt;Linuxの基礎的な知識があります（Linuxブートキャンプをやっているので）&lt;/li&gt;
&lt;li&gt;RDBの基本的な知識があります（Oracleを使っていた、RDBブートキャンプをやっている）&lt;/li&gt;
&lt;li&gt;基本的なIT用語を理解し、それを使っている現場に$1ではない立場で関わったことがあります（ETLツール、BIツール…etc）&lt;/li&gt;
&lt;li&gt;AWSではありませんが、社内のちょっとした環境をAWSで構築したことがあります。そのため以下のサービスを使用したことがあります。
&lt;ul&gt;
&lt;li&gt;EC2（踏み台サーバを利用したメンテ、ただしすべてWindows）&lt;/li&gt;
&lt;li&gt;VPC&lt;/li&gt;
&lt;li&gt;Route53&lt;/li&gt;
&lt;li&gt;ALB、NLB&lt;/li&gt;
&lt;li&gt;SES&lt;/li&gt;
&lt;li&gt;Lambda&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;…なので、学習開始時点で試験内容の3〜4割くらいは既知の内容だったかなあと思います。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#どうやって学習した&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;どうやって学習した？&lt;/h2&gt;
&lt;p&gt;巷でよく聞く教材ばかりですが、以下の教材を使用しました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#改訂新版-徹底攻略-aws認定-ソリューションアーキテクト--アソシエイト教科書saa-c02&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;改訂新版 徹底攻略 AWS認定 ソリューションアーキテクト − アソシエイト教科書［SAA-C02］&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.co.jp/exec/obidos/ASIN/4295010650/hatena-blog-22/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://m.media-amazon.com/images/I/51qrdW7dr+L._SL500_.jpg&quot; alt=&quot;(模擬問題付き)改訂新版 徹底攻略 AWS認定 ソリューションアーキテクト − アソシエイト教科書[SAA-C02]対応&quot; title=&quot;(模擬問題付き)改訂新版 徹底攻略 AWS認定 ソリューションアーキテクト − アソシエイト教科書[SAA-C02]対応&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.co.jp/exec/obidos/ASIN/4295010650/hatena-blog-22/&quot; target=&quot;_blank&quot;&gt;(模擬問題付き)改訂新版 徹底攻略 AWS認定 ソリューションアーキテクト − アソシエイト教科書[SAA-C02]対応&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;作者&lt;div&gt;&lt;/div&gt; 昭寛](&lt;a href=&quot;http://d.hatena.ne.jp/keyword/%C4%BB%C3%AB%C9%F4%20%BE%BC%B4%B2),%5B%E5%AE%AE%E5%8F%A3&quot; target=&quot;_blank&quot;&gt;http://d.hatena.ne.jp/keyword/%C4%BB%C3%AB%C9%F4%20%BE%BC%B4%B2),[宮口&lt;/a&gt; 光平](&lt;a href=&quot;http://d.hatena.ne.jp/keyword/%B5%DC%B8%FD%20%B8%F7%CA%BF),%5B%E8%8F%96%E8%92%B2&quot; target=&quot;_blank&quot;&gt;http://d.hatena.ne.jp/keyword/%B5%DC%B8%FD%20%B8%F7%CA%BF),[菖蒲&lt;/a&gt; 淳司&lt;/li&gt;
&lt;li&gt;$1&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.co.jp/exec/obidos/ASIN/4295010650/hatena-blog-22/&quot; target=&quot;_blank&quot;&gt;Amazon&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;基礎固め &amp;amp; 問題演習後の復習用に使っていました。最初は用語とか重要な概念をとりあえず頭に入れて問題演習に臨み、解けなかったら索引から検索して、その周辺のページを深読みするという使い方をしていました。&lt;/p&gt;
&lt;p&gt;SAA試験はその名の通り、ソリューションを構築できることが重要なので、用語は当然として各ケースでどういった対応をとるのか、というベストプ$1ティスを把握することが大事だなと思います。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#これだけでok-aws-認定ソリューションアーキテクト--アソシエイト試験突破講座saa-c02試験対応版&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座（SAA-C02試験対応版）&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://www.udemy.com/course/aws-associate/&quot; target=&quot;_blank&quot;&gt;www.udemy.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;基礎固めで使用しました。結構長い&amp;amp;前半までの内容は大体自分でやったことがあったので、動画だけみてハンズオンはスキップしていました。後半戦は実際に自分で手を動かしてやってみていました。&lt;/p&gt;
&lt;p&gt;ソフトウェア系の試験はどれもそうだと思いますが、実際にやってみていると「これはありえない」という選択肢が直感的にわかるようになるのでやっておいて損はないと思います。&lt;/p&gt;
&lt;p&gt;…というか資格を取るためだけに勉強しているわけではないのであれば、やっておいたらいいと思うんだ😅&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#saa-c02版aws-認定ソリューションアーキテクト-アソシエイト模擬試験問題集6回分390問&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;【SAA-C02版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問）&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://www.udemy.com/course/aws-knan/&quot; target=&quot;_blank&quot;&gt;www.udemy.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;全6回を複数回（4周くらい？）ときました。1周目はどれも50点くらいでしたが、2周目は大体80%くらいのスコアで、試験前日の状態では、平均スコア90%でした。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#cloudtech&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;CloudTech&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://aws-cloud-tech.com/&quot; target=&quot;_blank&quot;&gt;aws-cloud-tech.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;いろいろ有料制度もあるんですが、フリーコース（無料：会員登録必要）でSAA試験の練習問題200問を解きました。Udemyの問題で80%とれるようになったくらいでこちらを解いて、大体85%くらいの正答率でした。試験前日の段階では200問連続で解いて、195問正解という感じで試験に挑みました。&lt;/p&gt;
&lt;p&gt;難易度的にはUdemyの問題集よりもちょっと易しめで、一方でUdemyの問題集と全く同じ問題も結構ありました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#試験を受けてみての感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;試験を受けてみての感想&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#練習問題とのレベル感&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;練習問題とのレベル感&lt;/h3&gt;
&lt;p&gt;全体的には練習問題よりも難しかったです。わからない問題はそもそも問題文が何を言っているのかわかりませんでした。あとは各所で言われていますが、日本語訳が変な問題が結構多くて、英語をみてから「ああ、そういうことをいいたいのね」となるような問題が5問くらいありました。ここら辺が練習問題との差かもしれません。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#受かってよかったね&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;受かってよかったね&lt;/h3&gt;
&lt;p&gt;なにはともあれ、受かってよかったです（$1プ$1ティショナー合格してると、SAAの受験料半分なので、金銭的にも今回で受かってよかった）😊&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;以上、AWS SAA試験合格レポートでした〜！&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>RubyMine2021.2.3でdocker compose環境のRailsを動かしてみる</title><link>https://ikuma-t.com/blog/202111151636975063/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202111151636975063/</guid><description>動機昨今の開発において、常識になっているDocker。私もそろそろ学ばねばということで、書籍を使って概要を掴みました。仕組みと使い方がわかるDocker＆Kubernetesのきほんのきほん(Comp</description><pubDate>Mon, 15 Nov 2021 20:17:43 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#動機&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;動機&lt;/h2&gt;
&lt;p&gt;昨今の開発において、常識になっているDocker。&lt;/p&gt;
&lt;p&gt;私もそろそろ学ばねばということで、書籍を使って概要を掴みました。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.co.jp/exec/obidos/ASIN/B08T961HKP/hatena-blog-22/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://m.media-amazon.com/images/I/51vhRrY-JEL._SL500_.jpg&quot; alt=&quot;仕組みと使い方がわかる Docker＆Kubernetesのきほんのきほん (Compass Booksシリーズ)&quot; title=&quot;仕組みと使い方がわかる Docker＆Kubernetesのきほんのきほん (Compass Booksシリーズ)&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.co.jp/exec/obidos/ASIN/B08T961HKP/hatena-blog-22/&quot; target=&quot;_blank&quot;&gt;仕組みと使い方がわかる Docker＆Kubernetesのきほんのきほん (Compass Booksシリーズ)&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;作者&lt;div&gt;&lt;/div&gt; 種高&lt;/li&gt;
&lt;li&gt;$1&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.co.jp/exec/obidos/ASIN/B08T961HKP/hatena-blog-22/&quot; target=&quot;_blank&quot;&gt;Amazon&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Dockerの仕組み、Dockerfile、Docker Composeの基本はわかったけれど、実際にRailsアプリを動かしてみたらどうなるんだろう？と気になっていたところ、RubyMineの公式がDocker Compose環境でRailsを動かすサンプルRailsを公開していたので、Railsアプリの起動までやってみました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#やること&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;やること&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://pleiades.io/help/ruby/using-docker-compose-as-a-remote-interpreter.html&quot; target=&quot;_blank&quot;&gt;チュートリアル: リモートインタープリターとしての Docker Compose | RubyMine&lt;/a&gt;をやる&lt;/p&gt;
&lt;p&gt;サンプル$1：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/JetBrains/sample_rails_app&quot; target=&quot;_blank&quot;&gt;github.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;&lt;a href=&quot;#やってみる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;やってみる&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#まずはgit-clone&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;まずはgit clone&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211115/20211115164149.png&quot; alt=&quot;f:id:ikmbear:20211115164149p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211115/20211115164102.png&quot; alt=&quot;f:id:ikmbear:20211115164102p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;コマンドでも構いませんが、RubyMineを使用しているので、「Get from VCS」からサンプルVCSのURLを設定して、cloneを実施します。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#db設定をpostgresqlに変更する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;DB設定をPostgresqlに変更する&lt;/h3&gt;
&lt;p&gt;cloneした時点ではDB設定がsqlite3になっているようなので、&lt;code&gt;config/database.yml&lt;/code&gt;を開き、使用するDBを変更します。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211115/20211115170018.png&quot; alt=&quot;f:id:ikmbear:20211115170018p&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#コンテナを起動する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;コンテナを起動する&lt;/h3&gt;
&lt;p&gt;次に&lt;code&gt;docker-compose.yml&lt;/code&gt;を開いて、ガターにある矢印アイコンを押します。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211115/20211115164929.png&quot; alt=&quot;f:id:ikmbear:20211115164929p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;これで&lt;code&gt;/usr/local/bin/docker-compose -f /Users/tadokoroikuma/RubymineProjects/sandbox/sample_rails_app/docker-compose.yml up -d&lt;/code&gt;というコマンドが実行されます。&lt;/p&gt;
&lt;p&gt;つまりは、この&lt;code&gt;docker-compose.yml&lt;/code&gt;をベースとして、バックグラウンドでサービス（コンテナ）を起動するわけです。&lt;br /&gt;
これでPostgresqlとRubyのコンテナがそれぞれ作成&amp;amp;起動されます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#rubyーとしてコンテナ上のrubyを指定する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Rubyーとして、コンテナ上のRubyを指定する&lt;/h3&gt;
&lt;p&gt;次にRubyMineに対して、コンテナ上のRubyを参照するように設定します。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211115/20211115184357.png&quot; alt=&quot;f:id:ikmbear:20211115184357p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Preferences &amp;gt; Ruby SDK and Gemsを開き、「+」から「New Remote」を選択します。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211115/20211115184525.png&quot; alt=&quot;f:id:ikmbear:20211115184525p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211115/20211115184601.png&quot; alt=&quot;f:id:ikmbear:20211115184601p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;続いて、Docker ComposeのwebコンテナのRubyを参照するように設定し、「OK」を押します。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#db作成と1を行う&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;DB作成と$1を行う&lt;/h3&gt;
&lt;p&gt;次に&lt;code&gt;rails db:create&lt;/code&gt;と&lt;code&gt;rails db:migrate&lt;/code&gt;を実施します。&lt;br /&gt;
これに限らずですが、ターミナルからコンテナに入ってコマンドを直接実行する方法と、RubyMineの機能を使って実行する方法の2種類があるので、それぞれ解説します。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ターミナルからコンテナに入ってコマンドを直接実行する方法&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# webコンテナを指定してコマンドを実行する（bashを起動する）$ docker-compose exec web bash # DBの作成を行う（rails db:migrateも同様）$ rails db:createCreated database &apos;sample_rails_app_db&apos;Created database &apos;sample_rails_app_db_test&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;RubyMineの機能を使って実行する方法&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;RubyMineのRunAnythingに包含されている、Rake Taskの実行を用いて起動します。&lt;br /&gt;
（rakeタスクのコマンドはrailsコマンドに移管されたのですが、RubyMineの機能を使う場合は、Rakeタスクとして扱う必要があります。というかRailsコマンドで実行しても結局はRakeタスクを叩いているだけなので…）&lt;/p&gt;
&lt;p&gt;&lt;code&gt;^&lt;/code&gt;を2回押して、RunAnythingを呼び出し、&lt;code&gt;rake --tasks&lt;/code&gt;と入力してEnterで実行します。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211115/20211115185948.png&quot; alt=&quot;f:id:ikmbear:20211115185948p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;これをしないとどうもDocker環境でRakeタスクが認識できないようで…（これは不便）。&lt;/p&gt;
&lt;p&gt;これでRakeタスクが使えるようになったので、RunAnythingから&lt;code&gt;rake db:create&lt;/code&gt;を実行します（&lt;code&gt;rake db:migrate&lt;/code&gt;も同様）&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211115/20211115190247.png&quot; alt=&quot;f:id:ikmbear:20211115190247p&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#dbが作成されたか確認する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;DBが作成されたか確認する&lt;/h3&gt;
&lt;p&gt;$1にはありませんが、RubyMineのDBクライアント機能を使って作成されたDBを確認してみましょう。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211115/20211115190656.png&quot; alt=&quot;f:id:ikmbear:20211115190656p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;まずはDatabaseツールウィンドウを開いて、「+」ボタンからDataSourceとしてPostgreSQLを選択します。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211115/20211115191120.png&quot; alt=&quot;f:id:ikmbear:20211115191120p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;次に接続に必要な情報を以下の通り設定していきます。&lt;/p&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;項目&lt;/th&gt;&lt;th&gt;設定&lt;/th&gt;&lt;th&gt;説明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Port&lt;/td&gt;&lt;td&gt;54333&lt;/td&gt;&lt;td&gt;docker-compose.ymlで設定したポート$1ードにもとづき、54333を指定します。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Authentication&lt;/td&gt;&lt;td&gt;User &amp;amp; Password&lt;/td&gt;&lt;td&gt;postgresのコンテナの設定にしたがい、この認証方法を指定します。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;User&lt;/td&gt;&lt;td&gt;postgres&lt;/td&gt;&lt;td&gt;database.ymlで定義した内容に従って、postgresを指定します&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Password&lt;/td&gt;&lt;td&gt;&amp;lt;空欄&amp;gt;&lt;/td&gt;&lt;td&gt;docker-compose.ymlで指定した内容にて、パスワード不要のオプションを設定しているため、空欄にします&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;sample_rails_app_db&lt;/td&gt;&lt;td&gt;database.ymlで指定した内容に基づき、この名前のDBへの接続を指定します&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;入力が完了したら、TestConnectionを行い、問題なければOKを押してください。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211115/20211115191635.png&quot; alt=&quot;f:id:ikmbear:20211115191635p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;うまくいけばこのようにDatabaseの中身を確認することができます。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#railsアプリケーションの実行&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Railsアプリケーションの実行&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211115/20211115191735.png&quot; alt=&quot;f:id:ikmbear:20211115191735p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;RAILSの実行対象に「DEVELOPMENT&lt;/p&gt;&lt;div&gt;&lt;/div&gt;_RAILS_APP」を指定し、再生ボタンを押します。&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211115/20211115191943.png&quot; alt=&quot;f:id:ikmbear:20211115191943p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ブラウザを開き、&lt;code&gt;http://0.0.0.0:3000/&lt;/code&gt;にアクセスするとサンプルアプリが起動します。&lt;/p&gt;
&lt;p&gt;なおターミナルから実行する場合は以下のようにします。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$ docker-compose exec web bash$ bin/rails s -b 0.0.0.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#バインドマウントがされているか確認してみる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;バインドマウントがされているか確認してみる&lt;/h3&gt;
&lt;p&gt;後述のdocker-composeの設定で、node_modulesを除くすべてのファイルの変更がコンテナ上に反映されます。&lt;br /&gt;
実際にソースを少し改変して、反映されることを確認してみましょう。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;app/views/static_pages/home.html.erb&lt;/code&gt;を開き、23行目にある内容を書き換えてみましょう。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;h2&amp;gt;      BindMountTest      This is the home page for the      &amp;lt;a href=&quot;https://www.railstutorial.org/&quot;&amp;gt;Ruby on Rails Tutorial&amp;lt;/a&amp;gt;      sample application.    &amp;lt;/h2&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;この状態でアプリをリロードします。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211115/20211115192819.png&quot; alt=&quot;f:id:ikmbear:20211115192819p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;たしかに内容が変更されていることが確認できました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#定義ファイルを確認する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;定義ファイルを確認する&lt;/h2&gt;
&lt;p&gt;ここまでで実際にRailsアプリを立ち上げることができました。ここからはこの環境を作成した定義ファイルを確認していきたいと思います。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#docker-composeyml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;docker-compose.yml&lt;/h3&gt;
&lt;p&gt;まずは&lt;code&gt;docker-compose.yml&lt;/code&gt;からです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;version: &apos;3&apos;services:  db:    image: postgres    volumes:      - ./tmp/db:/var/lib/postgresql/data    environment:      POSTGRES_HOST_AUTH_METHOD: trust    ports:      - &quot;54333:5432&quot;  web:    build: .    command: tail -f /dev/null    volumes:      - .:/sample_rails_application      - /sample_rails_application/node_modules    ports:      - &quot;3000:3000&quot;      # Ports required for debugging      - &quot;1234:1234&quot;      - &quot;26166:26168&quot;    depends_on:      - db&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;順番に見ていきます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;version: &apos;3&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これは使用するDocker Composeのバージョンを指定しているだけです。&lt;br /&gt;
今回はバージョン3を指定しています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;services:  db:    # 略  web:    # 略&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;次にservices、つまり使用するコンテナの設定です。今回はdbというコンテナとwebというコンテナの2種類を立てます。&lt;br /&gt;
順を追ってみてみましょう。まずはdbコンテナです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;db:    image: postgres    volumes:      - ./tmp/db:/var/lib/postgresql/data    environment:      POSTGRES_HOST_AUTH_METHOD: trust    ports:      - &quot;54333:5432&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;以下各定義内容の説明です。&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;定義&lt;/th&gt;&lt;th&gt;意味&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;image:postgres&lt;/code&gt;&lt;/td&gt;&lt;td&gt;dbコンテナではpostgresqlをイメージとします&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;volumes&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;からみた$1で&lt;code&gt;var/lib/postgresql/data&lt;/code&gt;が呼び出されたら、ホストの&lt;code&gt;./tmp/db&lt;/code&gt;に読み取り、書き込みを行います。これによりデータが永続化できます&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;environment&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Postgresqlとして、&lt;code&gt;POSTGRES_HOST_AUTH_METHOD&lt;/code&gt;を定義し、その値に&lt;code&gt;trust&lt;/code&gt;を指定します。このオプションはPostgresqlのパスワードが不要になるもので、推奨はされていません（今回は検証用のPostgresqlなので…）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ports&lt;/code&gt;&lt;/td&gt;&lt;td&gt;ホストのポート54333を5432にポート$1ードします。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;code&gt;volumes&lt;/code&gt;の指定は、Dockerの2つある方法のうちの「バインドマウント（Dockerエンジン上ではなく、ホストの指定した箇所に保存する）」の指定で、&lt;code&gt;:&lt;/code&gt;を境にホスト&lt;/p&gt;&lt;div&gt;&lt;/div&gt;。&lt;p&gt;&lt;/p&gt;
&lt;p&gt;参考：&lt;a href=&quot;https://hub.docker.com/_/postgres&quot; target=&quot;_blank&quot;&gt;Postgres - Official Image | Docker Hub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;続いてwebコンテナを確認します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;web:    build: .    command: tail -f /dev/null    volumes:      - .:/sample_rails_application      - /sample_rails_application/node_modules    ports:      - &quot;3000:3000&quot;      # Ports required for debugging      - &quot;1234:1234&quot;      - &quot;26166:26168&quot;    depends_on:      - db&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;こちらも同様に各定義内容の説明です。&lt;/p&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;定義&lt;/th&gt;&lt;th&gt;意味&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;build&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;docker-compose&lt;/code&gt;から見た$1で&lt;code&gt;.&lt;/code&gt;つまり、カレント$1リにあるDockerfileをベースにしてコンテナを作成します。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;command&lt;/code&gt;&lt;/td&gt;&lt;td&gt;コンテナ起動時のコマンドを指定する。&lt;code&gt;tail -f /dev/null&lt;/code&gt;は何もしないで起動を続けるためのコマンドで、RubyMine側でRailsを起動する際に、コンテナ内でRailsが立ち上がっているとプロセスが重複して起動できなくなることを回避するために、このようにしています。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;volumes&lt;/code&gt;&lt;/td&gt;&lt;td&gt;一行目は、コンテナの&lt;code&gt;./sample_rails_application&lt;/code&gt;に対して、ホストの&lt;code&gt;.&lt;/code&gt;（カレント$1リ）をバインドマウントしています。2行目はコンテナ上の&lt;code&gt;node_modules&lt;/code&gt;$1リを名前なしボリュームとしてマウントしています&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ports&lt;/code&gt;&lt;/td&gt;&lt;td&gt;ポート$1ードを定義しています&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;depends_on&lt;/code&gt;&lt;/td&gt;&lt;td&gt;dbコンテナに依存することを定義しています&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;結構ややこしいのが、&lt;code&gt;node_modules&lt;/code&gt;の名前なしボリュームでのマウントです。&lt;br /&gt;
まず先の通り、手元のソースの反映はバインドマウントによって、すべてコンテナ上と同期されます。&lt;br /&gt;
こうすると、ホスト上とコンテナ上の&lt;code&gt;node_modules&lt;/code&gt;がそれぞれ同期されてしまうのですが、せっかくコンテナ上で固定したnodeが、ホストによって破壊されることになってしまいます。&lt;/p&gt;
&lt;p&gt;そのため、&lt;code&gt;node_modules&lt;/code&gt;のみはバインドの対象外とするのですが、コンテナが破棄されたのちもデータを永続化するため、DockerEngine上に名前なしボリュームとしてマウントする手段をとっています。&lt;/p&gt;
&lt;p&gt;参考：&lt;a href=&quot;https://zenn.dev/foolishell/articles/3d327557af3554&quot; target=&quot;_blank&quot;&gt;VSCode&amp;amp;Docker Volumeにおけるnode_modules問題を解決する&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ここまでに記述した内容でたしかにコンテナが起動しているかは、コマンドでも確認することができますが、RubyMineのServicesタブを使って確認することができます。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211115/20211115182514.png&quot; alt=&quot;f:id:ikmbear:20211115182514p&quot; /&gt; webコンテナのポート$1ード設定を確認&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#dockerfile&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Dockerfile&lt;/h3&gt;
&lt;p&gt;つづいて、Dockerfileです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# ruby2.7.2のイメージを使用するFROM ruby:2.7.2# yarnのリポジトリを追加します（apt-key add -は標準入力の内容を追加します。つまりcurlで取得した内容を追加します）RUN curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -# teeコマンドを使ってyarnのAPTパッケージレポジトリを自分のシステムに追加しますRUN echo &quot;deb https://dl.yarnpkg.com/debian/ stable main&quot; | tee /etc/apt/sources.list.d/yarn.list# 必要なパッケージをインストールしますRUN apt-get update -qq &amp;amp;&amp;amp; apt-get install -y build-essential libpq-dev nodejs postgresql-client yarn# RUN CMD ENTRYPOINT ADD COPYの際の作業ディレクトリを`/sample_rails_application`に指定RUN mkdir /sample_rails_applicationWORKDIR /sample_rails_application# 必要な初期設定系ファイルのコピーCOPY Gemfile /sample_rails_application/GemfileCOPY Gemfile.lock /sample_rails_application/Gemfile.lockCOPY package.json /sample_rails_application/package.jsonCOPY yarn.lock /sample_rails_application/yarn.lock# 初期設定系のインストールRUN gem install bundler -v &apos;2.2.15&apos;RUN bundle installRUN yarn install --check-files# イメージに`. /sample_rails_application`の内容を追加するCOPY . /sample_rails_application# ポート3000で通信するEXPOSE 3000&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;このimageを元に、docker-composeのwebコンテナは作成されるようです。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;素晴らしい書籍のおかげでDockerの基礎を理解できたのはよいものの、実際にRailsアプリを一から起動するとなると、ややハードルが高かったです。&lt;br /&gt;
しかしながら、この$1はすでに出来上がっている$1を使ってアプリを動かすので、その中継点として非常にちょうどいい題材だと思いました。&lt;/p&gt;
&lt;p&gt;一点気になったのが、node_modulesはVolumeTrickを使って名前なしボリュームにマウントしているのに、Gemfileはいいのか？というところです。&lt;br /&gt;
なんか同じような類なので、Gemfileもボリュームマウントした方がいい気がするんですが、その話はまた別の機会に調べようと思います。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>git initで作成されるブランチ名を変更する</title><link>https://ikuma-t.com/blog/202110201634692368/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202110201634692368/</guid><description>久しぶりに$1からgitinitしたら、以下のようなメッセージが表示されました。%gitinithint:Using&apos;master&apos;asthenamefortheinitialbranch.Thisd</description><pubDate>Wed, 20 Oct 2021 10:12:48 GMT</pubDate><content:encoded>&lt;p&gt;久しぶりに$1から&lt;code&gt;git init&lt;/code&gt;したら、以下のようなメッセージが表示されました。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;% git init hint: Using &apos;master&apos; as the name for the initial branch. This default branch name hint: is subject to change. To configure the initial branch name to use in all hint: of your new repositories, which will suppress this warning, call: hint: hint:  git config --global init.defaultBranch &amp;lt;name&amp;gt; hint: hint: Names commonly chosen instead of &apos;master&apos; are &apos;main&apos;, &apos;trunk&apos; and hint: &apos;development&apos;. The just-created branch can be renamed via this command: hint: hint:  git branch -m &amp;lt;name&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;git config --global init.defaultBranch &amp;lt;name&amp;gt;&lt;/code&gt;とすることで、ブランチ名のデフォルトを変えられるようです。最近いつも&lt;code&gt;master&lt;/code&gt;で作成してから&lt;code&gt;main&lt;/code&gt;に変更していたので、これを&lt;code&gt;main&lt;/code&gt;に変えてみます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% git config --global init.defaultBranch main&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;この状態で、&lt;code&gt;git init&lt;/code&gt;をしてみると、ブランチが&lt;code&gt;main&lt;/code&gt;で作成されていました。 &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211020/20211020101207.png&quot; alt=&quot;f:id:ikmbear:20211020101207p&quot; /&gt;&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>文字列に数値が含まれているか判定する</title><link>https://ikuma-t.com/blog/202110181634526176/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202110181634526176/</guid><description>Rubyである文字列wordに数値が含まれているかどうかをBoolean値で判定するには次のようにするdefself.include_number?(word)(word=~/[0-9]/)!=nil</description><pubDate>Mon, 18 Oct 2021 12:02:56 GMT</pubDate><content:encoded>&lt;p&gt;Rubyである文字列wordに数値が含まれているかどうかをBoolean値で判定するには次のようにする&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;def self.include_number?(word)    (word =~ /[0-9]/) != nil end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.ruby-lang.org/ja/latest/method/String/i/=3d=7e.html&quot; target=&quot;_blank&quot;&gt;docs.ruby-lang.org&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;String#=~&lt;/code&gt;は、$1を引数にとり、マッチすればそのインデックスを、そうでなければ&lt;code&gt;nil&lt;/code&gt;を返す。&lt;/p&gt;
&lt;p&gt;このメソッドでは、&lt;code&gt;nil&lt;/code&gt;と比較することで、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;見つからない場合は&lt;code&gt;nil != nil&lt;/code&gt; は&lt;code&gt;false&lt;/code&gt;を返す&lt;/li&gt;
&lt;li&gt;見つかった場合は&lt;code&gt;3 != nil&lt;/code&gt;のようになり、&lt;code&gt;true&lt;/code&gt;を返す&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;という仕組み。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>文字列に大文字と小文字が混在していることを判定する</title><link>https://ikuma-t.com/blog/202110181634525749/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202110181634525749/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211018/20211018115513.png小ネタ。Rubyで書</description><pubDate>Mon, 18 Oct 2021 11:55:49 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211018/20211018115513.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211018/20211018115513.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211018/20211018115513.png&quot; alt=&quot;f:id:ikmbear:20211018115513p&quot; /&gt; 小ネタ。Rubyで書いているけど他の言語でも同じ。&lt;/p&gt;
&lt;p&gt;ある文字列wordに大文字と小文字の両方が含まれているかチェックするには&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;wordをすべて大文字にした結果とwordが等しいか（例：IKUMAとikuMaが等しいか）&lt;/li&gt;
&lt;li&gt;wordをすべて小文字にした結果とwordが等しいか（例：ikumaとikuMaが等しいか）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;の$1を返せば良い。&lt;/p&gt;
&lt;p&gt;コードは次のようになる。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;def include_upper_and_lower_case?(word)     # 戻り値はBoolean     word.upcase != word &amp;amp;&amp;amp; word.downcase != word   end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;</content:encoded><author>ikuma-t</author></item><item><title>spotifyのプレイリストを自動で作るnpm（recommendify）を作った</title><link>https://ikuma-t.com/blog/202110171634472193/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202110171634472193/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211017/20211017210157.png少し前にspotif</description><pubDate>Sun, 17 Oct 2021 21:03:13 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211017/20211017210157.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211017/20211017210157.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211017/20211017210157.png&quot; alt=&quot;f:id:ikmbear:20211017210157p&quot; /&gt; 少し前にspotifyブートキャンプの課題でspotifyのプレイリストを自動作成してくれるnpm：recommendifyを作ったので、紹介します。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#何を作ったの&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;何を作ったの？&lt;/h2&gt;
&lt;p&gt;以下の4つの質問に答えると、それにあったSpotifyのプレイリストを作成してくれるnpmです（15曲入っています）。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;最近聴いた曲から1~3曲&lt;/li&gt;
&lt;li&gt;曲の明るさ&lt;/li&gt;
&lt;li&gt;アーティストの人気度&lt;/li&gt;
&lt;li&gt;曲のBPM&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href=&quot;https://www.npmjs.com/package/recommendify&quot; target=&quot;_blank&quot;&gt;recommendify - npm&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211017/20211017204037.gif&quot; alt=&quot;f:id:ikmbear:20211017204037g&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#どうして作ったの&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;どうして作ったの？&lt;/h2&gt;
&lt;p&gt;Spotifyのプレミアムプランに契約して、まあまあ曲は聴いているし、毎日使っているんですが、&lt;strong&gt;ついつい同じ曲を選んでしまうんですよね&lt;/strong&gt;。&lt;br /&gt;
自分で探しに行けばいいんですけど、Spotifyの検索画面ってジャンルを選ぶと人気の曲が出てくるので、結局最近聴いた曲ばっか出てきてしまう…。&lt;/p&gt;
&lt;p&gt;そこで「いっそのことプログラムに勝手にプレイリストを作らせてしまえばいいのでは」と思い、本npmを作成するに至りました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#どうやって使うの&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;どうやって使うの？&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.npmjs.com/package/recommendify&quot; target=&quot;_blank&quot;&gt;recommendify - npm&lt;/a&gt;にも記載がありますが、一応日本語でも記載しておきます。&lt;/p&gt;
&lt;p&gt;※Spotifyアカウントを持っていることが前提になります。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#前準備&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;前準備&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Spotifyの開発者Spotifyボードにログインする&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.spotify.com/dashboard/&quot; target=&quot;_blank&quot;&gt;developer.spotify.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol&gt;
&lt;li&gt;「CREATE AN APP」を選択する。App nameとApp descriptionに適当な値を入れてチェックをし、「CREATE」を選択する&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211017/20211017204403.png&quot; alt=&quot;f:id:ikmbear:20211017204403p&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;「EDIT SETTING」を開き、コールバックURLに&lt;code&gt;http://localhost:8888/callback&lt;/code&gt;を設定する&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211017/20211017204541.png&quot; alt=&quot;f:id:ikmbear:20211017204541p&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;クライアントIDとクライアントシークレットを控えておく&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211017/20211017204628.png&quot; alt=&quot;f:id:ikmbear:20211017204628p&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#実行&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;実行&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;recommendifyをインストールする&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% npm i -g recommendify&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;以下のコマンドを実行し、クライアントIDとシークレットを入力して、$1ンの取得を行う&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% recommendify settoken&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211017/20211017204810.png&quot; alt=&quot;f:id:ikmbear:20211017204810p&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;これでrecommendifyが実行可能になります！プレイリストを作成しましょう！&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% recommendify&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#工夫したところは&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;工夫したところは？&lt;/h2&gt;
&lt;p&gt;曲をどうやって選出するかですね。&lt;/p&gt;
&lt;p&gt;SpotifyのWebAPIでは結構いろいろなパラメータがあって、最初はそれらを全部選べるようにもしようかと思ったのですが、ランダムな曲を選ぶのにパラメータをいくつも選ぶのはいかがなものかと思いまして、現在の形に至りました。&lt;/p&gt;
&lt;p&gt;ガチャを回すので4手くらいが限界かなあと。&lt;/p&gt;
&lt;p&gt;あとは一応同じ選択肢を選んでもランダムになるように、曲にはシャッフルをかけています（一応SpotifyのAPIは同じパラメータだと同じ内容を返すように見えましたが、登録されている曲のリストが変われはその限りではないとも思っています）。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#難しかったところは&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;難しかったところは？&lt;/h2&gt;
&lt;p&gt;アクセス$1ンが切れた場合のリフレッシュ処理に少し苦労しました。&lt;/p&gt;
&lt;p&gt;SpotifyのアクセスSpotifyンはたしか1時間くらいで切れてしまうのですが、切れるたびにエラーになってはストレスなので、confというnpmを使ってリフレッシュSpotifyンをローカルに保存し、アクセス時にSpotifyンの有効期限が切れていれば、アクセスSpotifyンの再取得を行うようにしました。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const callApi = (func, argumentArray) =&amp;gt; {  return (async function callSpotifyApi (retryCounter = 1) {    try {      return await func.apply(spotifyApi, argumentArray)    } catch (error) {      if (error.body.error.status === 401 &amp;amp;&amp;amp; retryCounter) {        await refreshAccessToken()        return await callSpotifyApi(retryCounter - 1)      }      throw new Error(error)    }  }())}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/IkumaTadokoro/recommendify/blob/main/lib/create-playlist.js#L166&quot; target=&quot;_blank&quot;&gt;github.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;とはいっても、何回もリトライすると無限ループに陥る可能性があるので、$1処理として実装しつつも、複数回は実行しないようにする部分に結構頭を使いました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;個人的に結構気に入っているアプリです（本当はWebアプリとして実装できたらいいんですが…）。&lt;br /&gt;
皆さんもぜひダウンロードしてみてください。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>雑なプログラミング問題（LEET変換プログラム）</title><link>https://ikuma-t.com/blog/202110161634388429/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202110161634388429/</guid><description>ネットで見かけたプログラミング問題をRubyで解いてみました。簡単なテストコードも作ったので、みなさんも是非解いてみてください。問題Leet-Wikipediaとは、一部のアルファベットを一定のルール</description><pubDate>Sat, 16 Oct 2021 21:47:09 GMT</pubDate><content:encoded>&lt;p&gt;ネットで見かけたプログラミング問題をRubyで解いてみました。簡単なテストコードも作ったので、みなさんも是非解いてみてください。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#問題&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://ja.wikipedia.org/wiki/Leet&quot; target=&quot;_blank&quot;&gt;Leet - Wikipedia&lt;/a&gt;とは、一部のアルファベットを一定のルールに基づき、数値や記号に変換して表す遊び、仕組みです。ここでは、以下の変換ルールが適用されています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a/A = 4&lt;/li&gt;
&lt;li&gt;b/B = 8&lt;/li&gt;
&lt;li&gt;e/E = 3&lt;/li&gt;
&lt;li&gt;l/L = 1&lt;/li&gt;
&lt;li&gt;o/O = 0&lt;/li&gt;
&lt;li&gt;s/S = 5&lt;/li&gt;
&lt;li&gt;t/T = 7&lt;/li&gt;
&lt;li&gt;z/Z = 2&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例えば、文字列&lt;code&gt;I am a student&lt;/code&gt;は&lt;code&gt;I 4m 4 57ud3n7&lt;/code&gt;に置き換えられます。&lt;br /&gt;
変換対象の文字列：&lt;code&gt;original_string&lt;/code&gt;が与えられるので、それをleet文字列に変換した結果を返す関数leetifyを作成してください。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# 出力例leetify(&apos;I am a student&apos;) # I 4m 4 57ud3n7leetify(&apos;do re mi fa so ra si do&apos;) # d0 r3 mi f4 50 r4 5i d0leetify(&apos;Dairantou smash brothers&apos;) # D4ir4n70u 5m45h 8r07h3r5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;テストコード&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://gist.github.com/IkumaTadokoro/c1253bfc6ea4bb707bb72bd718ba6410&quot; target=&quot;_blank&quot;&gt;gist.github.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;&lt;a href=&quot;#回答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;回答&lt;/h2&gt;
&lt;p&gt;ハッシュテーブルを利用して変換します。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://gist.github.com/IkumaTadokoro/6359f38b93e64566390725cc2a5f20de#file-leetify-rb&quot; target=&quot;_blank&quot;&gt;gist.github.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;&lt;a href=&quot;#解説&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;解説&lt;/h2&gt;
&lt;p&gt;すごい短いので解説することもないですが…&lt;/p&gt;
&lt;p&gt;今回は文字列を&lt;code&gt;String#chars&lt;/code&gt;を利用して一文字ずつ配列に分解し、ハッシュテーブルを利用することで変換しています。&lt;br /&gt;
ハッシュテーブルに値がない場合は文字列そのままを返す必要があるのですが、これは短絡評価を利用することで短く表記しています。&lt;/p&gt;
&lt;p&gt;3項$1を使って書いてみると以下のような感じです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;def leetify(original_string)  string.chars.map { |s| LEET_TABLE[s] ? LEET_TABLE[s] : s }end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;ちなみに、すべてハッシュテーブルの中に値があることがわかっている場合は以下のように書けます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;def leetify(original_string)  string.chars.map(&amp;amp;LEET_TABLE)end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;この記法は&lt;a href=&quot;https://docs.ruby-lang.org/ja/latest/method/Hash/i/to_proc.html&quot; target=&quot;_blank&quot;&gt;Hash#to_proc (Ruby 3.0.0 リファレンスマニュアル)&lt;/a&gt;を利用したものです。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;おしまい&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>最近のScrapboxの使い方（2021/10）</title><link>https://ikuma-t.com/blog/202110151634273489/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202110151634273489/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211015/20211015135059.png私がいままでやってい</description><pubDate>Fri, 15 Oct 2021 13:51:29 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211015/20211015135059.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211015/20211015135059.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211015/20211015135059.png&quot; alt=&quot;f:id:ikmbear:20211015135059p&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#私がいままでやっていたことは情報の整頓だった&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;私がいままでやっていたことは「情報の整頓」だった&lt;/h2&gt;
&lt;p&gt;Notion、Mem、Bear、InkDrop…etc。メモアプリは色々と試してきました。いずれのアプリも最初のうちは「おお！めちゃいいやん」と快調にメモができていたのですが、メモの量が増えるにつれて、だんだん使いづらくなっていき、メモアプリヒッピーに。&lt;/p&gt;
&lt;p&gt;そんなときに『知的生産の技術』を読んだのですが、次のフレーズにハッとさせられました。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;整理というのは、ちらばっているものを目ざわりにならないように、きれいにかたづけることではない。それはむしろ整頓というべきであろう。ものごとがよく整理されているというのは、みた目にはともかく、必要なものが必要なときにすぐにとりだせるようになっている、ということだとおもう。&lt;/p&gt;
&lt;p&gt;『[知的生産の技術]』（$1刊）$1&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;自分が今までやっていたメモアプリの挫折は、まさにこの「整頓」に執着していることが原因だったのか！&lt;br /&gt;
新しいメモアプリを使い始めた瞬間は、使い始めた時点での情報、つまりは有限な要素であるため、綺麗に並べられる。&lt;br /&gt;
しかし情報が増えていくにつれて、使い始めた当初の分類では抑え切れなくなり、整頓が破綻していたのです。&lt;/p&gt;
&lt;p&gt;階層型のメモアプリでは、どうしても情報量が増えた際にスケールしなくなると感じ、いままでサブ的に使用していたScrapboxをメインのメモアプリに据えることにしました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#なんでもscrapboxにつっこむ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;なんでもScrapboxにつっこむ&lt;/h2&gt;
&lt;p&gt;先に述べた通り、Scrapboxをメインのメモアプリにしたため、なんでもかんでもScrapboxにつっこんでいます。&lt;/p&gt;
&lt;p&gt;現状では、日記ページを毎日作成し、そこからリンクを派生する形で色々なメモを作成しています。 &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211015/20211015133256.png&quot; alt=&quot;f:id:ikmbear:20211015133256p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;日記ページは現時点で以下のようなセクションで構成されており、$1の部分に雑にメモを書いていきます。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;前日 | 翌日のリンク&lt;/li&gt;
&lt;li&gt;タスクリスト&lt;/li&gt;
&lt;li&gt;感想&lt;/li&gt;
&lt;li&gt;$1&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;基本的にはその時の気持ちとかやったこととかをだらだら書いていますが、何かしら別テーマで書きたいことが出てきたら&lt;code&gt;[]&lt;/code&gt;でリンクを作成して、そこから別ページにメモします。 &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211015/20211015133311.png&quot; alt=&quot;f:id:ikmbear:20211015133311p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;日記ページは前日、翌日のリンクがあるので、暇な時にたまに見返すのですが、ここに別ページへのリンクを貼っておくとついついそのページも見て、知識の整理ができるというメリットがあります。&lt;/p&gt;
&lt;p&gt;もともと自分はpixiv百科事典を眺めるのが趣味で、芋づる式に関連項目に飛ぶのが面白いなと思ったことから、単独でページを作成せずに、最低限作成日からリンクを飛ばすような仕組みにした経緯があります。&lt;/p&gt;
&lt;p&gt;あと書いている最中は$1の中に書いていたけど、見返すと別テーマに切り出せそうなものは後から別ページにしています。これは$1でメソッド切り出しを行うような感じがしていて、結構気に入っています。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#使っているuser-scriptの紹介&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;使っているUser Scriptの紹介&lt;/h2&gt;
&lt;p&gt;…とここまでが（ざっくりですが）最近のScrapboxの使い方で、ここからは使用するにあたって利用しているUser Scriptを紹介します。&lt;/p&gt;
&lt;p&gt;なお&lt;a href=&quot;https://scrapbox.io/help-jp/UserScript&quot; target=&quot;_blank&quot;&gt;UserScript&lt;/a&gt;は、自分のプロフィールページにJavascriptでコードを書くことで、Scrapboxをカスタマイズできる機能です。詳細はリンク先参照。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#テンプレートボタン&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;テンプレートボタン&lt;/h3&gt;
&lt;p&gt;日記ページを自動で作成してくれるボタンです。新規ページを開いている時に押すことで機能します。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211015/20211015133656.gif&quot; alt=&quot;f:id:ikmbear:20211015133656g&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ソースは&lt;a href=&quot;https://scrapbox.io/scrasobox/%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%83%9A%E3%83%BC%E3%82%B8%E3%82%92%E4%BD%9C%E6%88%90%EF%BC%88UserScript%E7%89%88%EF%BC%89&quot; target=&quot;_blank&quot;&gt;テンプレートを使ってページを作成（UserScript版） - Scrapboxとあそぶ&lt;/a&gt;で紹介されているものを一部修正して使用させていただきました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#今日の日記ページに移動するボタン&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;今日の日記ページに移動するボタン&lt;/h3&gt;
&lt;p&gt;名前の通りです。別のメモを書いてから日記ページに戻るのに、一度トップページを挟むのが煩わしくて作りました。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20211015/20211015134049.gif&quot; alt=&quot;f:id:ikmbear:20211015134049g&quot; /&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;const today = new Date()  const year = today.getFullYear()  const month = (&quot;0&quot;+(today.getMonth() + 1)).slice(-2)  const date = (&quot;0&quot;+today.getDate()).slice(-2)  const formatToday = encodeURIComponent(`${year}/${month}/${date}`)  const menuTitle = &apos;Daily&apos;   scrapbox.PageMenu.addMenu({    title: menuTitle,    image: &apos;https://twitter.com/favicon.ico&apos;,    onClick: () =&amp;gt; window.location.href = `https://scrapbox.io/tadokoro/${formatToday}`  })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;見た目をFontAwesomeアイコンにするために、UserCSSも利用しています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;a#Daily.tool-btn:hover { text-decoration: none } a#Daily.tool-btn::before { position: absolute; content: &apos;\f783&apos;; font: 900 21px/46px &apos;Font Awesome 5 Free&apos; } a#Daily.tool-btn img { opacity: 0 }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;hr /&gt;
&lt;p&gt;あとは見た目関連のCSSやCSSをちょちょっといじって使っています。何か気になるものは質問いただけば、回答します。&lt;br /&gt;
Scrapboxに雑にメモできるせいで、記事もなんとなく雑になっちゃいましたね💦&lt;br /&gt;
皆さんもぜひScrapbox使ってみてください（締めまで雑）&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Node.jsでファイルが直接実行されたときだけ処理を呼び出す方法</title><link>https://ikuma-t.com/blog/202108191629300644/</link><guid isPermaLink="true">https://ikuma-t.com/blog/202108191629300644/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210819/20210819002958.png経緯JavaScri</description><pubDate>Thu, 19 Aug 2021 00:30:44 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210819/20210819002958.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210819/20210819002958.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210819/20210819002958.png&quot; alt=&quot;f:id:ikmbear:20210819002958p&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#経緯&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;経緯&lt;/h2&gt;
&lt;p&gt;JavaScriptの練習として、JavaScriptを解いており、ついでにJestでテストも書いていました。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// 実行ファイル：fizzbuzz.js// fizzbuzz関数const fizzbuzz = (num) =&amp;gt; {    ...}// 表示処理for (...) {    console.log(fizzbuzz(num))}module.exports = fizzbuzz&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// テストファイル：fizzbuzz.spec.jsconst fizzbuzz = require(&apos;./fizzbuzz&apos;)describe(&apos;FizzBuzz:1~20&apos;, () =&amp;gt; {  test(&apos;3の倍数の場合には「Fizz」を返す&apos;, () =&amp;gt; {    // テスト処理  })  ...})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;テスト自体はパスするようにできたのですが、テスト結果にも実行ファイルに書かれている&lt;code&gt;console.log&lt;/code&gt;の結果が表示されてしまう始末。これをどうにか表示させないようにするため、色々と調べてみました。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# テスト実行% npm test&amp;gt; test&amp;gt; jestPASS ./fizzbuzz.spec.js  FizzBuzz:1~20    ✓ 3の倍数の場合には「Fizz」を返す (1 ms)    ✓ 5の倍数の場合には「Buzz」を返す    ✓ 3と5両方の倍数の場合には｢FizzBuzz｣を返す    ✓ そのほかの数の時はそのままの数を返す (1 ms)# ==========テストとは関係ないので表示したくない（ここから）==========  console.log    1      at Object.&amp;lt;anonymous&amp;gt; (fizzbuzz.js:18:11)  console.log    2      at Object.&amp;lt;anonymous&amp;gt; (fizzbuzz.js:18:11)# ==========テストとは関係ないので表示したくない（ここまで）==========Test Suites: 1 passed, 1 totalTests:       4 passed, 4 totalSnapshots:   0 totalTime:        0.488 s, estimated 1 sRan all test suites.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#tl&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;TL&lt;div&gt;&lt;/div&gt;;&lt;/h2&gt;
&lt;p&gt;Node.jsでファイルが直接実行されているかどうかは、require.main === moduleで判断することができる。参考：&lt;a href=&quot;https://nodejs.org/api/modules.html#modules_accessing_the_main_module&quot; target=&quot;_blank&quot;&gt;https://nodejs.org/api/modules.html#modules_accessing_the_main_module&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;if (require.main === module) {    // 直接呼び出された場合にだけ実行したい処理}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#rubyの__file__--program_name的なイディオムがないか探してみる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Rubyの&lt;code&gt;__FILE__ = $PROGRAM_NAME&lt;/code&gt;的なイディオムがないか探してみる&lt;/h2&gt;
&lt;p&gt;やりたいことは次の2つです。- 実行ファイル（&lt;code&gt;fizzbuzz.js&lt;/code&gt;）を実行した際には、&lt;code&gt;console.log&lt;/code&gt;の結果を表示したい- 別のファイルから呼ばれた際には、&lt;code&gt;console.log&lt;/code&gt;を表示したくない&lt;/p&gt;
&lt;p&gt;Rubyの場合、以下のように記述することで、そのファイルが直接実行されたときだけ、特定の処理を呼び出すことができます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;if __FILE__ = $PROGRAM_NAME    # 直接呼び出された場合だけ実行したい処理end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;JavaScriptでも同じような処理ができないかと思い、「&lt;strong&gt;FILE&lt;/strong&gt; JavaScript」で検索してみました。&lt;br /&gt;
しかし、JavaScriptの&lt;code&gt;__FILE__&lt;/code&gt;はファイルのJavaScriptを参照し、また&lt;code&gt;$PROGRAM_NAME&lt;/code&gt;に相当するものも見つからなかったため、一度この方向性は断念しました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#fjordbootcamp内で質問してみる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;fjordbootcamp内で質問してみる&lt;/h2&gt;
&lt;p&gt;上記経緯からfjordboocamp内で質問してみたところ、「『Jest console.log』で$1と、&lt;code&gt;console.log&lt;/code&gt;をMock化しろと出ているよ」との声をいただきました。&lt;/p&gt;
&lt;p&gt;先ほどは実行ファイルの方で表示を制御する方法で検討していましたが、テストファイルで表示を制御する方法を提示いただいたわけです。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#jestでconsolelogをmock化してみる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Jestでconsole.logをMock化してみる&lt;/h2&gt;
&lt;p&gt;「Jest console.log」で検索した見つかった、下記記事を参考にMock化を図りました。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/@akameco/jest%E3%81%A7console-log%E3%82%92%E3%83%A2%E3%83%83%E3%82%AF%E3%81%99%E3%82%8B-fd6cd61bf926&quot; target=&quot;_blank&quot;&gt;Jestでconsole.logをモックする. 最近はテストを書くときはほとんどJestを使っています。今回は、v19から導入さ… | by 赤芽 | Medium&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;console.logの結果が残っています。これは、mockObj.mockImplementation(() =&amp;gt; customImplementation) かobject[methodName] = jest.fn(() =&amp;gt; customImplementation) を使うことで上書きできます。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Jestのドキュメント（&lt;a href=&quot;https://jestjs.io/ja/docs/jest-object#jestspyonobject-methodname&quot; target=&quot;_blank&quot;&gt;jest.spyOn&lt;/a&gt;）にも記載されているとおり、以下の記述で&lt;code&gt;console&lt;/code&gt;オブジェクトの&lt;code&gt;log&lt;/code&gt;メソッドを別の処理（&lt;code&gt;x =&amp;gt; x&lt;/code&gt;つまりなにもしない）に置き換えることができます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// consoleオブジェクトのlogメソッドをMock化して、その処理を`x =&amp;gt; x`に置き換えるjest.spyOn(global.console, &apos;log&apos;).mockImplementation(x =&amp;gt; x);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;しかしながら、テスト実行結果には変わらず&lt;code&gt;console.log&lt;/code&gt;の結果が出力されています。&lt;br /&gt;
Mock化とメソッドの上書きが正しく実行されているのか、それとも置き換え対象のメソッドがないのかの切り分けのため、以下のように&lt;code&gt;console.log&lt;/code&gt;が呼ばれたかどうかをテストに追記します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const fizzbuzz = require(&apos;./fizzbuzz&apos;)describe(&apos;FizzBuzz:1~20&apos;, () =&amp;gt; {  test(&apos;3の倍数の場合には「Fizz」を返す&apos;, () =&amp;gt; {    // テスト処理    // 追記箇所：console.logが呼ばれているか確認    expect(console.log).toBeCalled()  })  ...})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;この結果はテスト失敗、つまり&lt;code&gt;console.log&lt;/code&gt;は呼ばれていないこととなり、テストケースで呼ばれていない処理をMock化しても意味がないことがわかりました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#consolelogが何によって実行されているか確認してみる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;console.logが何によって実行されているか確認してみる&lt;/h2&gt;
&lt;p&gt;テストケース内で呼ばれていないことがわかったため、消去法的に実行ファイル&lt;code&gt;fizzbuzz.js&lt;/code&gt;を&lt;code&gt;require&lt;/code&gt;した瞬間に&lt;code&gt;console.log&lt;/code&gt;が実行されていると推測できます。&lt;/p&gt;
&lt;p&gt;（ちょっとここらへんどう検索したか忘れましたが、）実際に&lt;code&gt;require&lt;/code&gt;は実行された瞬間にそのファイルを読み込む仕様とSなっており、これを回避するための策として、以下の手順が書かれている記事をいくつか見つけました。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;if (!module.parent)    // 直接呼び出された時だけ実行される処理end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;module.parent&lt;/code&gt;はrequire元であり、自身がrequireされていれば、falsyになるという仕組みです。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#moduleparentの代替案を探す&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;module.parentの代替案を探す&lt;/h2&gt;
&lt;p&gt;いずれの記事も更新日時が古かったため、Node.jsの公式ドキュメントを確認すると、&lt;code&gt;module.parent&lt;/code&gt;は非推奨となっていました。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Deprecated: Please use require.main and module.children instead.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://nodejs.org/api/modules.html#modules_module_parent&quot; target=&quot;_blank&quot;&gt;Modules: CommonJS modules | Node.js v16.7.0 Documentation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;代わりに&lt;code&gt;require.main&lt;/code&gt;か&lt;code&gt;module.children&lt;/code&gt;を利用するように記載があります。&lt;br /&gt;
&lt;code&gt;require.main&lt;/code&gt;を確認すると、参考リンクに探し求めていた解決方法がありました😄&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When a file is run directly from Node.js, require.main is set to its module.&lt;a href=&quot;https://nodejs.org/api/modules.html#modules_accessing_the_main_module&quot; target=&quot;_blank&quot;&gt;Modules: CommonJS modules | Node.js v16.7.0 Documentation&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;「Node.jsから直接ファイルが実行されると、&lt;code&gt;require.main&lt;/code&gt;には、自身の&lt;code&gt;module&lt;/code&gt;が設定される。」つまり、次のように記述することで要件を満たすことができたのでした。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;if (require.main === module) {    // 直接呼び出された時にだけ実行される処理}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#まとめ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;まとめ&lt;/h2&gt;
&lt;p&gt;Node.jsでファイルが直接実行されているかどうかは、require.main === moduleで判断することができる。 参考：&lt;a href=&quot;https://nodejs.org/api/modules.html#modules_accessing_the_main_module&quot; target=&quot;_blank&quot;&gt;https://nodejs.org/api/modules.html#modules_accessing_the_main_module&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;今回全部調べ終わってから気がついたのですが、「JavaScirpt　直接実行された場合のみ」とか検索すると、日本語記事もいくつかヒットしましたね。しかしながら、非推奨の&lt;code&gt;module.parent&lt;/code&gt;を記載しているものもあったので、自分で調べてみてよかったです。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>【RubyMine】意図しない拡張子でファイルを開いてしまった時に、開く拡張子を変更する</title><link>https://ikuma-t.com/blog/20210811154900/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20210811154900/</guid><description>発端パーフェクトRailsを読みながらRailsの復習をしており、railsdb:migrateした結果を、RubyMineのDatabaseウィンドウで確認しようとしたのですが、誤ってdb/deve</description><pubDate>Wed, 11 Aug 2021 15:49:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#発端&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;発端&lt;/h2&gt;
&lt;p&gt;パーフェクトRailsを読みながらRailsの復習をしており、&lt;code&gt;rails db:migrate&lt;/code&gt;した結果を、RubyMineのDatabaseウィンドウで確認しようとしたのですが、誤って&lt;code&gt;db/development.sqlite3&lt;/code&gt;を「テキストファイル」として開いてしまいました。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210811/20210811153633.png&quot; alt=&quot;f:id:ikmbear:20210811153633p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;そのため、RubyMine上で拡張子が誤認されたファイルを、正しい拡張子に変更する方法を調べてみました。&lt;/p&gt;
&lt;p&gt;なおRubyMineのバージョンは2021.2です。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#結論&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;結論&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Preferences &amp;gt; File Types&lt;/code&gt;から、誤って指定したファイルタイプを選択し、&lt;code&gt;File name pattern&lt;/code&gt;を修正する。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#詳細&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;詳細&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210811/20210811154257.png&quot; alt=&quot;f:id:ikmbear:20210811154257p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Preferencesは、&lt;code&gt;⌘&lt;/code&gt; + &lt;code&gt;,&lt;/code&gt;もしくは、上図の場所から展開できます。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210811/20210811154358.png&quot; alt=&quot;f:id:ikmbear:20210811154358p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Preferencesを開くと、&lt;code&gt;Editor &amp;gt; File Types&lt;/code&gt;という項目があるので、これを選択。&lt;br /&gt;
すると、各拡張子ごとに、「どのようなファイル名であればそのタイプとして認識するか」の一覧が表示されています。&lt;/p&gt;
&lt;p&gt;今回はTextに対して、「.sqlite3」が紐づいてしまったので、これを選択して「-」で削除することで、紐付けを解除できます。&lt;/p&gt;
&lt;p&gt;紐付けが解除されたことで、今回は自動でDBとして再認識され、Databaseウィンドウも無事に開くことができました🎉&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210811/20210811154828.png&quot; alt=&quot;f:id:ikmbear:20210811154828p&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#参考&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;参考&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://pleiades.io/help/ruby/creating-and-registering-file-types.html&quot; target=&quot;_blank&quot;&gt;ファイルタイプの関連付けを設定する | RubyMine&lt;/a&gt;&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>リーダブルコード 第1部を読みました</title><link>https://ikuma-t.com/blog/20210810103733/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20210810103733/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210810/20210810103304.pngリーダブルコード第1</description><pubDate>Tue, 10 Aug 2021 10:37:33 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210810/20210810103304.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210810/20210810103304.png&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#リーダブルコード-第1部を読みました&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;リーダブルコード 第1部を読みました&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210810/20210810103304.png&quot; alt=&quot;f:id:ikmbear:20210810103304p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;名著と名高い、リーダブルコードの第1部を読み終えたので気になった部分をまとめてみました✍️&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.co.jp/dp/4873115655/ref=cm_sw_em_r_mt_dp_CKCCTS6RS380FVEWK26K&quot; target=&quot;_blank&quot;&gt;https://www.amazon.co.jp/dp/4873115655/ref=cm_sw_em_r_mt_dp_CKCCTS6RS380FVEWK26K&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#プログラミングの時間のほとんどはコードを読む時間&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;プログラミングの時間のほとんどはコードを読む時間&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;プログラミングの時間のほとんどはコードを読む時間なのだっ！— p.43&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;第1部では「表面上の改善」と題して、名前やコメントのあるべき姿を述べています。&lt;/p&gt;
&lt;p&gt;本書全体を通して、「理解しやすい」コードを書くためのTipsが散りばめられていますが、なぜ理解しやすいコードが必要なのでしょうか。&lt;/p&gt;
&lt;p&gt;本文の中にもいろいろと書いてあるのですが、個人的に一番ビビッと来たのは冒頭に引用した言葉です。&lt;/p&gt;
&lt;p&gt;SIerで初めてJavaを触った時、プロダクトのコードが全く理解できなくて、既存のコードをずーっと読み続けている時期がありました。読んでいくと次第に法則性がわかるようになってきて、法則性がわかると自分でも書けるようになっていきました。これが私がプログラミングの面白さに触れた原体験の部分であるため、「読む」という部分には強く共感しました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#コードは読むもの求められるのは論理性国語力&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;コードは読むもの→求められるのは論理性・国語力&lt;/h2&gt;
&lt;p&gt;プログラミングというと、どうしても「このメソッドを使うとより短く書ける」「この記法を使うと$1で書ける」といった部分を想起しがちですが、本書第1部で述べられているのはそういった$1なところではなく、もっと$1的な、教科で言えば「国語」的なアプローチです。&lt;/p&gt;
&lt;p&gt;例えば「3章 誤解されない名前」には次のような一節があります。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;名前が「他の意味と間違えられることはないだろうか」と何度も自問自答する— p.30&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;本書では、&lt;code&gt;filter&lt;/code&gt; メソッド名は抽出結果が曖昧である（取り除く対象なのか、取り除かれたものなのか）という例があげられています。&lt;/p&gt;
&lt;p&gt;この問い、つまり「他の意味と間違えられることはないだろうか」について、もう少しどういう考え方が必要か自分なりに考えてみると、「そのメソッドのインプットとアウトプットが、メソッド名で正しく紐づくか」という観点が重要なのではと思いました。&lt;/p&gt;
&lt;p&gt;A→(method)の結果がBに特定できるのであればいいけれど、B以外のCが検討できたり、そもそもBに紐づかないことはNG。A→（method）→Bとなるように因果関係を正しく構築できているかを確認することで、わかりやすいメソッドにできるのではないでしょうか。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210810/20210810103119.png&quot; alt=&quot;f:id:ikmbear:20210810103119p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;これはちょうど学生時代に国語の問題で因果関係が正しくなるように線で結ぶ問題と同じようなものです。プログラミングは論理的思考が求められるといいますが、それはプログラムの流れだけではなくて、名前にも適用されるのかもな〜なんて考えました🤔&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#情報密度の高い言葉を使う&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;情報密度の高い言葉を使う&lt;/h2&gt;
&lt;p&gt;一応コンサルみたいなことやっているので、日常的にカタカナ言葉にさらされているのですが、基本的によく意味を理解せず横文字を連発する人は嫌いです。&lt;/p&gt;
&lt;p&gt;それはさておき、英単語と日本語では厳密なイコールにならないため、英語一単語で複数の日本語を言い表せることもあります。概念的な言葉であれば尚のことです。&lt;/p&gt;
&lt;p&gt;本書ではコメントを圧縮して見やすいものにするために、これらを使うことを提案しています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;どこまでが一般認知とされているか&lt;/li&gt;
&lt;li&gt;対応する単語はどれか、別の捉え方にならないか&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;といった部分を考慮しないといけないので、簡単そうに見えて意外と難しそうなテクニックです。&lt;/p&gt;
&lt;p&gt;これも言葉の言い換えスキルなので、国語力が求められるといっていいのかなと感じました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;プログラミングといえば、$1や$1力などが重要なイメージですが、本書 第1部ではそれよりも論理力・国語力が重要である印象を受けました。&lt;/p&gt;
&lt;p&gt;私は文系かつ就職してからプログラミングに出会った人間なので、いわゆるプログラミング的な素養は乏しいですが、これまで経済・経営（社会科学）に向き合うことで培ってきた姿勢を生かして、リーダブルなコードを書けるように精進していきたいと思います。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>ブログをGatsbyjsに移行.... しかけてやめました</title><link>https://ikuma-t.com/blog/20210809102000/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20210809102000/</guid><description>Gatsbyjsでブログを作ってみました。久々の投稿です。仕事が忙しくてこのブログも学習も放置気味だったのですが、やっと落ち着いてきたので、いろいろ再開しています。実は7月の末あたりからブログを移管し</description><pubDate>Mon, 09 Aug 2021 10:20:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210809/20210809101914.png&quot; alt=&quot;f:id:ikmbear:20210809101914p&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#gatsbyjsでブログを作ってみました&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Gatsbyjsでブログを作ってみました。&lt;/h2&gt;
&lt;p&gt;久々の投稿です。&lt;br /&gt;
仕事が忙しくてこのブログも学習も放置気味だったのですが、やっと落ち着いてきたので、いろいろ再開しています。&lt;/p&gt;
&lt;p&gt;実は7月の末あたりからブログを移管しようと考えていて、実際に以下のGatsbyjsでブログを作成しました。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.work/&quot; target=&quot;_blank&quot;&gt;ikuma-t.work&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;JavaScriptはほとんど触ったことなかったので（もちろんReactも）、表記の仕方にだいぶ苦戦しましたが、なんとか形にはなりました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#seoが貧弱すぎるのでしばらくははてな継続&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;SEOが貧弱すぎるので、しばらくははてな継続&lt;/h2&gt;
&lt;p&gt;独自ドメインを取得して公開してみたはいいんですが、びっくりするほど検索に引っかからないです。&lt;/p&gt;
&lt;p&gt;今回ネットで検索してみて初めて分かったんですが、世の中には結構な数の「ikuma」さんがいました🐻なので「ikuma-t ブログ」なんて大きなキーワード検索しても辿りつかないわけです。&lt;/p&gt;
&lt;p&gt;必要最低限のmetaタグは設定こそすれど、SEOについてはいろいろと考えることが多そうなので、一旦メインブログはこのはてなブログで継続していくつもりです。（どちらもmarkdown形式で記述できるので、しばらくは両方に同時投稿するかもです）。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://ikuma-t.work/post/gatsbyjs-blog/&quot; target=&quot;_blank&quot;&gt;ikuma-t.work&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;👆この記事は嘘ですね笑&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#自分でブログを作ってみて思ったこと&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;自分でブログを作ってみて思ったこと&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#よかったこと&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;よかったこと&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;「Gatsbyjs使いたい！」という気持ちに一区切りついた&lt;/li&gt;
&lt;li&gt;JavaScriptへの耐性が少しついた（ブログ作るために、少しJS Primerとかかじったので）&lt;/li&gt;
&lt;li&gt;自分でデザインを考えられるので自由度が恐ろしく高い。&lt;/li&gt;
&lt;li&gt;HTML、CSSの復習ができる&lt;/li&gt;
&lt;li&gt;ブログサービスではなかった、デプロイ、ドメイン取得、meta設定などを体験することができた&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#微妙だったこと&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;微妙だったこと&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;タグ機能とか、Twitter用カード設定とか、ブログで必要そうなことも基本的には自前でやらないといけない&lt;/li&gt;
&lt;li&gt;SEO対策を自分でやらないといけない（これははてなでも同じだとは思いますが、もっと根本的なところからという意味で）&lt;/li&gt;
&lt;li&gt;絶妙に情報が少ないので（自分はCMSにContentfulを使用していますが、こちらの情報が少ない）、調べるのに苦労する&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;今後もこのブログではやってみたこと・学んだことをアウトプットしていきますので、よろしくお願い致します〜😊&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Gatsbyjsで作成したブログのTwitterCardを表示させる</title><link>https://ikuma-t.com/blog/gatsyby-twitter-card/</link><guid isPermaLink="true">https://ikuma-t.com/blog/gatsyby-twitter-card/</guid><description>問題CardValidator|TwitterDevelopersブログを作ってみたはいいんですが、投稿があるたびにTwitterで共有しようにもTwitterCard（OGP画像）が表示されずに困っ</description><pubDate>Fri, 06 Aug 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#問題&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題&lt;div&gt;&lt;/div&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://cards-dev.twitter.com/validator&quot; target=&quot;_blank&quot;&gt;Card Validator | Twitter Developers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ブログを作ってみたはいいんですが、投稿があるたびにTwitterで共有しようにもTwitterCard（OGP画像）が表示されずに困っていました.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;//images.contentful.com/ojolxk47aqpx/2NDvXseGewUwdYem3AYzqO/56cf35b59e27f3e11752c17c605e10f0/twitter-card-error.png&quot; alt=&quot;twitter-card-error&quot; /&gt;&lt;/p&gt;
&lt;p&gt;そこで今回はこのエラーの原因を突き止め、TwitterCardが表示されるようにしてみました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#tl&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;TL&lt;div&gt;&lt;/div&gt;;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;プラグイン&lt;code&gt;gatsby-react-helmet&lt;/code&gt;が追加・設定されていなかったことが原因&lt;/li&gt;
&lt;li&gt;Developer　Toolで確認するとmetaタグがあるように見えても、実際にビルドされたHTMLを確認して、必要なmetaタグが追加されているか確認することが大事&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#調査&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;調査&lt;/h2&gt;
&lt;p&gt;まずは次のような調査方針で進めてみました。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;TwitterCardが表示される仕組みを調べる&lt;/li&gt;
&lt;li&gt;1と現状のサイトを比較し、足りていない要素を調べ、追加する&lt;/li&gt;
&lt;li&gt;2で表示されなければ、調査方針再検討&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;&lt;a href=&quot;#twittercardが表示される仕組み&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;TwitterCardが表示される仕組み&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.twitter.com/ja/docs/tweets/optimize-with-cards/guides/getting-started&quot; target=&quot;_blank&quot;&gt;カードの利用開始&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://saruwakakun.com/html-css/reference/twitter-card&quot; target=&quot;_blank&quot;&gt;【2020年版】Twitterカードとは？使い方と設定方法まとめ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これらの記事を確認する限り、TwitterCardを表示するために必要なことは、以下のmetaデータを設定することのようです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;meta&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;twitter:card&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;content&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;カード種類&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt; &lt;/span&gt;&lt;span&gt;&amp;lt;!--①--&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;meta&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;twitter:site&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;content&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;@ユーザー名&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt; &lt;/span&gt;&lt;span&gt;&amp;lt;!--②--&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;meta&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;og:url&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;content&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;記事のURL&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt; &lt;/span&gt;&lt;span&gt;&amp;lt;!--③--&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;meta&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;og:title&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;content&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;記事のタイトル&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt; &lt;/span&gt;&lt;span&gt;&amp;lt;!--④--&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;meta&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;og:description&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;content&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;記事の要約（ディスクリプション）&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt; &lt;/span&gt;&lt;span&gt;&amp;lt;!--⑤--&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;meta&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;og:image&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;content&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;画像のURL&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt; &lt;/span&gt;&lt;span&gt;&amp;lt;!--⑥--&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#現状のサイトと比較&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;現状のサイトと比較&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;//images.contentful.com/ojolxk47aqpx/28QeOUSzT5zp1t7HFw0yXP/e9fc452813ba58bdf4f34dbe5bf9ef0c/meta-when-error.png&quot; alt=&quot;meta-when-error&quot; /&gt;&lt;/p&gt;
&lt;p&gt;確認したところ、エラー発生時には、次の3つのmetaデータがありませんでした。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;meta&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;twitter:site&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;content&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;@ユーザー名&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt; &lt;/span&gt;&lt;span&gt;&amp;lt;!--②--&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;meta&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;og:url&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;content&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;記事のURL&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt; &lt;/span&gt;&lt;span&gt;&amp;lt;!--③--&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;meta&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;og:image&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;content&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;画像のURL&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt; &lt;/span&gt;&lt;span&gt;&amp;lt;!--⑥--&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Twitter特有のmetaとしては、&lt;code&gt;twitter:site&lt;/code&gt;がもっとも怪しそうなので、まずはこちらを追加してみます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;`twitter:card`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;content&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;`summary_large_image`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;`twitter:site`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;content&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;`@ikumatdkr`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;//images.ctfassets.net/ojolxk47aqpx/2NDvXseGewUwdYem3AYzqO/56cf35b59e27f3e11752c17c605e10f0/twitter-card-error.png&quot; alt=&quot;twitter-card-error&quot; /&gt;&lt;/p&gt;
&lt;p&gt;なおも失敗してしまったので、&lt;code&gt;og:url&lt;/code&gt;を追加してみます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;`og:url`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;content&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;`https://ikuma-t.work/`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;//images.ctfassets.net/ojolxk47aqpx/2NDvXseGewUwdYem3AYzqO/56cf35b59e27f3e11752c17c605e10f0/twitter-card-error.png&quot; alt=&quot;twitter-card-error&quot; /&gt;&lt;/p&gt;
&lt;p&gt;またもや失敗してしまいました。エラーメッセージが変わらないのが気になるところです🤔&lt;/p&gt;
&lt;p&gt;最後に、まだ不足している&lt;code&gt;og:image&lt;/code&gt;を追加します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;`og:image`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;content&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;`https://ikuma-t.work/static/logo.png`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;//images.ctfassets.net/ojolxk47aqpx/2NDvXseGewUwdYem3AYzqO/56cf35b59e27f3e11752c17c605e10f0/twitter-card-error.png&quot; alt=&quot;twitter-card-error&quot; /&gt;&lt;/p&gt;
&lt;p&gt;エラーメッセージ含めて、何も解消されません。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#方針再設定&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;方針再設定&lt;/h2&gt;
&lt;p&gt;設定をしたにもかかわらず、Card Validatorが表示するメッセージが変わらないことを考慮すると、どうやら別のところに原因がありそうです。&lt;/p&gt;
&lt;p&gt;しかも登録しているmetaタグはいくつもあるのに&lt;code&gt;4 metatags were found&lt;/code&gt;としか表示されないことを考えると、次の2つの可能性が考えられます。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;metaタグが実際には生成されていない&lt;/li&gt;
&lt;li&gt;metaタグが生成されてはいるが、読み取られていない&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;まずは1つ目について確認してみることにしました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#生成されたmetaタグを確認する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;生成されたmetaタグを確認する&lt;/h3&gt;
&lt;p&gt;ここまではChrome Developer Toolで確認してきましたが、実際に&lt;code&gt;gatsby build&lt;/code&gt;によって生成されたhtmlがどうなっているかを確認してみます。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;//images.contentful.com/ojolxk47aqpx/6PXrmTdY02V9kcfbRUiem0/ffec97f19de0fa484fa20e58d2dee2d0/build-meta-when-error.png&quot; alt=&quot;build-meta-when-error&quot; /&gt;&lt;/p&gt;
&lt;p&gt;すると、metaタグに相当するのは4件のみで、Twitter関連で設定した内容は全く反映されていません。&lt;/p&gt;
&lt;p&gt;どうやらここが怪しそうです。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#gatsby-react-helmetが正しく機能しているかを確認&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;gatsby-react-helmetが正しく機能しているかを確認&lt;/h3&gt;
&lt;p&gt;メタデータを追加するために、&lt;code&gt;react-helmet&lt;/code&gt;を使用しているのですが、Gatsbyjsで使用するためには&lt;code&gt;gatsby-react-helmet&lt;/code&gt;も必要です。&lt;/p&gt;
&lt;p&gt;つまり、以下のような実際にmetaタグを定義するコンポーネントだけではNGで&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { Helmet } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;react-helmet&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Seo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Helmet&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;/* meta情報を記述 */&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;Helmet&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;それを使用する前提として、プラグインを追加し、&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;yarn&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;gatsby-plugin-react-helmet&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;react-helmet&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;それを&lt;code&gt;gatsby-config.js&lt;/code&gt;で宣言しておく必要があるのです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;plugins&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;`gatsby-plugin-react-helmet`&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://www.gatsbyjs.com/plugins/gatsby-plugin-react-helmet/&quot; target=&quot;_blank&quot;&gt;gatsby-plugin-react-helmet&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;…確認してみたところ、プラグインの追加と宣言が漏れていました。&lt;/p&gt;
&lt;p&gt;そのため上記設定を施し、再度&lt;code&gt;gatsby build&lt;/code&gt;を実行すると、ビルド結果のHTMLにmetaタグが追加されていました。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;//images.contentful.com/ojolxk47aqpx/6NuFsKszegEdfef8kp05Vv/27ee436926409889c701b5332b40d0f5/meta-when-succeed.png&quot; alt=&quot;meta-when-succeed&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Developer Toolでの確認結果も、metaタグが上位に表示されるようになり、&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;//images.contentful.com/ojolxk47aqpx/2K7tzy9Bp13TKnFdPwsKj2/c1637ae3a112b128678c56bbcd60e5e3/card-succeed.png&quot; alt=&quot;card-succeed&quot; /&gt;&lt;/p&gt;
&lt;p&gt;metaタグも読み取られ、Twitter Cardが表示されるようになりました。&lt;/p&gt;
&lt;p&gt;ついでに各記事ページごとにヒーローイメージを取得するように設定して、本件は任務完了です🥷
&lt;img src=&quot;//images.contentful.com/ojolxk47aqpx/25S7ZIGlJxv1Cr6tH2q8S6/940f89d1dd0207a4396d1f1ababd9f7f/ogimage-by-page.png&quot; alt=&quot;ogimage-by-page&quot; /&gt;&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>キーキャップをマンチェスターシティ色に替えてみた</title><link>https://ikuma-t.com/blog/change-keycap/</link><guid isPermaLink="true">https://ikuma-t.com/blog/change-keycap/</guid><description>キーボードへの情熱の高まり先日日暮里散策をしている際に、秋葉原まで足をのばして遊舎工房さんにたちよったのですが、その際にど〜〜しても新しいキーボードが欲しくなってしまいました。しかしながら、愛機Maj</description><pubDate>Tue, 03 Aug 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#キーボードへの情熱の高まり&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;キーボードへの情熱の高まり&lt;/h2&gt;
&lt;p&gt;先日日暮里散策をしている際に、秋葉原まで足をのばして&lt;a href=&quot;https://yushakobo.jp/&quot; target=&quot;_blank&quot;&gt;遊舎工房&lt;/a&gt;さんにたちよったのですが、その際にど〜〜しても新しいキーボードが欲しくなってしまいました。&lt;/p&gt;
&lt;p&gt;しかしながら、愛機Majestouch2はまだまだ現役、新しいものを買っても使用用途が複数あるわけでもないので、今回はキーキャップを変更することで、気分一新することに。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#ダイヤテックのオフィシャルサイトでキーキャップを購入&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ダイヤテックのオフィシャルサイトでキーキャップを購入&lt;/h2&gt;
&lt;p&gt;あまりキーボード界隈には明るくなく、購入したキーキャップがはまらないという可能性も考えられたので、今回はMajestouchの販売元であるダイヤテックさんのオフィシャルサイトでキーキャップを購入することにしました！&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.diatec.co.jp/products/keycap/&quot; target=&quot;_blank&quot;&gt;キーキャップの一覧 FILCO取り扱いキーキャップ | ダイヤテック株式会社&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;もともとのキーキャップは日本語配列かつ、かな文字印字タイプだったのですが、かな文字は不要なので、日本語配列かな文字なしから選択し、以下の４つの商品を購入。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.diatec.co.jp/shop/det.php?prod_c=1837&quot; target=&quot;_blank&quot;&gt;Majestouch 交換用キーキャップセット 日本語108キー・かななし 購入ページ | ダイヤテック株式会社&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.diatec.co.jp/shop/det.php?prod_c=4130&quot; target=&quot;_blank&quot;&gt;【通販限定】Majestouch 交換用カラーキーキャップセット 日本語108キー・かななし・ミルキーブルー 購入ページ | ダイヤテック株式会社&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.diatec.co.jp/shop/det.php?prod_c=4905&quot; target=&quot;_blank&quot;&gt;漆塗りキーキャップセット 銀河 購入ページ | ダイヤテック株式会社&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.diatec.co.jp/shop/det.php?prod_c=3254&quot; target=&quot;_blank&quot;&gt;【直販限定】Majestouch用　フラッグキーキャップ　『イギリス(Tabキー用)』 購入ページ | ダイヤテック株式会社&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;トータルで7000円くらいしました…💸&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;//images.contentful.com/ojolxk47aqpx/4KQftw8WarWKxOgjdst0hU/6462570a27f63345e1ecad4ff4de476d/keycap-2021.jpg&quot; alt=&quot;keycap-2021&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#いざ入れ替え作業へ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;いざ入れ替え作業へ&lt;/h2&gt;
&lt;p&gt;…といっても、キーキャップをとって、新しいものをはめるだけなので作業的には特に難しいことはないですが、今回は自分で配色をミックスするので、どんな色配置にするかが悩みどころでした。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;//images.contentful.com/ojolxk47aqpx/6Bg8f3ARVUI8mI55eRVyjq/d1f4ce79d9d7bc361ada8a1da808a2b0/keychrone.jpeg&quot; alt=&quot;keychrone&quot; /&gt;&lt;/p&gt;
&lt;p&gt;もともとkeychronのキーボードを購入しようと思っていたのですが、試し打ちしたところキーストロークが意外と浅かったので断念した経緯もあり、EscとBackSpaceは色を変えたいというイメージがありました。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;//images.contentful.com/ojolxk47aqpx/7DDP5wlhhbfdLq3tGi6aaj/fadac2c1077e52bfe5d062ce89b76dd6/iq-f96-color-coralsea-01.jpeg&quot; alt=&quot;iq-f96-color-coralsea-01&quot; /&gt;&lt;/p&gt;
&lt;p&gt;あわせてデザイン的に気に入っていたiqunixを参考に、文字部分と特殊キーの色は変えるイメージでキーキャップ入れ替えを実施しました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#完成&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;完成！！&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;//images.ctfassets.net/ojolxk47aqpx/71xx3qzdAJGvUmFi4amYFX/f11f2a9a441274909068f918f2bef5fb/keyboard-after-2021.jpg&quot; alt=&quot;keyboard-after-2021&quot; /&gt;&lt;/p&gt;
&lt;p&gt;できたのがこちら！文字部分を水色、それ以外を黒としながら、Tabキーと使用しないPrintScreen等を漆塗りのキーキャップにしてみました。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;//images.contentful.com/ojolxk47aqpx/5wocF1prJweoDSGUoLdAUe/49dac7a3c7be9224c671255b1c0e07cf/urushi-keycap.jpg&quot; alt=&quot;urushi-keycap&quot; /&gt;&lt;/p&gt;
&lt;p&gt;替えて数時間後にこのブログ書いてますが、ここの3つのキーはそもそも何だったか忘れました。
WindowsでOfficeソフトの作業する際にたまに使えるんですが、ほぼ使えないので、ここは飾り枠です。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;//images.contentful.com/ojolxk47aqpx/20MDQwEaNqZkDzQMOXXfcE/90c7fd05cd9dfaae61acc6afbdf6b6d9/esc.jpg&quot; alt=&quot;esc&quot; /&gt;&lt;/p&gt;
&lt;p&gt;BackSpaceもアクセントカラーになっていて、いい感じです😊&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;イギリスのキーキャップ、水色…図らずもマンチェスターシティみたいなキーボードになっちまいました。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;//images.contentful.com/ojolxk47aqpx/3OI2iAoRmj17818AsiDZ28/76c1570fbdbc628a9caec4d9b17a1ad2/city.jpeg&quot; alt=&quot;city&quot; /&gt;&lt;/p&gt;
&lt;p&gt;それはさておき、自分で色を決めて配置したことでよりキーボードに愛着が湧いてきました！これからもMajestouch2でスコスコしていきたいと思います💪&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>独習Gitを読んでみた</title><link>https://ikuma-t.com/blog/dokusyu-git/</link><guid isPermaLink="true">https://ikuma-t.com/blog/dokusyu-git/</guid><description>GUIに頼りきりでGitコマンドうろ覚えRubyMineを使っていると、Git操作はGUIで完結してしまい、ちょっとコマンドが覚えづらいというデメリットがあります（コマンドの概念と便利さを知る分には十</description><pubDate>Sun, 01 Aug 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#guiに頼りきりでgitコマンドうろ覚え&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;GUIに頼りきりでGitコマンドうろ覚え&lt;/h2&gt;
&lt;p&gt;RubyMineを使っていると、Git操作はGUIで完結してしまい、ちょっとコマンドが覚えづらいというデメリットがあります（コマンドの概念と便利さを知る分には十分有用です）。&lt;/p&gt;
&lt;p&gt;もちろん&lt;code&gt;git add&lt;/code&gt;、&lt;code&gt;git commit&lt;/code&gt;といった基本的なコマンドは使えますが、「差分コミットしたい」「一部だけステージから下ろしたい」など、イレギュラー操作はちょっとしたところでもコマンドでやろうとするとググらないといけないレベルです。&lt;/p&gt;
&lt;p&gt;そのため、この度独習Gitを購入し、コマンドの習得に励んでみました💪&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;//images.ctfassets.net/ojolxk47aqpx/4fVEbSzC7mEh0o6X16U4Be/fd3d3fff0ccd4868f40ca3de84d265d4/dokusyu-git.png&quot; alt=&quot;dokusyu-git&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.shoeisha.co.jp/book/detail/9784798144610&quot; target=&quot;_blank&quot;&gt;独習Git（リック・ウマリ 吉川 邦夫）｜翔泳社の本&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#学習方針&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;学習方針&lt;/h2&gt;
&lt;p&gt;先に述べたようにGitコマンド全部がわからないわけではないので、本書に登場する未知（or既知だけれども習熟していない）コマンドだけを、各章にある「この章のコマンド」ページから抜粋します。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#学習内容&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;学習内容&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#3章gitに馴染む&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;3章：Gitに馴染む&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;git config --list&lt;/code&gt;(ショートハンドは&lt;code&gt;-l&lt;/code&gt;)：すべてのGitの設定値を表示。エイリアスの設定値を確認するのにたまに使うけど、オプションを忘れがち。&lt;code&gt;git config&lt;/code&gt;だけ実行すると、usageが表示されるので、そこから再実行するのもよし。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#4章リポジトリの作り方と使い方&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;4章：リポジトリの作り方と使い方&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;git ls-files&lt;/code&gt;：リポジトリにあるファイルをリスト表示する。使い所あるかなあ。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#6章ファイルの追跡と更新&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;6章：ファイルの追跡と更新&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;git commit -a -m &quot;Message&quot;&lt;/code&gt;：git addとcommitを同時に実行する。&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;git&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;commit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--help&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;#&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;-a,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--all&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;           &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Tell&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;the&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;command&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;automatically&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;stage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;files&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;that&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;have&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;been&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;modified&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;and&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;deleted,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;but&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;files&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;you&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;have&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;not&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;told&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Git&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;about&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;are&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;not&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;affected.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;aオプションはallオプションのショートハンドで、変更があったファイルを自動的に追随するようにする内容見たいです。これは結構使い所が多そう。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;git log --shortstat --oneline&lt;/code&gt;：オプション重ねがけ。&lt;code&gt;--shortstat&lt;/code&gt;は各コミットで変更されたファイルのリストを一行で表示し、&lt;code&gt;--oneline&lt;/code&gt;はコミット自体を一行で表示する&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git add {-n | --dry-run} &amp;lt;変更対象&amp;gt;&lt;/code&gt;：&lt;code&gt;git add &amp;lt;変更対象&amp;gt;&lt;/code&gt;を実行した際に、どう言ったステージングが実施されるかを表示する。実際にはステージングはされない。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git diff&lt;/code&gt;、&lt;code&gt;git diff --staged&lt;/code&gt;：GUIでやっているとつい忘れがち。前者が作業ツリーとステージングエリアの差分、後者がステージングエリアとリポジトリとの差分を表示する&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#7章変更箇所をコミットする&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;7章：変更箇所をコミットする&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;git rm &amp;lt;ファイル名&amp;gt;&lt;/code&gt;：ステージングエリアからファイルを削除する。作業ツリーに対して削除を実施した場合、それをステージングエリアに反映する必要があるが、このコマンドの場合、直接ステージングエリアのファイルを削除できる。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git add -p&lt;/code&gt;：部分的なステージングを実行する。コマンドを実行すると、ステージング対象のハンク（一塊）が、順番に表示される。それぞれに対して、以下のいずれかを指定する。&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;Stage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hunk&lt;/span&gt;&lt;span&gt; [y,n,q,a,d,K,g,/,e,?]&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;stage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hunk&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;do&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;not&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;stage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hunk&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;q&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;quit&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;do&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;not&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;stage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hunk&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;or&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;of&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;the&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;remaining&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ones&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;stage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hunk&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;and&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;all&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;later&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hunks&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;the&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;d&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;do&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;not&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;stage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hunk&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;or&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;any&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;of&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;the&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;later&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hunks&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;the&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hunk&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;go&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;search&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hunk&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;matching&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;the&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;given&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;regex&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;leave&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hunk&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;undecided,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;see&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;previous&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hunk&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;manually&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;edit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;the&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;current&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hunk&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; - print help&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;※続きは随時更新&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Exercism(Ruby)で学んだこと</title><link>https://ikuma-t.com/blog/exercism-ruby/</link><guid isPermaLink="true">https://ikuma-t.com/blog/exercism-ruby/</guid><description>ExercismとはExercismは、無料でできるプログラミング練習問題サイトです。言語ごとに100種類近い練習問題が用意されており、ちょっとした文法の練習に最適です。（文法だけ読んでると退屈なので</description><pubDate>Sun, 01 Aug 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#exercismとは&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Exercismとは&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://exercism.io&quot; target=&quot;_blank&quot;&gt;Exercism&lt;/a&gt;は、無料でできるプログラミング練習問題サイトです。
言語ごとに100種類近い練習問題が用意されており、ちょっとした文法の練習に最適です。
（文法だけ読んでると退屈なので、これで遊んで覚えます）&lt;/p&gt;
&lt;p&gt;Exercismでの問題を解く流れは次の通りです。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;練習問題をコピー&lt;/li&gt;
&lt;li&gt;自分で解く&lt;/li&gt;
&lt;li&gt;提出&lt;/li&gt;
&lt;li&gt;他の人の回答が見られたり、レビューを受けられたりする&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;今回Rubyが久々ということもあって、人の回答を見る中で「そういうのもあるんか！」と思ったものが多々ありました。そこで、個人的に気になったものを随時この記事にまとめていこうと思います。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#学んだこと&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;学んだこと&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#integerdigits&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Integer#digits&lt;/h3&gt;
&lt;p&gt;登場回：Armstrong Numbers&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;base を基数として self を位取り記数法で表記した数値を配列で返します。 base を指定しない場合の基数は 10 です。&lt;a href=&quot;https://docs.ruby-lang.org/ja/latest/class/Integer.html#I_DIGITS&quot; target=&quot;_blank&quot;&gt;class Integer (Ruby 3.0.0 リファレンスマニュアル)&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://ja.wikipedia.org/wiki/%E3%83%8A%E3%83%AB%E3%82%B7%E3%82%B7%E3%82%B9%E3%83%88%E6%95%B0&quot; target=&quot;_blank&quot;&gt;ナルシシスト数&lt;/a&gt;の導出のために、与えられた数値を桁ごとに区切る必要があったのですが、自分の回答では、以下のように一旦文字列に置換してから分割処理を実施していました。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;irb&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;153&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;to_s&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;chars&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;#=&amp;gt;[&quot;1&quot;, &quot;5&quot;, &quot;3&quot;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;Integer#digits&lt;/code&gt;であれば文字列を介さずに、分割することが可能でした。ただし、1のくらいから順に格納されるので、中身は同じですが、順番が異なる配列が完成することに注意です。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;irb&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;153&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;digits&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;#=&amp;gt; [3, 5, 1]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#冪乗のe&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;冪乗の&lt;code&gt;e&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;登場回：Gigasecond&lt;/p&gt;
&lt;p&gt;これはRubyというよりも数学的なところですが、10の冪乗は&lt;code&gt;e&lt;/code&gt;を使っても表せるようです。
浮動小数点になることに注意が必要ですね。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;irb&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1e9&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;#=&amp;gt; 1000000000.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;参考&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://ja.wikipedia.org/wiki/%E6%8C%87%E6%95%B0%E8%A1%A8%E8%A8%98&quot; target=&quot;_blank&quot;&gt;指数表記 - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.ruby-lang.org/ja/latest/doc/spec=2fliteral.html&quot; target=&quot;_blank&quot;&gt;リテラル (Ruby 3.0.0 リファレンスマニュアル)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#rubyで等比数列&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Rubyで等比数列&lt;/h3&gt;
&lt;p&gt;登場回：Grain&lt;/p&gt;
&lt;p&gt;Rubyで等比数列を作る場合、以下のように記述できるようです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;geometric.rb&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# num: 初項&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# ratio: 公比&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# length: 数列の長さ&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;geometric_sequence&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;num&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ratio&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;Array&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;(length) { &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; num &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; ratio&lt;/span&gt;&lt;span&gt;**&lt;/span&gt;&lt;span&gt;n }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;参考：&lt;a href=&quot;https://qiita.com/kou_pg_0131/items/4b0700fba9c56b0cf159#%E7%AD%89%E6%AF%94%E6%95%B0%E5%88%97&quot; target=&quot;_blank&quot;&gt;【Ruby】等差数列・等比数列を作成する１番シンプルな処理 - Qiita&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;余談：このGrainという問題は、「&lt;a href=&quot;https://en.wikipedia.org/wiki/Wheat_and_chessboard_problem&quot; target=&quot;_blank&quot;&gt;Wheat and chessboard problem&lt;/a&gt;」といって、歴史ある数学的問題のようです。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>ブログをGatsbyjsに移行しました</title><link>https://ikuma-t.com/blog/gatsbyjs-blog/</link><guid isPermaLink="true">https://ikuma-t.com/blog/gatsbyjs-blog/</guid><description>はてなブログから乗り換えましたもともとセットプチフォッカというブログをはてなブログでやっていたのですが、Gatsbyjsでブログを作ってみたかったのと、独自ドメインで運営したかったので、この度ブログを</description><pubDate>Sun, 01 Aug 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#はてなブログから乗り換えました&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;はてなブログから乗り換えました&lt;/h2&gt;
&lt;p&gt;もともと&lt;a href=&quot;https://ikmbear.hatenablog.com/&quot; target=&quot;_blank&quot;&gt;セットプチフォッカ&lt;/a&gt;というブログをはてなブログでやっていたのですが、Gatsbyjsでブログを作ってみたかったのと、独自ドメインで運営したかったので、この度ブログを作り替えました。&lt;/p&gt;
&lt;p&gt;制作にあたっては、&lt;a href=&quot;https://zenn.dev/tomokiya/books/4b13342f6d878b93e06c&quot; target=&quot;_blank&quot;&gt;Gatsby入門&lt;/a&gt;を参照しました。
いまのところ、デザインも機能もここに記載の通りなので、徐々に拡張していきたいと思います。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>RubyMineのショートカット</title><link>https://ikuma-t.com/blog/rubymine-essential-shorcut/</link><guid isPermaLink="true">https://ikuma-t.com/blog/rubymine-essential-shorcut/</guid><description>だめだ…RubyMineのことが思い出せないどうもikuma-tです。仕事が忙しかった関係で、3ヶ月くらいRubyを触っていなかったのですが、それに伴いRubyMineのショートカットを半分くらい忘れ</description><pubDate>Sun, 01 Aug 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#だめだrubymineのことが思い出せない&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;だめだ…RubyMineのことが思い出せない&lt;/h2&gt;
&lt;p&gt;どうもikuma-tです。
仕事が忙しかった関係で、3ヶ月くらいRubyを触っていなかったのですが、それに伴いRubyMineのショートカットを半分くらい忘れました😅&lt;/p&gt;
&lt;p&gt;ここ1週間くらいは、このブログを立ち上げるためにJavaScriptとHTMLとCSSを触ってはいたのですが、なにせVSCodeでやってしまったもので、VSCodeのショートカットが馴染んでしまい、RubyMineで動かしても「あれ、動かない…」&lt;/p&gt;
&lt;p&gt;そんなわけで、次忘れた時のために、最低限覚えておきたいキーボードショートカットを書いておきます。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#前提&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;前提&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;RubyMine：2021.02&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#ショートカット&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ショートカット&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;行削除：&lt;code&gt;⌘&lt;/code&gt;+&lt;code&gt;⌫&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;新規行を追加：&lt;code&gt;⇧&lt;/code&gt;+&lt;code&gt;Enter&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;ターミナルを開く：&lt;code&gt;⌥&lt;/code&gt;+&lt;code&gt;F12&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;指定したファイルを分割ウィンドウで開く：ファイルを指定した状態で、&lt;code&gt;⇧&lt;/code&gt;+&lt;code&gt;Enter&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;選択行を上下に移動：&lt;code&gt;⌥&lt;/code&gt;+&lt;code&gt;⇧&lt;/code&gt;+&lt;code&gt;↓&lt;/code&gt;or&lt;code&gt;↑&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;リファクタリングのコンテキストメニューを開く：&lt;code&gt;Ctrl&lt;/code&gt;+&lt;code&gt;T&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;大文字小文字の切り替え：&lt;code&gt;⌘&lt;/code&gt;+&lt;code&gt;⇧&lt;/code&gt;+&lt;code&gt;u&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;キャメルケース等の切り替え：&lt;code&gt;⌥&lt;/code&gt;+&lt;code&gt;⇧&lt;/code&gt;+&lt;code&gt;u&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#参考&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;参考&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://pleiades.io/help/ruby/installation-guide.html&quot; target=&quot;_blank&quot;&gt;RubyMine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://qiita.com/yoppe/items/f7cbeb825c071691d3f2#-%E9%81%B8%E6%8A%9E%E8%A1%8C%E3%82%92%E4%B8%8A%E4%B8%8B%E3%81%AB%E7%A7%BB%E5%8B%95move-line-upmove-line-down&quot; target=&quot;_blank&quot;&gt;忙しい人のためのIntelliJ IDEAショートカット集（´-`） - Qiita&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>ikuma-t</author></item><item><title>日暮里で散策</title><link>https://ikuma-t.com/blog/shopping-at-nippori/</link><guid isPermaLink="true">https://ikuma-t.com/blog/shopping-at-nippori/</guid><description>日暮里で散策今日は天気も良かったので、日暮里周辺にちょっとお散歩に出かけてきました。日暮里駅の駅舎は古き良き町並みにあう景観になっていました。日暮里駅の文字がねこになっているのが可愛らしい😸TAYO</description><pubDate>Sun, 01 Aug 2021 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#日暮里で散策&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;日暮里で散策&lt;/h2&gt;
&lt;p&gt;今日は天気も良かったので、日暮里周辺にちょっとお散歩に出かけてきました。
&lt;img src=&quot;//images.contentful.com/ojolxk47aqpx/5Z3OewImZNxrIQbYUheHHV/aa2038831729391d2b7aa3b6e12f74b9/nippori-station.jpg&quot; alt=&quot;nippori-station&quot; /&gt;&lt;/p&gt;
&lt;p&gt;日暮里駅の駅舎は古き良き町並みにあう景観になっていました。日暮里駅の文字がねこになっているのが可愛らしい😸&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#tayoriでお昼&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;TAYORIでお昼&lt;/h2&gt;
&lt;p&gt;お昼は気になっていたTAYORI(&lt;a href=&quot;https://tayori.info/&quot; target=&quot;_blank&quot;&gt;食の郵便局TAYORI – 食の郵便局です。&lt;/a&gt;）というお店へ。&lt;/p&gt;
&lt;p&gt;ランチは5種類くらいから選べるんですが、今回は今週の日替わり=白身魚の唐揚げ定食に！&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;//images.ctfassets.net/ojolxk47aqpx/3qNWP4tjfVsV49A5RNuyNn/bfbb8cb0bed7cd999fa64ed4e09284ba/tayori-lunch.jpg&quot; alt=&quot;tayori-lunch&quot; /&gt;&lt;/p&gt;
&lt;p&gt;白身魚はとてもふわふわで、全体的に薄味ながらもしっかりと旨みを感じる料理で大満足でした👍&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#mother-houseでマネークリップ購入&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;MOTHER HOUSEでマネークリップ購入&lt;/h2&gt;
&lt;p&gt;お昼を食べて路地へ。「そういえば薄い財布買うと言っておきながら、全然買ってないね」なんて妻と話していると、商店街のMOTHER　HOUSEというお店が目に飛び込んできました。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://shop.mother-house.jp/category/ANTIQUE/&quot; target=&quot;_blank&quot;&gt;マザーハウス｜MOTHERHOUSE&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;「お、ちょうどマネークリップあるじゃん！」&lt;/p&gt;
&lt;p&gt;と興奮気味にマネークリップを物色し、5分ほどで購入決定。革でありながら、価格帯も1万円台とお求め安く、いい買い物ができました。&lt;img src=&quot;//images.contentful.com/ojolxk47aqpx/2WKHiSV7qjU80YWPKR18Gq/29dcdd04e9d062855f161e2b7833b922/mother-house-wallet.jpg&quot; alt=&quot;mother-house-wallet&quot; /&gt;&lt;/p&gt;
&lt;p&gt;なんか保護クリーム的なものを塗ってもらったので、2日間くらい休ませてから実際に使用です！楽しみ〜😄&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわり&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわり&lt;/h2&gt;
&lt;p&gt;まあこのあともフィルムカメラみたい、キーボード見に行ったりしたんですが、全部写真撮り忘れましたので割愛です😅&lt;/p&gt;
&lt;p&gt;散財こそすれど、出かけて、いろんな商店を覗いたことで世界が広がった1日でした。また日暮里散策したいです。&lt;/p&gt;
&lt;p&gt;おわり&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>うちNotion</title><link>https://ikuma-t.com/blog/20210223120727/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20210223120727/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210223/20210223123237.pngNotionいいよね</description><pubDate>Fri, 07 May 2021 18:10:27 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210223/20210223123237.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210223/20210223123237.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210223/20210223123237.png&quot; alt=&quot;f:id:ikmbear:20210223123237p&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#notionいいよね&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Notionいいよね&lt;/h2&gt;
&lt;p&gt;Notionいいですよね。日本でも最近かなりアツいプロダクトとなっていて、企業でも使われるケースが増えてきています。&lt;/p&gt;
&lt;p&gt;私も結構前からNotionを利用していて、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;個人用のNotion（ぼくNotion）&lt;/li&gt;
&lt;li&gt;家庭用のNotion（うちNotion）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;と用途別にアカウントを作って、運用しています。&lt;/p&gt;
&lt;p&gt;今回は家庭用（私と妻の二人暮らしです）に運用している「うちNotion」について紹介したいと思います。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#Notion%E3%81%84%E3%81%84%E3%82%88%E3%81%AD&quot;&gt;Notionいいよね&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%81%93%E3%82%8C%E3%81%8C%E3%81%86%E3%81%A1Notion%E3%81%AE%E5%85%A8%E8%B2%8C%E3%81%A0&quot;&gt;これが「うちNotion」の全貌だ！&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E8%8B%A6%E5%8A%B4%E3%81%AE%E6%9C%AB%E3%81%AB%E8%BE%BF%E3%82%8A%E7%9D%80%E3%81%84%E3%81%9FNotion%E5%AE%B6%E8%A8%88%E7%B0%BF&quot;&gt;苦労の末に辿り着いたNotion家計簿&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%AE%B6%E8%A8%88%E7%B0%BF%E3%81%AE%E5%A7%8B%E3%81%BE%E3%82%8A%E3%81%AFGoogle%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%83%89%E3%82%B7%E3%83%BC%E3%83%88%E3%81%A0%E3%81%A3%E3%81%9F&quot;&gt;家計簿の始まりはGoogleスプレッドシートだった&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%AE%B6%E8%A8%88%E7%B0%BF%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%81%AE%E6%A7%8B%E9%80%A0&quot;&gt;家計簿テンプレートの構造&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%81%AF%E9%83%BD%E5%BA%A6%E8%A6%8B%E7%9B%B4%E3%81%97%E6%9B%B4%E6%96%B0%E5%B1%A5%E6%AD%B4%E3%82%92%E8%A8%98%E9%8C%B2&quot;&gt;テンプレートは都度見直し、更新履歴を記録&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E6%88%91%E3%81%8C%E5%AE%B6%E3%81%AE%E5%9C%9F%E6%9B%9C%E3%83%AD%E3%83%BC%E3%83%89%E3%82%B7%E3%83%A7%E3%83%BC%E3%81%AFNotion%E3%81%8C%E3%81%8D%E3%81%A3%E3%81%8B%E3%81%91&quot;&gt;我が家の「土曜ロードショー」はNotionがきっかけ&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%81%84%E3%81%A4%E3%81%8B%E4%B8%80%E7%B7%92%E3%81%AB%E8%A6%8B%E3%81%9F%E3%81%84%E3%82%92%E7%A2%BA%E5%AE%9F%E3%81%AB&quot;&gt;「いつか一緒に見たい」を確実に&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%AE%B6%E4%BA%8B%E3%81%B8%E3%81%AE%E3%82%A2%E3%83%97%E3%83%AD%E3%83%BC%E3%83%81%E3%82%92Notion%E3%81%A7%E5%B9%B3%E6%BA%96%E5%8C%96&quot;&gt;家事へのアプローチをNotionで平準化&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E6%AF%8E%E5%9B%9E%E4%BF%AE%E6%AD%A3%E3%81%95%E3%82%8C%E3%82%8B%E6%B4%97%E6%BF%AF%E7%89%A9%E3%81%A8%E9%A0%AD%E3%81%AE%E5%83%8D%E3%81%8B%E3%81%AA%E3%81%84%E7%A7%81&quot;&gt;毎回修正される洗濯物と、頭の働かない私&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#Notion%E3%81%A7%E3%82%B5%E3%82%A4%E3%83%AD%E5%8C%96%E3%81%97%E3%81%9F%E6%B4%97%E6%BF%AF%E6%A5%AD%E5%8B%99%E3%82%92%E8%A6%8B%E4%BA%8B%E8%A7%A3%E6%B6%88&quot;&gt;Notionでサイロ化した洗濯業務を見事解消&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%ABNotion%E3%81%AE%E3%81%AF%E3%81%98%E3%82%81%E3%81%9F%E3%81%A6%E3%81%AF%E4%BD%9C%E3%82%8A%E8%BE%BC%E3%81%BF%E3%81%99%E3%81%8E%E3%81%AA%E3%81%84%E3%81%AE%E3%81%8C%E5%A4%A7%E5%88%87&quot;&gt;おわりに：Notionのはじめたては、作り込みすぎないのが大切&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#これがうちnotionの全貌だ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;これが「うちNotion」の全貌だ！&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210223/20210223115154.png&quot; alt=&quot;f:id:ikmbear:20210223115154p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;我が家のサイドバーはこの5種類です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;田所家：家族ページ。家族で使っているサービスとかNotionページへのリンク&lt;/li&gt;
&lt;li&gt;家計簿：我が家の家計簿&lt;/li&gt;
&lt;li&gt;カンバン：かんばん形式で家のタスクを管理。かなり緩め。&lt;/li&gt;
&lt;li&gt;映画：見たい映画、見た映画を管理するページ&lt;/li&gt;
&lt;li&gt;おうちメモ：家事の仕方やレシピ、2人で話したことをまとめています&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;「うちNotion」は「ぼくNotion」よりも運用コストを意図的に小さくしているので、アイコンは基本的にNotionのプリセットアイコンを使用しています。&lt;/p&gt;
&lt;p&gt;ただ家計簿だけは例外でフリーのアイコンサイトから落としてきたものを使用しています。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://iconscout.com/free-icons&quot; target=&quot;_blank&quot;&gt;Download Free Icons - 110,361+ Icons To Choose From Iconscout&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;家族ページとかんばんは結構一般的な形態で特筆事項もないので、それ以外について紹介したいと思います！&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#苦労の末に辿り着いたnotion家計簿&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;苦労の末に辿り着いたNotion家計簿&lt;/h2&gt;
&lt;p&gt;まずはNotion家計簿です。我が家のNotionはもともと家計簿ページだけから始まり、Notion運用に慣れてきたところで他のページをビッグバン的に作成しました。&lt;/p&gt;
&lt;p&gt;歴史があるだけあって、やや内部ページは多めですが、構成としては次の3つです。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210223/20210223115257.png&quot; alt=&quot;f:id:ikmbear:20210223115257p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;実際に毎日の入力を行う家計簿はこんな感じになっています。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210223/20210223115309.png&quot; alt=&quot;f:id:ikmbear:20210223115309p&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#家計簿の始まりはgooglegoogleだった&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;家計簿の始まりはGoogleGoogleだった&lt;/h3&gt;
&lt;p&gt;結婚して大体2年くらいになりますが、一緒に生活を始めたあたりから家計簿自体はつけていました。最初の数ヶ月は妻が家計簿アプリを使っていたのですが、私が入力する機会も多くなったので、共同編集ができるようにGoogleGoogleに切り替えました。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210223/20210223115328.png&quot; alt=&quot;f:id:ikmbear:20210223115328p&quot; /&gt; 左）$1での家計簿（第2版くらい？）。明細を一行ずつ入力すると、別シートで集計する。 右）レイアウトをカレンダービューにしようとした際のプロトタイプ&lt;/p&gt;
&lt;p&gt;$1は$1アプリなので集計は問題なかったのですが、運用を続けるにあたって次の問題が浮上してきました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;モバイルで入力するのが面倒&lt;/li&gt;
&lt;li&gt;毎月の集計列を作成するのが面倒&lt;/li&gt;
&lt;li&gt;計算式が複雑になってきてメンテナンスが大変&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;加えて、妻から「もっと上がるデザインがいい（意訳）」という要望が出たこともあり、妻がカレンダービューを持った家計簿を作成。&lt;/p&gt;
&lt;p&gt;しかしながらこちらも$1だったので同様の問題点があり、かつカレンダー入力のために費目をアルファベットにしたところ、入力が面倒に。&lt;/p&gt;
&lt;p&gt;そこで個人で使用していたNotionを使って家計簿を組んでみることに。&lt;/p&gt;
&lt;p&gt;これまでの$1運用で必要要件はわかっていたので、あとはそれをリンクドデータベースと、デザインに落とし込んでサクッと構築。&lt;/p&gt;
&lt;p&gt;ふんだんにアイコンも盛り込んで、妻も大満足なのでした😁&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#家計簿テンプレートの構造&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;家計簿テンプレートの構造&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210223/20210223115346.png&quot; alt=&quot;f:id:ikmbear:20210223115346p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;家計簿テンプレートは4つのDBから構成されていて、これをレゴブロックのようにはめこんで1ページに埋め込んでいます。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;家計簿入力（カレンダー）&lt;/li&gt;
&lt;li&gt;費目ごとの予算&lt;/li&gt;
&lt;li&gt;支払方法別集計&lt;/li&gt;
&lt;li&gt;全体収支&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;使い方としてはシンプルで、①のカレンダーに費目を入力するとRollUpで各DBが自動更新される仕組みです。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#テンプレートは都度見直し更新履歴を記録&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;テンプレートは都度見直し、更新履歴を記録&lt;/h3&gt;
&lt;p&gt;テンプレートを使っていると、「この費目が欲しい」とか「もっと入力を楽にしたい」という要望が出てくるので、都度都度更新しています。&lt;/p&gt;
&lt;p&gt;更新履歴は「家計簿テンプレートの使い方」ページに追加し、変遷をみられるようにしています。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210223/20210223115419.png&quot; alt=&quot;f:id:ikmbear:20210223115419p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;例えば最近だと、「妻は$1からNotionを起動して家計簿を入力する。大体スーパーの買い物で、支払手段は固定」という$1がわかったため、家計簿入力のテンプレートに「スーパー」というテンプレートを追加したりしています。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#我が家の土曜ロードショーはnotionがきっかけ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;我が家の「土曜ロードショー」はNotionがきっかけ&lt;/h2&gt;
&lt;p&gt;続いては映画ページです。このページでは、みたい映画、みた映画を2つのビューで管理しています。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210223/20210223122546.png&quot; alt=&quot;f:id:ikmbear:20210223122546p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;我が家では毎週土曜の夜は勝手に「土曜ロードショー」を開催しており、その際にボードビューでみる映画を検討しています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#いつか一緒に見たいを確実に&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;「いつか一緒に見たい」を確実に&lt;/h3&gt;
&lt;p&gt;妻はかなり映画やドラマが好きで、時間があれば一日中Netflixでなにかみています。&lt;/p&gt;
&lt;p&gt;対して私はというと、興味がないわけではないのですが、普段全然映画を見ません。パソコンをずっといじっているのが好きです。&lt;/p&gt;
&lt;p&gt;そんな映画の興味に格差がある家庭ですので、&lt;/p&gt;
&lt;p&gt;妻「これ今度一緒に見たい！」&lt;/p&gt;
&lt;p&gt;私「おお！みよう」&lt;/p&gt;
&lt;p&gt;…で結局見ない、そして妻は何をおすすめの映画を忘れるという事態が多発していました。&lt;/p&gt;
&lt;p&gt;そこで「パソコンをずっといじりたい自分」と「映画をおすすめしたい妻」の利害を一致させることを画策。&lt;/p&gt;
&lt;p&gt;「Notionで映画ページを運用する」ことで私の映画に対する興味を駆り立て、妻の記憶を共有。結果土曜ロードショー開催にこぎつけたのでした。&lt;/p&gt;
&lt;p&gt;なお見終わった映画には、ざっくりなレートとそのとき食べたおつまみをプロパティとして登録しています。&lt;/p&gt;
&lt;p&gt;ドライいちじくとゴーダチーズの組み合わせは最高😊&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#家事へのアプローチをnotionで平準化&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;家事へのアプローチをNotionで平準化&lt;/h2&gt;
&lt;p&gt;最後は「おうちメモ」です。こちらではざっくりといろんなメモを格納しています。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210223/20210223122643.png&quot; alt=&quot;f:id:ikmbear:20210223122643p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;何回かこういう類のページを作ってきたのですが、はじめはテーマごとにページを作るよりも、タグで分類する方が管理コストが低いのでおすすめです。&lt;/p&gt;
&lt;p&gt;タグごとに絵文字をテンプレート化しておくと、ぱっと見た時の見栄えもいいです。これはzenn.devから着想を得ました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#毎回修正される洗濯物と頭の働かない私&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;毎回修正される洗濯物と、頭の働かない私&lt;/h3&gt;
&lt;p&gt;我が家では妻が洗濯を担当しているのですが、面倒になったり、忙しかったりするとたまに私がやります。&lt;/p&gt;
&lt;p&gt;で、Notion導入前はほぼ毎回洗濯が終わるたびに、妻からの指摘が入っていました😅&lt;/p&gt;
&lt;p&gt;こうなると私は洗濯をしたくないし、妻も「頼むくらいなら自分でやろう」と思う悪循環です。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#notionでサイロ化した洗濯業務を見事解消&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Notionでサイロ化した洗濯業務を見事解消&lt;/h3&gt;
&lt;p&gt;そこで「Notionに作業メモ作るから、一から教えてください」と懇願し、洗濯作業テンプレを作ることに。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210223/20210223122700.png&quot; alt=&quot;f:id:ikmbear:20210223122700p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;あらためて文字に起こすことで、「洗濯物が干せればよかった私」と「洗濯物にいかにシワがつかず、乾きやすくなるように干せるかを考えている妻」とのギャップが浮き彫りに！以降、このメモを元に洗濯を行うことで、洗濯での指摘は大幅に減りました（なおゼロにはなっていない模様）&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりにnotionのはじめたては作り込みすぎないのが大切&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに：Notionのはじめたては、作り込みすぎないのが大切&lt;/h2&gt;
&lt;p&gt;いかがでしたでしょうか。Notionはかなり自由度が高いアプリなので、ついつい作り込んでしまうのですが、それゆえに「Notionをいじっていたが、なにも生活に寄与していない。ただ時間が溶けただけ」となりがちです。&lt;/p&gt;
&lt;p&gt;そのため、「何を解決したいのか」「どういう風に使っていくのか」を考え、スモールスタートで始めるのがいいんじゃないかなあと思っています。&lt;/p&gt;
&lt;p&gt;次回は「ぼくNotion」の方を紹介したいと思います！&lt;/p&gt;
&lt;p&gt;COMMENT&lt;/p&gt;&lt;div&gt;&lt;/div&gt;. 空白のブロックを2つ作る1. 1で作ったブロックの一方をドラッグして、横並びにする（これで2列になる）。1. 別に作っておいたカレンダーとテーブルを2で作った列に配置する。私はこちらの手順で横並びにしています。手順1,2は以下のツイートでも紹介しているので、ご参考までに😁&lt;a href=&quot;https://twitter.com/ikumatdkr/status/1288772066355769344COMMENT:EMAIL&quot; target=&quot;_blank&quot;&gt;https://twitter.com/ikumatdkr/status/1288772066355769344COMMENT:EMAIL&lt;/a&gt;: &lt;a href=&quot;mailto:m3104.510@gmail.com&quot;&gt;m3104.510@gmail.com&lt;/a&gt;いきなりのコメント失礼します。私も今notionで家計簿を作ろうとしていますが、カレンダーとテーブルビューが横並びにできないのですが、どうやって作成されましたか？&lt;p&gt;&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>【Excel】社内でExcelのデータ操作機能について勉強会をしました</title><link>https://ikuma-t.com/blog/20210215150518/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20210215150518/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210215/20210215110559.pngちょっと前なのですが</description><pubDate>Mon, 15 Feb 2021 15:05:18 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210215/20210215110559.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210215/20210215110559.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210215/20210215110559.png&quot; alt=&quot;f:id:ikmbear:20210215110559p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ちょっと前なのですが、社内勉強会でExcelについての勉強会を行いました。&lt;br /&gt;
せっかく資料を作ったので、供養のためにこのブログで晒します。&lt;/p&gt;
&lt;p&gt;実際に発表した資料はこちらです↓↓↓&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://speakerdeck.com/ikumatadokoro/powerqueryru-men&quot; target=&quot;_blank&quot;&gt;speakerdeck.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;スライド中でも述べていますが、Excel2010あたりからExcelにPowerQueryという機能が追加されました。&lt;/p&gt;
&lt;p&gt;簡単にいうとExcelでRDBMS的なデータ操作（JOINとかGROUP BYとか）ができるようになる機能で、ちょっとしたデータの加工だったらExcelで事足りるようになります。（詳しい使い方はスライドを参照してください🙇‍♂️）&lt;/p&gt;
&lt;p&gt;便利ではあるんですが、すでにRDBMSにデータが入っている場合はそちらを使った方がパフォーマンス的にも手間的にも得策ですね。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>わたしのリフレッシュ方法（2021年版）</title><link>https://ikuma-t.com/blog/20210116142332/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20210116142332/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210116/20210116135617.png最近ふと、「あ、これ</description><pubDate>Sat, 16 Jan 2021 14:23:32 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210116/20210116135617.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210116/20210116135617.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;最近ふと、「あ、これ疲れた時によくやっているなあ」と思ったので、私のリフレッシュ方法3選をまとめてみました。&lt;/p&gt;
&lt;p&gt;ちなみに選考基準はずばり「手軽さ」です。&lt;br /&gt;
リフレッシュはJustInTimeで届けないと意味がないことに加え、金がかかるとリフレッシュすることをためらってしまうので。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#シナモン&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;シナモン&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210116/20210116135617.png&quot; alt=&quot;f:id:ikmbear:20210116135617p:plain:w100&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.co.jp/%E3%83%8F%E3%82%A6%E3%82%B9-GABAN-%E3%82%B7%E3%83%8A%E3%83%A2%E3%83%B3%E3%82%B7%E3%83%A5%E3%82%AC%E3%83%BC-%E3%83%91%E3%82%A6%E3%83%80%E3%83%BC-32g%C3%975%E5%80%8B/dp/B00K183X96&quot; target=&quot;_blank&quot;&gt;Amazon | ハウス GABAN シナモンシュガー&amp;lt;パウダー&amp;gt; 32g×5個 | GABAN(ギャバン) | スパイス・ハーブ 通販&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;甘い匂いで一気にリフレッシュ！&lt;br /&gt;
砂糖も入っているので、焼いたトーストにバターを塗ってこれを振りかけるとシナモンシュガーバタートーストの完成です。&lt;/p&gt;
&lt;p&gt;アロマもいいですが、これは食えるところがいいですね。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#1ー&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;$1ー&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210116/20210116140117.png&quot; alt=&quot;f:id:ikmbear:20210116140117p:plain:w260&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://7premium.jp/product/search/detail?id=88&quot; target=&quot;_blank&quot;&gt;ジャスミン茶　600ml | セブンプレミアム公式 セブンプレミアム向上委員会&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これはオフィス勤務時によく買っているやつです。&lt;br /&gt;
シナモンと被りますが、こちらも$1の香りでリフレッシュ！飲んだ後にさっぱりするのもポイントですね〜。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210116/20210116140542.png&quot; alt=&quot;f:id:ikmbear:20210116140542p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;少し前からパッケージにでかでかと「茶」の文字が主張するようになりました。&lt;br /&gt;
私にはなぜかコムギに見えます。&lt;/p&gt;
&lt;p&gt;コンビニで買える$1ーとしては、ファミマの$1ミルク$1というのもおすすめだったのですが、今はもう売っていないようです。&lt;br /&gt;
（代わりに烏龍ミルク$1が出ていました。&lt;a href=&quot;https://www.family.co.jp/goods/drink/4222217.html&quot; target=&quot;_blank&quot;&gt;伊藤園　タリーズ　烏龍ミルクティー&lt;/a&gt;）&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#肩のストレッチ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;肩のストレッチ&lt;/h2&gt;
&lt;p&gt;ちょうどいい画像がなかったので引用。以下のサイトの「二の腕のストレッチ」のことです。&lt;a href=&quot;https://dews365.com/archives/164397.html&quot; target=&quot;_blank&quot;&gt;【部位別40種類】初心者向けストレッチのやり方を写真で解説！ | | Dews (デュース)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;子供の頃はなんてことのないストレッチだったのですが、&lt;strong&gt;大人になってからすごいきく！&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;肩こり予防、血流改善に効いてそうです。&lt;/p&gt;
&lt;p&gt;たまにTarzanを立ち読みして、「オフィスでできるストレッチ」みたいな特集をみるんですが、静まりかえったオフィスで大仰なストレッチをするのは無理+ストレッチ自体が思い出せないというのがほとんど。&lt;/p&gt;
&lt;p&gt;その点このストレッチは、腕の部分だけで、スペースを取らず、しかも慣れ親しんだ動きでできるので非常にいいです。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;以上、わたしのリフレッシュ方法（2021年版）でした〜。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>RubyMineでライブラリのソースをGrepする方法</title><link>https://ikuma-t.com/blog/20210116110546/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20210116110546/</guid><description>ActiveStorageのwith_attached_#{name}がどこに定義されているのか確認する過程で、RubyMineでの調べ方を覚えました。対象バージョンRubyMine2020.3.1F</description><pubDate>Sat, 16 Jan 2021 11:05:46 GMT</pubDate><content:encoded>&lt;p&gt;ActiveStorageの&lt;code&gt;with_attached_#{name}&lt;/code&gt;がどこに定義されているのか確認する過程で、RubyMineでの調べ方を覚えました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#対象バージョン&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;対象バージョン&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;RubyMine 2020.3.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#find-in-files&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Find in Files&lt;/h2&gt;
&lt;p&gt;RubyMineでGrep検索を行うには、編集 | 検索 | パス内検索 &lt;code&gt;⇧⌘ F&lt;/code&gt;から「Find in Files」メニューを起動します。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210116/20210116105129.png&quot; alt=&quot;f:id:ikmbear:20210116105129p&quot; /&gt;Find in Files画面&lt;/p&gt;
&lt;p&gt;試しに&lt;code&gt;with_attached&lt;/code&gt;あたりで検索をかけてみても、自分のソースで書いた部分しか引っ掛からず、定義元は抽出されません。&lt;br /&gt;
これは検索の対象（図中、緑枠）が&lt;code&gt;In Project&lt;/code&gt;になっているのが原因でした。&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;オプション&lt;/th&gt;&lt;th&gt;検索対象&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;In Project&lt;/td&gt;&lt;td&gt;現在のプロジェクト（外部ライブラリは含まない）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Module&lt;/td&gt;&lt;td&gt;モジュール指定ができるようになる。指定したモジュールの範囲で検索する&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Directory&lt;/td&gt;&lt;td&gt;$1リ指定ができるようになる。指定した$1リの範囲で検索する&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Scope&lt;/td&gt;&lt;td&gt;スコープが指定できるようになる。事前に定義されたスコープの範囲で検索する&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;スコープについては、&lt;a href=&quot;https://pleiades.io/help/ruby/configuring-scopes-and-file-colors.html&quot; target=&quot;_blank&quot;&gt;こちら&lt;/a&gt;を参照。&lt;br /&gt;
要はファイルを目的に応じてグルーピングできる機能です。&lt;/p&gt;
&lt;p&gt;自分で定義しなくてもRubyMineのプリセットがいくつかあるようですが、今回は大雑把に&lt;code&gt;All Places&lt;/code&gt;で$1を実施し、見事欲しいソースに到達できました。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210116/20210116110341.png&quot; alt=&quot;f:id:ikmbear:20210116110341p&quot; /&gt;&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>ActiveRecord::PendingMigrationErrorに初遭遇したので、ちゃんと対処する</title><link>https://ikuma-t.com/blog/20210110195603/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20210110195603/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210110/20210110195519.pngActiveReco</description><pubDate>Sun, 10 Jan 2021 19:56:03 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210110/20210110195519.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210110/20210110195519.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210110/20210110195519.png&quot; alt=&quot;f:id:ikmbear:20210110195519p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ActiveRecord::PendingMigrationErrorに初めて出会ったので、備忘がてらまとめていきます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E7%99%BA%E7%94%9F%E6%99%82%E3%81%AE%E7%8A%B6%E6%B3%81&quot;&gt;発生時の状況&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E7%92%B0%E5%A2%83&quot;&gt;環境&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E9%96%8B%E7%99%BA%E7%8A%B6%E6%B3%81&quot;&gt;開発状況&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#ActiveRecordPendingMigrationError%E3%81%A8%E3%81%AF&quot;&gt;ActiveRecord::PendingMigrationErrorとは&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%AF%BE%E5%87%A6%E6%96%B9%E6%B3%95%E4%BB%8A%E5%9B%9E%E3%81%AE%E3%82%B1%E3%83%BC%E3%82%B9%E3%81%AE%E5%A0%B4%E5%90%88&quot;&gt;対処方法（今回のケースの場合）&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#binrails-dbmigrate%E3%81%A0%E3%81%91%E3%81%A7%E3%81%AF%E8%A7%A3%E6%B1%BA%E3%81%97%E3%81%AA%E3%81%84&quot;&gt;bin/rails db&lt;div&gt;&lt;/div&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%81%9D%E3%81%AE1binrails-dbreset%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81B&quot;&gt;その1：bin/rails db&lt;div&gt;&lt;/div&gt;@ブランチB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%81%9D%E3%81%AE2binrails-dbrollback-STEP%E6%88%BB%E3%81%99%E6%95%B0%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81A&quot;&gt;その2：bin/rails db&lt;div&gt;&lt;/div&gt; [STEP=戻す数]を実行する@ブランチA&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%81%8A%E3%81%BE%E3%81%911binrails-dbmigratereset-%E3%81%A8-binrails-dbreset%E3%81%AE%E9%81%95%E3%81%84&quot;&gt;おまけ1：bin/rails db:migrate&lt;/a&gt;&lt;/p&gt;&lt;div&gt;&lt;/div&gt;&lt;a href=&quot;#%E3%81%8A%E3%81%BE%E3%81%911binrails-dbmigratereset-%E3%81%A8-binrails-dbreset%E3%81%AE%E9%81%95%E3%81%84&quot;&gt; と bin/rails db&lt;div&gt;&lt;/div&gt;&lt;/a&gt;&lt;p&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%81%8A%E3%81%BE%E3%81%912%E3%83%9E%E3%82%A4%E3%82%B0%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E7%8A%B6%E6%B3%81%E7%A2%BA%E8%AA%8D%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AB%E8%A6%9A%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8F%E3%81%A8%E8%89%AF%E3%81%95%E3%81%9D%E3%81%86%E3%81%AA%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89&quot;&gt;おまけ2：マイグレーションの状況確認のために、覚えておくと良さそうなコマンド&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%81%8A%E3%81%BE%E3%81%913binrails%E3%81%99%E3%82%8B%E3%81%B9%E3%81%8D%E3%81%8B&quot;&gt;おまけ3：bin/railsするべきか&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%8F%82%E8%80%83&quot;&gt;参考&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#発生時の状況&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;発生時の状況&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#環境&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;環境&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Rails 6.1&lt;/li&gt;
&lt;li&gt;Ruby 3.0.0&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#開発状況&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;開発状況&lt;/h3&gt;
&lt;p&gt;各ブランチのDDLファイルは以下の通り。DDLファイルの数は違うが、最終的に実行されるDDL文は同じ（ブランチAはRails6.1、ブランチBはRails6.0での作業→6.1アップグレード）。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;ブランチA：（自分）ActiveStorageに関する$1を実行&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;20210108102934_create_active_storage_tables.active_storage.rb&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ブランチB：（他の人）ActiveStorageに関する$1を実行&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;20201122075737_create_active_storage_tables.active_storage.rb&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;20201227052520_add_service_name_to_active_storage_blobs.active_storage.rb&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;20201227052521_create_active_storage_variant_records.active_storage.rb&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ブランチAで&lt;code&gt;bin/rails db:migrate&lt;/code&gt;を実行しているため、DBにはすでにテーブルが存在する。&lt;br /&gt;
ブランチAでの作業後に、ブランチBに切り替え&lt;code&gt;bin/rails s&lt;/code&gt;したところ、&lt;code&gt;ActiveRecord::PendingMigrationError&lt;/code&gt;が発生。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#activerecordpendingmigrationerrorとは&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ActiveRecord::PendingMigrationErrorとは&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210110/20210110181314.png&quot; alt=&quot;f:id:ikmbear:20210110181314p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;未実行の$1ファイルが存在するということ。&lt;br /&gt;
今回の場合は、ブランチBで作成されている3つの$1ファイルが実行されていないので、エラーとなっています。&lt;/p&gt;
&lt;p&gt;ちなみにRailsは次のような形でRailsファイルの実行状況を確認しているみたいです。&lt;br /&gt;
参考：&lt;a href=&quot;https://github.com/rails/rails/blob/914caca2d31bd753f47f9168f2a375921d9e91cc/activerecord/lib/active_record/migration.rb#L1120&quot; target=&quot;_blank&quot;&gt;rails/migration.rb at 914caca2d31bd753f47f9168f2a375921d9e91cc · rails/rails&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;$1リ内の$1ファイルをすべて検索&lt;/li&gt;
&lt;li&gt;テーブル&lt;code&gt;schema_migration&lt;/code&gt;から適用済みの$1ファイルを検索&lt;/li&gt;
&lt;li&gt;1と2の差分を確認する（差分がある場合に、&lt;code&gt;ActiveRecord::PendingMigrationError&lt;/code&gt;を発生させる）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;なお&lt;code&gt;schema_migration&lt;/code&gt;はDBに追加されているテーブルで、以下のような構造です。&lt;/p&gt;




















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;versions&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;20201122065204&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;20201121230730&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;20201121231228&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;20201121231845&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;&lt;a href=&quot;#対処方法今回のケースの場合&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;対処方法（今回のケースの場合）&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#binrails-db&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;bin/rails db&lt;div&gt;&lt;/div&gt;&lt;/h3&gt;
&lt;p&gt;今回の場合、$1自体を行っていないのがそもそもの原因なので、&lt;code&gt;bin/rails db:migrate&lt;/code&gt;を実施すれば良さそうです。&lt;br /&gt;
しかしながら、実際に$1を実行してみると&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Caused by:ActiveRecord::StatementInvalid: SQLite3::SQLException: table &quot;active_storage_blobs&quot; already exists&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;…こんな感じで怒られます。&lt;/p&gt;
&lt;p&gt;それもそのはずで、まったく同じ内容のDDLを実行しようとしているが故に、DB側でテーブルの重複が指摘されているわけですね。&lt;br /&gt;
じゃあどうするか？今回は2パターンの解決方法を記載してみようと思います。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#その1binrails-dbブランチb&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;その1：bin/rails db&lt;div&gt;&lt;/div&gt;@ブランチB&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;メリット：お手軽&lt;/li&gt;
&lt;li&gt;デメリット：登録してきたデータが全て消える&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;「テーブルが重複するなら、消せばいいじゃない」という考え方です。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bin/rails db:reset&lt;/code&gt;は内部的には以下のコマンドを実行しています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;bin/rails db:reset&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;bin/rails db:drop&lt;/code&gt;：現在のDBを全て削除する&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bin/rails db:setup&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;bin/rails db:create&lt;/code&gt;：データベースの作成&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bin/rails db:schema:load&lt;/code&gt;：$1（&lt;code&gt;schema.rb&lt;/code&gt;）からのテーブル作成&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bin/rails db:seed&lt;/code&gt;：初期データの登録&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;seedファイルにあるデータがあればいい、というのであれば別に問題ありませんが、コツコツ積み上げてきたデータがあった場合それらが消えてしまうので注意が必要です。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#その2binrails-db-step戻す数を実行するブランチa&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;その2：bin/rails db&lt;div&gt;&lt;/div&gt; [STEP=戻す数]を実行する@ブランチA&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;メリット：データが消えない&lt;/li&gt;
&lt;li&gt;デメリット：なんですかね。たまにコマンド忘れるとかかな😅あと一手間かかる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;「テーブルの追加を無かったことにしよう」という考え方です。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bin/rails db:rollback&lt;/code&gt;は$1ファイルを一つ前のバージョンに戻します。&lt;br /&gt;
STEPパラメータを指定することで、指定した数だけ$1することができます。&lt;/p&gt;
&lt;p&gt;今回であれば&lt;code&gt;bin/rails db:rollback STEP=1&lt;/code&gt;を実行した上でブランチBに移動し、DDLを実行すると、正常にDDLが実行されます。&lt;/p&gt;
&lt;p&gt;実際にやってみました。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% bin/rails db:rollback STEP=1== 20210108102934 CreateActiveStorageTables: reverting ========================-- drop_table(:active_storage_variant_records)   -&amp;gt; 0.0028s-- drop_table(:active_storage_attachments)   -&amp;gt; 0.0011s-- drop_table(:active_storage_blobs)   -&amp;gt; 0.0009s== 20210108102934 CreateActiveStorageTables: reverted (0.0105s) ===============# テーブルが破棄され、schema.rbに変更が加えられる。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;$1ファイル自体は削除されないんですが、DBの&lt;code&gt;schema_migration&lt;/code&gt;から該当の$1ファイルのレコードが削除されることで、pending判定にはかかりません。&lt;br /&gt;
&lt;code&gt;schema.rb&lt;/code&gt;が変更されているので、&lt;code&gt;git stash&lt;/code&gt;して、ブランチBにうつります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% bin/rails db:migrate== 20201122075737 CreateActiveStorageTables: migrating ========================-- create_table(:active_storage_blobs)   -&amp;gt; 0.0033s-- create_table(:active_storage_attachments)   -&amp;gt; 0.0030s== 20201122075737 CreateActiveStorageTables: migrated (0.0065s) ================= 20201227052520 AddServiceNameToActiveStorageBlobs: migrating ===============-- column_exists?(:active_storage_blobs, :service_name)   -&amp;gt; 0.0016s-- add_column(:active_storage_blobs, :service_name, :string)   -&amp;gt; 0.0011s-- change_column(:active_storage_blobs, :service_name, :string, {:null=&amp;gt;false})   -&amp;gt; 0.0153s== 20201227052520 AddServiceNameToActiveStorageBlobs: migrated (0.0337s) ======== 20201227052521 CreateActiveStorageVariantRecords: migrating ================-- create_table(:active_storage_variant_records)   -&amp;gt; 0.0029s== 20201227052521 CreateActiveStorageVariantRecords: migrated (0.0031s) =======&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;正常に$1を実行することができました🎉&lt;br /&gt;
（見せられないですが、別のテーブルに作成していたデータもそのまま残っています）&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おまけ1binrails-dbmigrate-と-binrails-db&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おまけ1：bin/rails db:migrate&lt;div&gt;&lt;/div&gt; と bin/rails db&lt;div&gt;&lt;/div&gt;&lt;/h2&gt;
&lt;p&gt;どちらもDBや$1を一度削除するのは同じですが、再作成に用いるファイルが異なります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;bin/rails db:migrate:reset&lt;/code&gt;：$1ファイルをすべて再実行し、DBを再作成します。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bin/rails db:reset&lt;/code&gt;：&lt;code&gt;schema.rb&lt;/code&gt;を実行し、DBを再作成します。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;schema.rb&lt;/code&gt;に変更が適用されていない$1ファイルがある場合、意図したとおりのDBにならない可能性があります。&lt;br /&gt;
そういった点で&lt;code&gt;bin/rails db:reset&lt;/code&gt;は&lt;code&gt;bin/rails db:migrate:reset&lt;/code&gt;よりも、強力なリセットと言えるでしょう。&lt;/p&gt;
&lt;p&gt;今回のケースではブランチBの内容さえ使えればいいので、&lt;code&gt;bin/rails db:reset&lt;/code&gt;で十分です。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おまけ21の状況確認のために覚えておくと良さそうなコマンド&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おまけ2：$1の状況確認のために、覚えておくと良さそうなコマンド&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;bin/rails db:version&lt;/code&gt;：現在の実行済みの$1のバージョンを表示します。&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% bin/rails db:versionCurrent version: 20210108102934&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;bin/rails db:migrate:status&lt;/code&gt;：$1の実行状況を、バージョンID、$1名とステータスで一覧表示します。&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% bin/rails db:migrate:statusdatabase: db/development.sqlite3 Status   Migration ID    Migration Name   up     20201121230730  Create books   up     20201121231228  Add author to books   up     20201121231845  Add picture to books   up     20201122003800  Devise create users   up     20201122011641  Add name and postal code and address and self introduction to users   up     20201122065204  Add omniauth to users  down    20201122075737  Create active storage tablesactive storage  down    20201227052520  Add service name to active storage blobsactive storage  down    20201227052521  Create active storage variant recordsactive storage   up     20210108102934  ********** NO FILE **********&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;ステータスは、upが適用済み、downが未適用です。&lt;br /&gt;
この実行結果はブランチBで実行しているので、3つの$1が未実行、最新の$1ファイルがブランチAにしかないので&lt;code&gt;********** NO FILE **********&lt;/code&gt;となっています。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おまけ3binrailsするべきか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おまけ3：bin/railsするべきか&lt;/h2&gt;
&lt;p&gt;この記事では、すべてのコマンドを&lt;code&gt;bin/rails&lt;/code&gt;で記載しており、実際に使用しているコマンドもその形式です。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bin/rails&lt;/code&gt;を使用する理由は、Springを使用して高速にコマンドを実行するため、なのですが残念ながら&lt;code&gt;bin/rails db...&lt;/code&gt;系のコマンドはSpringが起動しないので関係ありません。&lt;/p&gt;
&lt;p&gt;コマンドによってSpringが起動したりしなかったりする+つけても実害はないので、忘れないようにすべて&lt;code&gt;bin/rails&lt;/code&gt;の形で記載しています。&lt;br /&gt;
なので例えば&lt;code&gt;bin/rails db:reset&lt;/code&gt;は&lt;code&gt;rails db:reset&lt;/code&gt;でも問題ありません。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#参考&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;参考&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.amazon.co.jp/dp/B07QW41QCM/ref=dp-kindle-redirect?_encoding=UTF8&amp;amp;btkr=1&quot; target=&quot;_blank&quot;&gt;独習Ruby on Rails&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;FJORD BOOT CAMPのQ&amp;amp;A&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>ikuma-t</author></item><item><title>【Todoist→Pixela】Todoistでタスクを完了したら草生やす</title><link>https://ikuma-t.com/blog/20210108122806/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20210108122806/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210108/20210108111222.jpgTodoistのタス</description><pubDate>Fri, 08 Jan 2021 12:28:06 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210108/20210108111222.jpg&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210108/20210108111222.jpg&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210108/20210108111222.jpg&quot; alt=&quot;f:id:ikmbear:20210108111222j&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;&lt;a href=&quot;#todoistのタスクが完了したら草を生やしたい&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Todoistのタスクが完了したら草を生やしたい&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://pixe.la/ja&quot; target=&quot;_blank&quot;&gt;Pixela&lt;/a&gt;というサービスを知ってから、私の頭の中は「どう草を生やすか」で持ちきりです。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://pixe.la/ja&quot; target=&quot;_blank&quot;&gt;pixe.la&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;今回は私が日常的に使っているタスク管理アプリ「Todoist」と連携し、タスクが完了したら草を生やすようにしてみました。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;なんでも草を生やしたがるお年頃&lt;/p&gt;
&lt;p&gt;ikuma-t/todoist-graph | Pixela &lt;a href=&quot;https://t.co/2eRIHRZq5W&quot; target=&quot;_blank&quot;&gt;https://t.co/2eRIHRZq5W&lt;/a&gt; &lt;a href=&quot;https://twitter.com/hashtag/Pixela?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot; target=&quot;_blank&quot;&gt;#Pixela&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;— Ikuma_t (@ikumatdkr) &lt;a href=&quot;https://twitter.com/ikumatdkr/status/1347345273626845186?ref_src=twsrc%5Etfw&quot; target=&quot;_blank&quot;&gt;2021年1月8日&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#Todoist%E3%81%AE%E3%82%BF%E3%82%B9%E3%82%AF%E3%81%8C%E5%AE%8C%E4%BA%86%E3%81%97%E3%81%9F%E3%82%89%E8%8D%89%E3%82%92%E7%94%9F%E3%82%84%E3%81%97%E3%81%9F%E3%81%84&quot;&gt;Todoistのタスクが完了したら草を生やしたい&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#Pixela%E5%81%B4%E3%81%AE%E8%A8%AD%E5%AE%9A&quot;&gt;Pixela側の設定&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#1-%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E6%9C%AA%E7%99%BB%E9%8C%B2%E3%81%AE%E5%A0%B4%E5%90%88%E3%83%A6%E3%83%BC%E3%82%B6%E7%99%BB%E9%8C%B2&quot;&gt;1. （ユーザー未登録の場合）ユーザ登録&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#2-Todoist%E7%94%A8%E3%81%AE%E3%82%B0%E3%83%A9%E3%83%95%E3%81%AE%E4%BD%9C%E6%88%90&quot;&gt;2. Todoist用のグラフの作成&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#3-Webhook%E3%81%AE%E7%99%BB%E9%8C%B2&quot;&gt;3. Webhookの登録&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#Todoist%E5%81%B4%E3%81%AE%E8%A8%AD%E5%AE%9A&quot;&gt;Todoist側の設定&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E6%96%B9%E6%B3%951IFTTT%E3%82%92%E4%BD%BF%E3%81%86&quot;&gt;方法1：IFTTTを使う&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#1-If-This%E3%81%ABTodoist%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B&quot;&gt;1. If ThisにTodoistを設定する&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#2-Then-That%E3%81%ABWebhook%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B&quot;&gt;2. Then ThatにWebhookを設定する&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E6%96%B9%E6%B3%952TodoistAPI%E3%82%92%E4%BD%BF%E3%81%86Todoist%E3%83%97%E3%83%AC%E3%83%9F%E3%82%A2%E3%83%A0%E3%83%A6%E3%83%BC%E3%82%B6%E5%90%91%E3%81%91&quot;&gt;方法2：TodoistAPIを使う（※Todoistプレミアムユーザ向け）&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E8%8D%89%E3%81%AF%E3%81%84%E3%81%84%E3%82%88%E3%81%AD&quot;&gt;草はいいよね&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;&lt;a href=&quot;#pixela側の設定&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Pixela側の設定&lt;/h1&gt;
&lt;p&gt;一億総草生やし社会の実現のためには、「いつものそれ」ではいけませんね。というわけで、Pixela側の設定も記載します。&lt;/p&gt;
&lt;p&gt;手順としては次の通りです。全部ターミナルから&lt;code&gt;curl&lt;/code&gt;コマンドで実行しています。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;（ユーザー未登録の場合）ユーザー登録&lt;/li&gt;
&lt;li&gt;Todoist用のグラフの作成&lt;/li&gt;
&lt;li&gt;Webhook の登録&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;&lt;a href=&quot;#1-ユーザー未登録の場合ユーザ登録&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;1. （ユーザー未登録の場合）ユーザ登録&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$ curl -X POST https://pixe.la/v1/users -d &apos;{&quot;token&quot;:&quot;{PASSWORD}&quot;, &quot;username&quot;:&quot;ikuma-t&quot;, &quot;agreeTermsOfService&quot;:&quot;yes&quot;, &quot;notMinor&quot;:&quot;yes&quot;}&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;token&lt;/code&gt;の後ろの&lt;code&gt;{PASSWORD}&lt;/code&gt;には任意のパスワードを、&lt;code&gt;username&lt;/code&gt;にはグローバルに一意な自分のユーザIDを設定してください。
※以降も設定した値に置き換えて進めてください。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#2-todoist用のグラフの作成&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;2. Todoist用のグラフの作成&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$ curl -X POST https://pixe.la/v1/users/ikuma-t/graphs -H &apos;X-USER-TOKEN:{PASSWORD}&apos; -d &apos;{&quot;id&quot;:&quot;todoist-graph&quot;,&quot;name&quot;:&quot;todoist-graph&quot;,&quot;unit&quot;:&quot;updates&quot;,&quot;type&quot;:&quot;int&quot;,&quot;color&quot;:&quot;ichou&quot;,&quot;timezone&quot;:&quot;Asia/Tokyo&quot;}&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;指定できるパラメータは&lt;a href=&quot;https://docs.pixe.la/entry/post-graph&quot; target=&quot;_blank&quot;&gt;POST - /v1/users//graphs - Pixela API Document&lt;/a&gt;を参照してください。
Scrapboxの更新頻度で草を生やす際に芝生色を使ったので、今回は&lt;code&gt;color&lt;/code&gt;に&lt;code&gt;ichou&lt;/code&gt;を指定しています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#3-webhookの登録&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;3. Webhookの登録&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$ curl -X POST https://pixe.la/v1/users/ikuma-t/webhooks -H &apos;X-USER-TOKEN:{PASSWORD}&apos; -d &apos;{&quot;graphID&quot;:&quot;todoist-graph&quot;,&quot;type&quot;:&quot;increment&quot;}&apos; | pbcopy&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;リク$1トすると&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&quot;webhookHash&quot;:&quot;xxxxx.....xxxxx&quot;,&quot;message&quot;:&quot;Success.&quot;,&quot;isSuccess&quot;:true}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;こんな感じの値が返ってくるのですが、これをコピーするために&lt;code&gt;pbcopy&lt;/code&gt;をくっつけています（手動でコピーしてもいいんですけどね）。
実際に使うのは&lt;code&gt;&quot;webhookHash&quot;:&quot;xxxxx.....xxxxx&quot;&lt;/code&gt;の値だけです。&lt;/p&gt;
&lt;p&gt;これでPixelaの設定は完了です！Todoistの設定をしましょう！&lt;/p&gt;
&lt;h1&gt;&lt;a href=&quot;#todoist側の設定&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Todoist側の設定&lt;/h1&gt;
&lt;p&gt;Todoistのタスク完了時に草を生やすには2種類の方法があります。&lt;/p&gt;




















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;TodoistAPI&lt;/th&gt;&lt;th&gt;IFTTT&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;利用可能なTodoistプラン&lt;/td&gt;&lt;td&gt;プレミアム&lt;/td&gt;&lt;td&gt;制限なし&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;送信可能なタイミング&lt;/td&gt;&lt;td&gt;タスク（追加、更新、完了、完了解除、削除） &lt;br /&gt;メモ（追加、更新、削除） &lt;br /&gt;プロジェクト（追加、更新、削除、$1、$1解除） &lt;br /&gt;ラベル（追加、更新、削除） &lt;br /&gt;フィルタ（追加、更新、削除） &lt;br /&gt;リマインダー（発火時）&lt;/td&gt;&lt;td&gt;タスク（追加、完了 ※いずれもPJもしくはラベル指定可能）&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;今回はタスクを完了したら草生やすだけなので、どちらを使っても変わらないです。
この記事では両方の方法をご紹介したいと思います。（ちなみにIFTTTを通さない分、少し反映が早い(?)ので私はTodoistAPIを使っています）&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#方法1iftttを使う&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;方法1：IFTTTを使う&lt;/h2&gt;
&lt;p&gt;※IFTTTのアカウントを持っている前提で話を進めます。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://ifttt.com/create&quot; target=&quot;_blank&quot;&gt;ifttt.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;こちらから新しいアプリを作成していきます。&lt;/p&gt;
&lt;p&gt;流れとしては&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If ThisにTodoistを設定する&lt;/li&gt;
&lt;li&gt;Then ThatにWebhookを設定する&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;以上です！&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#1-if-thisにtodoistを設定する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;1. If ThisにTodoistを設定する&lt;/h3&gt;
&lt;p&gt;※初めての場合、IFTTTとTodoistの連携が必要です。今回は省略いたします。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210108/20210108114030.png&quot; alt=&quot;f:id:ikmbear:20210108114030p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;1.If Thisからスタートします。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210108/20210108114113.png&quot; alt=&quot;f:id:ikmbear:20210108114113p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;2.連携するサービスにTodoistを設定します。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210108/20210108114528.png&quot; alt=&quot;f:id:ikmbear:20210108114528p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;3.トリガーを設定します。
各トリガーの説明は図の通りです。今回はタスク完了時を想定しているので、「New Completed Task」を設定します&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210108/20210108114701.png&quot; alt=&quot;f:id:ikmbear:20210108114701p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;4.Todoistのどのプロジェクトを監視対象にするか設定します。今回は全部のタスクを監視対象としたいので「Any Project」のままにしておきます。&lt;/p&gt;
&lt;p&gt;5.&lt;code&gt;Create trigger&lt;/code&gt;を押して設定を完了します。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#2-then-thatにwebhookを設定する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;2. Then ThatにWebhookを設定する&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210108/20210108115007.png&quot; alt=&quot;f:id:ikmbear:20210108115007p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;1.Then Thatからスタートします。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210108/20210108115047.png&quot; alt=&quot;f:id:ikmbear:20210108115047p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;2.連携するサービスにWebhooksを設定します。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210108/20210108115137.png&quot; alt=&quot;f:id:ikmbear:20210108115137p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;3.道なりに進みます。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210108/20210108115452.png&quot; alt=&quot;f:id:ikmbear:20210108115452p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;4.リク$1トを設定します。&lt;/p&gt;
&lt;p&gt;URLには以下の値を設定します。なお&lt;code&gt;{webhookHashの値}&lt;/code&gt;は、Pixelaの設定「3. Webhookの登録」で取得したwebhookHashの値に読み替えてください。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;https://pixe.la/v1/users/{ユーザID}/webhooks/{webhookHashの値}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Pixelaはリク$1トボディを必要としない（セットしても無視される）ので、画像の通り、&lt;code&gt;Body&lt;/code&gt;は空欄にしておきましょう。
&lt;a href=&quot;https://docs.pixe.la/entry/invoke-webhook&quot; target=&quot;_blank&quot;&gt;POST - /v1/users//webhooks/ - Pixela API Document&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ここまできたら、&lt;code&gt;Create action&lt;/code&gt; &amp;gt; &lt;code&gt;continue&lt;/code&gt; &amp;gt; &lt;code&gt;finish&lt;/code&gt;と道なりに進んで設定完了です！
試しにtodoistでタスクを完了してみると、草が生えますwwww&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#方法2todoistapiを使うtodoistプレミアムユーザ向け&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;方法2：TodoistAPIを使う（※Todoistプレミアムユーザ向け）&lt;/h2&gt;
&lt;p&gt;次にTodoistAPIを利用した設定方法を説明します。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.todoist.com/appconsole.html&quot; target=&quot;_blank&quot;&gt;developer.todoist.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;1.Todoist App Management Consoleにアクセス&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210108/20210108120453.png&quot; alt=&quot;f:id:ikmbear:20210108120453p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;2.&lt;code&gt;Create a new app&lt;/code&gt;を選択&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210108/20210108120733.png&quot; alt=&quot;f:id:ikmbear:20210108120733p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;3.Pixelaをアプリとして登録する。
&lt;code&gt;App display name&lt;/code&gt;はなんでもいいです。わかりやすいように今回はPixelaとし、&lt;code&gt;Create App&lt;/code&gt;を選択します。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210108/20210108120957.png&quot; alt=&quot;f:id:ikmbear:20210108120957p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;4.Webhookの設定をする下にスクロールすると「Webhooks」の設定欄があるので、以下のように設定し&lt;code&gt;Activate webhooks&lt;/code&gt;を選択します。
なお&lt;code&gt;{webhookHashの値}&lt;/code&gt;は、Pixelaの設定「3. Webhookの登録」で取得したwebhookHashの値に読み替えてください。&lt;/p&gt;





















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;項目&lt;/th&gt;&lt;th&gt;値&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Webhooks callback URL&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://pixe.la/v1/users/&quot; target=&quot;_blank&quot;&gt;https://pixe.la/v1/users/&lt;/a&gt;&lt;code&gt;{ユーザID}/webhooks/{webhookHashの値}&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Webhooks version&lt;/td&gt;&lt;td&gt;8（デフォルト）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Watched Events&lt;/td&gt;&lt;td&gt;item&lt;div&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210108/20210108121829.png&quot; alt=&quot;f:id:ikmbear:20210108121829p&quot; /&gt; 5.開発用のアクセス$1ンを発行する
「Webhooks」の少し上に&lt;code&gt;create test token&lt;/code&gt;ボタンがあるので、押してください。&lt;/p&gt;
&lt;p&gt;ここまでできたら設定完了です！
試しにtodoistでタスクを完了してみると、草が生えますwwww&lt;/p&gt;
&lt;h1&gt;&lt;a href=&quot;#草はいいよね&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;草はいいよね&lt;/h1&gt;
&lt;p&gt;草を生やすと、「は！今日も草生やさなきゃ！」とモチベーション維持に繋がって良いですね〜。&lt;/p&gt;
&lt;p&gt;次は「Notionを更新したら草を生やす」に挑戦したいのですが、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Notionからの更新通知受け取り先はSlackしか対応していない&lt;/li&gt;
&lt;li&gt;Slackに投稿されたことをトリガーにしようと思っても、Pixelaへのリク$1ト時に&lt;code&gt;challenge&lt;/code&gt;に失敗してしまう&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;という状況なので、ちょっと難しいかもですね。うまくできたらまたブログにまとめたいと思います！&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>【Rails】ActiveRecord::core#==はidを比較する（Rails6.1）</title><link>https://ikuma-t.com/blog/20210104212208/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20210104212208/</guid><description>きっかけソースをみるRubyの演算子の優先順位コメントを眺めてみるまとめきっかけ&amp;lt;%if@user.id==current_user.id%&amp;gt;$1ブートキャンプの課題で、こんなコードを書い</description><pubDate>Mon, 04 Jan 2021 21:22:08 GMT</pubDate><content:encoded>&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%81%8D%E3%81%A3%E3%81%8B%E3%81%91&quot;&gt;きっかけ&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%82%BD%E3%83%BC%E3%82%B9%E3%82%92%E3%81%BF%E3%82%8B&quot;&gt;ソースをみる&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#Ruby%E3%81%AE%E6%BC%94%E7%AE%97%E5%AD%90%E3%81%AE%E5%84%AA%E5%85%88%E9%A0%86%E4%BD%8D&quot;&gt;Rubyの演算子の優先順位&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88%E3%82%92%E7%9C%BA%E3%82%81%E3%81%A6%E3%81%BF%E3%82%8B&quot;&gt;コメントを眺めてみる&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%81%BE%E3%81%A8%E3%82%81&quot;&gt;まとめ&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#きっかけ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;きっかけ&lt;/h2&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;% if @user.id == current_user.id %&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;$1ブートキャンプの課題で、こんなコードを書いていたら&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ActiveRecordはデフォルトでid同士を比較するので@user == current_userでOKです。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;とレビューいただきました。&lt;/p&gt;
&lt;p&gt;「$1〜そうなんや」ではもったいないので、ソースを追っかけてみました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#ソースをみる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;ソースをみる&lt;/h2&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Returns true if +comparison_object+ is the same exact object, or +comparison_object+# is of the same type and +self+ has an ID and it is equal to +comparison_object.id+.## Note that new records are different from any other record by definition, unless the# other record is the receiver itself. Besides, if you fetch existing records with# +select+ and leave the ID out, you&apos;re on your own, this predicate will return false.## Note also that destroying a record preserves its ID in the model instance, so deleted# models are still comparable.def ==(comparison_object)  super ||    comparison_object.instance_of?(self.class) &amp;amp;&amp;amp;    !id.nil? &amp;amp;&amp;amp;    comparison_object.id == idendalias :eql? :==&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/rails/rails/blob/c7dfe33f3958295a857d7bfb1070302e5b7429ff/activerecord/lib/active_record/core.rb#L411&quot; target=&quot;_blank&quot;&gt;rails/core.rb at c7dfe33f3958295a857d7bfb1070302e5b7429ff · rails/rails&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;それでは頭の悪さを晒していきましょう。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#rubyのrubyの優先順位&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;RubyのRubyの優先順位&lt;/h3&gt;
&lt;p&gt;$1ばっかりで面食らいました。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;は&lt;code&gt;||&lt;/code&gt;よりも優先順位が高いので、このメソッドは以下のように書き換えることができます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;def ==(comparison_object)  super || (comparison_object.instance_of?(self.class) &amp;amp;&amp;amp; !id.nil? &amp;amp;&amp;amp; comparison_object.id == id)end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;参考：&lt;a href=&quot;https://docs.ruby-lang.org/ja/latest/doc/spec=2foperator.html&quot; target=&quot;_blank&quot;&gt;演算子式 (Ruby 3.0.0 リファレンスマニュアル)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Rubyは式全体の真偽を決定するまで、左辺から順に式を評価します。&lt;br /&gt;
つまりは&lt;code&gt;super&lt;/code&gt;（自分とまったく同じオブジェクトなら真）が偽であれば、&lt;code&gt;||&lt;/code&gt;以降の内容が評価されることになります。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#コメントを眺めてみる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;コメントを眺めてみる&lt;/h3&gt;
&lt;p&gt;ソースに書いてあることを全部調べた上で、コメントをみてみましょう。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Returns true if +comparison_object+ is the same exact object, or +comparison_object+ is of the same type and +self+ has an ID and it is equal to +comparison_object.id+.&lt;br /&gt;
比較対象がまったく同じオブジェクト、もしくはクラスが同じで、IDを持ち、かつIDの値が比較対象同士で同じならtrueを返す&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;これはソースそのものの通りですね。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that new records are different from any other record by definition, unless the other record is the receiver itself.&lt;br /&gt;
新しいレコードは、他のレコードがレシーバ自身でない限り、定義上、他のレコードとは異なることに注意してください。&lt;/p&gt;
&lt;p&gt;Besides, if you fetch existing records with +select+ and leave the ID out, you’re on your own, this predicate will return false.&lt;br /&gt;
また、既存のレコードを+select+で取得する際にIDを対象外とすると、このメソッドはfalseを返します。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;いずれもこのメソッドでは&lt;code&gt;!id.nil?&lt;/code&gt;が条件となっているので、必ずfalseがかえるということですかね。&lt;/p&gt;
&lt;p&gt;1つ目は、newしたばかりのレコードはidがnilだから、&lt;br /&gt;
2つ目は&lt;code&gt;select&lt;/code&gt;でカラムを指定する際に&lt;code&gt;id&lt;/code&gt;を対象外とすると、&lt;code&gt;id&lt;/code&gt;はnilだから、ということでしょうか。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note also that destroying a record preserves its ID in the model instance, so deleted models are still comparable.&lt;br /&gt;
また、レコードの削除はモデル$1のIDを保持するので、削除されたモデルはまだ比較可能であることにも注意してください。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;いまいちよくわからなかった箇所。結局&lt;code&gt;id&lt;/code&gt;が残ってさえいれば、いつまでもtrueがか返すということでしょうか…🤔&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;book = Book.find(1)bookA = Book.find(1)book == bookA#=&amp;gt; truebook.deletebook == bookA#=&amp;gt; true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#まとめ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;まとめ&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ActiveRecord::core#==&lt;/code&gt;は&lt;code&gt;id&lt;/code&gt;同士を比較する&lt;/li&gt;
&lt;li&gt;&lt;code&gt;id&lt;/code&gt;がnilの場合は、必ずfalseを返す&lt;/li&gt;
&lt;li&gt;&lt;code&gt;id&lt;/code&gt;とクラスさえ合っていれば、他の値が違っていてもtrueを返す&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>ikuma-t</author></item><item><title>「$HOME/git/ignore」と 「$GIT_DIR/info/exclude」と「.gitignore」の使い分け</title><link>https://ikuma-t.com/blog/20210102104829/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20210102104829/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210102/20210102104736.png現在のプロジェクトで</description><pubDate>Sat, 02 Jan 2021 10:48:29 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210102/20210102104736.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210102/20210102104736.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20210102/20210102104736.png&quot; alt=&quot;f:id:ikmbear:20210102104736p&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E7%8F%BE%E5%9C%A8%E3%81%AE%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%A7%E8%87%AA%E5%88%86%E3%81%A0%E3%81%91%E3%81%8C%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92Git%E3%81%AE%E5%AF%BE%E8%B1%A1%E5%A4%96%E3%81%AB%E3%81%97%E3%81%9F%E3%81%84&quot;&gt;現在のプロジェクトで「自分だけ」が使用しているファイルをGitの対象外にしたい&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E7%B5%90%E8%AB%96&quot;&gt;結論&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#Git%E3%81%AE%E5%AF%BE%E8%B1%A1%E5%A4%96%E3%81%A8%E3%81%99%E3%82%8B%E9%9A%9B%E3%81%AE%E4%BD%BF%E3%81%84%E5%88%86%E3%81%91&quot;&gt;Gitの対象外とする際の使い分け&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#gitignore&quot;&gt;.gitignore&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#GIT_DIRinfoexclude&quot;&gt;$GIT_DIR/info/exclude&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#HOMEgitignore&quot;&gt;$HOME/git/ignore&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%8F%82%E8%80%83Git---gitignore-Documentation&quot;&gt;参考：Git - gitignore Documentation&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#現在のプロジェクトで自分だけが使用しているファイルをgitの対象外にしたい&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;現在のプロジェクトで「自分だけ」が使用しているファイルをGitの対象外にしたい&lt;/h2&gt;
&lt;p&gt;最近Railsを6.1にあげたのですが、これが原因でrailwaysというRubyMineでルーティングを表示するRailsが使えなくなりました😅&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Rails6.1にあげた事で&lt;code&gt;rake routes&lt;/code&gt;が使用できなくなり、RubyMineのrailways$1（&lt;code&gt;rake routes&lt;/code&gt;が必要）が動かなくなった。&lt;a href=&quot;https://t.co/OzkrSsW3dw&quot; target=&quot;_blank&quot;&gt;https://t.co/OzkrSsW3dw&lt;/a&gt;&lt;a href=&quot;https://t.co/M5WJnv3FfX&quot; target=&quot;_blank&quot;&gt;https://t.co/M5WJnv3FfX&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;— Ikuma_t (@ikumatdkr) &lt;a href=&quot;https://twitter.com/ikumatdkr/status/1345167531611328514?ref_src=twsrc%5Etfw&quot; target=&quot;_blank&quot;&gt;2021年1月2日&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;railwaysが対応してくれるまでは、一旦Rakeタスクを自分で追加しています（他力本願…自分で直せるようになりたい😓）。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;暫定対応として、routes.rakeファイルを作って&lt;code&gt;rails routes&lt;/code&gt;をラップしてる（毎回やるのは面倒😅)&lt;/p&gt;
&lt;p&gt;— Ikuma_t (@ikumatdkr) &lt;a href=&quot;https://twitter.com/ikumatdkr/status/1345168426289938432?ref_src=twsrc%5Etfw&quot; target=&quot;_blank&quot;&gt;2021年1月2日&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;このファイルの使用状況は以下の通りです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自分しか使っていない（RubyMineでrailwaysを使う人しか必要ない）&lt;/li&gt;
&lt;li&gt;railwaysが治れば、このファイル自体が不要。なのでグローバルにはGitの対象外としたくない（あとあとメンテナンスが面倒なので）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;この場合どうGitの対象外にすればいいのか迷ったので、調べてみました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#結論&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;結論&lt;/h2&gt;
&lt;p&gt;現在のプロジェクトで「自分だけ」が使用しているファイルをGitの対象外にするには、&lt;strong&gt;&lt;code&gt;$GIT_DIR/info/exclude&lt;/code&gt;に追記する&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#gitの対象外とする際の使い分け&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Gitの対象外とする際の使い分け&lt;/h2&gt;
&lt;p&gt;Gitの対象外とするには次の3つの方法があります。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;.gitignore&lt;/code&gt;に追記：特定の$1を利用するすべての人が対象外とすべきものをここに追記する。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$GIT_DIR/info/exclude&lt;/code&gt;に追記：特定の$1で対象外とすべきだけれど、他の人に共有すべきではないものをここに追記する。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$HOME/git/ignore&lt;/code&gt;に追記：自分が利用するすべての$1で対象外とすべきものをここに追記する。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;例えば今FJORD BOOT CAMPでRailsアプリケーションの課題を進めていますが、その場合の設定例は次の通りです。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#gitignore&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.gitignore&lt;/h3&gt;
&lt;p&gt;Railsのデフォルトに加え、画像のアップロード先、Railsの設定先を対象外として追記しています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# See https://help.github.com/articles/ignoring-files for more about ignoring files.## If you find yourself ignoring temporary files generated by your text editor# or operating system, you probably want to add a global ignore instead:#   git config --global core.excludesfile &apos;~/.gitignore_global&apos;# Ignore bundler config./.bundle# Ignore the default SQLite database./db/*.sqlite3/db/*.sqlite3-journal/db/*.sqlite3-*# Ignore all logfiles and tempfiles./log/*/tmp/*!/log/.keep!/tmp/.keep# Ignore pidfiles, but keep the directory./tmp/pids/*!/tmp/pids/!/tmp/pids/.keep# Ignore uploaded files in development./storage/*!/storage/.keep/public/assets.byebug_history# Ignore master key for decrypting credentials and more./config/master.key/public/packs/public/packs-test/node_modules/yarn-error.logyarn-debug.log*.yarn-integrity/public/uploads/*.env&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#git_dirinfoexclude&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;$GIT_DIR/info/exclude&lt;/h3&gt;
&lt;p&gt;railways用に今回の$1に追加したRakeタスクを対象外とします。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# git ls-files --others --exclude-from=.git/info/exclude# Lines that start with &apos;#&apos; are comments.# For a project mostly in C, the following would be a good set of# exclude patterns (uncomment them if you want to use them):# *.[oa]# *~/lib/tasks/routes.rake&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#homegitignore&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;$HOME/git/ignore&lt;/h3&gt;
&lt;p&gt;Mac上でRubyMineを使用して開発をしているので、全Macで対象外とします。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# General.DS_Store.AppleDouble.LSOverride# Icon must end with two \rIcon# Thumbnails._*# Files that might appear in the root of a volume.DocumentRevisions-V100.fseventsd.Spotlight-V100.TemporaryItems.Trashes.VolumeIcon.icns.com.apple.timemachine.donotpresent# Directories potentially created on remote AFP share.AppleDB.AppleDesktopNetwork Trash FolderTemporary Items.apdisk# RubyMine.idea.ediotorconfig&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#参考git---gitignore-documentation&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;参考：&lt;a href=&quot;https://git-scm.com/docs/gitignore&quot; target=&quot;_blank&quot;&gt;Git - gitignore Documentation&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Which file to place a pattern in depends on how the pattern is meant to be used.&lt;/p&gt;
&lt;p&gt;Patterns which should be version-controlled and distributed to other repositories via clone (i.e., files that all developers will want to ignore) should go into a .gitignore file.&lt;/p&gt;
&lt;p&gt;Patterns which are specific to a particular repository but which do not need to be shared with other related repositories (e.g., auxiliary files that live inside the repository but are specific to one user’s workflow) should go into the $GIT_DIR/info/exclude file.&lt;/p&gt;
&lt;p&gt;Patterns which a user wants Git to ignore in all situations (e.g., backup or temporary files generated by the user’s editor of choice) generally go into a file specified by core.excludesFile in the user’s ~/.gitconfig. Its default value is $XDG_CONFIG_HOME/git/ignore. If $XDG_CONFIG_HOME is either not set or empty, $HOME/.config/git/ignore is used instead.&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded><author>ikuma-t</author></item><item><title>年始に向けてブログのデザインを整える</title><link>https://ikuma-t.com/blog/20201231162656/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20201231162656/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201231/20201231150902.pngみなさん年末いかがお</description><pubDate>Thu, 31 Dec 2020 16:26:56 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201231/20201231150902.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201231/20201231150902.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201231/20201231150902.png&quot; alt=&quot;f:id:ikmbear:20201231150902p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;みなさん年末いかがお過ごしでしょうか。私は職場の勉強会の資料を作りたくなくて、現実逃避しています。&lt;/p&gt;
&lt;p&gt;さて今日で一年も終わり。来年はたくさんブログを書けるように、CSSのカスタムCSSを利用してブログのデザインを変更してみました。&lt;/p&gt;
&lt;p&gt;大した変更ではありませんが、地味にハマったところを自分への備忘録として書き残しておきたいと思います。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0CSS%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9&quot;&gt;カスタムCSSの使い方&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%A4%89%E6%9B%B4%E7%82%B9%E3%81%96%E3%81%A3%E3%81%8F%E3%82%8A&quot;&gt;変更点（ざっくり）&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E8%A8%98%E4%BA%8B%E5%85%A8%E4%BD%93&quot;&gt;記事全体&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E7%9B%AE%E6%AC%A1&quot;&gt;目次&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%82%B3%E3%83%BC%E3%83%89%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF&quot;&gt;コードブロック&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%BC%95%E7%94%A8%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF&quot;&gt;引用ブロック&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%82%B5%E3%82%A4%E3%83%89%E3%83%90%E3%83%BC%E3%81%AE%E3%82%A2%E3%82%A4%E3%83%86%E3%83%A0&quot;&gt;サイドバーのアイテム&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%82%84%E3%81%A3%E3%81%A6%E3%81%84%E3%81%A6%E3%81%A4%E3%81%BE%E3%81%A3%E3%81%9F%E3%81%A8%E3%81%93%E3%82%8D&quot;&gt;やっていてつまったところ&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%83%A1%E3%83%87%E3%82%A3%E3%82%A2%E3%82%AF%E3%82%A8%E3%83%AA%E3%81%8C%E9%81%A9%E7%94%A8%E3%81%95%E3%82%8C%E3%81%AA%E3%81%84&quot;&gt;メディアクエリが適用されない&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#1%E9%9A%8E%E5%B1%A4%E7%9B%AE%E3%81%AE%E3%83%AA%E3%82%B9%E3%83%88%E3%81%AB%E3%81%A0%E3%81%91CSS%E3%82%92%E9%81%A9%E7%94%A8%E3%81%99%E3%82%8B%E3%82%BB%E3%83%AC%E3%82%AF%E3%82%BF&quot;&gt;1階層目のリストにだけ、CSSを適用するセレクタ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB&quot;&gt;おわりに&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#カスタムcssの使い方&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;カスタムCSSの使い方&lt;/h2&gt;
&lt;p&gt;カスタムCSSを開くには、まずCSSの右上に表示されている「デザイン」メニューを選択します。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201231/20201231151440.png&quot; alt=&quot;f:id:ikmbear:20201231151440p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;次に、表示されたデザインメニューのサイドバーから「カスタマイズ」を選択します。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201231/20201231151639.png&quot; alt=&quot;f:id:ikmbear:20201231151639p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;カスタマイズタブにある「カスタムCSS」の欄にCSSを書いていくことで、デザインが適用されます。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201231/20201231151724.png&quot; alt=&quot;f:id:ikmbear:20201231151724p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;フォームからフォーカスが外れるとプレビューが更新され、画面上部の「変更を保存する」ボタンを押すことでブログにCSSが反映されます。カスタムCSSの使い方は以上です。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#変更点ざっくり&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;変更点（ざっくり）&lt;/h2&gt;
&lt;p&gt;デザインについては、無料配布されている&lt;a href=&quot;https://blog.hatena.ne.jp/-/store/theme/17391345971627985862&quot; target=&quot;_blank&quot;&gt;soboku&lt;/a&gt;というテーマをベースにしています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#記事全体&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;記事全体&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201231/20201231152541.png&quot; alt=&quot;f:id:ikmbear:20201231152541p&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;囲んで影つけて、各アイテムごとのタイトル文字を太くしました。&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;#wrapper {    box-shadow: 0 2px 4px rgba(67,133,187,.1);    padding: 20px 30px;    border-radius: 12px;    background-color: #fdfdfd;}/* スマホ用 */@media screen and  (max-width: 559px){#container {    padding: 10px}#wrapper {    padding: 10px 10px;}}.entry-content h2 {    font-weight: 700;}.entry-content h3 {    font-weight: 600;}.entry-title-link {    font-weight: 700;    }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#目次&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;目次&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201231/20201231161001.png&quot; alt=&quot;f:id:ikmbear:20201231161001p&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;noteっぽくしました&lt;/li&gt;
&lt;li&gt;「◆目次」を追加しました&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;.entry-content .table-of-contents {    background-color: #f7f9f9;    border-radius: 5px;    padding: 16px 20px;    margin: 36px 0;    border: none;}.entry-content .table-of-contents:before {    content: &quot;◆目次&quot;;    border-bottom: 1px solid #e6e6e6;    font-weight: 600;    margin-bottom: 16px;    color: #787c7b;}    .entry-content .table-of-contents&amp;gt;li&amp;gt;a {    font-weight: 600;    padding-top: 3px;}.entry-content .table-of-contents * {    color: #787c7b;    text-decoration: none;    list-style: none;    padding: 8px 4px;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#コードブロック&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;コードブロック&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201231/20201231152655.png&quot; alt=&quot;f:id:ikmbear:20201231152655p&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;背景を黒にしました&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;.entry-content pre {    padding: 16px;    border-radius: 3px;    background-color: #2c2d3a;    color: #F7F7F7;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#引用ブロック&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;引用ブロック&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201231/20201231152726.png&quot; alt=&quot;f:id:ikmbear:20201231152726p&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;背景色をグレーに変更して、文字色も薄くしました。&lt;/li&gt;
&lt;li&gt;全体的に余白を大きく取っています&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;.entry-content blockquote {    border: none;    color: #626e77;    margin: 1.4rem 0;    padding: 25px 36px;    line-height: 36px;    background: #f7f9f9;    border-radius: 3px;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#サイドバーのアイテム&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;サイドバーのアイテム&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201231/20201231152435.png&quot; alt=&quot;f:id:ikmbear:20201231152435p&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;囲んで影つけて、各アイテムごとのタイトル文字を太くしました。&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;.hatena-module {    padding: 15px 20px 15px;    box-shadow: 0 2px 4px rgba(67,133,187,.1);    border-radius: 12px;    background-color: #fdfdfd;}.hatena-module-title {    font-weight: 700;    }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#やっていてつまったところ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;やっていてつまったところ&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#メディアクエリが適用されない&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;メディアクエリが適用されない&lt;/h3&gt;
&lt;p&gt;記事全体について、修正初期段階では$1で見ると少し幅が狭かったです。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ブログのCSS少しいじった。PCは良さげだけど、CSSだともっと画面いっぱいに広げた方が読みやすそう。&lt;br /&gt;
暇な時変えよう &lt;a href=&quot;https://t.co/GB2l3QTyOa&quot; target=&quot;_blank&quot;&gt;pic.twitter.com/GB2l3QTyOa&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;— Ikuma_t (@ikumatdkr) &lt;a href=&quot;https://twitter.com/ikumatdkr/status/1344492755905433601?ref_src=twsrc%5Etfw&quot; target=&quot;_blank&quot;&gt;2020年12月31日&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;メディアクエリで$1の場合だけpaddingを広げようとしたのですが、なぜか適用されませんでした。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/* ミスっていた時のCSS * //* スマホ用 */@media screen and  (max-width: 559px){#container {    padding: 10px}#wrapper {    padding: 10px 10px;}}#wrapper {    box-shadow: 0 2px 4px rgba(67,133,187,.1);    padding: 20px 30px;    border-radius: 12px;    background-color: #fdfdfd;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これはCSSの書き順の問題だったようで、メディアクエリーの箇所を最後に適用するようにしたら、正しく反映されました。This is「カスケードスタイル」…&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#1階層目のリストにだけcssを適用するcss&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;1階層目のリストにだけ、CSSを適用するCSS&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201231/20201231161526.png&quot; alt=&quot;f:id:ikmbear:20201231161526p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;目次部分はすべて順序付きリストで構成されているので、単純に&lt;code&gt;li&lt;/code&gt;指定だとすべてのアイテムに装飾が施されてしまいます。&lt;/p&gt;
&lt;p&gt;今回は一階層目（つまり記事内の見出し2）だけを太字にしたかったので、直下の子要素を指定する&lt;code&gt;&amp;gt;&lt;/code&gt;を利用して、&lt;code&gt;.table-of-contents&amp;gt;li&amp;gt;a&lt;/code&gt;としました。&lt;/p&gt;
&lt;p&gt;参考：&lt;a href=&quot;https://webliker.info/css-selector-cheat-sheet/&quot; target=&quot;_blank&quot;&gt;CSSのセレクタチートシート | webliker&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#おわりに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おわりに&lt;/h2&gt;
&lt;p&gt;ブログのデザイン変更は今年中にやろうと思っていたので、完了できてよかったです😊&lt;/p&gt;
&lt;p&gt;来年の執筆まわりの目標としては&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ローカルの執筆環境を整える（バージョン管理したい）&lt;/li&gt;
&lt;li&gt;月5本は記事を投稿する&lt;/li&gt;
&lt;li&gt;読みやすい文章に関する知識を蓄える&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;こんなところをやっていけたらいいな〜と思っています。&lt;/p&gt;
&lt;p&gt;それではみなさま良いお年を〜🐄&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>Rubocop実行時のparserに関する警告を解消する</title><link>https://ikuma-t.com/blog/20201228210412/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20201228210412/</guid><description>環境macOSRubyMine.3Ruby.7.1Rubocop.4.2parser.7.2.0Rubocopからの警告Rubocop実行時にいつの間にか、以下の警告が出るようになっていました。war</description><pubDate>Mon, 28 Dec 2020 21:04:12 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;a href=&quot;#環境&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;環境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;macOS&lt;div&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;RubyMine&lt;div&gt;&lt;/div&gt;.3&lt;/li&gt;
&lt;li&gt;Ruby&lt;div&gt;&lt;/div&gt;.7.1&lt;/li&gt;
&lt;li&gt;Rubocop&lt;div&gt;&lt;/div&gt;.4.2&lt;/li&gt;
&lt;li&gt;parser&lt;div&gt;&lt;/div&gt;.7.2.0&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#rubocopからの警告&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Rubocopからの警告&lt;/h2&gt;
&lt;p&gt;Rubocop実行時にいつの間にか、以下の警告が出るようになっていました。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;warning: parser/current is loading parser/ruby27, which recognizeswarning: 2.7.2-compliant syntax, but you are running 2.7.1.warning: please see https://github.com/whitequark/parser#compatibility-with-ruby-mri.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;please seeのURLに飛んで、いろいろ調べてみたところ&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;RubocopはRubyのRubyに&lt;a href=&quot;https://github.com/whitequark/parser&quot; target=&quot;_blank&quot;&gt;whitequark/parser: A Ruby parser.&lt;/a&gt;を使用する&lt;/li&gt;
&lt;li&gt;RubyはパッチリリースごとにRubyへのバックポート&lt;a href=&quot;#f-51de6e0e&quot;&gt;*1&lt;/a&gt;を盛り込むことがある。Rubyを担うparserはこれに対応する必要がある。&lt;/li&gt;
&lt;li&gt;上記に対応するため、parserは1つのバージョンで複数のマイナーバージョンをサポートできないそう（parser2.7.2.0では、Ruby2.7.2のみをサポートしていて、2.7.1をサポートしていない）&lt;/li&gt;
&lt;li&gt;そのため、Rubyのバージョン（2.7.1）とparserの対応しているバージョン（2.7.2）が異なると警告が出る。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;今回事象が発生している環境では特にRubocopのバージョンもしていなかったので、parserも最新版が入っているみたいでした。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Gemfile.lockparser (2.7.2.0)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;参考記事&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/whitequark/parser#compatibility-with-ruby-mri&quot; target=&quot;_blank&quot;&gt;whitequark/parser: A Ruby parser.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://koic.hatenablog.com/entry/parser-gem-and-target-ruby-version-of-rubocop&quot; target=&quot;_blank&quot;&gt;Parser gem のバージョニングと RuboCop の TargetRubyVersion - koicの日記&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#parserのバージョンを下げる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;parserのバージョンを下げる&lt;/h2&gt;
&lt;p&gt;Rubyに合わせてparserを2.7.2.0未満に下げることでエラーを解消します。&lt;/p&gt;
&lt;p&gt;1.Gemfileにparserのバージョンを追記する&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# 2.7.2.0未満の最新版をインストールするgem &apos;parser&apos;, &apos;&amp;lt; 2.7.2.0&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;2.parserをupdateするGemfile.lockで既にparserの2.7.2.0が指定されているので、updateしていく。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% bundle update parser&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;3.Rubocopを実行する&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% bundle exec rubocopInspecting 20 files....................20 files inspected, no offenses detected&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;見事エラー解消！&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#実は今回は無視してもいい警告&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;実は（今回は）無視してもいい警告&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/whitequark/parser/pull/748&quot; target=&quot;_blank&quot;&gt;* Bump 2.7 branch to 2.7.2 by koic · Pull Request #748 · whitequark/parser&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ruby 2.7.2 has been released.&lt;a href=&quot;https://www.ruby-lang.org/en/news/2020/10/02/ruby-2-7-2-released/&quot; target=&quot;_blank&quot;&gt;https://www.ruby-lang.org/en/news/2020/10/02/ruby-2-7-2-released/&lt;/a&gt;&lt;br /&gt;
It seems like no changes have been made to ruby27.y where Parser gem should be changed (backported).ruby/ruby@v2_7_1…v2_7_2&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;特にRuby2.7.1と2.7.2の間に変化はないっぽいので、今回はこの警告を無視してもRubocopの実行結果は変わらなそうでした。&lt;/p&gt;
&lt;p&gt;でも、ドキュメント読んだりエラー解消したり、いろいろと勉強になったのでよしとしましょう！&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#以下調査過程のメモ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;以下、調査過程のメモ&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#原文&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;原文&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/whitequark/parser#compatibility-with-ruby-mri&quot; target=&quot;_blank&quot;&gt;whitequark/parser: A Ruby parser.&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Unfortunately, Ruby MRI often changes syntax in patchlevel versions. This has happened, at least, for every release since 1.9; for example, commits c5013452 and 04bb9d6b were backported all the way from HEAD to 1.9. Moreover, there is no simple way to track these changes.This policy makes it all but impossible to make Parser precisely compatible with the Ruby MRI parser. Indeed, at September 2014, it would be necessary to maintain and update ten different parsers together with their lexer quirks in order to be able to emulate any given released Ruby MRI version.As a result, Parser chooses a different path: the parser/rubyXY parsers recognize the syntax of the latest minor version of Ruby MRI X.Y at the time of the gem release.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#単語語句構文&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;単語・語句・構文&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Ruby MRI&lt;/code&gt;：CRuby（Matz’ Ruby Implementation）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;backport&lt;/code&gt;：あるバージョンのソフトウェアに追加した機能やセキュリティ対策などの改良を、それより以前のバージョンのソフトウェアにも取り込むこと。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;c5013452&lt;/code&gt;、&lt;code&gt;04bb9d6b&lt;/code&gt;：いずれも&lt;code&gt;parse.y&lt;/code&gt;におけるバックポートの例。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lexer quirks&lt;/code&gt;：lexerが字句解析。字句解析の特徴といったところ？&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#内容に関する知識&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;内容に関する知識&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;parse.y&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ruby/ruby/blob/master/parse.y&quot; target=&quot;_blank&quot;&gt;ruby/parse.y at master · ruby/ruby&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;parse.y&lt;/code&gt;はRubyのRubyのルールを記述したもの（記述されたPGは、字句解析→Rubyの順に解析される）&lt;/li&gt;
&lt;li&gt;yaccは、パーサを自動生成するツール。 &lt;code&gt;.y&lt;/code&gt;という拡張子のファイルを入力とし、 Cのソースを出力する。&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codezine.jp/article/detail/8409&quot; target=&quot;_blank&quot;&gt;Ruby開発者・まつもとゆきひろ氏の新言語「Streem」のソースコードを読んでみよう！ ～ 文法と構造を規定する「lex.l」と「parse.y」 (1/4)：CodeZine（コードジン）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://kmaebashi.com/programmer/devlang/yacclex.html&quot; target=&quot;_blank&quot;&gt;プログラミング言語を作る/yaccとlex&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#疑問点と思考過程&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;疑問点と思考過程&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;中の人が言及している記事があった：&lt;a href=&quot;https://koic.hatenablog.com/entry/parser-gem-and-target-ruby-version-of-rubocop&quot; target=&quot;_blank&quot;&gt;Parser gem のバージョニングと RuboCop の TargetRubyVersion - koicの日記&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;RubyのバージョンアップごとにrubocopのRubyを担うparserもそれに追随するが、各バージョンのparserは複数のパッチバージョン (2.7 系, 2.6 系, 2.5 系, 2.4 系, 2.3 系…) のみ。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Gemfile.lock&lt;/code&gt;を確認してみると&lt;code&gt;parser (2.7.2.0)&lt;/code&gt;、つまりは2.7系では2.7.2のみに対応しているので、今回のような警告が発生している。
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/whitequark/parser/pull/748&quot; target=&quot;_blank&quot;&gt;* Bump 2.7 branch to 2.7.2 by koic · Pull Request #748 · whitequark/parser&lt;/a&gt;で言及されているように、特に影響はなさそう。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#訳文deeplと少し自分&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;訳文（deepLと少し自分）&lt;/h3&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;残念なことに、Ruby MRI はパッチレベルのバージョンで構文を変更することがよくあります。例えば、コミット c5013452 や 04bb9d6b は HEAD から 1.9 までバックポートされています。さらに、これらの変更を追跡する簡単な方法はありません。このポリシーにより、ParserをRubyのMRIパーサーと正確に互換性を持たせることは不可能になっています。実際、2014年9月時点では、リリースされたRuby MRIバージョンをエミュレートするためには、10種類の異なるパーサを、それらのlexerの癖と一緒に維持し、更新する必要があります。その結果、Parserは別の道を選択します: parser/rubyXYパーサーはgemのリリース時に最新のマイナーバージョンのRuby MRI X.Yの構文を認識します。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;#fn-51de6e0e&quot;&gt;*1&lt;/a&gt;&lt;/p&gt;&lt;div&gt;&lt;/div&gt;、それより以前のバージョンのソフトウェアにも取り込むこと。&lt;p&gt;&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>アウトプットを阻むプライドと戦う〜スモールアウトプットのすすめ〜</title><link>https://ikuma-t.com/blog/20201218064703/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20201218064703/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201217/20201217221725.pngこの記事は「フィヨル</description><pubDate>Fri, 18 Dec 2020 06:47:03 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201217/20201217221725.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201217/20201217221725.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201217/20201217221725.png&quot; alt=&quot;f:id:ikmbear:20201217221725p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;この記事は「&lt;a href=&quot;https://adventar.org/calendars/5086&quot; target=&quot;_blank&quot;&gt;フィヨルドブートキャンプ Part 1 Advent Calendar 2020 - Adventar&lt;/a&gt;」の18日目の記事です。Part2もあります→&lt;a href=&quot;https://adventar.org/calendars/5230&quot; target=&quot;_blank&quot;&gt;フィヨルドブートキャンプ Part 2 Advent Calendar 2020 - Adventar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;昨日の記事はharukusさんの「&lt;a href=&quot;https://harukus.hatenablog.com/entry/2020/12/17/104632&quot; target=&quot;_blank&quot;&gt;初めてのオンラインLT会の準備と感想 - harukus ぶろぐ&lt;/a&gt;」でした!&lt;/p&gt;
&lt;p&gt;さて、憧れの$1人生初挑戦ということで、せっかくなので技術系の記事を書く予定でした。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201216/20201216194903.png&quot; alt=&quot;f:id:ikmbear:20201216194903p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;そう、予定でした。&lt;/p&gt;
&lt;p&gt;「これが師走ってやつか」&lt;/p&gt;
&lt;p&gt;つぶやく側から物凄い勢いで殴りかかる仕事。12月の業務調整に見事に失敗した私には、技術系の記事をしっかり書く時間など残っておりません。というわけで技術系の記事は来年に期待です。&lt;/p&gt;
&lt;p&gt;気を取り直して。みなさん、アウトプットはしているでしょうか？「インプットよりアウトプットが大事」なんて分かってはいるつもりでも、なかなかアウトプットって難しいし、時間がかかりますよね。&lt;/p&gt;
&lt;p&gt;今回はそんなアウトプットについて、私が感じていることを書きたいと思います。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%82%A2%E3%82%A6%E3%83%88%E3%83%97%E3%83%83%E3%83%88%E3%82%92%E3%81%95%E3%81%BE%E3%81%9F%E3%81%92%E3%82%8B%E3%81%AE%E3%81%AF%E3%83%97%E3%83%A9%E3%82%A4%E3%83%89%E3%81%A0&quot;&gt;アウトプットをさまたげるのはプライドだ&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%82%A2%E3%83%89%E3%83%99%E3%83%B3%E3%83%88%E3%82%AB%E3%83%AC%E3%83%B3%E3%83%80%E3%83%BC%E5%85%A8%E7%84%B6%E3%81%8B%E3%81%91%E3%81%AA%E3%81%84%E3%81%AE%E5%88%83-%E7%84%A1%E9%99%90%E5%88%97%E8%BB%8A%E7%B7%A8&quot;&gt;アドベントカレンダー全然かけないの刃 無限列車編&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E4%B8%80%E6%99%82%E3%81%AF%E3%83%97%E3%83%A9%E3%82%A4%E3%83%89%E3%82%92%E5%85%8B%E6%9C%8D%E3%81%99%E3%82%8B%E3%82%82&quot;&gt;一時はプライドを克服するも…&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%81%93%E3%81%A0%E3%82%8F%E3%82%8A%E3%81%AF%E6%89%8B%E3%81%AE%E9%80%9F%E3%81%95%E3%82%92%E6%89%8B%E3%81%AB%E5%85%A5%E3%82%8C%E3%81%A6%E3%81%8B%E3%82%89%E5%B0%91%E3%81%97%E3%81%9A%E3%81%A4&quot;&gt;「こだわりは手の速さを手に入れてから少しずつ」&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%82%B9%E3%83%A2%E3%83%BC%E3%83%AB%E3%82%A2%E3%82%A6%E3%83%88%E3%83%97%E3%83%83%E3%83%88%E3%81%AE%E3%81%99%E3%81%99%E3%82%81&quot;&gt;スモールアウトプットのすすめ&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#Scrapbox%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B&quot;&gt;Scrapboxを使ってみる&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#Stockr%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B&quot;&gt;Stockrを使ってみる&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E6%97%A5%E5%A0%B1%E3%81%AF%E6%9C%80%E4%BD%8E15%E5%88%86%E6%84%9F%E6%83%B3%E3%81%A8%E6%9B%B8%E3%81%91%E3%82%8C%E3%81%B0%E3%82%84%E3%81%A3%E3%81%9F%E3%81%93%E3%81%A8%E3%81%8C%E3%81%82%E3%82%8C%E3%81%B0%E3%81%84%E3%81%84%E3%81%93%E3%81%A8%E3%81%AB%E3%81%99%E3%82%8B&quot;&gt;日報は最低15分、感想（と書ければやったこと）があればいいことにする&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%82%84%E3%81%A3%E3%81%B1%E3%82%8A%E5%87%BA%E3%81%AA%E3%81%84%E7%A5%9E%E6%9C%AC%E3%82%88%E3%82%8A%E5%87%BA%E3%82%8B%E7%B3%9E%E6%9C%AC&quot;&gt;やっぱり「出ない神本より出る糞本」&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#アウトプットをさまたげるのはプライドだ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;アウトプットをさまたげるのはプライドだ&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#1全然かけないの刃-無限列車編&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;$1全然かけないの刃 無限列車編&lt;/h3&gt;
&lt;p&gt;繰り返しになりますが、アウトプットって難しいですよね。7月から$1ブートキャンプに参加して以来、何度もその難しさに悩まされています。なぜアウトプットに苦しむのか。私の場合「自分のプライドが邪魔をしているから」です。&lt;/p&gt;
&lt;p&gt;この記事も書くまでに何回もアウトラインが変わり、いよいよ公開前日の帰りの電車で書いています😭ここ3日間くらい$1の記事を書いては消し、書いては消しとしていますが、その時に頭に浮かんでいることはこんなことです。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201217/20201217200737.png&quot; alt=&quot;f:id:ikmbear:20201217200737p&quot; /&gt;アニメ版とpixiv大百科で$1のストーリー全話補完した$1「あぁ〜〜、$1生の記事みんないい話・ためになる話すぎるよぉ。僕そんなん書けないよぉ、たんじろぉ」&lt;br /&gt;
「まぁ12月入ってから残業もめちゃくちゃ多かったしぃ、引越しもしてたしぃ、wifiも通ってないしぃ、しょうがないよね、うん仕方ない」&lt;/p&gt;
&lt;p&gt;つまり私はこんなことを思ってしまっているんです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;みんなが書いているようなすごい記事を書きたい&lt;/li&gt;
&lt;li&gt;内容を評価されたい&lt;/li&gt;
&lt;li&gt;しょぼい自分を晒したくない、めちゃくちゃ言い訳したい&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;なさけない…&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#一時はプライドを克服するも&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;一時はプライドを克服するも…&lt;/h3&gt;
&lt;p&gt;そんな私が初めてプライドと向き合ったのは、iosブートキャンプに入って26日目、2020年8月6日のこと。iosエンジニアの堤さんのこの動画をみました。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=j7ifT8S5pN0&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://img.youtube.com/vi/j7ifT8S5pN0/0.jpg&quot; alt=&quot;Embedded YouTube video&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=j7ifT8S5pN0&quot; target=&quot;_blank&quot;&gt;www.youtube.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;その日の日報でメンターのkomagataさんとこんなやりとりをしています。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;私「自分は「ネタは自分の渾身の知見」と思っていたことがハードルになっていて、全然ブログをかけていないと感じました😅。」&lt;/p&gt;
&lt;p&gt;komagataさん「僕も昔からブログ書いてますが、「ネットで見る凄い人のようにレベルの高いことを書きたい。」「レベルの低い話は恥ずかしいので書きたくない。」みたいに思いがちなところを、&lt;strong&gt;「現在自分のレベルが低いのは客観的な事実。」 「レベルの低い状態は誰しもが通過している。その時期に見栄をはって隠すか隠さないかの違いだけ。」&lt;br /&gt;
「現状を素直にアウトプットした方が成長は早まる。」&lt;/strong&gt; と考えたらどんどん書けるようになりました。」&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;そして翌日、早速&lt;a href=&quot;https://ikmbear.hatenablog.com/entry/2020/08/07/123531&quot; target=&quot;_blank&quot;&gt;VSCodeVimで使えるインデントオブジェクト - セットプチフォッカ&lt;/a&gt;を書きます。ここまでは絵に描いたような理想ムーブです。&lt;/p&gt;
&lt;p&gt;しかしながらその時の心をすっかり失い、今も私はプライドに汚染されています。プライドってのはなかなか曲げられないからプライドなんですねえ （他人事）&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#こだわりは手の速さを手に入れてから少しずつ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;「こだわりは手の速さを手に入れてから少しずつ」&lt;/h2&gt;
&lt;p&gt;話は変わりますが、私は「SHIROBAKO」というアニメ制作が舞台のアニメが大好きです。アニメは5周 + 音声だけで2周するほど好きです（まだ映画版は見られていない）。&lt;/p&gt;
&lt;p&gt;それはさておき、アウトプットの話をするとSHIROBAKOのキャラの1人、ベテランアニメータである杉江さんの言葉がいつもよぎるのでご紹介します。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201217/20201217195637.png&quot; alt=&quot;f:id:ikmbear:20201217195637p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;「速く描くには上手くなる、上手く描くにはいっぱい描く、いっぱい描くには速く描く」&lt;br /&gt;
「技術とスピードは、実は全く別の問題でね」&lt;br /&gt;
「仕事へのこだわりは、手の速さを手に入れてから少しずつだな」&lt;/p&gt;
&lt;p&gt;う〜ん、何度聞いてもいい言葉🧝‍♀️&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#スモールアウトプットのすすめ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;スモールアウトプットのすすめ&lt;/h2&gt;
&lt;p&gt;さて&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;みんなが書いているようなすごい記事を書きたい&lt;/li&gt;
&lt;li&gt;内容を評価されたい&lt;/li&gt;
&lt;li&gt;しょぼい自分を晒したくない&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;こんなプライドに惑わされず、&lt;/p&gt;
&lt;p&gt;「速く描くには上手くなる、上手く描くにはいっぱい描く、いっぱい描くには速く描く」&lt;br /&gt;
「技術とスピードは、実は全く別の問題でね」&lt;br /&gt;
「仕事へのこだわりは、手の速さを手に入れてから少しずつだな」&lt;/p&gt;
&lt;p&gt;こんな風に数をこなすために、どうしたらいいのでしょうか。&lt;/p&gt;
&lt;p&gt;私は「&lt;strong&gt;一回のアウトプットの範囲を小さくする&lt;/strong&gt;」ことをおすすめします（まだ全然成果は出ていないけど、言いきりましょう）。&lt;/p&gt;
&lt;p&gt;小さな範囲にすることで&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;すぐ書ける&lt;/li&gt;
&lt;li&gt;たくさん書ける&lt;/li&gt;
&lt;li&gt;一つの記事のテーマが小さいので、見返りを求めなくなる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;というメリットがあります。具体的には次のようなツール・やり方をしています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#scrapboxを使ってみる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Scrapboxを使ってみる&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201217/20201217203951.png&quot; alt=&quot;f:id:ikmbear:20201217203951p&quot; /&gt;「$1と$1って似てない？」と思ってから、$1の面影を感じる芸能人を集めている&lt;a href=&quot;https://scrapbox.io/ikuma-t/&quot; target=&quot;_blank&quot;&gt;ikuma-t-kokoro&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;$1ブートキャンプの中でも、結構使われている方が多かったので、自分も使ってみたのですが、すぐにかけるのが非常に心地いいです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;記法はあるが、基本WYSIWIGで書ける&lt;/li&gt;
&lt;li&gt;下書きと公開の区別がない&lt;/li&gt;
&lt;li&gt;メモ同士がタグで結びつくので、あとあと大きなアウトプットにつなげる際にもまとめやすい&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;個人的には下書きモードがないというのが結構ポイントです。書いたものがそのまま曝け出されるので、ブログだったら「う〜ん仕上がりがいまいちだから、後悔はやめよう」と思っていたところが、自然と「まずは書いて公開しよう」というフローに変わりました。&lt;/p&gt;
&lt;p&gt;twitterやtwitterのように「誰がみた」「誰がいいねした」というのがないのも、プライドに惑わされずアウトプットするポイントです。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#stockrを使ってみる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Stockrを使ってみる&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201217/20201217210321.png&quot; alt=&quot;f:id:ikmbear:20201217210321p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;自分の場合は人に見せない記事でも、割とカチッとやらなければと思うタイプみたいなので、結構振り返りにも苦労していました。&lt;/p&gt;
&lt;p&gt;振り返りはしっかりやりたい&lt;br /&gt;
→振り返るための仕組みをNotionとかでかっちり作る&lt;br /&gt;
→毎日書くのが大変。&lt;br /&gt;
→大変だから振り返り自体をしなくなる&lt;/p&gt;
&lt;p&gt;そこで最近では&lt;a href=&quot;https://stockr.bldt.jp/&quot; target=&quot;_blank&quot;&gt;Stockr | 気づきの習慣化をサポートするアプリ&lt;/a&gt;を使用しています。&lt;/p&gt;
&lt;p&gt;これはtwitterみたいに振り返りをつぶやくと、毎朝7時に過去の振り返りをリマインドしてくれるだけのアプリです（どこにも共有されません）。&lt;/p&gt;
&lt;p&gt;こちらもシンプル故に、「振り返りのアウトプットをたくさんして、力に変えていく」という本来の目的を達成しやすくなりました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#日報は最低15分感想と書ければやったことがあればいいことにする&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;日報は最低15分、感想（と書ければやったこと）があればいいことにする&lt;/h3&gt;
&lt;p&gt;一時期勉強する時間はあったけど、$1ブートキャンプの学習記録=日報がとだえた時期がありました。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201218/20201218064529.png&quot; alt=&quot;f:id:ikmbear:20201218064529p&quot; /&gt;真ん中の青くない部分がそう&lt;/p&gt;
&lt;p&gt;復帰明けに書いていた日報には、こんなことが書いてあります。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;時間がない→5分だけでもやろう（実際にやる）→やったら日報書かなきゃ→（わかったことに書くことがなく）う〜ん、日報に書くほどのことはやっていないな→じゃあ今日は日報書かないでいいか→（…習慣が途切れる音…）今日もやらなくていいか…というのがモチベーション停滞の原因だったのかなと思います。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;この「日報に書くほどのことはやっていないな」というところに「日報はある程度のレベルに達しなければ、書いてはいけない」というプライドが感じられます😅&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# ✔︎やったこと# ✎学習したこと# ☞次にやること# ♨︎感想・余談&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;今も昔もテンプレートとしては上記のようなものを使用していますが、当時は「これを全て埋めないと提出できない！」と勝手に$1ラインを作ってしまっていました。&lt;/p&gt;
&lt;p&gt;この日報にメンターの方からは以下のコメントが。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;個人的には日報にはやったことと感じたことの2点があればOKかなと思ってます。さらにどちらか選べと言われたら「感じたこと」を取りますね。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;これ以来、書けなさそうな時はテンプレートを加工して、とりあえず以下の内容がかければいいことにしています。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# ✔︎やったこと# ♨︎感想・余談&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;…とはいいつつも、$1生の日報ってかなり面白いんですよね。それでついつい「自分も面白いもの・しっかりしたものを書かなければ」と思ってしまうんですが、日報が途絶えて思うことは「やっぱり日報を継続して書いているときは調子がいい」ということ。だからこそ、ちょっとしたことだけでも、まずは書くことが大切なんじゃないかな〜と思います。&lt;/p&gt;
&lt;p&gt;日報については、今回の$1で佐野さんが書かれているので、こちらもどうぞ！&lt;a href=&quot;https://mashoo1101.hatenablog.com/entry/2020/12/14/084200&quot; target=&quot;_blank&quot;&gt;日報を書こう! (日報自動投稿プログラムもあるヨ!) - 佐野 真潮(Mashio Sano)の個人日記&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#やっぱり出ない神本より出る糞本&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;やっぱり「出ない神本より出る糞本」&lt;/h2&gt;
&lt;p&gt;今回のこの記事も書きながら「こんなレベルでいいんかなあ」と思いながら、書き上げました。正直あんまり役に立たないかもしれないです。&lt;/p&gt;
&lt;p&gt;でも公開しなかったら、絶対に誰の役にも立ちません。公開したらもしかしたら誰かの役に立つかもです。もし誰の役に立たなかったとしても、自分が書いたという経験は積み上がります。積み上がった経験で書いた記事はきっと誰かの役に立ちます！&lt;/p&gt;
&lt;p&gt;…と、自分に言い聞かせて終わりたいと思います！みなさまもスモールアウトプットで素敵なアウトプット生活をお過ごしください👨‍👨‍👧‍👧&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>⚡️初めてのLT会 Vol.5でRubyMineの話をしました！</title><link>https://ikuma-t.com/blog/20201025130327/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20201025130327/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201025/20201025125820.jpg⚡️初めてのLT会V</description><pubDate>Sun, 25 Oct 2020 13:03:27 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201025/20201025125820.jpg&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201025/20201025125820.jpg&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201025/20201025125820.jpg&quot; alt=&quot;f:id:ikmbear:20201025125820j&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%EF%B8%8F%E5%88%9D%E3%82%81%E3%81%A6%E3%81%AELT%E4%BC%9A-Vol5%E3%81%AB%E5%8F%82%E5%8A%A0%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F&quot;&gt;⚡️初めてのLT会 Vol.5に参加しました！&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%8F%82%E5%8A%A0%E3%81%AE%E7%B5%8C%E7%B7%AF&quot;&gt;参加の経緯&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%89%8D%E5%9B%9E%E3%81%AELT%E4%BC%9A%E3%81%AB%E6%84%9F%E5%8C%96%E3%81%95%E3%82%8C%E5%8F%82%E5%8A%A0%E3%82%92%E6%B1%BA%E6%84%8F&quot;&gt;前回のLT会に感化され、参加を決意&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%83%86%E3%83%BC%E3%83%9E%E3%81%AF%E3%81%BC%E3%82%93%E3%82%84%E3%82%8A%E3%81%A8RubyMine%E3%82%92%E5%B8%83%E6%95%99%E3%81%99%E3%82%8B&quot;&gt;テーマはぼんやりと「RubyMineを布教する」&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E8%B3%87%E6%96%99%E4%BD%9C%E6%88%90&quot;&gt;資料作成&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E7%99%BA%E8%A1%A8%E5%86%85%E5%AE%B9%E3%82%92%E6%B1%BA%E3%82%81%E3%82%8B&quot;&gt;発表内容を決める&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#RubyMine%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E8%AA%BF%E3%81%B9%E3%82%8B&quot;&gt;RubyMineについて調べる&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E8%AA%BF%E3%81%B9%E3%81%9F%E3%81%93%E3%81%A8%E3%81%AB%E3%83%84%E3%83%83%E3%82%B3%E3%83%9F%E3%82%92%E5%85%A5%E3%82%8C%E3%82%8B&quot;&gt;調べたことにツッコミを入れる&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E6%89%8B%E6%9B%B8%E3%81%8D%E3%81%A7%E3%81%96%E3%81%A3%E3%81%8F%E3%82%8A%E3%81%A8%E8%A9%B1%E3%81%97%E3%81%9F%E3%81%84%E3%81%93%E3%81%A8%E3%82%92%E3%81%BE%E3%81%A8%E3%82%81%E3%82%8B&quot;&gt;手書きでざっくりと話したいことをまとめる&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%82%B9%E3%83%A9%E3%82%A4%E3%83%89%E4%BD%9C%E3%82%8AKeynote%E3%81%AB%E6%8C%91%E6%88%A6&quot;&gt;スライド作り/Keynoteに挑戦！&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E9%85%8D%E8%89%B2%E9%81%B8%E3%81%B3&quot;&gt;配色選び&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%83%AC%E3%82%A4%E3%82%A2%E3%82%A6%E3%83%88%E3%82%92%E8%80%83%E3%81%88%E3%82%8B&quot;&gt;レイアウトを考える&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%82%B9%E3%83%A9%E3%82%A4%E3%83%89%E5%AE%8C%E6%88%90%E7%B7%B4%E7%BF%92&quot;&gt;スライド完成！練習&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#1%E4%BA%BAweb%E7%99%BA%E8%A1%A8%E4%BC%9A&quot;&gt;1人web発表会&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#keynote%E3%81%AE%E3%82%B9%E3%83%A9%E3%82%A4%E3%83%89%E3%82%B7%E3%83%A7%E3%83%BC%E8%A8%98%E9%8C%B2%E6%A9%9F%E8%83%BD%E3%81%A7%E9%8C%B2%E9%9F%B3&quot;&gt;keynoteのスライドショー記録機能で録音&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%81%8A%E9%A2%A8%E5%91%82%E3%81%A7%E7%B7%B4%E7%BF%92&quot;&gt;お風呂で練習&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%BD%93%E6%97%A5%E3%83%AA%E3%83%8F%E3%83%BC%E3%82%B5%E3%83%AB&quot;&gt;当日リハーサル&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E6%9C%AC%E7%95%AA%E3%81%9F%E3%81%AE%E3%81%97%E3%81%8B%E3%81%A3%E3%81%9FLT%E4%BC%9A&quot;&gt;本番！たのしかったLT会！&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%81%8A%E3%81%BE%E3%81%91RubyMine%E3%81%AE%E3%81%AF%E3%81%98%E3%82%81%E3%81%AE%E4%B8%80%E6%AD%A9&quot;&gt;おまけ。RubyMineのはじめの一歩。&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%85%AC%E5%BC%8F%E3%83%98%E3%83%AB%E3%83%97%E3%82%92%E3%81%BF%E3%82%8B&quot;&gt;公式ヘルプをみる&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E6%97%A5%E6%9C%AC%E8%AA%9E%E5%8C%96%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%82%92%E5%85%A5%E3%82%8C%E3%82%8B&quot;&gt;日本語化プラグインを入れる&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#KeyPromoterX%E3%82%92%E5%B0%8E%E5%85%A5%E3%81%99%E3%82%8B&quot;&gt;KeyPromoterXを導入する&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E4%BB%8A%E6%97%A5%E3%81%AETips%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B&quot;&gt;今日のTipsを確認する&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%8F%82%E8%80%83&quot;&gt;参考&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E8%AA%BF%E6%9F%BB%E3%81%AE%E9%81%8E%E7%A8%8B%E3%81%A7%E8%AA%AD%E3%82%93%E3%81%A0%E8%A8%98%E4%BA%8B&quot;&gt;調査の過程で読んだ記事&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;&lt;a href=&quot;#️初めてのlt会-vol5に参加しました&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;⚡️初めてのLT会 Vol.5に参加しました！&lt;/h1&gt;
&lt;p&gt;昨日&lt;a href=&quot;https://bootcamp.fjord.jp/&quot; target=&quot;_blank&quot;&gt;FJORD BOOT CAMP（フィヨルドブートキャンプ）&lt;/a&gt;で開催された、ライトニング$1初心者のための発表会、「⚡️初めてのLT会 Vol.5」に参加しました！&lt;/p&gt;
&lt;p&gt;今回のテーマは「Rubyブートキャンプの歩み方🏃‍♂️」ということで、私は開発ツール「RubyMine」を使うことでRubyの学習が捗るよ〜という話をさせていただきました。&lt;/p&gt;
&lt;p&gt;文字通り初めてのLT参加だったので、参加に至る経緯〜発表を終えるまでを振り返ってみようと思います！&lt;/p&gt;
&lt;h1&gt;&lt;a href=&quot;#参加の経緯&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;参加の経緯&lt;/h1&gt;
&lt;h2&gt;&lt;a href=&quot;#前回のlt会に感化され参加を決意&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;前回のLT会に感化され、参加を決意&lt;/h2&gt;
&lt;p&gt;初めてのLT会は、今回でVol.5となるFJORD BOOT CAMPの継続コンテンツです。私が初めて参加したのはVol.4だったのですが、皆さんの発表を見て「自分もやってみたい」「こういう機会でやらなきゃ、死ぬとき絶対後悔する」と思い、その日の日報にやってみようかなと書いてみました（2020/8/22のこと）。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201025/20201025095220.png&quot; alt=&quot;f:id:ikmbear:20201025095220p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;この日報に心配ごとへのTipsや後押しのコメントをいただき、参加の決意を硬くしたのでした。&lt;strong&gt;後押しいただいたみなさま、ありがとうございます🙏&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#テーマはぼんやりとrubymineを布教する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;テーマはぼんやりと「RubyMineを布教する」&lt;/h2&gt;
&lt;p&gt;こちらも日報でのやりとりからです。&lt;/p&gt;
&lt;p&gt;メンターの&lt;a href=&quot;https://blog.jnito.com/&quot; target=&quot;_blank&quot;&gt;伊藤さん&lt;/a&gt;の「RubyMine布教してみては」というコメントから、「たしかに自分も使いこなせていないし、アウトプットを通じてRubyMineについて詳しくなるのもいいな」と感じ、ぼんやりと次の機会があったらRubyMineについて発表しようと思っていたのでした。&lt;/p&gt;
&lt;h1&gt;&lt;a href=&quot;#資料作成&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;資料作成&lt;/h1&gt;
&lt;h2&gt;&lt;a href=&quot;#発表内容を決める&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;発表内容を決める&lt;/h2&gt;
&lt;p&gt;前述の経緯から、ぼんやりと「RubyMineを布教しよう」ということは決まっていたのですが、具体的なところは未定状態でした。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#rubymineについて調べる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;RubyMineについて調べる&lt;/h3&gt;
&lt;p&gt;まずは情報収集ということで、RubyMineを知るところから始めました。&lt;/p&gt;
&lt;p&gt;ということで、世間一般で言われている「RubyMineどこがいいのよ」という話をかたっぱしから読んでみたり、公式マニュアルをみて試したことを$1（Xmindを使用）にまとめました。&lt;/p&gt;
&lt;p&gt;※実際に読んだ記事はこの記事の参考に載せているので、チェックしてみてください！&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201025/20201025101401.png&quot; alt=&quot;f:id:ikmbear:20201025101401p&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#調べたことにツッコミを入れる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;調べたことにツッコミを入れる&lt;/h3&gt;
&lt;p&gt;次は調べたことにツッコミ（本当にそれ便利なの？）を入れました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;コードジャンプでGemの中がみられるのは嬉しいけど、FJORD BOOT CAMPのプRubyティスではgemなしでRubyの課題解くよな&lt;/li&gt;
&lt;li&gt;rails系の機能って、後半戦にならないと使わないのよね。私もまだrailsやってないし&lt;/li&gt;
&lt;li&gt;SearchEverywhereもよく便利と言われるけど、ファイル1つで完結するようなRubyの課題ではそれほどメリット感じないよな（もちろんアクションとかの検索にも使えるけど）&lt;/li&gt;
&lt;li&gt;Gitもめちゃくちゃみやすいし使ってるけど、今のプRubyティスの順番だとRubyの方が先なんだよな&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;…などなど。ツッコミの結果から、競合分析ってほどではないですが、自分が話すことで他の人にメリットをありそうなところを確認。結果として「初心者=PureRubyでFJORD BOOT CAMPのRubyプRubyティスを進める人」への機能に絞って、発表することに決定しました。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201025/20201025103019.jpg&quot; alt=&quot;f:id:ikmbear:20201025103019j&quot; /&gt;&lt;/p&gt;
&lt;p&gt;あとから振り返ると、&lt;strong&gt;ペルソナを仮定して準備を進めると、発表の粒度の指針ができていいな&lt;/strong&gt;と感じました（今回だと、「IDEってなんのことか説明する」「RuboCopとは何かを説明する」など。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#手書きでざっくりと話したいことをまとめる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;手書きでざっくりと話したいことをまとめる&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201025/20201025104100.jpg&quot; alt=&quot;f:id:ikmbear:20201025104100j&quot; /&gt; 最初は手書き（ipadのGoodNotes5を利用）で、話したいことをどういう風にスライドを配置するかを考えます。&lt;/p&gt;
&lt;p&gt;またスライドを作るとどうしようもないネタ（およそ自己満足）が生まれることがあるので、そういうことを客観視するための機会でもあります。&lt;/p&gt;
&lt;p&gt;今回も「RuboCopハードモードってキャッチーでええやん！」と思いつきで書いてみたものの、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;全然本質ではない、そんなにキャッチーでもなく面白くもない&lt;/li&gt;
&lt;li&gt;話すときに文字数を食う&lt;/li&gt;
&lt;li&gt;RuboCopがゴゴゴしてるイラスト作るの大変&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;などの理由で手書きの段階で却下しました。&lt;/p&gt;
&lt;p&gt;この段階で30枚くらいのスライドになりそうだったので、全体のバランスをみながら集約できそうな情報はまとめ、いらない情報は削りました。&lt;/p&gt;
&lt;p&gt;よくビジネス本で言われることですが、&lt;strong&gt;スライドにいきなり取り掛かるとレイアウトに気がとられてしまうので&lt;/strong&gt;、まずは手書きがおすすめです（RuboCopのゴゴゴも、もしスライドにいきなり作っていたらサンクコストが原因で変なスライドになっていた可能性があります）。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#スライド作りkeynoteに挑戦&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;スライド作り/Keynoteに挑戦！&lt;/h2&gt;
&lt;p&gt;話すことが決まったら、実際にスライドに落とし込んでいきます。普段の仕事ではWindows、PowerPointユーザなので、今回Keynote初挑戦！&lt;/p&gt;
&lt;p&gt;せっかく初めて使う機会なので使い方を覚えるために、テンプレートを使用せずに一から自分で作って見ることにしました。&lt;/p&gt;
&lt;p&gt;PowerPointユーザがKeynoteを使ってみた感想はちょっと長そうなので、また別の記事で。今回はデザインの部分だけを簡単に。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#配色選び&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;配色選び&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;配色選びには&lt;a href=&quot;https://www.palettable.io&quot; target=&quot;_blank&quot;&gt;Palettable&lt;/a&gt;というサイトをよく使っています。&lt;/strong&gt; &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201025/20201025110511.png&quot; alt=&quot;f:id:ikmbear:20201025110511p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;このサイトでは表示された色に「Like」「DisLike」を選択していくだけで、自分の好きな色を使ったよさげなカラーパレットが出来上がります。&lt;/p&gt;
&lt;p&gt;今回はRubyMineのブランドカラーから、「赤系」と「黒系」をマストでチョイス。加えて配色の裏テーマとして、「錦鯉」を選び、錦鯉にはいってそうな色を「Like」していきました。（鯉の登竜門伝承と「はじめてのLT会は、LTの登竜門」というところでシンパシーを感じたのです😅） &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201025/20201025110905.png&quot; alt=&quot;f:id:ikmbear:20201025110905p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;というわけでできたカラーパレットがこちらです。実際には一番右は使っていなかったり、ディスプレイをみて赤の彩度を調整したりしてます。 &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201025/20201025110732.png&quot; alt=&quot;f:id:ikmbear:20201025110732p&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#レイアウトを考える&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;レイアウトを考える&lt;/h3&gt;
&lt;p&gt;今回のレイアウトはそんなに複雑ではないですが、一応ポイントはやっぱり「錦鯉」です笑。&lt;/p&gt;
&lt;p&gt;錦鯉の丸い模様をスライドのあしらいとして利用しました。なので表紙のスライドはこんな作りになっています。 &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201025/20201025123724.png&quot; alt=&quot;f:id:ikmbear:20201025123724p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;他にアクセントとして使っているのはふきだしですが、こちらはデザイン研究所というデザインのいろはを教えてくれるアカウントが呟いていた「プロっぽい$1の話」を参考に作りました。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://togetter.com/li/1608390&quot; target=&quot;_blank&quot;&gt;2日で1万人のフォロワーが増えた？ 話題の吹き出しデザインをプロっぽくするテクニック「プロと初心者のフキダシの違い」 - Togetter&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/designkenkyujo?s=20&quot; target=&quot;_blank&quot;&gt;twitter.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;&lt;a href=&quot;#スライド完成練習&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;スライド完成！練習&lt;/h1&gt;
&lt;h2&gt;&lt;a href=&quot;#1人web発表会&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;1人web発表会&lt;/h2&gt;
&lt;p&gt;今回はオンラインでの登壇なので（もちろん初）、見ている側の見え方を探るためにPC2台を用意し、zoomでプレゼンしてみました。&lt;/p&gt;
&lt;p&gt;すると当然ですが、&lt;strong&gt;オンライン故にスライドをめくるところにタイムラグがある&lt;/strong&gt;ことが判明。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201025/20201025112428.png&quot; alt=&quot;f:id:ikmbear:20201025112428p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;上図のような&lt;strong&gt;いわゆるLTっぽい、秒で通過するスライドが非常に使いづらい（話すタイミングとスライド切り替えのタイミングが若干ずれる）ことがわかった&lt;/strong&gt;ので、ほとんど消しました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#keynoteのスライドショー記録機能で録音&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;keynoteのスライドショー記録機能で録音&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201025/20201025112655.png&quot; alt=&quot;f:id:ikmbear:20201025112655p&quot; /&gt;  &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201025/20201025112816.png&quot; alt=&quot;f:id:ikmbear:20201025112816p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;keynoteにはスライドショーを記録してくれる機能があります（再生 &amp;gt; スライドショーを記録）。これを使うと、スライドの切り替えと音声を記録してくれます。&lt;/p&gt;
&lt;p&gt;自宅でmacで録音→iCloudで自動同期されるので、通勤中にiPadで確認、という感じでセmacビューを実施（iPadでは録音はできませんが、同じように全画面再生が可能）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;話していて練習不足以外で詰まるところは、そもそも論に無理がある&lt;/strong&gt;ので、スライドを適宜修正しました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#お風呂で練習&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;お風呂で練習&lt;/h2&gt;
&lt;p&gt;とはいえ嫁さんも家にいるので、録音を大体的にするのは恥ずかしかったりします。なので、お風呂でプレゼンの練習もしております。&lt;/p&gt;
&lt;p&gt;中学で生徒会長をやっているときから、演説の前には毎回お風呂で練習していたのですが、これがなんだかんだ一番きいている気がしますね〜。&lt;/p&gt;
&lt;h1&gt;&lt;a href=&quot;#当日リハーサル&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;当日リハーサル&lt;/h1&gt;
&lt;p&gt;当日の本番直前に配信テストをやったのですが、その際に&lt;strong&gt;表示されるスライドが思いのほか小さいことに気がつきました&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;そこそこデカイ字で書いていたつもりですが、見えない可能性を危惧して、本番開始前に少しだけ画像やフォントサイズを大きくしました。&lt;/p&gt;
&lt;p&gt;これがSpeakerDeckに上げている版。 &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201025/20201025114310.png&quot; alt=&quot;f:id:ikmbear:20201025114310p&quot; /&gt; こっちが当日用に大きくしたスライド。 &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201025/20201025114247.png&quot; alt=&quot;f:id:ikmbear:20201025114247p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ここらへんは前回のLT会の動画をみていれば気づけたので、もうちょっと研究しておくべきでした。&lt;/p&gt;
&lt;h1&gt;&lt;a href=&quot;#本番たのしかったlt会&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;本番！たのしかったLT会！&lt;/h1&gt;
&lt;p&gt;いよいよ本番。緊張しましたが、なんとか喋り切ることができました！（なんだかんだ本番が一番つまらずに喋ることができたという😅）&lt;/p&gt;
&lt;p&gt;この発表の後に、何人かRubyMineを試している方がいらっしゃって、「自分の経験したこと、調べたこと」が誰かの役に立つんだ！ととてもうれしく思いました😆&lt;/p&gt;
&lt;p&gt;皆さんも「自分のレベルでは話すことなんてないな」と思わず、**「自分の経験を自分の言葉でアウトプットすれば、まず自分の知識が深まる！そしてきっと誰かの役に立つ。」**と思ってぜひLTに登壇してみてください！&lt;/p&gt;
&lt;h1&gt;&lt;a href=&quot;#おまけrubymineのはじめの一歩&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;おまけ。RubyMineのはじめの一歩。&lt;/h1&gt;
&lt;p&gt;LT後の懇親会で、「どうやってRubyMineの使い方を覚えました？」と聞かれたので、ざっくりと。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#公式ヘルプをみる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;公式ヘルプをみる&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201025/20201025115517.png&quot; alt=&quot;f:id:ikmbear:20201025115517p&quot; /&gt; &lt;a href=&quot;https://pleiades.io/help/ruby/get-started.html#gsc.tab=0&quot; target=&quot;_blank&quot;&gt;RubyMine 入門 - 公式ヘルプ | RubyMine&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;RubyMineには公式で日本語ヘルプがあります。インストール含めて必要な機能は大体ここにあるので、まずはここを見るのがいいと思います。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#日本語化1を入れる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;日本語化$1を入れる&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201025/20201025115905.png&quot; alt=&quot;f:id:ikmbear:20201025115905p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;RubyMineを日本語にするには、日本語化パッケージを別途配置して設定ファイルに記述する方法と$1を使用する方法があるのですが、後者がおすすめです。&lt;/p&gt;
&lt;p&gt;どちらも日本語訳の範囲と訳語のレベルはそこまで変わらないのですが、$1の場合は切り替えが楽（設定の書き換えが不要）だというメリットがあります。&lt;/p&gt;
&lt;p&gt;機能を知りたい！という意味では日本語の方がわかりやすいのですが、プログラミングで使う用語は英語の方がわかりやすいことが多いです。例えば、「属性アクセサー」より「attribute accessor」の方が個人的にはわかりやすい気がします（人によるのかもですが…）。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201025/20201025120415.png&quot; alt=&quot;f:id:ikmbear:20201025120415p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;こういうときに気軽に言語をスイッチできた方が個人的には便利かな〜と思うので、$1の方がおすすめです！&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#keypromoterxを導入する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;KeyPromoterXを導入する&lt;/h2&gt;
&lt;p&gt;RubyMineではどんなことでもShift二回押せば検索できるのですが、より適切なショートカットを覚えて直接起動できた方が、効率的に作業できます。&lt;/p&gt;
&lt;p&gt;ショートカット を覚えるのに便利な$1が「KeyPromoterX」です。 &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201025/20201025120918.png&quot; alt=&quot;f:id:ikmbear:20201025120918p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;この$1は、ショートカットが割り当てされているメニューをクリックで起動すると、そのショートカットと今までショートカット を忘れた回数を表示してくれます。&lt;/p&gt;
&lt;p&gt;&lt;a&gt;RubyMine 公式ショートカット一覧 (日本語版) Mac&lt;/a&gt;と一緒にショートカットを覚えるのがおすすめです！&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#今日のtipsを確認する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;今日のTipsを確認する&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201025/20201025121247.png&quot; alt=&quot;f:id:ikmbear:20201025121247p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ヘルプメニューの中に今日のTipsということで、RubyMineの便利機能を教えてくれるメニューがあります（非表示にしていなければ起動時に勝手に出現するはず）。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20201025/20201025121417.png&quot; alt=&quot;f:id:ikmbear:20201025121417p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;開発の息抜きがてら、「こんな機能あるのね〜」と覚えてみるのもいいかもです。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;以上、初めてのLT会参加レポでした〜。&lt;/p&gt;
&lt;h1&gt;&lt;a href=&quot;#参考&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;参考&lt;/h1&gt;
&lt;h2&gt;&lt;a href=&quot;#調査の過程で読んだ記事&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;調査の過程で読んだ記事&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://speakerdeck.com/morizyun/rubymine-falseiitokoro?slide=5&quot; target=&quot;_blank&quot;&gt;IntelliJ IDEA / RubyMine のいいところ - Speaker Deck&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@jiraffestaff/rubymine%E3%81%A7%E5%B9%B8%E3%81%9B%E3%81%AB%E3%81%AA%E3%81%A3%E3%81%9F%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%AE%E8%A9%B1-613266cd92c1&quot; target=&quot;_blank&quot;&gt;RubyMineで幸せになったエンジニアの話. はじめまして。エンジニア山本(女)です。… | by 株式会社ジラフ | Medium&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pavlog.tokyo/entry/rubymine-preview&quot; target=&quot;_blank&quot;&gt;【必読】開発者が「RubyMine」を使ってはいけない4つの理由【JetBrains】 - pavlog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://hogesuke.hateblo.jp/entry/2014/08/10/031812&quot; target=&quot;_blank&quot;&gt;IntelliJ IDEAのいいところ10選 - 無理しない感じ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://employment.en-japan.com/engineerhub/entry/2020/01/09/103000&quot; target=&quot;_blank&quot;&gt;IntelliJ IDEAをもっと便利で使いやすく！ つまずきがちな設定や、便利な機能を細かに解説します。 - エンジニアHub｜若手Webエンジニアのキャリアを考える！&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://employment.en-japan.com/engineerhub/entry/2020/01/09/103000#IntelliJ-IDEA%E3%81%AF%E6%9C%89%E5%84%9F%E3%81%AEIDE&quot; target=&quot;_blank&quot;&gt;IntelliJ IDEAをもっと便利で使いやすく！ つまずきがちな設定や、便利な機能を細かに解説します。 - エンジニアHub｜若手Webエンジニアのキャリアを考える！&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://morizyun.github.io/blog/intellij-rubymine-jetbrain-good-point/&quot; target=&quot;_blank&quot;&gt;複数言語を使うならRubyMine/IntelliJオススメ！ | 酒と涙とRubyとRailsと&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://qiita.com/akiko-pusu/items/1caa46bb1fd2f0c60916&quot; target=&quot;_blank&quot;&gt;ここが好きだよIntelliJ - Qiita&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kei178.me/programming/1143/&quot; target=&quot;_blank&quot;&gt;Rails専門エディタRubyMineを購入した理由 - Kei178’s blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://qiita.com/ruzia/items/2edd8d45c16ac2c70dd7&quot; target=&quot;_blank&quot;&gt;RubyMine が気になる人に捧ぐ、ざっくり入門編 - Qiita&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://samuraism.com/2020/09/13/11795&quot; target=&quot;_blank&quot;&gt;#JetBrainsIDEテクニック Presentation Assistant | 株式会社サムライズム&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://qiita.com/spring_aki/items/04c229a771e44396c4fd&quot; target=&quot;_blank&quot;&gt;RubyMineで簡単に行ごとのコミットログを見る方法 (Annotate,Blame) - Qiita&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://qiita.com/mnuma/items/05b6cb759e880a09bef5&quot; target=&quot;_blank&quot;&gt;RubyMineでリファクタリングいくつか - Qiita&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://qiita.com/jnchito/items/762595fad3aff6d00c19&quot; target=&quot;_blank&quot;&gt;RubyMineアドベントカレンダー2014で集まった質問に回答します - Qiita&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://qiita.com/Avene/items/756c17f87d28d2ee47a4#%E3%83%9E%E3%83%8B%E3%82%A2%E3%83%83%E3%82%AF%E3%81%A0%E3%81%91%E3%81%A9%E8%B6%85%E4%BE%BF%E5%88%A9%E3%81%AA%E3%82%B3%E3%83%BC%E3%83%89%E3%82%B8%E3%83%A3%E3%83%B3%E3%83%974%E3%81%A4&quot; target=&quot;_blank&quot;&gt;知らないと損?RubyMine(IntelliJ)で役立つ細かいテクニック７つ - Qiita&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://qiita.com/ABE_TAKASHI/items/fc3c5432d22d7b4bcf36&quot; target=&quot;_blank&quot;&gt;PhpStorm 2020.1からの日本語化は純正のJapanese Language Packプラグインがいいみたい - Qiita&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://qiita.com/jnchito/items/a3bf917947d87b0b41ac&quot; target=&quot;_blank&quot;&gt;RubyMineでコミットメッセージだけをamendで修正する方法 - Qiita&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://qiita.com/Sayatam/items/2ae8bc47386e9ac21a31&quot; target=&quot;_blank&quot;&gt;JetBrains エディターの便利な機能まとめ(RubyMineで検証) - Qiita&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.mothule.com/tools/rubymine/tools-rubymine-how-to-conditioned-breakpoint&quot; target=&quot;_blank&quot;&gt;RubyMineで条件付きブレイクポイントを使いこなす方法 - もちゅろぐ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://qiita.com/iwaseasahi/items/e59ac503373adf1a7f11#:~:text=%E6%A6%82%E8%A6%81,%E5%AF%BE%E5%BF%9C%E3%81%99%E3%82%8B%E5%BF%85%E8%A6%81%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82&quot; target=&quot;_blank&quot;&gt;RubyMine：Macで日本語対応 - Qiita&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>ikuma-t</author></item><item><title>今月のフォカッチャ〜ドライトマトのフォカッチャ〜【2020/08】</title><link>https://ikuma-t.com/blog/20200913185817/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20200913185817/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200913/20200913185635.jpg今月のフォカッチャは</description><pubDate>Sun, 13 Sep 2020 18:58:17 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200913/20200913185635.jpg&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200913/20200913185635.jpg&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#今月のフォカッチャは1のフォカッチャです&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;今月のフォカッチャは$1のフォカッチャです&lt;/h2&gt;
&lt;p&gt;同じレシピだとブログネタとして代わり映えしないので、今月は$1のフォカッチャです。&lt;/p&gt;
&lt;p&gt;…って言っても、この前のフォカッチャに$1のっけただけですが。（そしてしれっとまた月を跨いでいる）&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#レシピ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;レシピ&lt;/h2&gt;
&lt;p&gt;今日は昼も夜もフォカッチャを食べたいというリク$1トにお応えして、いつもの2倍量で作ります&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;パン生地&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;強力粉：600g&lt;/li&gt;
&lt;li&gt;塩：10g&lt;/li&gt;
&lt;li&gt;砂糖：10g&lt;/li&gt;
&lt;li&gt;$1：10g&lt;/li&gt;
&lt;li&gt;オリーブオイル：20g&lt;/li&gt;
&lt;li&gt;水：400g&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;トッピング&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$1（オイル漬け）：適量&lt;/li&gt;
&lt;li&gt;バジル・$1：適量&lt;/li&gt;
&lt;li&gt;岩塩：好きなだけ。適量&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#環境&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;環境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;室温：26℃&lt;/li&gt;
&lt;li&gt;オーブン：SHARP　RE-S70A&lt;/li&gt;
&lt;li&gt;ゴムベラ：セリアで買った100円のゴムベラ&lt;/li&gt;
&lt;li&gt;ボウル：$1のボウル（もらいもの）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#作り方&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;作り方&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#混ぜる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;混ぜる&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200913/20200913181603.jpg&quot; alt=&quot;f:id:ikmbear:20200913181603j&quot; /&gt;&lt;/p&gt;
&lt;p&gt;前回同様、ひたすら混ぜます。今回と前回の相違点は「作る量が倍である」という点です。&lt;/p&gt;
&lt;p&gt;倍だからといって、混ぜる時間が倍になるとか、混ぜる労力が倍になるということはありませんが、量が増えたことで気にしなければならない点が出てきます。それは「だま」ができやすくなることです。&lt;/p&gt;
&lt;p&gt;$1がかなりだまになりやすく、またオリーブオイルも水を挟まないで直接粉にかけるとそこでだまができます。&lt;/p&gt;
&lt;p&gt;というわけで、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;粉はあらかじめ全部混ぜておく&lt;/li&gt;
&lt;li&gt;オリーブオイルは水を入れた後、水のある場所に注ぐ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;といった工夫が必要です。&lt;/p&gt;
&lt;p&gt;今回のTipsは手間もほぼ変わらず、半量でも効果があるので「パンを作るときはすべからくそうすべし」と鵜呑みにしてしまってもよいのですが、必ずしもそうではないですよね。&lt;/p&gt;
&lt;p&gt;「ある一定の規模なら効果があるけど、少ない量の時は全然効果ないし、ただの手間」というならやるべきではないわけです。&lt;/p&gt;
&lt;p&gt;「大規模になることで、小規模では見えなかった問題点が顕在化し、それに対して先人たちは知恵を残し、その恩恵を後に続く人が享受する。お前はただ利益のみを享受するのではなく、その背景をしっかり把握しなさい」と、またパン生地に教えられました。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200913/20200913181722.jpg&quot; alt=&quot;f:id:ikmbear:20200913181722j&quot; /&gt;&lt;/p&gt;
&lt;p&gt;とか言いながらオリーブオイル直接入れました。教え忘れちゃいました。忘れちゃいましたけど何か？（真顔）&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#一次発酵&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;一次発酵&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200913/20200913181801.jpg&quot; alt=&quot;f:id:ikmbear:20200913181801j&quot; /&gt; いい感じに混ぜ終わったら、ラップをして1hくらい発酵させます。 &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200913/20200913181828.jpg&quot; alt=&quot;f:id:ikmbear:20200913181828j&quot; /&gt; 気温が高いとサクサク発酵してくれるので楽チンですね。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#分割ベンチタイム&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;分割・ベンチタイム&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200913/20200913181901.jpg&quot; alt=&quot;f:id:ikmbear:20200913181901j&quot; /&gt; 今回は倍量なので、生地を2つに分割し、あとで成形しやすいように軽くまるめておきます&lt;/p&gt;
&lt;p&gt;（あまり丸めすぎると、生地がしまってしまい成形までに時間がかかるので、軽めにします）。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#成形二次発酵1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;成形・二次発酵・$1&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200913/20200913181923.jpg&quot; alt=&quot;f:id:ikmbear:20200913181923j&quot; /&gt;&lt;/p&gt;
&lt;p&gt;まるめた生地を麺棒で伸ばし、型にはいる大きさにします。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200913/20200913181947.jpg&quot; alt=&quot;f:id:ikmbear:20200913181947j&quot; /&gt; フォカッチャは$1中の破裂を防ぐために生地にくぼみをぷすぷすと刺すのですが、今回はこのくぼみに$1をつっこんでいきます。&lt;/p&gt;
&lt;p&gt;ちなみに今回のトッピングはこの人たちです。$1はカルディで買いました（700~800円くらい）。こいつのせいで原価爆上がりです。 &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200913/20200913182017.jpg&quot; alt=&quot;f:id:ikmbear:20200913182017j&quot; /&gt;&lt;/p&gt;
&lt;p&gt;トッピング量ですが、以下のような基準でふりかけています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$1：フォカッチャに開いた穴の分だけ。穴を開ければ開けるほど、家庭に穴が開く。&lt;/li&gt;
&lt;li&gt;バジル・$1：好きなだけ。$1自体が割と$1風味だったので、今回はバジルの方が多め。&lt;/li&gt;
&lt;li&gt;岩塩：好きなだけ。目玉焼きに醤油とかソースをかける感覚で、「このパンにちょっと塩降るならこんなもんかな〜」と自分が思う量。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;焼いている間も生地は膨らむので、生半可な気持ちで$1をつっこむと、焼き上がりに$1が浮いてしまいます。なので「これはお前のためにやっているんだよ」という気持ちで、容赦無く$1をめり込ませます。 &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200913/20200913182050.jpg&quot; alt=&quot;f:id:ikmbear:20200913182050j&quot; /&gt;&lt;/p&gt;
&lt;p&gt;生地を二等分したので、片方は$1、もう片方はさらにチーズをトッピングして$1です（チーズの方は撮り忘れました）。 &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200913/20200913185635.jpg&quot; alt=&quot;f:id:ikmbear:20200913185635j&quot; /&gt;&lt;/p&gt;
&lt;p&gt;焼きは250℃に余熱したオーブンで20分前後（家庭用オーブンは癖が強く火力も弱いので、適宜調整してください）です。&lt;/p&gt;
&lt;p&gt;うちのオーブンのサイズでは一つしか入らないので、ちゃんと二次発酵すると2枚目が過発酵気味になります。なので、&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;1枚目の生地を成形する&lt;/li&gt;
&lt;li&gt;オーブンの余熱を始める&lt;/li&gt;
&lt;li&gt;2枚目の生地を成形する、余熱が終わり次第1枚目をオーブンに入れる&lt;/li&gt;
&lt;li&gt;1枚目が焼け次第、2枚目を焼く&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;という感じで作業をすると、1枚目は微妙に発酵足りない感じ、2枚目はまあまあいい感じで仕上がります。まあでもあんまり厳密にやらなくても美味いから大丈夫です。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#完成&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;完成&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200913/20200913185658.jpg&quot; alt=&quot;f:id:ikmbear:20200913185658j&quot; /&gt; うわ〜うまい！うますぎる〜！ただのピザ〜〜〜&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;もう焼く前からすでに美味いという確信があったのですが、実際にめちゃめちゃおいしかったです。&lt;/p&gt;
&lt;p&gt;オイル漬けの$1の場合、惜しみなくそのオイルをパンに塗っておくと、トマトがない部分もトマトの味がしていいなあと思いました。&lt;/p&gt;
&lt;p&gt;次回は何フォカッチャにするかな〜。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>【RubyMine】デバッグ時、requireで怒られたときの対処法（小ネタ）</title><link>https://ikuma-t.com/blog/20200815155129/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20200815155129/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200815/20200815154953.pngRubyMine小ネ</description><pubDate>Sat, 15 Aug 2020 15:51:29 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200815/20200815154953.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200815/20200815154953.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;RubyMine小ネタです。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#byebugを無視した罰当たり&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Byebugを無視した罰当たり&lt;/h2&gt;
&lt;p&gt;本日チェリー本でByebugを覚えました。&lt;/p&gt;
&lt;p&gt;「覚えたからって関係ねえ、Byebugを使用せずに私はRubyMineで$1をやるんだ」と$1を試みたところ、デバッガが異常終了してしまいました。これは罰当たりか…？&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Uncaught exception: cannot load such file -- ./lib/effects    /Users/username/RubymineProjects/ruby-book/lib/word_synth.rb:1:in `require&apos;    /Users/username/RubymineProjects/ruby-book/lib/word_synth.rb:1:in `&amp;lt;top (required)&amp;gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#原因は1の構成&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;原因は$1の構成&lt;/h2&gt;
&lt;p&gt;$1から通常通り実行していた際は、以下のrequireで問題なく動いていました。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;require &apos;./lib/effects&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これを以下のように書き換えてあげるとうまく実行できるようになります。つまりシェルからの実行時と、Rubymineのデバッガでは$1の基準点がずれているわけです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;require &apos;./effects&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;ではカレント$1リがどこで決まっているかというと、画面右上のプルダウンをクリックすると展開されるので… &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200815/20200815154953.png&quot; alt=&quot;f:id:ikmbear:20200815154953p&quot; /&gt; その中のEdit Configrationsを押すと、各ファイルごとの設定をみることができます。 &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200815/20200815154609.png&quot; alt=&quot;f:id:ikmbear:20200815154609p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;上図内赤枠の「Working Directory」が$1の基準点になるので、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;このパスを書き換える&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;もしくは&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;実行ファイルのrequireのパスを書き換える&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ことで、$1実行が正しくできるようになりました。&lt;/p&gt;
&lt;p&gt;以$1ネタでした〜。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>RubyMineのIdeaVimで、jjをEscにマッピングする方法</title><link>https://ikuma-t.com/blog/20200814081503/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20200814081503/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200814/20200814073502.pngタイトルの通り設定し</description><pubDate>Fri, 14 Aug 2020 08:15:03 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200814/20200814073502.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200814/20200814073502.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;タイトルの通り設定しました。設定の再読み込みが$1からうまく実行できなかったですが（現在も原因はわからぬまま）、とりあえず設定自体はできたので書きます。&lt;/p&gt;
&lt;p&gt;結論以降は試行錯誤の記録なので、設定方法だけわかればいいという方は飛ばしてください。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#結論&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;結論&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;~/.ideavimrcを開く&lt;/li&gt;
&lt;li&gt;&lt;code&gt;imap jj &amp;lt;Esc&amp;gt;&lt;/code&gt;を入力して保存&lt;/li&gt;
&lt;li&gt;RubyMineを再起動&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;&lt;a href=&quot;#環境&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;環境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;macOS Catalina 10.15.6&lt;/li&gt;
&lt;li&gt;RubyMine &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200814/20200814073502.png&quot; alt=&quot;f:id:ikmbear:20200814073502p&quot; /&gt;&lt;/li&gt;
&lt;li&gt;シェル：zsh&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#ideavimrcにキー1を追記&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;~/.ideavimrcにキー$1を追記&lt;/h2&gt;
&lt;p&gt;デフォルトのキー$1だけで頑張ってきたのですが、Escはどうも手が届かないので&lt;code&gt;jj&lt;/code&gt;に変更しようと思い、下記参考に設定しました。&lt;br /&gt;
&lt;a href=&quot;https://stackoverflow.com/questions/25560616/intellij-ideavim-how-to-set-key-map-for-esc&quot; target=&quot;_blank&quot;&gt;vim - Intellij Ideavim how to set key map for - Stack Overflow&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;具体的には&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% vim ~/.ideavimrc&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;もしくは、RubyMineの画面右下にIdeaVimのアイコンがあるので、そこから開いても良しです。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200814/20200814074338.png&quot; alt=&quot;f:id:ikmbear:20200814074338p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;そして、.ideavimrcに&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;imap jj &amp;lt;Esc&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;と記述して、保存。ここまでは何も問題ありませんでした。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#1からの再読み込みがうまくいかない&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;$1からの再読み込みがうまくいかない&lt;/h2&gt;
&lt;p&gt;こういう設定ファイルの常ですが、設定を追記したら再読み込みしないと設定が適用されません。&lt;/p&gt;
&lt;p&gt;というわけで再読み込みを実行するわけですが…&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% source ~/.vimrc.ideavimrc:1: parse error near `&amp;gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;う〜ん、&amp;gt;付近で解析できなかったと言われてもコマンドはこれだしなあ…。いろいろググって、似たような事例で「”」で囲むといいよという例あり。試してみる。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://stackoverflow.com/questions/22278748/zsh-parse-error-near-n-when-adding-aws-keys-as-environment-variables&quot; target=&quot;_blank&quot;&gt;ruby on rails - zsh: parse error near `\’ when Adding AWS keys as environment variables - Stack Overflow&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% vim ~/.ideavimrc# シングルクォートで囲むimap jj &apos;&amp;lt;Esc&amp;gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;そして実行&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% source ~/.ideavimrccommand not found: imap&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;imapコマンドがないと言われてしまえば、もうお手上げ。残念無念また来年。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#rubymine自体を再起動しました&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;RubyMine自体を再起動しました&lt;/h2&gt;
&lt;p&gt;結局RubyMine自体を再起動すれば、設定ファイルは読み込みされるので再起動しました。&lt;/p&gt;
&lt;p&gt;ちなみに、現在起動中のプロジェクトを閉じると、プロジェクト選択ウィンドウが出ますが、こちらも閉じないと再起動にはなりませんのでご注意を。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200814/20200814075447.png&quot; alt=&quot;f:id:ikmbear:20200814075447p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;再起動すると、無事に&lt;code&gt;jj&lt;/code&gt;でINSERT MODEから抜けられるようになりました…！？ &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200814/20200814075834.gif&quot; alt=&quot;f:id:ikmbear:20200814075834g&quot; /&gt;&lt;/p&gt;
&lt;p&gt;NORMAL MODEにはなっているのですが、「”」が入ってしまいました。これは先ほどの試行錯誤で&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% vim ~/.ideavimrc# シングルクォートで囲むimap jj &apos;&amp;lt;Esc&amp;gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;としたせいです。つまり「&lt;code&gt;jj&lt;/code&gt;というキーをおしたら、&lt;code&gt;&apos;&apos;&lt;/code&gt;を入力して、‘Esc’するよ」という$1になってしまいました。なので元の通りの設定に直しておきましょう。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% vim ~/.ideavimrc# シングルクォートを除外するimap jj &amp;lt;Esc&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#bashでも試してみる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;bashでも試してみる&lt;/h2&gt;
&lt;p&gt;たまにzsh特有のエラーである可能性もあるので、RubyMineのシェルをbashに変更して試してみます。シェルの変更方法は&lt;a href=&quot;https://pleiades.io/help/ruby/terminal-emulator.html&quot; target=&quot;_blank&quot;&gt;ターミナル - 公式ヘルプ | RubyMine&lt;/a&gt;を参照しています。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200814/20200814080703.png&quot; alt=&quot;f:id:ikmbear:20200814080703p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Prefereceを開き、TerminalメニューにあるShellPathを&lt;code&gt;/bin/bash&lt;/code&gt;に変更します。 &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200814/20200814080849.png&quot; alt=&quot;f:id:ikmbear:20200814080849p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;APPLYを押して、設定を閉じます。ターミナルを一度閉じてもう一度開くと、bashに切り替わるので、zshと同じように試してみます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$ source ~/.ideavimrcsyntax error near unexpected token `newline&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;bashでもzshと同様にエラーが出てしまいました。どうやら大人しくRubyMineを再起動した方が良さそうですね。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;結局$1からの再読み込みはできずじまいで、少しもやもやです。そんな頻繁に設定いじらないからいいんですけどね。&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>フィヨルドブートキャンプに入って1ヶ月が経ちました</title><link>https://ikuma-t.com/blog/20200811114419/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20200811114419/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200810/20200810130426.png$1ブートキャンプに</description><pubDate>Tue, 11 Aug 2020 11:44:19 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200810/20200810130426.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200810/20200810130426.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200810/20200810130426.png&quot; alt=&quot;f:id:ikmbear:20200810130426p&quot; /&gt;$1ブートキャンプに入ってから、1ヶ月が経過しました〜。せっかくなので、この1ヶ月を振り返っていきたいと思います。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#1%E3%83%B6%E6%9C%88%E3%81%A7%E3%82%84%E3%81%A3%E3%81%A6%E3%81%8D%E3%81%9F%E3%81%93%E3%81%A8&quot;&gt;1ヶ月でやってきたこと&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%81%A9%E3%81%AE%E3%81%8F%E3%82%89%E3%81%84%E5%8B%89%E5%BC%B7%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F%E3%81%8B&quot;&gt;どのくらい勉強しましたか？&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E4%BD%95%E3%81%8C%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%AA%E3%81%A3%E3%81%9F%E3%82%93%E3%81%A7%E3%81%99%E3%81%8B&quot;&gt;何ができるようになったんですか？&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E7%8B%AC%E5%AD%A6%E3%82%92%E3%82%84%E3%82%81%E3%81%9F%E3%81%93%E3%81%A8%E3%81%A7%E9%A2%A8%E5%90%91%E3%81%8D%E3%81%AF%E5%A4%89%E3%82%8F%E3%82%8A%E3%81%BE%E3%81%97%E3%81%9F%E3%81%8B&quot;&gt;独学をやめたことで風向きは変わりましたか？&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E6%96%B9%E5%90%91%E6%80%A7%E3%81%8C%E8%A6%8B%E3%81%88%E3%81%9F%E3%81%93%E3%81%A8%E3%81%A7%E5%85%88%E3%81%AB%E9%80%B2%E3%82%81%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%AA%E3%81%A3%E3%81%9F&quot;&gt;方向性が見えたことで、先に進めるようになった&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%AD%A6%E7%BF%92%E6%99%82%E9%96%93%E3%82%92%E7%B4%94%E7%B2%8B%E3%81%AB%E6%8A%80%E8%A1%93%E3%82%92%E7%BF%92%E5%BE%97%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E6%99%82%E9%96%93%E3%81%AB%E5%BD%93%E3%81%A6%E3%82%89%E3%82%8C%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%AA%E3%81%A3%E3%81%9F&quot;&gt;学習時間を純粋に「技術を習得するための時間」に当てられるようになった&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%83%95%E3%82%A3%E3%83%A8%E3%83%AB%E3%83%89%E3%83%96%E3%83%BC%E3%83%88%E3%82%AD%E3%83%A3%E3%83%B3%E3%83%97%E3%82%921%E3%83%B6%E6%9C%88%E9%96%93%E3%81%A4%E3%81%A5%E3%81%91%E3%81%A6%E3%81%84%E3%81%A6%E8%BE%9B%E3%81%84%E3%81%93%E3%81%A8%E3%81%AF%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%81%8B&quot;&gt;フィヨルドブートキャンプを1ヶ月間つづけていて、辛いことはありますか？&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%AD%A6%E7%BF%92%E3%81%AE%E7%B6%99%E7%B6%9A%E3%81%AB%E5%BD%B9%E7%AB%8B%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B%E4%BB%95%E7%B5%84%E3%81%BF&quot;&gt;学習の継続に役立っている仕組み&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#todoist&quot;&gt;todoist&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#Notion&quot;&gt;Notion&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#1%E3%83%95%E3%82%A3%E3%83%A8%E3%83%AB%E3%83%89%E3%83%96%E3%83%BC%E3%83%88%E3%82%AD%E3%83%A3%E3%83%B3%E3%83%97%E3%81%AE%E5%AD%A6%E7%BF%92%E8%A8%88%E7%94%BB%E7%AE%A1%E7%90%86%E3%82%86%E3%82%8B%E3%82%81&quot;&gt;1.フィヨルドブートキャンプの学習計画管理（ゆるめ）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#2%E5%AD%A6%E7%BF%92%E3%83%A1%E3%83%A2%E3%81%A8%E5%8F%82%E8%80%83%E8%A8%98%E4%BA%8B%E3%81%AE%E3%82%B9%E3%83%88%E3%83%83%E3%82%AF&quot;&gt;2.学習メモと参考記事のストック&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#3%E3%83%93%E3%82%B8%E3%83%A5%E3%82%A2%E3%83%AB%E6%8B%85%E5%BD%93&quot;&gt;3.ビジュアル担当&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E6%9C%9D%E5%8B%89%E5%BC%B7%E3%81%A7%E3%81%8D%E3%81%9F%E3%82%AB%E3%83%AC%E3%83%B3%E3%83%80%E3%83%BC&quot;&gt;朝勉強できたカレンダー&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E6%9C%9D%E3%81%AE%E3%82%82%E3%81%8F%E3%82%82%E3%81%8F%E4%BC%9A&quot;&gt;朝のもくもく会&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%83%95%E3%82%A3%E3%83%A8%E3%83%AB%E3%83%89%E3%83%96%E3%83%BC%E3%83%88%E3%82%AD%E3%83%A3%E3%83%B3%E3%83%97%E3%81%AE%E6%97%A5%E5%A0%B1%E3%81%B8%E3%81%AE%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88&quot;&gt;フィヨルドブートキャンプの日報へのコメント&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%83%95%E3%82%A3%E3%83%A8%E3%83%AB%E3%83%89%E3%83%96%E3%83%BC%E3%83%88%E3%82%AD%E3%83%A3%E3%83%B3%E3%83%97%E3%81%AE%E8%8A%9D&quot;&gt;フィヨルドブートキャンプの芝&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%AD%A6%E7%BF%92%E3%81%AE%E7%B6%99%E7%B6%9A%E3%81%AB%E5%BD%B9%E7%AB%8B%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B%E8%80%83%E3%81%88%E6%96%B9&quot;&gt;学習の継続に役立っている考え方&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%AF%E9%9D%A2%E7%99%BD%E3%81%84&quot;&gt;プログラミングは面白い&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E7%BF%92%E6%85%A3%E5%8C%96%E3%81%AE%E6%B3%95%E5%89%87%E3%81%AB%E3%81%AE%E3%81%A3%E3%81%8B%E3%82%8B&quot;&gt;習慣化の法則にのっかる&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E6%96%B0%E3%81%97%E3%81%84%E3%81%93%E3%81%A8%E3%82%92%E5%AD%A6%E3%81%B6%E6%99%82%E3%81%AF%E9%83%B7%E3%81%AB%E5%85%A5%E3%81%A3%E3%81%A6%E3%81%AF%E9%83%B7%E3%81%AB%E5%BE%93%E3%81%88%E3%81%AE%E7%B2%BE%E7%A5%9E&quot;&gt;新しいことを学ぶ時は「郷に入っては郷に従え」の精神&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E4%BA%BA%E3%81%AB%E3%81%AF%E4%BA%BA%E3%81%AE%E4%B9%B3%E9%85%B8%E8%8F%8C%E3%81%AE%E7%B2%BE%E7%A5%9E&quot;&gt;「人には人の乳酸菌」の精神&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%95%8F%E9%A1%8C%E3%82%92%E8%A7%A3%E3%81%8F%E6%99%82%E3%81%AF%E3%82%B7%E3%83%A3%E3%83%BC%E3%83%9A%E3%83%B3%E3%81%98%E3%82%83%E3%81%AA%E3%81%84%E3%83%9C%E3%83%BC%E3%83%AB%E3%83%9A%E3%83%B3%E3%81%A7%E3%81%AE%E7%B2%BE%E7%A5%9E&quot;&gt;問題を解く時は「シャーペンじゃない、ボールペンで」の精神&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%81%93%E3%82%8C%E3%81%8B%E3%82%89%E3%81%AE%E8%A9%B1%E3%81%96%E3%81%A3%E3%81%8F%E3%82%8A&quot;&gt;これからの話（ざっくり）&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%82%A2%E3%82%A6%E3%83%88%E3%83%97%E3%83%83%E3%83%88%E3%82%92%E7%BF%92%E6%85%A3%E5%8C%96%E3%81%99%E3%82%8B&quot;&gt;アウトプットを習慣化する&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%B0%86%E6%9D%A5%E3%82%92%E8%80%83%E3%81%88%E3%81%A6%E3%81%84%E3%81%8B%E3%81%AA%E3%81%84%E3%81%A8%E3%81%84%E3%81%91%E3%81%AA%E3%81%84&quot;&gt;将来を考えていかないといけない&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E6%9C%80%E5%BE%8C%E3%81%AB&quot;&gt;最後に&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#1ヶ月でやってきたこと&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;1ヶ月でやってきたこと&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#どのくらい勉強しましたか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;どのくらい勉強しましたか？&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200810/20200810234907.png&quot; alt=&quot;f:id:ikmbear:20200810234907p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;学習時間としては、30日で190.3時間。1日平均で大体6hくらい勉強しました。平日は働いているので、ざっくりこんな感じの生活を送っています。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200810/20200810013453.png&quot; alt=&quot;f:id:ikmbear:20200810013453p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;実際にはこれよりも残業していたりもするので、もう少し学習時間が少ない時もあります（コロナの影響で基本リモートワークですが、たまに外勤もしているのでこの通りにいかない日もあります）。休日は6~12hくらい勉強してます。暇人ですね〜。&lt;/p&gt;
&lt;p&gt;ちなみに進捗は39%です。&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200810/20200810235015.png&quot; alt=&quot;f:id:ikmbear:20200810235015p&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#何ができるようになったんですか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;何ができるようになったんですか？&lt;/h3&gt;
&lt;p&gt;細々書くといろいろあるんですが、プ$1ティスに沿って記述すれば&lt;br /&gt;
「LinuxサーバでNginxを動かし、ちゃんとCSSも適用した静的ページをローカルPCから配置・配信できるようになった。あと作ったページはバージョン管理もできるよ。」&lt;br /&gt;
といったことができるようになりました。&lt;/p&gt;
&lt;p&gt;とりあえず、突然母親に「いま私がやってるサークルのサイト立ち上げてよ」と無茶振りされても役に立つことができるようになりました。え？お問い合わせフォーム？会員専用ページ？ごめんなさいまだ無理です。&lt;/p&gt;
&lt;p&gt;$1ベルで進捗を例えると（なぜ例えるし）、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ザケル・ラシルド・ジケルド（HTML・Linux・Nginx…etc）はまだ初級ランクだけで使える。技のコンビネーションでなんとか敵は倒してる。&lt;/li&gt;
&lt;li&gt;そろそろバオウ・ザケルガ（Ruby）覚える。&lt;/li&gt;
&lt;li&gt;たぶんバオウにのまれる展開（Rubyむずい〜〜〜）がそのうちある&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;まずはバオウ・ザケルガ覚えて、リオウ戦（Railsとかかな）ですごい感情抱いて、ザケルなどの初級呪文がギガノ級へ進化することを期待する日々です。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#独学をやめたことで風向きは変わりましたか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;独学をやめたことで風向きは変わりましたか？&lt;/h3&gt;
&lt;h4&gt;&lt;a href=&quot;#方向性が見えたことで先に進めるようになった&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;方向性が見えたことで、先に進めるようになった&lt;/h4&gt;
&lt;p&gt;Railsブートキャンプのコースは「RailsRailsコース」と銘打っているので、Rubyが初級の状態ではまだまだです。&lt;/p&gt;
&lt;p&gt;しかし、自分でサーバーを借りてそこから静的ページを配置することができるようになったことは、独学時代になしえなかった大きな一歩でした。&lt;/p&gt;
&lt;p&gt;もう少し詳しくいうと、独学時代には&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;「どこまでできるようになればいいんだCSS。模写か、模写を続ければいいのか」&lt;/li&gt;
&lt;li&gt;「サーバ立ち上げるにも何が必要かわからん。前提知識は何が必要？そもそもこのPCでできるの？」&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;と思い悩んでずっと同じ場所から進めていなかったのですが、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;「CSSはまずHoly-Grail layoutの成果物が作れるようになろう」&lt;/li&gt;
&lt;li&gt;「サーバを立ち上げるにはLinuxのこれは最低限必要。んでもってHTTPLinuxも知っておいて…」&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;と、方向性が見えていることで前に進めるようになりました。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#学習時間を純粋に技術を習得するための時間に当てられるようになった&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;学習時間を純粋に「技術を習得するための時間」に当てられるようになった&lt;/h4&gt;
&lt;p&gt;こうして方向性が見えることによる変化は、学習時間の使い方の変化にもつながっています。&lt;/p&gt;
&lt;p&gt;これまでは「う〜ん、学習の進め方が悪いのかも。他の人のやり方を調べるか。」「計画をしっかりたてやってみよう」と&lt;strong&gt;学習の進め方自体に時間をかけていた&lt;/strong&gt;のですが、キャンプイン後はほぼすべての時間を**「具体的な技術を習得するための時間」にかけることができるように**なりました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#1ブートキャンプを1ヶ月間つづけていて辛いことはありますか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;$1ブートキャンプを1ヶ月間つづけていて、辛いことはありますか？&lt;/h3&gt;
&lt;p&gt;強いてあげるなら&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;（後述）学習の習慣化のために、最初の1ヶ月は$1ブートキャンプのプ$1ティスを進めることに全振りしていたので、プ$1ティスに関係ない本はいったん読めなかった。&lt;/li&gt;
&lt;li&gt;睡眠時間が少し減って眠い。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ぐらいです。&lt;/p&gt;
&lt;p&gt;プログラミングが楽しくて始めたことなので、今のところはあまり辛くないです。&lt;/p&gt;
&lt;p&gt;わかんないことが出てきても、わかった時の$1が全て精算してくれるので、むしろプラスです。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#学習の継続に役立っている仕組み&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;学習の継続に役立っている仕組み&lt;/h2&gt;
&lt;p&gt;せっかく1ヶ月続いたので、働きながらの学習に役立っている仕組み・考え方を振り返ってみます。まずは仕組みの方から。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#todoist&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;todoist&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200810/20200810013531.png&quot; alt=&quot;f:id:ikmbear:20200810013531p&quot; /&gt;todoist&lt;/p&gt;
&lt;p&gt;可処分時間を増やすために、本業のタスク管理で使用しています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;どのタスクをいつまでに終わらせる必要があるのかを一覧で認識できる。&lt;/li&gt;
&lt;li&gt;仕事が降ってきた際に、進め方を考えてから着手できるよう無限に子タスクに分解できる。&lt;/li&gt;
&lt;li&gt;可処分時間を勉強に回すと、記憶のキャパシティが足りないので、すべて機械が覚えて通知してくれる。&lt;/li&gt;
&lt;li&gt;タスク自体にコメント（PDFファイルとかも）を追加可能なので、ここをみとけば全部把握できる&lt;/li&gt;
&lt;li&gt;タスク管理ツール自体を使うのに多大な$1がかからない&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;可処分時間のほとんどを学習時間に当てたことによる、**「実は今まで頭で覚えていた」部分の抜け漏れが怖かったため、**柔軟に繰り返しタスク追加ができるtodoistはかなり重宝しています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#notion&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Notion&lt;/h3&gt;
&lt;p&gt;学習におけるNotionの役割は次の3つです。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;$1ブートキャンプの学習計画管理（ゆるめ）&lt;/li&gt;
&lt;li&gt;学習メモと参考記事のストック&lt;/li&gt;
&lt;li&gt;ビジュアル担当&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;&lt;a href=&quot;#11ブートキャンプの学習計画管理ゆるめ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;1.$1ブートキャンプの学習計画管理（ゆるめ）&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200810/20200810013759.png&quot; alt=&quot;f:id:ikmbear:20200810013759p&quot; /&gt;学習計画&lt;/p&gt;
&lt;p&gt;まず学習管理というほどの管理ではないのですが、Notionのカレンダービューを使って、直近1ヶ月のプ$1ティスの取組日程を記載するようにし、完了したらチェックを入れる形にしています。&lt;/p&gt;
&lt;p&gt;（1ヶ月以降の日程も一応$1していますが、こっちは適当です。そこにたどり着く時に自分がどんな前提知識あるのかもわからないですし）&lt;/p&gt;
&lt;p&gt;$1ブートキャンプは$1カの大学ばりに卒業するのが大変（&lt;a href=&quot;https://bootcamp.fjord.jp/faq&quot; target=&quot;_blank&quot;&gt;FAQ | FJORD BOOT CAMP（フィヨルドブートキャンプ）&lt;/a&gt;）ということで有名なので、毎日学習を進めていても「のれんに腕押し、糠に釘、豆腐にかすがい…」と思ってしまわぬように、&lt;strong&gt;「あらかじめここまで進めるんだ」「自分はこれだけ進んだんだ」と自分で納得感を出せるよう&lt;/strong&gt;にしています。&lt;/p&gt;
&lt;p&gt;カレンダーのあるページには、各言語の学習メモへのリンクと自分の考えたこと（アウトプット）も一覧できるようにしています。これも「やった感」を自分に訴えかける工夫のひとつです。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#2学習メモと参考記事のストック&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;2.学習メモと参考記事のストック&lt;/h4&gt;
&lt;p&gt;次に学習メモと参考記事のストックです。&lt;/p&gt;
&lt;p&gt;$1ブートキャンプには日報システムがあるので、そこにつらつら書き連ねるのも一つの手ではあります。ただ横断検索と$1がないことに加え、自分の場合は学習に関する情報をNotionに集約したかったので、Notionで学習メモと参考資料をまとめています。あとは「何でもかんでも日報に書くのはあれだけど、勉強のためにメモしておきたいな〜」という場面が多いということも理由です。&lt;/p&gt;
&lt;p&gt;学習内容ごとに一つのページを用意し、学習メモと参考記事を配置するテンプレートを採用しています。&lt;/p&gt;
&lt;p&gt;（NotionTip的なところですが、テンプレートで作るとChromeのWebClipperでどれも同じ名前になってしまうので、インラインページにもちゃんとアイコンを設定することをおすすめします）。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200810/20200810013841.png&quot; alt=&quot;f:id:ikmbear:20200810013841p&quot; /&gt;Rubyの学習ページ&lt;/p&gt;
&lt;p&gt;学習メモは参考書を読む時、課題に取り組む時、調べ物をする時は必ず用意し、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;学習時点ではよくわかっていることでもわりとしっかり書く&lt;/li&gt;
&lt;li&gt;自分がやってみたことは手順をまとめておく&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;こんなことに気をつけて書いています。&lt;/p&gt;
&lt;p&gt;カリキュラム上は課題を提出すればクリアになるのですが、それは「この技術とはもうお別れだよ」でも「この技術は完璧にマスターしたね」でもありません。&lt;/p&gt;
&lt;p&gt;カリキュラム上で先に出てくる技術は、その後の技術の前提知識です。そして人間なので時間と共に忘れる可能性があります。&lt;/p&gt;
&lt;p&gt;そのため少し時間はかかりますが、&lt;strong&gt;トータルの学習効率を優先して、「忘れた時に自分がスッと分かっている状態に復帰できるメモ」「初心者の自分が、理解したことを後から教えてくれるメモ」と&lt;/strong&gt;なるように書いています。&lt;/p&gt;
&lt;p&gt;参考記事は、Chrome拡張のwebclipper機能でどんどん入れていきます。ブックマークバーだといくつあっても足りないので。&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#3ビジュアル担当&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;3.ビジュアル担当&lt;/h4&gt;
&lt;p&gt;完全に個人的な好みです。私は仕事でもExcelのフォントや配色が適当だと気になるタイプなので、モチベーション維持のためには学習に使用するツールがビジュアル的にいけていることがマストでした。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200810/20200810013920.png&quot; alt=&quot;f:id:ikmbear:20200810013920p&quot; /&gt;Nginxの学習ページ&lt;/p&gt;
&lt;p&gt;ちなみに今のところ、一番綺麗だなあと思っているのはNginxの学習ページです。「NGINXってアロマ通販サイトの名前なのか」と錯覚するような$1ル系ビジュアルです。&lt;/p&gt;
&lt;p&gt;しょうもないですが、意外とこういうところは学習の継続に効いているんじゃないかと個人的に思っています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#朝勉強できたカレンダー&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;朝勉強できたカレンダー&lt;/h3&gt;
&lt;p&gt;私の場合、学習の絶対時間を伸ばすためには、朝時間の活用が欠かせません。&lt;/p&gt;
&lt;p&gt;そのため6&lt;/p&gt;&lt;div&gt;&lt;/div&gt;、学習する習慣としています。この習慣を支えるのが朝学習カレンダーです。&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200810/20200810014107.png&quot; alt=&quot;f:id:ikmbear:20200810014107p&quot; /&gt;朝学習カレンダー&lt;/p&gt;
&lt;p&gt;ルールは簡単で、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;習慣を守れたら奥さんにサインをもらう&lt;/li&gt;
&lt;li&gt;サインが1ヶ月たまったら、二人でおいしいものを食べる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これだけです。大学時代も「6&lt;/p&gt;&lt;div&gt;&lt;/div&gt;→11&lt;div&gt;&lt;/div&gt;→16&lt;div&gt;&lt;/div&gt;」みたいなことはやっていたのですが、仕事の疲れや加齢とともに前ほどすっきり早起きできなくなっているので、&lt;strong&gt;朝学習を続ける仕組みは多ければ多いほどいいです（面倒でないほどに）&lt;/strong&gt;。&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#朝の1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;朝の$1&lt;/h3&gt;
&lt;p&gt;毎日6&lt;/p&gt;&lt;div&gt;&lt;/div&gt;、sasaboさんという方がslack上で朝の$1を開いてくださっています（本当にありがたい）！&lt;p&gt;&lt;/p&gt;
&lt;p&gt;私の朝は6&lt;/p&gt;&lt;div&gt;&lt;/div&gt;、slackに返信して始まります。繰り返しますが、朝学習を続ける仕組みは多ければ多いほどいいです。&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#1ブートキャンプの日報へのコメント&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;$1ブートキャンプの日報へのコメント&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200810/20200810131128.png&quot; alt=&quot;f:id:ikmbear:20200810131128p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;$1期なので仕組みといえるか微妙ですが、$1ブートキャンプでは学習をした日は必ず日報を書きます。そしてたまにコメントがきます。&lt;/p&gt;
&lt;p&gt;「良いやり方ですね」「いい心がけですね」「その調子で頑張ってください！」「参考になりました！」&lt;/p&gt;
&lt;p&gt;コメントは基本こないものだと思っているので、不意打ちで来て嬉しさ倍増。&lt;/p&gt;
&lt;p&gt;これで明日も頑張れそうな気がします。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#1ブートキャンプの芝&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;$1ブートキャンプの芝&lt;/h3&gt;
&lt;p&gt;Githubブートキャンプのプロフィールページには、Github同様にキャンプでの勉強時間に応じた芝が実装されています。&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200810/20200810131255.png&quot; alt=&quot;f:id:ikmbear:20200810131255p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;「いっぱいあったら、いっぱいうれしい」&lt;/p&gt;
&lt;p&gt;そんな単純な人間です。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#学習の継続に役立っている考え方&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;学習の継続に役立っている考え方&lt;/h2&gt;
&lt;p&gt;役立っているという観点とは少し違うけれど、単にそういうこと考えているよ〜といった類のことも混じっています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#プログラミングは面白い&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;プログラミングは面白い&lt;/h3&gt;
&lt;p&gt;だから$1ブートキャンプに入っているんですが、やっぱり**「楽しい」は最大のモチベーション**ですね。朝起きて勉強するのも楽しいから続いているわけで。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#習慣化の法則にのっかる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;習慣化の法則にのっかる&lt;/h3&gt;
&lt;p&gt;「ずっと読み続けている一冊はありますか？」と言われて、真っ先に答えるのがこの本です。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.co.jp/gp/product/B01KJAOI9E/ref=dbs_a_def_rwt_bibl_vppi_i5&quot; target=&quot;_blank&quot;&gt;https://www.amazon.co.jp/gp/product/B01KJAOI9E/ref=dbs_a_def_rwt_bibl_vppi_i5&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.co.jp/gp/product/B01KJAOI9E/ref=dbs_a_def_rwt_bibl_vppi_i5&quot; target=&quot;_blank&quot;&gt;www.amazon.co.jp&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;習慣には種類があり、「学習を続ける」といった行動に関する習慣は行動習慣に分類される。&lt;/li&gt;
&lt;li&gt;一般的に行動習慣は定着までに30日かかる。&lt;/li&gt;
&lt;li&gt;人間は現状維持を好む。多くのことを並行して習慣化しようとすると、拒絶反応が大きいので、習慣化する内容は一つに絞るべき。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;本書の内容に沿って「$1ブートキャンプでの学習を継続したい」という習慣だけをこの1ヶ月は徹底しました。仕事は別として、「運動不足だから毎日運動するか」「やっぱ読書習慣身に付けたいな」と思っても、全部やらずに徹底したことで1ヶ月の勉強習慣が定着したと感じています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#新しいことを学ぶ時は郷に入っては郷に従えの精神&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;新しいことを学ぶ時は「郷に入っては郷に従え」の精神&lt;/h3&gt;
&lt;p&gt;なまじ仕事でJavaとかAPサーバをかじったことがあるおかげで、プJavaティスで出てくる新しい概念も「ああ、これはJavaでいうあれね」といった比較による吸収が可能です。&lt;/p&gt;
&lt;p&gt;これ自体は効率的でいいとは思うのですが、如何せん比較対象の知識自体が曖昧なので、比較による理解はせず、新しく学ぶ概念の言葉で理解するように心がけています。&lt;strong&gt;比較で学習しようとすると、比較元の理解度でしか新しい概念を理解できない&lt;/strong&gt;ような気がするので。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#人には人の乳酸菌の精神&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;「人には人の乳酸菌」の精神&lt;/h3&gt;
&lt;p&gt;$1ブートキャンプにはいろいろな人がいます。バックグラウンドも違うので、学習進度の比較はあまり意味がありません。&lt;strong&gt;「自分がちゃんと進めているか？」を大切に&lt;/strong&gt;します。&lt;/p&gt;
&lt;p&gt;※そのための仕組みがNotionです。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#問題を解く時はシャーペンじゃないボールペンでの精神&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;問題を解く時は「シャーペンじゃない、ボールペンで」の精神&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;学習している過程では間違えるのは当たり前。だったら臆せずにどんどん間違えを晒して残して、成長につなげよう&lt;/strong&gt;といった意味合いです。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ここから余談ですが、これはもともと中学の数学の教師に言われた言葉です。&lt;br /&gt;
自分で言うのもなんですが、私は「学校」で常に高い評価を得られていたので、常に「優等生」であろうとしていました。そのことが邪魔をして、ノートに問題を解く時も間違った記録を残さないよう消して、あたかも最初から正しい解答をしているかのように書き直す癖があったんですね。&lt;br /&gt;
そして次第にテストの点数が上がらなくなった時に、それを見抜いたのか数学の教師から言われたのが&lt;br /&gt;
「問題を解く時はシャーペンじゃなくて、ボールペンで$1にかけ。間違いをたくさん積み重ねろ」&lt;br /&gt;
大人になった今でも「失敗を晒すのは恥ずかしい」と思っている自分はどこかにいますが、その度にこの言葉を思い出して「今は間違え時」と言い聞かせています。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;&lt;a href=&quot;#これからの話ざっくり&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;これからの話（ざっくり）&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#アウトプットを習慣化する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;アウトプットを習慣化する&lt;/h3&gt;
&lt;p&gt;先の習慣化の話には続きがあって、&lt;/p&gt;
&lt;p&gt;「人間は新しい習慣を拒むけれど、一方で同じ習慣が続くと飽きる生き物。習慣が身についてきたら、新しい習慣を始めることでマンネリを防ぐべき」&lt;/p&gt;
&lt;p&gt;という説明があります。これに則って、8月からは学習習慣にプラスしてアウトプットを習慣化したいと思います。1週間に2記事くらいかけるといいなあと思っています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#将来を考えていかないといけない&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;将来を考えていかないといけない&lt;/h3&gt;
&lt;p&gt;「楽しさ」を原点として本腰を入れ始めた**プログラミングに対して、「どうして仕事にしたいのか」「どんな仕事をしたいのか」**ということを、これからぼちぼちと考えていきたいと思っています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;仕事であれば、その時間含め長い時間プログラミングに触っていられる。&lt;/li&gt;
&lt;li&gt;個人とは規模感が違う。その規模感ならではの$1を体験することができる。&lt;/li&gt;
&lt;li&gt;仕事には責任が伴う。責任があるからこその試行錯誤がありそれが楽しい。…etc&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#最後に&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;最後に&lt;/h2&gt;
&lt;p&gt;最近「自分はいい時代に生まれたよなあ」と思っています（Windows95と同い年です）。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;もしプログラミングという概念が生まれたばかりの時代だったら&lt;/li&gt;
&lt;li&gt;もしJavaScriptが使えないものだと思われている時代だったら&lt;/li&gt;
&lt;li&gt;もし個人でさくっとWebアプリが作れる時代でなかったら&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;今ある技術はなくて、そしてその技術を懇切丁寧に教えてくれる環境もきっとなかったんですよね（もちろん、その中で学んでいくことも楽しいんだとは思いますが、今よりずっと大変）。&lt;/p&gt;
&lt;p&gt;せっかく$1ブートキャンプという場所を選べる時代に生まれて、その機会を自分で選択したのだから、最後までやり通さないと損ですよね！&lt;/p&gt;
&lt;p&gt;1ヶ月くらいで「やりきった」テイストの記事書いてますが、まだまだこれから！！プログラミング楽しんでまいります！&lt;/p&gt;
&lt;p&gt;↓こちらもどうぞ&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://ikmbear.hatenablog.com/entry/2020/07/22/194545&quot; target=&quot;_blank&quot;&gt;ikmbear.hatenablog.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded><author>ikuma-t</author></item><item><title>zshからの実行時、 Rangeオブジェクトを使った繰り返しで、最後の文字が「%」になって困った</title><link>https://ikuma-t.com/blog/20200810160101/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20200810160101/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200810/20200810155847.png実行環境なぜ範囲の最</description><pubDate>Mon, 10 Aug 2020 16:01:01 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200810/20200810155847.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200810/20200810155847.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200810/20200810155847.png&quot; alt=&quot;f:id:ikmbear:20200810155847p&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%AE%9F%E8%A1%8C%E7%92%B0%E5%A2%83&quot;&gt;実行環境&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%81%AA%E3%81%9C%E7%AF%84%E5%9B%B2%E3%81%AE%E6%9C%80%E5%BE%8C%E3%81%AE%E6%95%B0%E5%AD%97%E3%81%8C%E5%87%BA%E5%8A%9B%E3%81%95%E3%82%8C%E3%81%AA%E3%81%84&quot;&gt;なぜ範囲の最後の数字が出力されない？&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#Range%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AF%E3%83%89%E3%83%83%E3%83%88%E3%81%AE%E6%95%B0%E3%81%A7%E5%A2%83%E7%95%8C%E3%82%92%E5%90%AB%E3%82%80%E3%81%8B%E3%81%A9%E3%81%86%E3%81%8B%E3%81%8C%E5%A4%89%E3%82%8F%E3%82%8B&quot;&gt;Rangeオブジェクトは、ドットの数で境界を含むかどうかが変わる。&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E7%92%B0%E5%A2%83%E8%B5%B7%E5%9B%A0%E3%81%8B%E3%82%92%E7%A2%BA%E3%81%8B%E3%82%81%E3%81%A6%E3%81%BF%E3%82%8B&quot;&gt;環境起因かを確かめてみる&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#zsh%E3%81%A7%E3%81%AF%E6%94%B9%E8%A1%8C%E3%81%AE%E3%81%AA%E3%81%84%E7%B5%90%E6%9E%9C%E8%A1%8C%E3%82%92%E5%87%BA%E5%8A%9B%E3%81%99%E3%82%8B%E6%99%82%E3%81%AB%E3%83%97%E3%83%AD%E3%83%B3%E3%83%97%E3%83%88%E3%82%92%E8%A1%A8%E7%A4%BA%E3%81%99%E3%82%8B&quot;&gt;zshでは改行のない結果行を出力する時に、プロンプト「%」を表示する&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E4%BD%99%E8%AB%87&quot;&gt;余談&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%82%92%E6%8E%92%E9%99%A4%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF%E3%81%A9%E3%81%86%E3%81%99%E3%82%8C%E3%81%B0%E3%82%88%E3%81%84%E3%81%8B&quot;&gt;「%」を排除するにはどうすればよいか&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E6%84%9F%E6%83%B3&quot;&gt;感想&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%8F%82%E8%80%83&quot;&gt;参考&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#実行環境&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;実行環境&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;macOS Catalina 10.15.6&lt;/li&gt;
&lt;li&gt;Ruby 2.7.0&lt;/li&gt;
&lt;li&gt;シェル：zsh&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#なぜ範囲の最後の数字が出力されない&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;なぜ範囲の最後の数字が出力されない？&lt;/h2&gt;
&lt;p&gt;実際に取り組んでいた問題はもう少し複雑だったんですが、簡単にいうとこんなコードを書いていました。やりたいことは、1から10までをただ横並びに出力したいということです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# print_num.rb#!/usr/bin/env ruby(1...10).each {|n| print n}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これをVSCodeのターミナル（zsh）から実行すると…&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% ./print_num.rb123456789%&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;「あれ？10が出ない代わりに”%“が出力されている？」&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#rangeオブジェクトはドットの数で境界を含むかどうかが変わる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Rangeオブジェクトは、ドットの数で境界を含むかどうかが変わる。&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.ruby-lang.org/ja/latest/class/Range.html&quot; target=&quot;_blank&quot;&gt;class Range (Ruby 2.7.0 リファレンスマニュアル)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;さしずめ、「あれドットの数って何個だったけな？国語的には3つで1つだから、3つで書いてみるか…。お！動いたやっぱり3つか！」みたいことを思っていたのでしょう、この私。甘すぎて尼になっちゃうわ。&lt;/p&gt;
&lt;p&gt;「Rangeオブジェクト」のリファレンスマニュアルを確認すると、次のようなサンプルがあります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Range.new(1, 5) # 1 以上 5 以下1..5            # 同上1...5           # 1 以上 5 未満&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;つまり、Rangeオブジェクトは&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ドットが2つの場合、終端を含む&lt;/li&gt;
&lt;li&gt;ドットが3の場合、終端を含まない&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;という仕様です。なので、今回やりたいことは次のように書けば解決します！&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# print_num.rb#!/usr/bin/env ruby(1..10).each {|n| print n} # ドットを一つ減らし、終端を含むように変更した。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これを実行すると…&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% ./print_num.rb12345678910%&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;あれれ？10は表示されましたが、「%」の謎は残ったままです…。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#環境起因かを確かめてみる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;環境起因かを確かめてみる&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200810/20200810154547.png&quot; alt=&quot;f:id:ikmbear:20200810154547p&quot; /&gt; この実行結果はVSCodeのターミナル（zsh）で実行したものなので、環境起因の可能性がないかチェックします。&lt;/p&gt;
&lt;p&gt;mac標準のターミナル（zsh）で実行して結果を確認してみると、同じ現象が発生しています。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200810/20200810154611.png&quot; alt=&quot;f:id:ikmbear:20200810154611p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;一方、pryでの実行結果を確認すると、こちらは%は表示されていません。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200810/20200810154625.png&quot; alt=&quot;f:id:ikmbear:20200810154625p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;つまり、「&lt;strong&gt;%が表示されるのはzsh特有の現象&lt;/strong&gt;」であると言えそうです。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#zshでは改行のない結果行を出力する時にプロンプトを表示する&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;zshでは改行のない結果行を出力する時に、プロンプト「%」を表示する&lt;/h2&gt;
&lt;p&gt;zsh特有だというヒントが得られたので、ドキュメントをチェックしてみます。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://zsh.sourceforge.net/Doc/Release/Options.html#Prompting&quot; target=&quot;_blank&quot;&gt;zsh: 16 Options&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;PROMPT_SP Attempt to preserve a partial line (i.e. a line that did not end with a newline) that would otherwise be covered up by the command prompt due to the PROMPT_CR option. This works by outputting some cursor-control characters, including a series of spaces, that should make the terminal wrap to the next line when a partial line is present (note that this is only successful if your terminal has automatic margins, which is typical).When a partial line is preserved, by default you will see an inverse+bold character at the end of the partial line: a ‘%’ for a normal user or a ‘#’ for root. If set, the shell parameter PROMPT_EOL_MARK can be used to customize how the end of partial lines are shown.NOTE: if the PROMPT_CR option is not set, enabling this option will have no effect. This option is on by default.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;順に読んでいきましょう。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Attempt to preserve a partial line (i.e. a line that did not end with a newline) that would otherwise be covered up by the command prompt due to the PROMPT_CR option.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;「PROMPT_CR オプションにより$1で覆われてしまうような部分行 (改行で終わらない行) を保存しようとする」&lt;/p&gt;
&lt;p&gt;PROMPT_CRオプションについてはその上に記述があり、プロンプト（zshでは%）を表示する前にキャリッジリターン（CR）を印刷する（同一行の行頭に戻す）仕様のようです。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This works by outputting some cursor-control characters, including a series of spaces, that should make the terminal wrap to the next line when a partial line is present&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;「カーソル文字（一連のスペースを含む）を出力することで、部分行を次の行に折り返す」&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When a partial line is preserved, by default you will see an inverse+bold character at the end of the partial line: a ‘%’ for a normal user or a ‘#’ for root.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;「これが実行される時は、デフォルトでは反転して太文字で部分行の最後に一般ユーザなら「%」が、ルートユーザなら「#」が表示される」&lt;/p&gt;
&lt;p&gt;字面だけだといまいちよくわからないので、具体的なソースと合わせて、動きを書いてみたいと思います。&lt;/p&gt;
&lt;p&gt;まずrubyプログラムを実行します。printメソッドは改行を出力しません。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% ./print_num.rb123456789&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;ここでPROMPT_CRオプションに基づいて、CRを印刷します。すると改行がされていないため、同一行の先頭に移動した結果、出力結果が消えます。これが「PROMPT_CR オプションにより$1で覆われてしまうような部分行」ということです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% ./print_num.rbusername@userMacbook folder%&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;で、こういうことが起こらないように、PROMPT_SPオプションがPROMPT_CRオプションに先んじて仕事をします。具体的には、一般ユーザであれば改行を含まない行の最後に（色が）反転した「%」を表示して改行します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% ./print_num.rb123456789%&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;最後にPROMPT_CRオプションのCRが印刷されたのち、プロンプトが表示され、結果はこうなります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% ./print_num.rb123456789%username@userMacbook folder%&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#余談&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;余談&lt;/h3&gt;
&lt;p&gt;PROMPT_SPオプションを無効にすることで、「PROMPT_CR オプションにより$1で覆われてしまうような部分行」を実際に確認することができます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% vi ~/.zshrc# .zshrcを編集unsetopt PROMPT_SP% source ~/.zshrc&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;実行結果&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200810/20200810154709.png&quot; alt=&quot;f:id:ikmbear:20200810154709p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;部分行がCRにより覆われてしまい、見えなくなっていることがわかります。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#を排除するにはどうすればよいか&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;「%」を排除するにはどうすればよいか&lt;/h2&gt;
&lt;p&gt;一つの手段はRuby側で改行を出力することです。最初のプログラムで&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# print_num.rb#!/usr/bin/env ruby(1...10).each {|n| print n}puts &quot;\n&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;としておけば、出力結果が部分行に相当しないので、%は表示されません。&lt;/p&gt;
&lt;p&gt;別の手段は、zshの設定（~/.zshrc）を書き換えてしまうことです。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If set, the shell parameter PROMPT_EOL_MARK can be used to customize how the end of partial lines are shown.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;ここに記載の通り、PROMPT_EOL_MARKが、部分行の最後に出力される文字です。&lt;/p&gt;
&lt;p&gt;これを「”（空白）」にしてしまえば、%は表示されず、部分行も保持されます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;% vi ~/.zshrc# .zshrcを編集export PROMPT_EOL_MARK=&apos;&apos;% source ~/.zshrc% ./print_num.rb123456789&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;プログラム側で制御でき、環境に依存しないという点ではRubyで改行を出力してしまうのがいいのかなあと思いました。&lt;/li&gt;
&lt;li&gt;あと誰かが英訳力をプレゼントしてくれないかなと思う今日この頃です。&lt;/li&gt;
&lt;li&gt;ついでに記事のタイトルつける力もください、なんでもしますから。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#参考&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;参考&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.ruby-lang.org/ja/latest/class/Range.html&quot; target=&quot;_blank&quot;&gt;class Range (Ruby 2.7.0 リファレンスマニュアル)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://zsh.sourceforge.net/Doc/Release/Options.html#Prompting&quot; target=&quot;_blank&quot;&gt;zsh: 16 Options&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>ikuma-t</author></item><item><title>VSCodeVimで使えるインデントオブジェクト</title><link>https://ikuma-t.com/blog/20200807123531/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20200807123531/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200807/20200807101559.gifVimではiiコマン</description><pubDate>Fri, 07 Aug 2020 12:35:31 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200807/20200807101559.gif&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200807/20200807101559.gif&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#Vim%E3%81%A7%E3%81%AFii%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%A7%E5%85%A8%E9%81%B8%E6%8A%9E%E3%81%A7%E3%81%8D%E3%82%8B&quot;&gt;Vimではiiコマンドで全選択できる？&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#i%E3%81%AF%E3%82%A4%E3%83%B3%E3%83%87%E3%83%B3%E3%83%88%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88VScodeVim&quot;&gt;iは「インデントオブジェクト」（VScodeVim）&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%AE%9F%E8%B7%B5%E3%82%A4%E3%83%B3%E3%83%87%E3%83%B3%E3%83%88%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88&quot;&gt;実践！インデントオブジェクト&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#operator-ii-%E3%82%AB%E3%83%BC%E3%82%BD%E3%83%AB%E3%81%AE%E4%BD%8D%E7%BD%AE%E3%81%A8%E5%90%8C%E3%81%98%E3%82%A4%E3%83%B3%E3%83%87%E3%83%B3%E3%83%88%E3%82%92%E6%8C%87%E5%AE%9A&quot;&gt;&amp;lt;operator&amp;gt; ii ：カーソルの位置と同じインデントを指定&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#operator-ai-%E3%82%AB%E3%83%BC%E3%82%BD%E3%83%AB%E3%81%AE%E4%BD%8D%E7%BD%AE%E3%81%A8%E5%90%8C%E3%81%98%E3%82%A4%E3%83%B3%E3%83%87%E3%83%B3%E3%83%88%E3%81%9D%E3%81%AE%E3%82%A4%E3%83%B3%E3%83%87%E3%83%B3%E3%83%88%E3%81%AE%E4%B8%80%E8%A1%8C%E4%B8%8A%E3%82%92%E6%8C%87%E5%AE%9A&quot;&gt;&amp;lt;operator&amp;gt; ai ：カーソルの位置と同じインデント+そのインデントの一行上を指定&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#operator-aI-%E3%82%AB%E3%83%BC%E3%82%BD%E3%83%AB%E3%81%AE%E4%BD%8D%E7%BD%AE%E3%81%A8%E5%90%8C%E3%81%98%E3%82%A4%E3%83%B3%E3%83%87%E3%83%B3%E3%83%88%E3%81%9D%E3%81%AE%E3%82%A4%E3%83%B3%E3%83%87%E3%83%B3%E3%83%88%E3%81%AE%E4%B8%80%E8%A1%8C%E4%B8%8A%E3%81%A8%E4%B8%8B%E3%82%92%E6%8C%87%E5%AE%9A&quot;&gt;&amp;lt;operator&amp;gt; aI ：カーソルの位置と同じインデント+そのインデントの一行上と下を指定&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%81%A7%E5%86%8D%E7%A2%BA%E8%AA%8D&quot;&gt;テキストで再確認&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%81%BE%E3%81%A8%E3%82%81&quot;&gt;まとめ&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E6%84%9F%E6%83%B3&quot;&gt;感想&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%8F%82%E8%80%83&quot;&gt;参考&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#vimではiiコマンドで全選択できる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Vimでは&lt;code&gt;ii&lt;/code&gt;コマンドで全選択できる？&lt;/h2&gt;
&lt;p&gt;Google検索で「vim 全選択」と検索すれば、こんな感じのコマンドが出てきます。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;gg&lt;/li&gt;
&lt;li&gt;Shift + v（行選択ビジュアルモードにしないと、最後の一行がうまく選択されないので注意）&lt;/li&gt;
&lt;li&gt;G&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200807/20200807101559.gif&quot; alt=&quot;f:id:ikmbear:20200807101559g&quot; /&gt;&lt;/p&gt;
&lt;p&gt;この方法が正攻法なのですが、へっぽこvimmerである私はキーボーvimmerチャコンの末に別の方法で全選択する方法を見つけました（注意：結論としてはこれは全選択のコマンドではありません）！&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200807/20200807102024.gif&quot; alt=&quot;f:id:ikmbear:20200807102024g&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ビジュアルモードにした後、コマンド&lt;code&gt;ii&lt;/code&gt;を入力すると、上図のような結果（全選択）になります。&lt;/p&gt;
&lt;p&gt;「テキストオブジェクト「ii」を入力すると全選択できる？ 」&lt;br /&gt;
「いやちょっと待てよ、テキストオブジェクトで「i」なんて聞いたことないぞ」&lt;br /&gt;
そこで今回は&lt;code&gt;ii&lt;/code&gt;すなわち「inner i?」の「i」とはなんぞやを調べてみました。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#iはインデントオブジェクトvscodevim&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;code&gt;i&lt;/code&gt;は「インデントオブジェクト」（VScodeVim）&lt;/h2&gt;
&lt;p&gt;まず同じテキストファイルに対して、シェル上で同じコマンドを入力しても全選択にはなりません（無効なキーを押した時のあの音がなります）。&lt;/p&gt;
&lt;p&gt;ということは、この機能はVSCodeのVSCode「VSCodeVim」特有の機能ということになります。&lt;/p&gt;
&lt;p&gt;そこでvimのページを確認してみると、「vim-indent-object」なるものが。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200807/20200807102402.png&quot; alt=&quot;f:id:ikmbear:20200807102402p&quot; /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Based on vim-indent-object, it allows for treating blocks of code at the current indentation level as text objects. Useful in languages that don’t use braces around statements(e.g Python)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;要はカーソルの現在位置と同じインデントを、テキストオブジェクトとして扱うことができるということです（以降インデントオブジェクトと呼ぶ）。&lt;/p&gt;
&lt;p&gt;（私はPython触ったことないので初めて知りましたが）Pythonのようにインデントでブロックを構成する言語には、このインデントオブジェクトはめちゃ便利ということらしいです。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;a = 3if a == 5:    print &quot;AAA&quot;    # if文の対象    print &quot;BBB&quot;    # if文の対象print &quot;CCC&quot;        # if文の対象ではない&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;引用：&lt;a href=&quot;http://www.tohoho-web.com/python/syntax.html&quot; target=&quot;_blank&quot;&gt;とほほのPython入門 - 構文 - とほほのWWW入門&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#実践インデントオブジェクト&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;実践！インデントオブジェクト&lt;/h2&gt;
&lt;p&gt;VSCodeVimの概要ページにはコマンドの説明もあるので、実際に試してみます（ビジュアルモードで試すので、オペレーターは指定しません）。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#operator-ii-カーソルの位置と同じインデントを指定&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;code&gt;&amp;lt;operator&amp;gt; ii&lt;/code&gt; ：カーソルの位置と同じインデントを指定&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200807/20200807102640.gif&quot; alt=&quot;f:id:ikmbear:20200807102640g&quot; /&gt;&lt;/p&gt;
&lt;p&gt;冒頭でのべた「iiで全選択」は**「一番外側のインデントにカーソルをおいて、インデントオブジェクト&lt;code&gt;ii&lt;/code&gt;を指定すれば、実質全選択」**ということでした。&lt;/p&gt;
&lt;p&gt;（サンプルのアニメで上下移動も怪しいへっぽこvimmerだということがばれましたね…）&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#operator-ai-カーソルの位置と同じインデントそのインデントの一行上を指定&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;code&gt;&amp;lt;operator&amp;gt; ai&lt;/code&gt; ：カーソルの位置と同じインデント+そのインデントの一行上を指定&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200807/20200807102838.gif&quot; alt=&quot;f:id:ikmbear:20200807102838g&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#operator-ai-カーソルの位置と同じインデントそのインデントの一行上と下を指定&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;code&gt;&amp;lt;operator&amp;gt; aI&lt;/code&gt; ：カーソルの位置と同じインデント+そのインデントの一行上と下を指定&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200807/20200807103642.gif&quot; alt=&quot;f:id:ikmbear:20200807103642g&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#テキストで再確認&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;テキストで再確認&lt;/h3&gt;
&lt;p&gt;テキストで各コマンドの範囲を確認すると、以下のようになります。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;div&amp;gt;  &amp;lt;p&amp;gt;vimvimvimvimvimvimvimvimvimvimvimvimvim&amp;lt;/p&amp;gt;    &amp;lt;div&amp;gt;　&amp;lt;!--aiと、aIの上方向はここまで--&amp;gt;      &amp;lt;p&amp;gt;vimvimvimvimvimvimvimvimvimvimvimvimvim&amp;lt;/p&amp;gt; &amp;lt;!--iiだとここまで--&amp;gt;      &amp;lt;p&amp;gt;vimvimvimvimvimvimvimvimvimvimvimvimvim&amp;lt;/p&amp;gt;      &amp;lt;p&amp;gt;vimvimvimvimvimvimvimvimvimvimvimvimvim&amp;lt;/p&amp;gt;      &amp;lt;p&amp;gt;vimvimvimvimvimvimvimvimvimvimvimvimvim&amp;lt;/p&amp;gt; &amp;lt;!--ここでコマンドを実行--&amp;gt;    &amp;lt;/div&amp;gt; &amp;lt;!--aIの下方向はここまで--&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#まとめ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;まとめ&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;VSCodeVimでは、標準で「インデントオブジェクト」がサポートされている。&lt;/li&gt;
&lt;li&gt;「インデントオブジェクト」：現在のカーソル位置のインデントを基準として、同じインデントの範囲を指定する。&lt;/li&gt;
&lt;li&gt;一番外側のインデントにカーソルをおいてインデントオブジェクトを指定すると、実質全選択をすることができる。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;vimの世界だけでも広かったのに、VscodeVimの世界も広がってしまいました（vimの説明をみた限りでは、なんか他にもいろいろ独自のvimがありそうな感じでした）。&lt;br /&gt;
困ったら都度都度覚えるしかないですね〜😭&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#参考&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;参考&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.tohoho-web.com/python/syntax.html&quot; target=&quot;_blank&quot;&gt;とほほのPython入門 - 構文 - とほほのWWW入門&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/michaeljsmith/vim-indent-object&quot; target=&quot;_blank&quot;&gt;vim-indent-object&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wonwon-eater.com/vscode-vim-all-select/&quot; target=&quot;_blank&quot;&gt;VSCode Vim ワンキーで全選択(ctrl+a)をしたい │ wonwon eater&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>ikuma-t</author></item><item><title>今月のフォカッチャ</title><link>https://ikuma-t.com/blog/20200806000514/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20200806000514/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200728/20200728164816.png今月のと言いながら焼</description><pubDate>Thu, 06 Aug 2020 00:05:14 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200728/20200728164816.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200728/20200728164816.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;今月のと言いながら焼いたのは先月（2020/7）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%83%91%E3%83%B3%E3%81%A8%E3%81%AE%E6%80%9D%E3%81%84%E5%87%BA&quot;&gt;パンとの思い出&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%83%95%E3%82%A9%E3%82%AB%E3%83%83%E3%83%81%E3%83%A3%E4%BD%9C%E3%82%8A&quot;&gt;フォカッチャ作り&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E4%BB%8A%E5%9B%9E%E4%BD%9C%E3%82%8B%E3%82%82%E3%81%AE&quot;&gt;今回作るもの&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%83%AC%E3%82%B7%E3%83%94&quot;&gt;レシピ&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E4%BD%9C%E3%82%8A%E6%96%B9%E7%B0%A1%E6%98%93%E7%89%88&quot;&gt;作り方（簡易版）&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E6%B7%B7%E3%81%9C%E3%82%8B&quot;&gt;混ぜる&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E4%B8%80%E6%AC%A1%E7%99%BA%E9%85%B5&quot;&gt;一次発酵&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E4%BA%8C%E6%AC%A1%E7%99%BA%E9%85%B5%E7%84%BC%E6%88%90&quot;&gt;二次発酵〜焼成&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E6%84%9F%E6%83%B3&quot;&gt;感想&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#パンとの思い出&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;パンとの思い出&lt;/h2&gt;
&lt;p&gt;エンジニアとしてのアウトプットブログなのに、3記事目からパンの話だと「こいつエンジニアの卵の化けの皮を被ったパン屋だな」と思われそうです。&lt;/p&gt;
&lt;p&gt;一応、高校上がりたての頃は本気でパン屋になろうと思っており、大学入学と同時にチェーンのベーカリーへ。&lt;br /&gt;
1年間働いた後、「一からパン作りがしたい」という思いから、$1の個人経営ベーカリーに転職（※バイトです）し、大学卒業まで製造〜売り子までやっていました。&lt;/p&gt;
&lt;p&gt;1店舗目は出来合いのパン生地を発酵させるだけで、なんか腑に落ちなかったんですよね。&lt;br /&gt;
自分で仕組みを理解して作り上げるという工程を踏まないと気が済まないみたいです。&lt;/p&gt;
&lt;p&gt;そんなこんなで現在も趣味でイタリアの食事パン「フォカッチャ」を焼いているので、月に一度のご紹介です。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#フォカッチャ作り&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;フォカッチャ作り&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#今回作るもの&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;今回作るもの&lt;/h3&gt;
&lt;p&gt;まず今回作るのはこちらのフォカッチャです。大量のバジルと岩塩で味をブーストさせたベストオブ食事パンです。 &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200728/20200728164816.png&quot; alt=&quot;f:id:ikmbear:20200728164816p&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#レシピ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;レシピ&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;強力粉：300g&lt;/li&gt;
&lt;li&gt;塩：5g&lt;/li&gt;
&lt;li&gt;砂糖：5g&lt;/li&gt;
&lt;li&gt;$1：5g&lt;/li&gt;
&lt;li&gt;オリーブオイル：10g&lt;/li&gt;
&lt;li&gt;水：200g&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#作り方簡易版&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;作り方（簡易版）&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#混ぜる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;混ぜる&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200728/20200728165207.png&quot; alt=&quot;f:id:ikmbear:20200728165207p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;まずはひたすら混ぜます。&lt;/p&gt;
&lt;p&gt;2件目のパン屋で働く前は、「手でこねるのこそ至高。パン職人はこうあるべき」とか思ってたんですが、今はゴムベラしか使わないです（成形段階になったら手でやりますが）。 混ぜるときは手につかない方が効率がいいし、生地の量も減らなくて済むので。&lt;/p&gt;
&lt;p&gt;しかもパン屋は機械使ってますからね。フランスのパン屋は「いかに楽をするか」ということを常に考えていて、それゆえ作業の機械化が進んだとかなんとか。まるでエンジニア。&lt;/p&gt;
&lt;p&gt;こうしてパン生地を捏ねていると、自分の思い込みの極論ではなくて、ちゃんと現実と向き合って、目的に見合ったやり方を採択することが大事なんだと思い知らされます。&lt;/p&gt;
&lt;p&gt;Excelを使うことが悪なんじゃない。システム化の中でExcelの方が費用対効果がいいときだってあるし、Excelにしかないメリットがあるんだとか。何でもかんでもExcelでやろうとするからいけないんだみたいな。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#一次発酵&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;一次発酵&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200728/20200728170248.png&quot; alt=&quot;f:id:ikmbear:20200728170248p&quot; /&gt; 写真くらいまとまってきたらラップして一次発酵です。時間は適当。大体勉強しながら作るので、いつのまにかいい大きさになっています（冬場だと気温が低いので発酵しにくいですが）。&lt;/p&gt;
&lt;p&gt;この工程も昔は生地にハリツヤが出て、$1チェック合格できるくらいまで捏ねていました（画像くらいだと15~20分くらい捏ねたところです）。市販のパン作りの教科書に書いてあるので、それが正しいと思ってずーっと捏ねていました。&lt;/p&gt;
&lt;p&gt;でもこれくらいの捏ね具合でも、発酵を重ねるときれいになって、美味しいパンになるんですよ。&lt;/p&gt;
&lt;p&gt;「基本に忠実に、完璧になるまでそこをやるっていうのもいいが、大体把握できたらまずはその先へ行ってみて、各工程・レベルのエッセンスを掴むことこそが大事ではないか」、とパンに言われているような気がしました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#二次発酵1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;二次発酵〜$1&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200728/20200728171359.png&quot; alt=&quot;f:id:ikmbear:20200728171359p&quot; /&gt; 一次発酵後です。あとはガスを抜いてもう一回発酵し、型に入れます（以降の工程の写真は撮り忘れました）。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200805/20200805235743.jpg&quot; alt=&quot;f:id:ikmbear:20200805235743j&quot; /&gt; 焼きに入れる前に、塩とバジルとオリーブオイルを振りかけます。&lt;br /&gt;
塩はうまいものがいいです。これは実家の母が知り合いからもらったいい塩です。めちゃうまいです（馬鹿みたいな文章だなあ）。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200728/20200728164816.png&quot; alt=&quot;f:id:ikmbear:20200728164816p&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;原価100~150円くらいでできるので、めちゃくちゃお得〜&lt;br /&gt;
エンジニア全然関係ないですけど、同じ内容を定点観測していくとアウトプットの質も上がる気がするので、これからもフォカッチャ作りお届けしたいと思います！&lt;/p&gt;</content:encoded><author>ikuma-t</author></item><item><title>突然ssh接続でDebianに繋がらなくなったときの対処法</title><link>https://ikuma-t.com/blog/20200805234305/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20200805234305/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200805/20200805215246.png記憶喪失のDebia</description><pubDate>Wed, 05 Aug 2020 23:43:05 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200805/20200805215246.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200805/20200805215246.png&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#記憶喪失のdebian&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;記憶喪失のDebian？&lt;/h2&gt;
&lt;p&gt;3日前くらいに、さくらVPS上のDebianに対して公開鍵の設定しました。&lt;br /&gt;
設定当初から問題なく公開鍵認証で接続できていたのですが、今日ssh接続を試みると、突然&lt;code&gt;Permission denied (public key)&lt;/code&gt;と言われてしまいました。 &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200805/20200805215246.png&quot; alt=&quot;f:id:ikmbear:20200805215246p&quot; /&gt;&lt;/p&gt;
&lt;p&gt;何も設定を変えていなかったので、どうしたもんかと。アニメ「一週間フレンズ」しかり、Debianは数日立つと私のことを忘れてしまうのでしょうか。&lt;/p&gt;
&lt;p&gt;「Debian！俺だよ！思い出してくれよ！」&lt;br /&gt;
そう叫んだところで相手はシステム。思いは届きません。一つずつ確認しましょう。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E8%A8%98%E6%86%B6%E5%96%AA%E5%A4%B1%E3%81%AEDebian&quot;&gt;記憶喪失のDebian？&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%89%8D%E6%8F%90&quot;&gt;前提&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E6%80%9D%E3%81%84%E5%87%BA%E3%81%9BDebian%E7%B7%A8&quot;&gt;思い出せDebian編&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E8%A6%9A%E3%81%88%E3%81%A6%E3%82%8B%E3%81%8B%E4%BF%BA%E3%81%9F%E3%81%A1%E6%98%94%E3%81%AF%E3%83%91%E3%82%B9%E3%83%AF%E3%83%BC%E3%83%89%E3%81%A7ssh%E6%8E%A5%E7%B6%9A%E3%81%97%E3%81%9F%E3%82%8A%E3%81%97%E3%81%A6%E3%81%95&quot;&gt;覚えてるか？俺たち、昔はパスワードでssh接続したりしてさ…&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E8%A6%9A%E3%81%88%E3%81%A6%E3%82%8B%E3%81%8B%E3%81%93%E3%81%AE%E9%8D%B5%E5%8D%8A%E5%88%86%E3%81%8A%E5%89%8D%E3%81%AB%E6%B8%A1%E3%81%97%E3%81%A6%E3%81%95&quot;&gt;覚えてるか？この鍵。半分、お前に渡してさ…&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%81%AA%E3%81%82Debian%E9%96%89%E3%81%96%E3%81%97%E3%81%9F%E5%BF%83%E3%82%92%E9%96%8B%E3%81%84%E3%81%A6%E3%81%8F%E3%82%8C%E3%82%88&quot;&gt;なあDebian、閉ざした心を開いてくれよ…&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#Debian%E3%81%8A%E5%89%8D%E3%82%82%E3%81%97%E3%81%8B%E3%81%97%E3%81%A6&quot;&gt;Debian、お前もしかして…&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#Debian%E3%81%AF%E8%A6%9A%E3%81%88%E3%81%A6%E3%81%84%E3%81%9F%E7%B7%A8&quot;&gt;Debianは覚えていた編&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%BF%98%E3%82%8C%E3%81%9F%E3%81%AE%E3%81%AF%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88mac%E3%81%AE%E3%82%AD%E3%83%BC%E3%83%81%E3%82%A7%E3%83%BC%E3%83%B3&quot;&gt;忘れたのはクライアント（mac）のキーチェーン&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%82%AD%E3%83%BC%E3%83%81%E3%82%A7%E3%83%BC%E3%83%B3%E3%81%ABDebian%E3%81%A8%E3%81%AE%E5%8F%8B%E6%83%85%E3%82%92%E9%82%AA%E9%AD%94%E3%81%95%E3%81%9B%E3%81%AA%E3%81%84&quot;&gt;キーチェーンにDebianとの友情を邪魔させない。&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%82%82%E3%81%A3%E3%81%A8Debian%E3%81%A8%E4%BB%B2%E8%89%AF%E3%81%8F%E3%81%AA%E3%82%8B&quot;&gt;もっとDebianと仲良くなる&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E6%84%9F%E6%83%B3&quot;&gt;感想&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%8F%82%E8%80%83&quot;&gt;参考&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#前提&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;前提&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;sshクライアント：macOS Catalina（10.15.6）&lt;/li&gt;
&lt;li&gt;接続先：さくらVPSに構築したDebian10.4&lt;/li&gt;
&lt;li&gt;以前は公開鍵認証で問題なく接続できていたが、突然&lt;code&gt;Permission denied (public key)&lt;/code&gt;により接続できなくなった。&lt;/li&gt;
&lt;li&gt;公開鍵認証については、&lt;a href=&quot;http://www.tooyama.org/ssh-key.html&quot; target=&quot;_blank&quot;&gt;ssh接続を鍵認証で行う&lt;/a&gt;を参考に実施済み。つまり
&lt;ul&gt;
&lt;li&gt;client_rsaというキーペアを作成&lt;/li&gt;
&lt;li&gt;クライアントのキーチェーンには$1を登録済（&lt;code&gt;ssh-add -K ~/.ssh/client_rsa&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;Debian側にも公開鍵を登録済&lt;/li&gt;
&lt;li&gt;Debian側のsshd_configは以下の設定がしてある&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;PasswordAuthentication  noChallengeResponseAuthentication  noUsePAM  yes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#思い出せdebian編&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;思い出せDebian編&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#覚えてるか俺たち昔はパスワードでssh接続したりしてさ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;覚えてるか？俺たち、昔はパスワードでssh接続したりしてさ…&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;確認したいこと：原因が公開鍵認証によるものなのかの切り分け&lt;/li&gt;
&lt;li&gt;確認方法：Debian側のsshd_configで&lt;code&gt;PasswordAuthentication yes&lt;/code&gt;に設定変更する。&lt;/li&gt;
&lt;li&gt;確認結果：パスワード認証では問題なくssh接続できる。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Debian「今もパスワード認証できるで」&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#覚えてるかこの鍵半分お前に渡してさ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;覚えてるか？この鍵。半分、お前に渡してさ…&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;確認したいこと：公開鍵がちゃんとサーバ側に格納されているかどうかを確認&lt;/li&gt;
&lt;li&gt;確認方法：macで作成した公開鍵を確認し、debian側のフォルダに配置されているものと比較する。
&lt;ul&gt;
&lt;li&gt;具体的には以下の流れでクライアント、サーバでのcat結果を比較。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# クライアント（mac）にキーペアが作成されていることを確認$ ls ~/.ssh$ cat ~/.ssh/client_rsa.pub# サーバ（debian）に公開鍵が配置されていることを確認$ ls ~/.ssh$ cat ~/.ssh/authorized_keys&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;確認結果：作成した公開鍵がサーバ側に正しく格納されている。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Debian「今もちゃんと持ってるで、覚えとるで」&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#なあdebian閉ざした心を開いてくれよ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;なあDebian、閉ざした心を開いてくれよ…&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;確認したいこと：エラーメッセージにある&lt;code&gt;Permission Denied&lt;/code&gt;が本当に$1が原因か確認する。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;確認方法：クライアント、サーバ側それぞれの.sshsshリのsshを確認する。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;クライアントは700（rwx）&lt;/li&gt;
&lt;li&gt;サーバ側は600（rw）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;確認結果：どちらも期待通り。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Debian「心オープンやで〜」&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#debianお前もしかして&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Debian、お前もしかして…&lt;/h3&gt;
&lt;p&gt;Debian「さっきから好き勝手疑ってくれてますけど」&lt;br /&gt;
Debian「全然こっちは問題ないですから。」&lt;br /&gt;
Debian「もうひとつ言っておくと、使用する鍵をちゃんと指定すればssh接続できますから！こんな感じで。」&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$ ssh -i ~/.ssh/client_rsa -p 3090 YYYYYYYYYYYY@XXX.XX.XX.XXX&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#debianは覚えていた編&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Debianは覚えていた編&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#忘れたのはクライアントmacのキーチェーン&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;忘れたのはクライアント（mac）のキーチェーン&lt;/h3&gt;
&lt;p&gt;実は問題があるのはDebianではなく、キーチェーンの方でした。&lt;br /&gt;
macOS 10.12 Sierra以降、キーチェーンが再起動時に読み込まれなくなる仕様となったそうです。&lt;/p&gt;
&lt;p&gt;タイトルに「突然」とありますが、実際には「macの再起動」をトリガーとして本事象が発生します。（事象発生まではmacbookをスリープするだけで、再起動していなかったんでしょうね…）&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#キーチェーンにdebianとの友情を邪魔させない&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;キーチェーンにDebianとの友情を邪魔させない。&lt;/h3&gt;
&lt;p&gt;再度&lt;code&gt;ssh-add -K ~/.ssh/client_rsa&lt;/code&gt;を実行することで、一時的には繋がるようになりますが、再起動すると、またssh接続できなくなってしまいます。&lt;br /&gt;
そのため、恒久対応として~/.ssh/configに以下の設定を追加します。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Host *  UseKeychain yes  AddKeysToAgent yes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#もっとdebianと仲良くなる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;もっとDebianと仲良くなる&lt;/h3&gt;
&lt;p&gt;せっかくconfigの設定をしたので、毎回ポートやipを打たずに済むような設定もしておきます。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Host ikuma-t  HostName XXX.XXX.XX.XX  User ikuma-t  IdentityFile ~/.ssh/client_rsa  Port 3090  TCPKeepAlive yes  IdentitiesOnly yes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;これで再起動しても&lt;code&gt;ssh ikuma-t&lt;/code&gt;で繋がるようになりました！&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#感想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;感想&lt;/h2&gt;
&lt;p&gt;コマンドだけでリモートとやり取りするような部分って、「これ何やってんだ？」「どれチェックしたか忘れた…もう一回しらみ潰しにやり直してみよう」ってことが多いと思います。&lt;/p&gt;
&lt;p&gt;今回はDebianが記憶喪失したというストーリーで擬人化して考えましたが、とっつきにくい内容だからこそ、自分で噛み砕いてコミカルにしてみるのはなかなか効果的でした！&lt;/p&gt;
&lt;p&gt;Debian「途中で設定とかストーリー書くの面倒になったでしょ」&lt;br /&gt;
私「ファッ！！！」&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#参考&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;参考&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://qiita.com/youcune/items/2f427979403771f2e03a&quot; target=&quot;_blank&quot;&gt;SSH で Permission Denied となる傾向と対策 - Qiita&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://apple.stackexchange.com/questions/48502/how-can-i-permanently-add-my-ssh-private-key-to-keychain-so-it-is-automatically&quot; target=&quot;_blank&quot;&gt;How can I permanently add my SSH private key to Keychain so it is automatically available to ssh? - Ask Different&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://qiita.com/sonots/items/a6dec06f95fca4757d4a&quot; target=&quot;_blank&quot;&gt;macOS で再起動しても ssh agent に秘密鍵を保持させ続ける二つの方法 - Qiita&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://qiita.com/0084ken/items/2e4e9ae44ec5e01328f1&quot; target=&quot;_blank&quot;&gt;.ssh/configファイルでSSH接続を管理する - Qiita&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>ikuma-t</author></item><item><title>フィヨルドブートキャンプにキャンプインしました</title><link>https://ikuma-t.com/blog/20200722194545/</link><guid isPermaLink="true">https://ikuma-t.com/blog/20200722194545/</guid><description>IMAGE:https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200722/20200722142831.pngはじめにプログラミン</description><pubDate>Wed, 22 Jul 2020 19:45:45 GMT</pubDate><content:encoded>&lt;p&gt;IMAGE: &lt;a href=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200722/20200722142831.png&quot; target=&quot;_blank&quot;&gt;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200722/20200722142831.png&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB&quot;&gt;はじめに&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%82%B9%E3%82%AF%E3%83%BC%E3%83%AB%E3%81%AB%E5%85%A5%E3%82%8B%E3%81%BE%E3%81%A7%E3%81%AE%E7%B5%8C%E7%B7%AF&quot;&gt;プログラミングスクールに入るまでの経緯&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%A8%E3%81%AE%E5%87%BA%E4%BC%9A%E3%81%84201712201912&quot;&gt;プログラミングとの出会い（2017/12〜2019/12）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%A8%E3%81%AE%E5%88%A5%E3%82%8C20201&quot;&gt;プログラミングとの別れ（2020/1〜）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E7%8B%AC%E5%AD%A6%E6%99%82%E4%BB%A3202026&quot;&gt;独学時代（2020/2〜6）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%82%AD%E3%83%A3%E3%83%B3%E3%83%97%E3%82%A4%E3%83%B320207&quot;&gt;キャンプイン（2020/7〜）&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%85%A5%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%A6%E3%82%88%E3%81%8B%E3%81%A3%E3%81%9F%E3%81%93%E3%81%A8%E3%82%AD%E3%83%A3%E3%83%B3%E3%83%97%E3%81%AE%E3%81%84%E3%81%84%E3%81%A8%E3%81%93%E3%82%8D&quot;&gt;入ってみてよかったこと（キャンプのいいところ）&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%81%A9%E3%82%8C%E3%81%8B%E3%82%89%E5%8B%89%E5%BC%B7%E3%82%92%E9%80%B2%E3%82%81%E3%81%A6%E3%81%84%E3%81%8F%E3%81%8B%E3%81%AB%E7%B5%82%E6%AD%A2%E7%AC%A6%E3%82%92%E3%81%86%E3%81%A4%E3%81%93%E3%81%A8%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%9F&quot;&gt;「どれから勉強を進めていくか」に終止符をうつことができた&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E8%87%AA%E8%B5%B0%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E7%92%B0%E5%A2%83%E3%81%8C%E6%95%B4%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B&quot;&gt;自走のための環境が整っている&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E5%85%A5%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%A6%E3%82%88%E3%81%8B%E3%81%A3%E3%81%9F%E3%81%93%E3%81%A8%E5%89%AF%E7%94%A3%E7%89%A9%E7%B7%A8&quot;&gt;入ってみてよかったこと（副産物編）&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E3%83%AC%E3%83%93%E3%83%A5%E3%82%A4%E3%83%BC%E3%81%AE%E6%B0%97%E6%8C%81%E3%81%A1%E3%82%92%E6%80%9D%E3%81%84%E5%87%BA%E3%81%9B%E3%82%8B&quot;&gt;レビュイーの気持ちを思い出せる&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E7%94%9F%E6%B4%BB%E3%83%AA%E3%82%BA%E3%83%A0%E3%81%8C%E8%A6%8F%E5%89%87%E6%AD%A3%E3%81%97%E3%81%8F%E3%81%AA%E3%82%8B&quot;&gt;生活リズムが規則正しくなる&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#slack%E6%96%87%E5%8C%96%E3%81%AB%E6%85%A3%E3%82%8C%E3%82%8B&quot;&gt;slack文化に慣れる&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#%E6%9C%80%E5%BE%8C%E3%81%AB&quot;&gt;最後に&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#はじめに&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;はじめに&lt;/h2&gt;
&lt;p&gt;この度&lt;a href=&quot;https://bootcamp.fjord.jp/&quot; target=&quot;_blank&quot;&gt;フィヨルドブートキャンプ&lt;/a&gt;というプログラミングスクールに参加しました。本業（SIer）との両立で大変なところもありますが、エンジニアとしてのスキルを伸ばすべく頑張ります！&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#プログラミングスクールに入るまでの経緯&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;プログラミングスクールに入るまでの経緯&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#プログラミングとの出会い201712201912&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;プログラミングとの出会い（2017/12〜2019/12）&lt;/h3&gt;
&lt;p&gt;先の通り、私の本業はSIerで現在入社3年目（新卒から入った会社です）。内容は業務コンサルよりな仕事です。&lt;/p&gt;
&lt;p&gt;SIerに入社こそしていますが、大学の学部は文系だったため、プログラミングに本格的に出会ったのは就職活動の時でした。ネットワーク系のSIerでの計3日ほどのSIerで、完全にこのITの世界にハマりSIerに就職。&lt;/p&gt;
&lt;p&gt;ただこの時は特にプログラミングをやっておらず、一方で技術を理解して伝えるという点に強みを感じていたため、「〇〇 × IT」、つまり「自分は〇〇を解決するために、ITという手段をうまく使う人」という考えで、コンサルよりのSIerを選びました。&lt;/p&gt;
&lt;p&gt;入社してから1~2年目は、研修含めてJavaを習得。業務知識も順調に習得し、現場ではコンサルしながら、Javaしてバグを直しと個人的にめちゃくちゃ充実した日々を送っていました。&lt;br /&gt;
このとき「ああ、私はSIerのSIer&lt;a href=&quot;#f-2f1eacaf&quot;&gt;*1&lt;/a&gt;になるんだな」と確信しました。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#プログラミングとの別れ20201&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;プログラミングとの別れ（2020/1〜）&lt;/h3&gt;
&lt;p&gt;一つ目のPJを有終の美で終えたのち、次のPJに入ったところで突然プログラミングとの別れがきました（あくまで最初のプログラミングはお試し期間だったようです）。&lt;br /&gt;
でも大丈夫、私にはSQLがついているじゃないか。batじいさんだっているんだ、ちょっとしたツールを作る喜びはある!&lt;br /&gt;
$1だって怪我しても、ホームラン打ってますし。&lt;/p&gt;
&lt;p&gt;しかしCASE文と$1での一人遊びはそう長く続きません。&lt;/p&gt;
&lt;p&gt;Qiitaに、メルカリ、$1、どんどん増えていく若手エントリー。&lt;br /&gt;
増える手取り、感じる焦り、一人始めるProgate。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#独学時代202026&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;独学時代（2020/2〜6）&lt;/h3&gt;
&lt;p&gt;最初の一年をかなり飛ばしていたおかげで、燃えつき症候群&amp;amp;時間を持て余していたので、Progateに粛々と挑戦。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200722/20200722142831.png&quot; alt=&quot;f:id:ikmbear:20200722142831p&quot; /&gt; Progate&lt;/p&gt;
&lt;p&gt;1ヶ月ほどでいわゆるWeb系っぽいおおよそのコースはクリア。&lt;/p&gt;
&lt;p&gt;その後udemyでいくつかのコースをやり、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.udemy.com/share/101WjqBUQceVdQQX4=/:title&quot; target=&quot;_blank&quot;&gt;HTML/CSS/JavaScript フロントエンドエンジニアになりたい人の Webプログラミング入門 &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.udemy.com/share/1023iKBUQceVdQQX4=/&quot; target=&quot;_blank&quot;&gt;はじめてのRuby on Rails入門-RubyとRailsを基礎から学びWebアプリケーションをネットに公開しよう&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.udemy.com/share/1021OEBUQceVdQQX4=/&quot; target=&quot;_blank&quot;&gt;Git： もう怖くないGit！チーム開発で必要なGitを完全マスター&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Qiitaのハンズオン系記事に飛びつく期間が続きますが、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;基礎が終わったような気がするし、実戦で経験値を積みたい。でも実際には基礎ができていない、のかもわからないが、まずは前提知識を増やさないといけない。&lt;/li&gt;
&lt;li&gt;やろうと思っても、基礎はどこまで？どこからやればいい？となり進めない。&lt;/li&gt;
&lt;li&gt;その通りにやれば最後まで辿り着ける講座は、応用になるとうまくできない。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;と壁にぶつかるのでした。&lt;/p&gt;
&lt;p&gt;もちろんJavaをやっていたわけですから、RubyとかRailsをやってみても、各メソッドがどう関連して作用していくのかは理解できました。&lt;br /&gt;
ただ、Javaをやっているときは「すでに出来上がっているアプリに、改修を加えていく」という作業だったため、フロントエンドやインフラの細かい点を意識せず、サーバサイド の具体的なロジックをどうするかだけ考えればよかったんですよね。&lt;br /&gt;
一から作る場合は、インフラ含めたそのロジックが作用する土台や、見た目を作っていく必要があるので、そこの前提知識が全然足りなかったのかなと思っています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#キャンプイン20207&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;キャンプイン（2020/7〜）&lt;/h3&gt;
&lt;p&gt;「このままではずっと同じところから抜け出せないなあ、でもどうやって勉強進めたらいいかわからないなあ」&lt;br /&gt;
そんな現状を打破すべく、$1ブートキャンプにキャンプイン。&lt;/p&gt;
&lt;p&gt;選定理由は雰囲気です。&lt;br /&gt;
やっぱり学習をしていく上で、このコミュニティでやっていくのはしんどいな、と思うことがあっては続かないと思うんですよ。じゃあどうやってそれを判断するかといったら、私の場合は雰囲気、フィーリングなんです。 &lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200722/20200722162914.png&quot; alt=&quot;f:id:ikmbear:20200722162914p&quot; /&gt; これが$1ブートキャンプのホームページですけど、この画像をみて「怪しいな」「弱そう」「かわいい」「優しそう」といろんな感じ方ができるかと思います。&lt;br /&gt;
私はこれをみて「なんか優しい雰囲気そうだな、やっていけそうだな」と思ったのでこれにしました。&lt;/p&gt;
&lt;p&gt;みすず理論ってやつですね（私が勝手に呼んでるだけですが）。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;あのCMを見て、「何となく面白そうだな」と感じる、シャレの分かる、明るくて素直な子に来てほしいのです。&lt;a href=&quot;https://www.misuzu-gakuen.jp/cm/&quot; target=&quot;_blank&quot;&gt;みすず学園&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;もちろん価格とか、カリキュラムといった最低限の情報はみましたけどね。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#入ってみてよかったことキャンプのいいところ&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;入ってみてよかったこと（キャンプのいいところ）&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#どれから勉強を進めていくかに終止符をうつことができた&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;「どれから勉強を進めていくか」に終止符をうつことができた&lt;/h3&gt;
&lt;p&gt;ここが今のところ、一番大きいです。&lt;br /&gt;
自分の場合は、「プログラミングはできるようになりたい。自分で勉強もできる。けれど、学ぶべき技術が幅広すぎて、どこから手をつけていいかわからない」という悩みがありましたが、カリキュラムがあるキャンプに入ることはこの悩みを直接的に解決してくれました。&lt;/p&gt;
&lt;p&gt;成長$1という本に、「進むべき道でブレーキを踏んでしまうことは、成長を阻害する要因の一つ」という一節があります。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-ak.f.st-hatena.com/images/fotolife/i/ikmbear/20200722/20200722165117.png&quot; alt=&quot;f:id:ikmbear:20200722165117p&quot; /&gt; 　&lt;a href=&quot;#f-b22bb704&quot;&gt;*2&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.co.jp/%E6%88%90%E9%95%B7%E3%83%9E%E3%82%A4%E3%83%B3%E3%83%89%E3%82%BB%E3%83%83%E3%83%88-%E5%90%89%E7%94%B0-%E8%A1%8C%E5%AE%8F-ebook/dp/B07CBTDJ5F&quot; target=&quot;_blank&quot;&gt;https://www.amazon.co.jp/%E6%88%90%E9%95%B7%E3%83%9E%E3%82%A4%E3%83%B3%E3%83%89%E3%82%BB%E3%83%83%E3%83%88-%E5%90%89%E7%94%B0-%E8%A1%8C%E5%AE%8F-ebook/dp/B07CBTDJ5F&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.co.jp/%E6%88%90%E9%95%B7%E3%83%9E%E3%82%A4%E3%83%B3%E3%83%89%E3%82%BB%E3%83%83%E3%83%88-%E5%90%89%E7%94%B0-%E8%A1%8C%E5%AE%8F-ebook/dp/B07CBTDJ5F&quot; target=&quot;_blank&quot;&gt;www.amazon.co.jp&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;「基礎はやらなきゃいけないけど、本当にこれから初めていいのかな。どこまでやればいいのかな」と思い続けながら自走しようとしていた時期は、完全にブレーキを踏みながらアクセルを踏んでいる時期でした。&lt;br /&gt;
「カリキュラムがある」という点は別のスクールでも同じだと思っているので、これは「勉強方針に迷っている社会人がプログラミングスクールに入ってよかったこと」ですね。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#自走のための環境が整っている&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;自走のための環境が整っている&lt;/h3&gt;
&lt;p&gt;$1ブートキャンプでは、演習に対して提出物があるものの、そこに至るステップを明確に規定しません。代わりに参考書籍・サイト、ドキュメントなどが課題ページに書いてあるので、自分で必要なものを選んで学習し、課題に挑みます。&lt;/p&gt;
&lt;p&gt;もちろんそれだけでは足りないこともあるので、キャンプ内の生徒・メンター全員がみられるQ&amp;amp;Aや他の人の日報を参考にしながら進めます。&lt;/p&gt;
&lt;p&gt;ここがいい点だと思う理由は次の3点です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;プログラミングの楽しさである、自分で考えて解決する余地を残している&lt;/li&gt;
&lt;li&gt;課題を解決するための探索力向上を促す一方、いざ聞くべき環境はシステムとして用意している&lt;/li&gt;
&lt;li&gt;同じ課題をやる生徒を見つけることで、モチベーション意地に繋がる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;物事に絶対はないので、カリキュラムを充実させることにももちろんメリットがあります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;スクール側は運営が楽になり、スケールさせやすい。すると、生徒の環境に資金投下もしやすい（$1ブートキャンプの場合は、メンターさんの頑張りで支えられている感じがします。そして生徒さんの間でも支え合いの概念が浸透しているように思います）。&lt;/li&gt;
&lt;li&gt;生徒としても、カリキュラムをやることで一定のレベルが保証される（自分で考える余地があるということは、やらなかったら当然力にならない）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ここは考え方次第です。私の場合は自分で自走したいけれど、先の通り、どう進めればいいかわからないという悩みを解決したかったので、キャンプのシステムがあっているかなと。&lt;br /&gt;
小$1から大手塾が苦手で、受験の時だけ基本放置なこじんまりした塾に通っていて結果が出ていたので、そういう人間なのかも。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#入ってみてよかったこと副産物編&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;入ってみてよかったこと（副産物編）&lt;/h2&gt;
&lt;p&gt;ここからは、別にキャンプ特有の内容ではありません。社会人が何かを勉強するコミュニティに入ったら、勝手にそうなったというだけですが、一応紹介します。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#レビュイーの気持ちを思い出せる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;レビュイーの気持ちを思い出せる&lt;/h3&gt;
&lt;p&gt;一般的に社会人3年目って、仕事の流れを一通り覚えて、後輩もできて…みたいな年頃かと思います。&lt;br /&gt;
そして放置される年頃かと思います（私の場合、割と入社当初から最初から放置されがちでした）。&lt;/p&gt;
&lt;p&gt;そうすると、上からのレビューを受ける立場（レビュイー）は徐々に減り、逆にレビュアーになるんですよね。私は特殊スキルで「謎の信頼」を発動しているので、レビューの場を設定しても何も言われなくなりました。&lt;/p&gt;
&lt;p&gt;で、キャンプに入ったことで、また教えをこう立場に戻れたわけです。すると仕事をする際にも、レビュイーの気持ちに共感しやすくなる（同感はNGですが）というメリットがありました。どこまで教えようか、どう伝えようか、などなど。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#生活リズムが規則正しくなる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;生活リズムが規則正しくなる&lt;/h3&gt;
&lt;p&gt;普段は本業をやっているので、どこかで学習時間を確保しないといけません。私の場合、今はテレワーク中なので、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;6&lt;div&gt;&lt;/div&gt; ~ 8&lt;div&gt;&lt;/div&gt; キャンプ&lt;/li&gt;
&lt;li&gt;8&lt;div&gt;&lt;/div&gt; ~ 17&lt;div&gt;&lt;/div&gt;(~19&lt;div&gt;&lt;/div&gt;) 仕事&lt;/li&gt;
&lt;li&gt;19&lt;div&gt;&lt;/div&gt; ~ 23&lt;div&gt;&lt;/div&gt; キャンプ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;とすることで時間を確保しています。時間を確保するためには早起きしないといけないので、必然的に生活リズムがよくなりました。ついでにいうと、仕事も切り上げないと勉強できないので、タスク管理も今まで以上にテキパキやっています（感覚ですが）。&lt;/p&gt;
&lt;p&gt;ちなみにキャンプではslackに学習用チャンネルがあり、そこで「朝の$1」を開催してくださっている生徒の方がいらっしゃるので、私も便乗してなんとか朝の習慣を続けています。&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#slack文化に慣れる&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;slack文化に慣れる&lt;/h3&gt;
&lt;p&gt;本業の方でもslackはあるのですが、基本的にメール文化です。すると、slackを使ったやりとりに$1ハードルがあるんですよね。&lt;/p&gt;
&lt;p&gt;私も最初は会ったことのない人にチャットをするのは緊張しましたが、慣れました。&lt;br /&gt;
SIerから転職ありきでプログラミングスクールに入るのであれば、Web系ではslackは当たり前に使われていると思うので、練習できる場があるのは嬉しいかな〜と個人的に。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#最後に&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;最後に&lt;/h2&gt;
&lt;p&gt;まずは本業とキャンプの両立を維持しながら、コツコツとプ$1ティスを進めていきたいと思います。やっていく中で、学んだこと、感じたこと、時々フォッカチオ作りをこのブログに描ければなと思います。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#fn-2f1eacaf&quot;&gt;*1&lt;/a&gt;&lt;/p&gt;&lt;div&gt;&lt;/div&gt;、一般的にはどちらかの$1リストを目指す&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#fn-b22bb704&quot;&gt;*2&lt;/a&gt;&lt;/p&gt;&lt;div&gt;&lt;/div&gt;$1 図17より引用&lt;p&gt;&lt;/p&gt;</content:encoded><author>ikuma-t</author></item></channel></rss>