GitBook から HonKit に移行する

iEdit のユーザーズガイド

iedit.kondoumh.com

GitBook で作ってました。

blog.kondoumh.com

今年の2月に動作環境の文言を修正しようとして久々に更新した時 gitbook-cli が Deplicated になっているのに気付きました。

GitBook.com のホスティングサービス専用になって、OSS の方はメンテされなくなった模様です。

www.gitbook.com

ユーザーズガイドは GitHub Pages で公開していますが、今後 メンテされないとなると新規のドキュメントには使わない方がいいなあと思っていました。

最近 azu さんが GitBook を fork した HonKit という OSS の開発を開始されました。

github.com

自分はGitBook(legacy)の機能的にはある程度満足していたので、 主にコードベースの整理、TypeScript化、QやjQueryの依存を外すなど質的なメンテナンスが中心になる気がしています。

efcl.info

TypeScript 化や jQuery 依存の除去などは今後メンテナンスを続け、Contribute しやすくなるメリットがあると思います。

iEdit のドキュメントを HonKit でビルドしてアップデートしました。NPM 管理には移行していたので、gitbook-cli を honkit に置き換えて、script で使用するコマンドを gitbook -> honkit に変更するだけで移行完了。利用しているプラグインはそのまま動作しました。

  "devDependencies": {
-   "gitbook-cli": "^2.3.2"
+   "honkit": "^3.4.0"
  },
  "scripts": {
-   "serve": "gitbook serve",
-   "build": "gitbook build ./ ./docs"
+   "serve": "honkit serve",
+   "build": "honkit build ./ ./docs"
  },

HonKit を使えば、既存の GitBook 資産を Netlify や GitHub Pages などで安心してホスティングできるので、何より既存 GitBook ユーザには朗報ですね。

Blazor WebAssembly を触る

先月 Blazor WebAssembly 3.2.0 がリリースされ、.NET Core 3.1.300 以降にアップデートすることで使用できるようになりました。

devblogs.microsoft.com

すでに Infragistics など著名な UI コンポーネントベンダーが対応しておりプロダクションレディな感じが漂っています。

WebAssembly 上に .NET CLR が実装され、Client と Server で共通の C# コードが動き、ASP.NET Core の要領でモダンな Web UI が作れるという、なんだかすごいフレームワークに興味津々で .NET Core を更新。

dotnet.microsoft.com

前回インストールして試してから1年近く経ってました。

blog.kondoumh.com

ブログにあるようにコマンドを実行。

f:id:kondoumh:20200618103342p:plain

localhost:5001 にアクセスすると、素敵な Webアプリが表示されます。

f:id:kondoumh:20200618104023p:plain

f:id:kondoumh:20200618104307p:plain

f:id:kondoumh:20200618104331p:plain

プロジェクトのファイルを覗くと ASP.NET MVC の Razor 構文に似たテンプレートと C# コードでできてます。

開発の雰囲気を掴むために、このアプリに何かページを追加してみます。

GitHub に ASP.NET Core Blazer の Extension が公開されてます。

github.com

Canvas では 2D グラフィックスや WebGL のレンダリングがサポートされてます。

github.com

これを使って Canvas に描画する Page を追加しようってことで dotnet add package を実行し Canvas 拡張を追加。

f:id:kondoumh:20200618123947p:plain

index.html に必要な JS ライブラリを追加。

<body>
    <app>Loading...</app>

    <div id="blazor-error-ui">
        An unhandled error has occurred.
        <a href="" class="reload">Reload</a>
        <a class="dismiss">🗙</a>
    </div>
    <script src="_framework/blazor.webassembly.js"></script>
    <script src="_content/Blazor.Extensions.Canvas/blazor.extensions.canvas.js"></script>
</body>

README に従って page (Canvas2D.razor) を追加

@page "/canvas2d"

<h1>Canvas 2D</h1>

<BECanvas Width="300" Height="400" @ref="_canvasReference" ></BECanvas>

@code {
    @using Blazor.Extensions
    @using Blazor.Extensions.Canvas
    @using Blazor.Extensions.Canvas.Canvas2D

    private Canvas2DContext _context;

    protected BECanvasComponent _canvasReference;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        this._context = await this._canvasReference.CreateCanvas2DAsync();
        await this._context.SetFillStyleAsync("green");

        await this._context.FillRectAsync(10, 100, 100, 100);

        await this._context.SetFontAsync("48px serif");
        await this._context.StrokeTextAsync("Hello Blazor!!!", 10, 100);
    }
}

Navigation に page を追加。iconify のアイコンを指定できるようです。

https://iconify.design/icon-sets/oi/

<div class="top-row pl-4 navbar navbar-dark">
    <a class="navbar-brand" href="">BlazorApp1</a>
    <button class="navbar-toggler" @onclick="ToggleNavMenu">
        <span class="navbar-toggler-icon"></span>
    </button>
</div>

<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
    <ul class="nav flex-column">
             :
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="canvas2d">
                <span class="oi oi-map" aria-hidden="true"></span> Canvas 2D
            </NavLink>
        </li>
    </ul>
</div>

@code {
    private bool collapseNavMenu = true;

    private string NavMenuCssClass => collapseNavMenu ? "collapse" : null;

    private void ToggleNavMenu()
    {
        collapseNavMenu = !collapseNavMenu;
    }
}

そして、dotnet run するとなんか出ました。

f:id:kondoumh:20200618125927p:plain

次に、WebGL グラフィックスを描画するサンプルです。こちらのテストプロジェクトからコードを持ってきました。

Canvas/test/Blazor.Extensions.Canvas.Test.ClientSide/Pages at master · BlazorExtensions/Canvas · GitHub

テストプロジェクト通りに razor ファイルと cs ファイルを分離して @inherits を使って書いてみたのですが、cs 側で持ってる BECanvasComponent 型のフィールドを暗黙型変換できないというエラーが解消できませんでした。仕方なく Canvas 2D 同様 razor の @code ブロックに直書きしました。

なんか出ました。

f:id:kondoumh:20200618214213p:plain

C# と Razor のコードしか書いてないので、昔ながらの ASP.NET MVC 開発の感覚になります。React や Vue でおなじみの Live Reloading 機能はまだないらしく、ファイルを編集したら Ctrl-C で中断し再び dotnet run してブラウザ側を更新・・というちょっとめんどくさいワークフローになってます*1

VS Code を当然使ってるわけですが、C# 拡張の他にデバッグのため JavaScript Debugger (Nightly) を導入することが推奨されています。

marketplace.visualstudio.com

launch.json の設定をして、デバッグ用の Chrome が起動したのですが、僕の環境ではブレークポイントで実行が止まってくれませんでした。

今回のお試しコード

dotnetcore-study/BlazorApp1 at master · kondoumh/dotnetcore-study · GitHub

Blazor アプリのホスティングモデルの説明を読むとブラウザで完結する Blazor WebAssembly モデルとBlazor サーバーモデルがあり、今回見たのは Blazor WebAssembly の方です。Blazor サーバーは、ASP.NET Core アプリで WASM が実行され、ブラウザと SignalR で通信します。Blazor サーバーモデルではブラウザが WASM 対応している必要はないようです。Blazor WASM モデルだと規模が大きくなってくると、ダウンロードやローディングの時間が気になるレベルになりそうです。

docs.microsoft.com

今回初めて触りましたが完成度高い感じしました。WASM を基盤としているため Silverlight のようなプラグインが不要なのと、まんま ASP.NET のプログラミングモデルということで C#er には受け入れられやすい気がします。

*1:やり方を知らないだけという可能性はあります。

Scrapbox ページ一覧と Graph 可視化のプロト PWA 作成

以前 Scrapbox から API でデータを取得して、ページ間リンクを可視化する (ための Graphviz dot ファイルを吐く) CLI を作成しました。

blog.kondoumh.com

その後 Graphviz よりインタラクティブな可視化ができる技術として D3.js の force simulation を使ったサンプルを作ってました。

まだ色々改善ポイントありますが、ひとまず動いてます。

野良 Scrapbox アプリでは、ページ一覧を作っています。

github.com

これらの機能を PWA にしてモバイルからも閲覧できるようにしたいと思い、プロトタイプの PWA を作りました。

sb-data-kondoumh.netlify.app

Scrapbox の API は CORS を許可してないのでビルド時にデータ取得してアプリと一緒にデプロイしてます。

一覧画面。野良 Scrapbox アプリと違ってクエリについての制約がなくなったので検索機能とか追加してます。

f:id:kondoumh:20200610222921p:plain

Home と Full List に同じ一覧画面があるのですが、これは Home で最新の更新情報を短いタイムスパンで、Full List で全ページの情報を比較的長めのタイムスパンで更新することを想定しているためです。

Graph 表示画面。D3.js の画面を無理やり Vue.js のコンポーネントにして表示してます。

f:id:kondoumh:20200610223306p:plain

About 画面は使用しているテクノロジースタックのリンク集になっています。

f:id:kondoumh:20200610223359p:plain

久々に Vue CLI で PWA をやってみましたが、iPadOS も PWA サポートが進んでます。以前は起動すると Safari のタブが開くだけだったのが、アプリっぽく動くようになりました*1

f:id:kondoumh:20200610230437j:plain

プラットフォーム側の対応が進んでいるのを感じます。

*1:このスクリーンショットは夜間に撮ったのでダークモードになってます。

ThinkPad TrackPoint Keyboard II 購入

今年初めに ThinkPad TrackPoint Keyboard のワイヤレス専用版がリニューアルされ Bluetooth に加えてワイヤレス USB 接続をサポートしました。そして先月 JP 版が発売になりました。

www.lenovo.com

昔 ThinkPad やスペースセーバーキーボードのユーザだったというのもあるのですが、ちょうど自宅でテレワーク用の端末と MacBook Pro で HHKB と Magic Keyboard の2台を取り替えて使ってるのが煩雑だったので、1台に統合できるならということで買ってみました。もちろん JP 配列です。

ThinkPad のキーボードらしくキートップの下側に R が入ってます。近年のモデルにあるタッチパッドも省かれているためコンパクトです。クリックボタンの左右がちょっとしたパームレストにもなります。

f:id:kondoumh:20200605083509j:plain

上部側面に Bluteooth - ワイヤレスの切り替えスイッチ、Windows と Android の切り替えスイッチ、充電用の USB-C ポート、ワイヤレスのドングル格納ソケットが配置されています。電源スイッチは右側面にあります。チルトスタンドは使った方が打ちやすい気がします。

f:id:kondoumh:20200605084818j:plain

軽量薄型キーボードとしてはストロークもそれなりにあって打ちやすいです。慣れれば Magic Keyboard よりいいかなと。

キー配列はコンパクトな JP キーボードとしてはまあ標準的です。Windows ではたまに使う Home と End がファンクションキーの並びにあるのはよいと思いました。しかし、右 Alt と Ctrl の間にねじ込まれている PrtSc は使わないので省いてピッチを広げて欲しかったですね。さらに PgUp/PgDn が左右カーソルキーのすぐ上に配置されているため、誤タイプでページングしてしまいびっくりします。ほぼ使わないので Fn のコンビネーションでいいと思いました。後述のようにリマップツールでカーソルキーにマッピングしちゃいました。

TrackPoint は専用のドライバーソフトウェアを導入しなくても Windwos / macOS 共に動作しました。ThinkPad X40 を使ってた頃はドームタイプのキャップを沢山ストックしてたりしましたが、今時は TrackPoint だけで頑張るのはつらいのでマウスや Trackpad と併用します。ホームポジションのままカーソルを動かせるのはやはりいいですね。

macOS では Karabiner-Elements でキーリマップしました。

HHKB でも使ってるやつです。

blog.kondoumh.com

Windows キーボードの共通設定。

f:id:kondoumh:20200607181302p:plain

TrackPoint Keyboard 固有の設定。

f:id:kondoumh:20200607181325p:plain

Windows では KeySwap を使いました。

KeySwap for XPの詳細情報 : Vector ソフトを探す!

かなり昔からあるレジストリ変更してキーマップを変えてしまうツールです。

f:id:kondoumh:20200607141657p:plain

もうちょいモダンなツールないかなとは思うのですが。

ともあれ、打ちやすいコンパクトキーボード1個で環境を切り替えられるようになったので満足しています。

Puppeteer Recorder でテスト用スクリプトを生成する

Puppeteer を使うと Web 画面の E2E テストが手軽に書けます。

github.com

ただ最近の Web UI は DOM 要素に ID が振られていないことが多く、Selector 書くのに Chrome DevTools などで要素をインスペクトしてパスをコードに貼り付けるという作業が多くなります。そうやって作ったスクリプトもサイトデザインの変更で動かなくなったりします。

Puppeteer Recorder はブラウザの操作を記録して、Puppeteer のスクリプトを生成してくれる Chrome 拡張です。

chrome.google.com

インストールすると拡張のアイコンから操作を記録可能になります。

f:id:kondoumh:20200603124701p:plain

Record ボタンをクリックして記録を開始します。kondoumh を検索して、僕のホームページを開くという操作をしてみました。イベントが記録されています。

f:id:kondoumh:20200603144235p:plain

ストップボタンを押すと Puppeteer のコードが表示され、クリップボードにコピーできるようになります。

f:id:kondoumh:20200603144301p:plain

生成されたコード

const puppeteer = require('puppeteer');
(async () => {
  const browser = await puppeteer.launch()
  const page = await browser.newPage()
  
  const navigationPromise = page.waitForNavigation()
  
  await navigationPromise
  
  await page.goto('https://www.google.com/search?q=kondoumh&oq=kondoumh&aqs=chrome.0.69i59j69i60l5.2485j0j7&sourceid=chrome&ie=UTF-8')
  
  await page.setViewport({ width: 1280, height: 689 })
  
  await page.waitForSelector('.g:nth-child(1) > .rc > .r > a > .LC20lb')
  await page.click('.g:nth-child(1) > .rc > .r > a > .LC20lb')
  
  await navigationPromise
  
  await browser.close()
})()

HTML 要素による判定とかは無理ですが、大枠の操作は手早く作れて便利だと思います。

Windows Terminal 正式リリース版をチェック

Windows Terminal Preview 版を触ったのは1年ぐらい前。

blog.kondoumh.com

最近正式リリースされたらしいと聞いていたので、会社の Let's note の Windows Update をかけてからバージョンを確認したところ、確かに 1.0 に到達していました。

f:id:kondoumh:20200531102400p:plain

起動時にエラーが出て、settings.json のフォーマットに breaking change があったことが分かりました。この issue の指示に従って、globals の内容をフラットに展開したらエラーは消えました。

github.com

ペインを水平・垂直に分けられたり、Direct Write でテキストレンダリングしてたり、コマンドプロンプトのリプレイスとしてリッチなターミナルが使えるようになったものです。

f:id:kondoumh:20200531104426p:plain

今は Git for Windows の bash をデフォルトにしてますが、Windows 10 May 2020 Update でリリースされた WSL 2 と共に試したいところ。Windows マシンも Update しないとですが。

Cloud Native Buildpacks を GitHub Actions で使うための Action 作ってます

Buildpacks ステキでした。

blog.kondoumh.com

これを社内プロジェクトの CI で使うために GitHub Actions の Action にすることを試みました*1

最初 Docker Action でサクッと作れるだろうとたかを括っていたのですが、よく考えるとコンテナイメージを Docker コンテナ内でビルドするので DinD (Docker in Docker) になってしまいます。かといって JavaScript Action でこういう CLI ラッパーを作るのはやだなぁと思って Docker の公式 dind イメージ使えばなんとかなるんじゃないかと試してみました。

docker/Dockerfile at master · docker-library/docker · GitHub

結果、問題なくイメージがビルドできました。

github.com

Marketplace に出すのはもう少し社内プロジェクトで評価してからにします。

2020.6.2 追記

Marketplace に公開しました。

github.com

*1:というか社内プロジェクトで使いたいという話でちょっと調べたのでした。