ラベルと値の静的表示
本ツールは,ソフトウェア開発のドキュメントやGitHubのREADMEファイルなどで広く利用されているシールド状のカスタムバッジを,SVG(Scalable Vector Graphics)形式で静的に生成するためのフロントエンドアプリケーションです.利用者が画面上の「左ラベル (Label)」および「右データ (Value)」の入力フィールドに任意の文字列を入力すると,即座にReactのステートフック(useState)によって状態が更新され,DOM上に動的にレンダリングされるSVGコードへと反映されます.
例えば,左ラベルに「build」,右データに「passing」と入力した場合,ツールはこれを検知して,内部のSVGテンプレートにこれらの文字列を組み込みます.出力されるSVGコードは,<svg>タグをルート要素とし,xmlns="http://www.w3.org/2000/svg"の宣言を含みます.
バッジのビジュアルは主に2つの矩形(<rect>)で構成されており,左側には暗い背景色(デフォルトではグレー)を持つラベル領域,右側にはユーザー指定色(デフォルトではグリーン)を持つデータ領域が配置されます.
このツールは完全な静的バッジ生成に特化しているため,CI/CDパイプラインからビルドステータスを動的に取得したり,外部のサービスAPIと通信して最新のバージョン番号をフェッチしたりする機能は一切備えていません.入力フィールドに入力された文字列がそのままSVG内の<text>要素として埋め込まれるという非常にシンプルで予測可能な挙動をとります.
文字のレンダリングには,視認性を高めるためにベースラインのわずかに下に半透明の黒色でドロップシャドウを模したテキスト要素が配置され,その直上にメインの白色のテキストが重ねられます.
また,<text>要素にはtext-anchor="middle"が設定されており,左側および右側の矩形領域の幾何学的な中央に配置されるように計算されています.テキストのフォントファミリはVerdana,Geneva,DejaVu Sans,sans-serifと指定されており,ブラウザやOSの標準的なサンセリフ体へのフォールバックが機能するよう実装されています.
外部のWebフォントを読み込む処理を持たないため,ユーザーの環境によってテキストの描画結果(文字の太さや細かなカーニング)がわずかに異なる場合があります.アイコン画像の埋め込みやPNG形式への出力といった機能も実装されていないため,純粋に軽量なベクトルデータのテキストバッジを必要とする用途において利用できます.
三スタイルと色
生成されるSVGバッジの視覚的な印象は,利用者が選択可能な「バッジスタイル」および「カラー設定」によって決定されます.スタイルオプションとしては「Flat(フラット)」「Flat Square(四角)」「Plastic(立体)」の3種類が用意されており,UI上のセレクトボックスから選択することができます.
「Flat」スタイルは,現代のWebデザインで標準的に用いられるフラットデザインを採用しています.SVG内部では,<linearGradient>タグを用いて上部から下部にかけてわずかな明暗のグラデーション(半透明のグレーから透明へ)を重ねることで,フラットでありながらも微かな質感を表現しています.
「Flat Square」スタイルは,角の丸みを完全に排除したシャープなデザインです.グラデーションのオーバーレイレイヤーが適用されず,純粋な単色のベタ塗りとしてレンダリングされます.「Plastic」スタイルは,立体的な光沢を持ちます.複数の<stop>要素を持つ複雑なグラデーション(上部に強いハイライト,中間に透明な層,下部に強いシャドウ)を重ねることで,プラスチックのような質感をシミュレートしています.
カラー設定においては,左ラベル背景と右データ背景のそれぞれに対して,HTMLの標準的なカラーピッカー(<input type="color">)またはテキスト入力フィールドを介してHEXコードを指定することが可能です.右データ用のカラーについては,Green,Bright Green,Yellow,Yellow Green,Orange,Red,Blue,Grey,Light Greyといった9種類のプリセットボタンが用意されており,これらをクリックするだけで即座に特定のHEXコード(例:Bright Greenなら#97ca00)が右側の背景色として適用されます.
これらのスタイルやカラー情報は,SVG内の<rect>要素のfill属性に直接バインディングされます.バッジ全体の形状を制御するために,<clipPath>タグを用いて角丸の矩形マスクが定義されており,そのマスク内に左右の背景矩形とグラデーションレイヤーがグループ化(<g>タグ)されて収められます.
なお,本ツールは標準的なシールドバッジと視覚的に似たデザインを出力しますが,外部生成サービスとの完全な互換性を保証するものではなく,実装におけるグラデーションの係数やシャドウのオフセット値は独自のシンプルな定義に基づいています.
寸法と簡易文字幅
SVGバッジを生成する上で,可変長であるテキストを適切に内包しつつ,美しい余白を保つためには,入力された文字列が占有する物理的な幅を事前にある程度予測し,全体のSVGキャンバス(width属性)や矩形の幅を動的に決定する必要があります.本ツールでは,外部のフォントメトリクスAPIや高度なCanvas測定を使用せず,JavaScriptの組み込みロジックによる簡易的な文字幅見積もり関数を実装してこの課題を解決しています.
この見積もりロジックでは,入力された文字列を1文字ずつ走査し,そのUTF-16コードユニットに基づいて仮想的な幅の係数を加算していきます.具体的には,基準となるフォントサイズ11pxに対して,数字(0〜9)は6.5px,大文字のラテンアルファベット(A〜Z)は7.5px,小文字のラテンアルファベット(a〜z)は6.0px,そして全角のCJK(中国語・日本語・韓国語)文字は11.5px,その他の記号やスペースには4.5pxという固定の係数が割り当てられています.
入力文字列全体に対してこれらの係数を合算したのち,ユーザーが指定したバッジの高さに応じたフォントサイズ(高さの55%として算出)の比率を掛け合わせることで,最終的なピクセル幅を概算します.
算出されたテキスト幅に対し,バッジの高さの50%に相当する左右のパディング値が加算され,左側ラベル領域の幅と右側データ領域の幅がそれぞれ確定します.これら2つの領域の幅の合計がバッジ全体の総幅となります.バッジの高さ自体は,UI上の数値入力フィールドを通じて14pxから40pxの範囲で指定可能です.
UI側にはmin="14"およびmax="40"の制約が設けられており,さらにJavaScriptのMath.minとMath.maxを用いたクランプ処理によって,極端に大きな値や負の値が入力された場合でもこの範囲内に強制的に収まるよう制御されています.同様に,角の丸み度合い(rx)についても0から12の範囲でクランプされます.
このアプローチは軽量かつ高速に動作しますが,あくまでVerdanaフォントを基準とした簡易的な係数計算であるため,OS環境によってフォールバックされるフォント(DejaVu Sansなど)によっては,実際のレンダリング結果と予測された幅との間にわずかな誤差が生じる可能性があります.
例えば,Wなどのプロポーショナルフォントで特異な幅を持つ文字列を連続して入力した場合,左右の余白が不均等に見えるケースが存在します.これはブラウザの実行環境に依存しない静的生成エンジンの仕様上の制限です.
XMLエスケープと不正色
ユーザーが入力した任意の文字列をSVG(XMLベースのマークアップ言語)のノード内に安全に埋め込むためには,適切なエスケープ処理が不可欠です.本ツールでは,入力されたラベルおよび値の文字列に対して,正規表現を用いた独自のXMLエスケープ関数を適用しています.この関数は,文字列内に含まれるアンパサンド(&),小なり記号(<),大なり記号(>),ダブルクォーテーション("),シングルクォーテーション(')の5種類の特殊文字を検知し,それぞれ対応する実体参照(&, <, >, ", ')へと置換します.
たとえば,右データのフィールドに「<100% & "passing"」と入力した場合,この処理によって「<100% & "passing"」に変換されてからSVGの<text>タグ内に挿入されます.これにより,意図しないタグの終了や属性の破壊といったSVGの構文エラーを未然に防ぎ,ブラウザがバッジを正しくパースして描画できる状態を担保しています.
一方,カラーコードの指定におけるバリデーションも重要です.ユーザーがテキストフィールドに直接カラーコードを入力する場合,無効な文字列やCSSのカラーネーム(例:red,rgba(255,0,0,0.5)など)が入力される可能性があります.本ツールでは,指定されたカラーコードが正しい3桁または6桁のHEXコード(16進数)であるかを判定するための関数を実装しています.
この判定では,正規表現を用いて,先頭がハッシュ記号(#)で始まり,続く文字が16進数の文字種のみで構成されているかをチェックします.
もしユーザーの入力がこの条件を満たさない不正な形式であった場合,ツールは生成処理を停止させることなく,安全なデフォルトカラーへのフォールバックを自動的に実行します.左側のラベル背景色に不正な値が指定された場合は「#555555」が,右側のデータ背景色に不正な値が指定された場合は「#4c1」が代わりに採用され,SVGのfill属性に出力されます.入力色が条件外の場合にも既定色で生成を続けます.
コピーとSVG保存
本ツールでは,生成されたSVGコードを外部のプロジェクトで利用するための2つの主要な出力インターフェースを備えています.「コードをコピー」機能と「SVGファイルをダウンロード」機能です.これらはいずれもクライアントサイドのJavaScript APIを駆使して実装されており,外部サーバーへの通信を一切伴いません.
「コードをコピー」ボタンをクリックすると,Reactの状態として保持されている最新のSVGソースコード文字列が,ブラウザのClipboard APIを通じてオペレーティングシステムのクリップボード領域へ直接書き込まれます.この際,ユーザーに対するフィードバックとしてボタンのアイコンが一時的にチェックマークに変わり,テキストが「コピー完了」に変化します.
この状態は一定時間後に元の状態に復帰するよう制御されています.コピーされるテキストは純粋なSVGタグのみであり,マークダウン形式のラッパーやHTMLの<img>タグなどは自動付与されません.
「SVGファイルをダウンロード」ボタンによるエクスポート処理は,ブラウザのBlob APIとURL.createObjectURLを利用して実現されています.まず,SVGのソースコード文字列を内容とし,MIMEタイプをimage/svg+xmlに指定したBlobオブジェクトがメモリ上に生成されます.
次に,このBlobへの一時的な参照URLが作成され,動的に生成されたアンカータグ(<a>要素)のhref属性に割り当てられます.
ダウンロードされるファイル名(download属性)は,ユーザーが入力した左ラベルと右データを連結した文字列をベースに動的に決定されます.ファイル名として無効または問題を引き起こす可能性のある特殊文字を排除するため,正規表現を用いて,Unicodeの文字,数字,アンダースコア,ハイフン以外の文字はすべてアンダースコア(_)に置換されます.
さらに,ファイル名が過度に長くなることを防ぐため,置換後の文字列の先頭から120文字で切り捨てを行い,最後に.svgの拡張子を付加します.このアンカータグをJavaScriptからプログラム的にクリックすることで保存ダイアログが起動し,処理後は即座にURLオブジェクトが破棄されてメモリを解放します.
README等での利用と状態更新の非対応
ダウンロードまたはコピーされたSVGバッジは,GitHubのREADME.mdファイルや各種プロジェクトのドキュメントに組み込んで利用することができます.バッジを表示させる方法としては,リポジトリ内に.svgファイルをコミットして配置し,Markdownの画像記法を用いて相対パスで参照する方法や,HTMLの<img>タグのsrc属性に指定する方法が一般的です.
ここで技術的に注意すべき重要な点として,クリップボードにコピーしたSVGの生のソースコード(<svg>から始まる文字列)を,HTMLファイル内に直接複数貼り付ける(インライン展開する)場合のID競合問題が存在します.本ツールが生成するSVGコード内には,グラデーションを定義するための<linearGradient id="s">や,角丸のクリッピングマスクを定義するための<clipPath id="r">といった固定のID属性がハードコーディングされています.
そのため,1つのHTMLドキュメント(DOMツリー)の中に,本ツールで生成した複数のSVGコードをそのままの形でインライン配置すると,同じ「s」や「r」というIDを持つ要素が重複してしまいます.結果として,ブラウザのレンダリングエンジンは最初に見つけたID定義をページ内のすべての同ID参照に適用してしまい,意図しないグラデーションの適用や表示の崩れが発生します.
この問題を回避するためには,インライン展開ではなく外部ファイルとして<img>タグで読み込むか,利用者が手動でSVGコード内のID属性をユニークな文字列に変更する必要があります.
また,本ツールは静的なジェネレーターであるため,出力されたSVGバッジ自体には自律的に内容を更新する機能は備わっていません.例えばテストのカバレッジ率や最新のリリースバージョンが変わったとしても,一度ダウンロードしたSVGファイルの内容が自動的に追従して書き換わることはありません.
値を更新したい場合は,再度本ツールの画面上で新しい数値を入力し,SVGを再生成して手動でファイルを置き換える必要があります.これは,動的に画像を出力し続けるサーバーホスト型のバッジサービスとは異なる仕様です.しかしながら,プロジェクトの外部依存を増やさず,通信エラーやサービス終了によるリンク切れの外部のバッジ生成サービスに依存しないアセットとしてリポジトリに同梱できる点は,静的バッジ特有の利点となります.