Intro Hexoを、Icarusを、初期投資としてガンガン便利にしていく。
TL; DR VSCode側で画像のpathを手動で修正せずとも、scirpts配下のjsファイルで自動で対応した。 さらに、見た目のよいAlertboxも作成できるようになった。
Difference of Image Path between VSCode and Hexo HexoでMarkdownをHTMLにCompileすると、画像が表示されなくなる問題が発生した。画像が全部消えるのは困るよねぇ。
Image Path on VSCode VSCodeでは1-2年前からMarkdownを編集する際、拡張機能なしのPureな状態で 画像をEditor上に直接Pasteやドラッグできるようになった。 その際、設定の内容に従って所定のpathで画像ファイルが作成されつつ、Markdown側にはMarkdown記法で画像が挿入される。
画像ファイル名を気にせずドキュメント作成できるのはあまりに便利だ。 筆者も常用している。
Image Path on Hexo では何が問題になるのかを説明するために、ChatGPTへの実際の指示を修正したものを示そう。画像でも作ればわかりやすいのかもしれないが、面倒
VSCodeに画像をペーストすると、指定した形式に従ってフォルダやファイルが生成されつつ、結果が表示される。 ただ、そのままではhexoのcompile後に画像の指定が失敗する。 すなわち、
hexo compile前: source/_post/2024/07/06/sample.mdからの相対pathとして解釈される。Markdownファイルにpasteした時点でsource/_post/2024/07/06/sample/sample1.pngに保存される。 同時に./sample/sample1.pngとしてMarkdownファイルに自動記載されて、うまく解釈される。 hexo compile後: 記事の位置がdomain.com/2024/07/06/sampleになる。そして、domain.com/つまりrootからのパスとして解釈される。このとき./sample/sample1.pngはdomain.com/sample/sample1.pngと変換される。 ここではdomain.com/2024/07/06/sample/sample1.pngと変換されてほしい Solution 上記で生成された回答を多少修正することで解決した。
HexoでMarkdownファイルに埋め込まれた画像パスが、コンパイル前後で異なる問題を解決するためには、いくつかのアプローチがあります。以下は、画像パスを正しく解釈させるための方法です。
(前略)
方法 3: カスタムフィルターを作成 Hexoのカスタムフィルターを使用して、Markdownファイルの画像パスをビルド時に動的に変更する方法もあります。
スクリプトの作成 scripts フォルダをHexoプロジェクトのルートに作成します。その中に image_path_filter.js という名前のファイルを作成します。 image_path_filter.js の内容image_path_filter.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 hexo.extend .filter .register ('before_post_render' , function (data ) { const path = require ('path' ); const postAssetFolder = hexo.config .post_asset_folder ; if (!postAssetFolder) return data; const regex = /!\[([^\]]*)\]\(([^)]+)\)/g ; data.content = data.content .replace (regex, function (match, altText, imgPath ) { const postDir = path.dirname (data.source ); const fullPath = path.join ('/' , postDir, imgPath).replace (/\\/g , '/' ).replace ("_posts/" , "" ); return `` ; }); data.thumbnail = data.thumbnail ? path.join ('/' , path.dirname (data.source ), data.thumbnail ).replace (/\\/g , '/' ).replace ("_posts/" , "" ) : null ; data.cover = data.cover ? path.join ('/' , path.dirname (data.source ), data.cover ).replace (/\\/g , '/' ).replace ("_posts/" , "" ) : null ; return data; });
このスクリプトはMarkdownファイルの画像パスを自動的に調整します。
(後略)
なお、この節の内容のようにjsやcssをhexoに適用する場合、hexo clean && hexo generateだけでは反映されず、remove public db.json -rf && touch db.json; hexo c && hexo g && hexo dが必要になる。
YAML内の画像path変換 記事本体内の画像pathは修正できたが、その時点ではYAML内で指定している画像(coverやthumbanil)のpathは修正できていなかった。
当初はこれらの画像が表示されていなかった。
YAML内の画像をhtmlに入れ込む部分を特定して、themeのjsxファイルをいじることである程度対応できた。 ただ、なぜか一向にCard内のThumbnailのpathを修正できない。Thumbnailで検索をかけても、未着手のファイルは見つからない。お前はどこで変換されてるんだ。
article.jsx 1 2 3 4 5 6 const cover = page.cover ? url_for (page.cover ) : null ;const cover = page.cover ? url_for (page.path + path.basename (page.cover )) : null ;
結果として 先のjs内でYAML内の画像pathも修正することに。
image_path_filter.js 1 2 3 data.thumbnail = data.thumbnail ? path.join ('/' , path.dirname (data.source ), data.thumbnail ).replace (/\\/g , '/' ).replace ("_posts/" , "" ) : null ; data.cover = data.cover ? path.join ('/' , path.dirname (data.source ), data.cover ).replace (/\\/g , '/' ).replace ("_posts/" , "" ) : null ;
実際、この方がシンプルで安全ではある。 不採用になったとはいえ、jsxファイルを修正していたからこそたどり着けた発想だろう。
Plugins for Hexo 参照: https://photo-tea.com/p/usecase-of-hexo-plugin/ Hexoには多くのプラグインが存在し、機能を拡張することができる。以下にいくつか代表的なプラグインを紹介する。
hexo-toc: 記事内の見出しを自動で目次に変換するプラグイン。hexo-uglify: JavaScriptを圧縮するプラグイン。hexo-tag-instagram: Instagramの投稿を埋め込むプラグイン。hexo-include-markdown: Markdownファイルを挿入するプラグイン。たとえば、この記事の場合<\!-- toc -->(実際は\なし)が自動的に冒頭の目次に変換されている。
Alertbox for Hexo 参照: https://github.com/kristofzerbe/hexo-tag-plugins?tab=readme-ov-file 参照: https://omathin.com/icarus-bulma/ HackMDやQiitaにあるようなAlertboxが欲しくて調べてみた。ないわけがないよなぁと思いつつ。
すると、下記のようなRepositoryにたどり着いた。 シンプルでよさそうだ。
こちらは作者の考えのもと、あえてmodule化されてない。npm installする代わりに、直接Scriptを設置する。実際、単体で機能するのでその方が安全ではある。が、正直面倒。 さらに、目的のalertboxに関して、htmlタグへの変換はできたが、cssが適用されない。困った困った。
そして再度調べていて、参照サイト2を見つけた。こちらはIcarusで利用されているBulmaを適用しているらしい。見た目もいいじゃないか。
サイト内ではMarkdown内にhtmlタグを直接書き込む方法で示されていたが、それは面倒だ。 それに何より、参照1の結果としてhtmlタグへの変換まではできている。そこを少しいじるだけでよいはずだ。
というわけで、その結果が下記の通り。ついでにLabelも設定できるようにした。
このTweetは次のように入力されている。
1 2 3 {% alertbox info Tweet %} というわけで、その結果が下記の通り。ついでにLabelも設定できるようにした。 {% endalertbox %}
得られたscriptは下記の通り。<hexo_root>/scripts/ytomo_tag-alertbox.jsに配置する。
scripts/ytomo_tag-alertbox.js 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 26 27 28 29 30 31 hexo.extend .tag .register ("alertbox" , function (args, content ) { const alertType = args[0 ].toLowerCase (); const alertLabel = args[1 ] || alertType.charAt (0 ).toUpperCase () + alertType.slice (1 ); const content_renderred = hexo.render .renderSync ({ text : content, engine : 'markdown' }); const element = ` <article class="message is-${alertType} "> <div class="message-header"> <p>${alertLabel} </p> </div> <div class="message-body"> ${content_renderred} </div> </article> ` ; return element; }, { ends : true });
endtag入力が面倒すぎてそれを省略したalertmsgも作成してみた
上記tweetは下記のように入力されている。
1 {% alertmsg info Tweet endtag入力が面倒すぎてそれを省略したalertmsgも作成してみた %}
で、それを実現しているのが下記のスクリプトだ。
scripts/ytomo_tag-alertmsg.js 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 26 27 28 29 hexo.extend .tag .register ("alertmsg" , function (args ) { const alertType = args[0 ].toLowerCase (); const alertLabel = args[1 ]; const content_renderred = hexo.render .renderSync ({ text : args.slice (2 ).join (" " ), engine : 'markdown' }); const element = ` <article class="message is-${alertType} "> <div class="message-header"> <p>${alertLabel} </p> </div> <div class="message-body"> ${content_renderred} </div> </article> ` ; return element; }, { ends : false });
Snippets on VSCode 直前のAlertboxを含めて、hexoでは (厳密にはhexo以外でも多くのMarkdownの拡張では){% TAG %}のような表記が多い。何なら{% alertbox info Tweet %}\nTweetの内容\n{% endalertbox %}のようにendを伴う場合はさらに面倒だ。
1 2 3 4 {% alertbox info Tweet %} はじめ、YAML内の画像path変換のためにthemeのjsxファイルをいじっていたが、一向にCard内のThumbnailを修正できなかった。とはいえ、上記のjs内でYAMLの値にも直接触れることを思いつくのは、jsxファイルを修正していたからだろう。 {% endalertbox %}
これを毎回手で打つのは煩雑なので、何らかの入力支援が必要だなぁと思って調べたところ、Snippetsを利用すればよいらしい。
今までに何度もなんとなく目にしていたSnippetsは、なんとなく入力補完くらいのものだと思っていたが、どちらかというと自由度の高い変換機能だった。 こんにちは、Snippets。
markdown.json 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 { "Hexo End Tag" : { "prefix" : [ "tagend" ] , "body" : [ "{% ${1|alertbox,blockquote|} %}" , "$0" , "{% end${1|alertbox,blockquote|} %}" ] , "description" : "Insert tag plugin with end for hexo" } , "Hexo Single Tag" : { "prefix" : [ "tagplg" ] , "body" : [ "{% $0 %}" ] , "description" : "Insert single tag plugin for hexo" } }
しかし、何度試してもVSCodeのSnippetsが効かない。 どうもGitHub Copilotと共存できなさそうな気がしてきた。Tabを食い合ってるものなぁ。
さようなら、Snippets on VSCode。多分、他人だった。
Icarus Style 脱中華圏Font 参照: https://omathin.com/icarus-theme-change/
Icarus Themeの最優先フォントはMicrosoft YaHeiだ。これは中華フォントで、日本語の表示には適しているとは言えない。themes/icarus/layout/base.stylを編集して、Microsoft YaHeiを削除した。ついでに好きなfontを上位に設定した。
Hexoの開発や界隈における中華圏の割合をうかがい知ることができる。HackMDもそうだったなぁ。
Width 参照: https://hyabc.github.io/hexo-icarus-customization/ 参照先に合わせて対応したが、どうも変化してないように見える。 保留だなぁ。
ついでに GitHub Copilot for Markdown 参照: https://techblog.ap-com.co.jp/entry/2023/12/28/175847 GitHub Copilotは、VSCodeの拡張機能として提供されているAIアシスタントだ。Markdownの記述をサポートしてくれるため、記事作成時に大変便利だ。 しかし、Markdownを開いている際は動作しない。てっきり、プログラミングじゃないからそういう仕様なのかと思っていたが、そうではなかった。
わざわざ設定でMarkdownについては無効にされていただけだった。
ちなみに、この小節の大半はGitHub Copilotによって生成された。
LinkedInなど blogの設定をするついでに、SNSアカウントを作成するなり整理するなりした。Twitterの(実質)本名垢も作るか……それか再始動するか……。
しかし、LinkedInて(そういうサービスだとは言え)スキル登録する際、個人開発の部分は経験歴の登録はできないんだね。冷たいやつだ……。
これはGitHubをもう少しまともに作れということなのかもしれない。 しかし、PJ演習で作成したTypeScriptは社外公開はできないよなぁ。
まとめ HexoのIcarusテーマをカスタマイズするために、フォントや幅を変更した。 Alertboxを作成するためのスクリプトを作成した。 YAML内の画像path変換もできるようにした。 その他、HexoのプラグインやIcarusの機能についても調査した。