ラボツール拡張計画: テキスト処理系ツールの追加候補
導入
Geminiにlilting.ch/labを見てもらったところ、DevToysとの比較分析をもらった。
DevToysが「プログラマの道具箱」なら、あなたのサイトは「クリエイター(特に画像・AI・Web制作)のための工房」という印象で、かなり方向性が違って面白いです。
確かにその通りで、現状のLabは画像処理系が充実している一方、テキストデータ処理系が手薄になっている。
現状のツール分布(全31個):
| カテゴリ | ツール数 |
|---|---|
| 画像変換 | 4 |
| 画像変形 | 4 |
| 画像編集 | 4 |
| 画像エフェクト | 3 |
| ビューワー | 6 |
| 自然言語処理 | 4 |
| 汎用ツール | 6 |
テキスト処理系は「マークダウンエディター」「形態素解析」「OCR」など自然言語処理寄りのものはあるが、JSONフォーマッターやBase64変換といった開発者向けツールがない。
追加候補一覧
優先度付きで追加候補をリストアップした。
| 優先度 | ツール | 用途 |
|---|---|---|
| 高 | JSONフォーマッター | JSON整形・検証・minify |
| 高 | Base64変換 | テキスト/画像のエンコード・デコード |
| 中 | YAMLフォーマッター | YAML整形・検証・JSON相互変換 |
| 中 | テキスト差分比較 | 2つのテキストのDiff表示 |
| 中 | URLエンコード/デコード | 日本語URLなどの変換 |
| 中 | タイムスタンプ変換 | UNIX時間 ↔ 日時の相互変換 |
| 中 | HTMLエンティティ変換 | < ↔ < などの相互変換 |
| 低 | UUID生成 | ランダムID生成 |
| 低 | ハッシュ生成 | MD5/SHA256計算 |
| 低 | JWTデコーダー | 認証トークン解析 |
| 低 | .envエディター | 環境変数ファイルの整形・検証 |
| 低 | INIエディター | INIファイルの整形・検証 |
各ツールの実装仕様
JSONフォーマッター(優先度: 高)
機能概要:
- JSON文字列の整形(pretty print)
- minify(圧縮)
- バリデーション(構文エラー検出)
- シンタックスハイライト
UI構成案:
- 左: 入力テキストエリア
- 右: 出力テキストエリア(ハイライト付き)
- 上部: インデント設定(2/4スペース、タブ)、整形/minifyボタン
- エラー時: エラー位置と内容を表示
使用ライブラリ候補:
- シンタックスハイライト: Prism.jsまたはカスタムCSS
- JSON処理: ブラウザ標準の
JSON.parse()/JSON.stringify()で十分
実装メモ:
JSON.stringify(obj, null, indent)でインデント付き整形JSON.stringify(obj)でminify- try-catchでバリデーション、エラーメッセージから行番号を抽出
Base64変換(優先度: 高)
機能概要:
- テキスト → Base64エンコード
- Base64 → テキストデコード
- 画像 → Base64(data URI形式)
- Base64 → 画像プレビュー
UI構成案:
- タブ切り替え: 「テキスト」「画像」
- テキストモード: 入力/出力テキストエリア + エンコード/デコードボタン
- 画像モード: ドラッグ&ドロップエリア + Base64出力 + プレビュー
使用ライブラリ候補:
- ブラウザ標準API:
btoa()/atob()(ASCII)、TextEncoder/TextDecoder(UTF-8対応) - 画像処理: FileReader API
実装メモ:
- UTF-8対応のエンコード:
const base64 = btoa(unescape(encodeURIComponent(text))); - UTF-8対応のデコード:
const text = decodeURIComponent(escape(atob(base64))); - 画像のdata URI:
data:image/png;base64,${base64}
YAMLフォーマッター(優先度: 中)
機能概要:
- YAML文字列の整形
- バリデーション(構文エラー検出)
- JSON ↔ YAML 相互変換
UI構成案:
- 左: 入力テキストエリア
- 右: 出力テキストエリア
- 上部: 整形ボタン、JSON変換ボタン、YAML変換ボタン
- エラー時: エラー位置と内容を表示
使用ライブラリ候補:
実装メモ:
- js-yamlの場合:
import yaml from 'js-yaml'; // YAML → JSON const obj = yaml.load(yamlString); const json = JSON.stringify(obj, null, 2); // JSON → YAML const yamlOutput = yaml.dump(JSON.parse(jsonString)); - YAMLはインデントが意味を持つので、整形時の設定(インデント幅)をオプションで提供
テキスト差分比較(優先度: 中)
機能概要:
- 2つのテキストを並べて表示
- 差分箇所をハイライト(追加=緑、削除=赤)
- 行単位/文字単位の切り替え
- 統合ビュー/分割ビューの切り替え
UI構成案:
- 上部: 2つの入力テキストエリア(横並びまたは縦並び)
- 下部: 差分表示エリア
- オプション: 空白無視、大文字小文字無視
使用ライブラリ候補:
- diff: 軽量なdiffライブラリ
- monaco-editor: VSCodeのエディタ(diffビュー内蔵だが重い)
実装メモ:
- diffライブラリの
diffLines()/diffChars()を使用 - 結果をHTMLに変換してハイライト表示
- monaco-editorはバンドルサイズが大きいので、シンプルな用途なら避ける
URLエンコード/デコード(優先度: 中)
機能概要:
- テキスト → URLエンコード
- URLエンコード → テキストデコード
- 全体エンコード/コンポーネントエンコードの切り替え
UI構成案:
- 入力テキストエリア
- 出力テキストエリア
- ボタン: エンコード/デコード
- オプション:
encodeURI/encodeURIComponentの切り替え
使用ライブラリ候補:
- ブラウザ標準API:
encodeURI()/decodeURI()、encodeURIComponent()/decodeURIComponent()
実装メモ:
encodeURI: URL全体をエンコード(/、?、&などは保持)encodeURIComponent: クエリパラメータなど部分的にエンコード(すべての特殊文字を変換)- 違いをUIで説明すると親切
タイムスタンプ変換(優先度: 中)
機能概要:
- UNIXタイムスタンプ → 人間が読める日時
- 日時 → UNIXタイムスタンプ
- ミリ秒/秒の切り替え
- タイムゾーン対応(UTC/ローカル/任意)
UI構成案:
- 上部: UNIXタイムスタンプ入力 + 「現在時刻」ボタン
- 下部: 日時表示(複数フォーマット)
- 逆変換: 日時入力 → タイムスタンプ出力
- タイムゾーン選択ドロップダウン
使用ライブラリ候補:
実装メモ:
- 基本変換:
// タイムスタンプ → 日時 const date = new Date(timestamp * 1000); // 秒の場合 const date = new Date(timestamp); // ミリ秒の場合 // 日時 → タイムスタンプ const timestamp = Math.floor(date.getTime() / 1000); // 秒 const timestampMs = date.getTime(); // ミリ秒 - ISO 8601形式:
date.toISOString() - ローカル形式:
date.toLocaleString('ja-JP') - 桁数で秒/ミリ秒を自動判定(10桁=秒、13桁=ミリ秒)
HTMLエンティティ変換(優先度: 中)
機能概要:
- HTML特殊文字 → エンティティ(エスケープ)
- エンティティ → HTML特殊文字(アンエスケープ)
- 数値参照(
<)と名前参照(<)の両対応
UI構成案:
- 入力テキストエリア
- 出力テキストエリア
- ボタン: エンコード/デコード
- オプション: 全文字変換/最小限変換
使用ライブラリ候補:
- he: HTMLエンティティの定番ライブラリ
- 自前実装: 基本的な文字(
<>&"')だけなら簡単
実装メモ:
- 基本的なエスケープ:
function escapeHtml(text) { const map = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }; return text.replace(/[&<>"']/g, c => map[c]); } - アンエスケープ(ブラウザAPIを利用):
function unescapeHtml(text) { const doc = new DOMParser().parseFromString(text, 'text/html'); return doc.documentElement.textContent; } - 全文字を数値参照に変換する場合:
&#${char.charCodeAt(0)};
UUID生成(優先度: 低)
機能概要:
- UUID v4(ランダム)の生成
- 複数個を一括生成
- 大文字/小文字の切り替え
- ハイフンあり/なしの切り替え
UI構成案:
- 生成ボタン
- 生成数の入力(1〜100)
- 出力テキストエリア(コピーボタン付き)
- オプション: 大文字/小文字、ハイフン有無
使用ライブラリ候補:
- uuid: 定番ライブラリ
- ブラウザ標準:
crypto.randomUUID()(モダンブラウザ対応)
実装メモ:
crypto.randomUUID()が使えるならライブラリ不要- ハイフン除去:
uuid.replace(/-/g, '') - 大文字化:
uuid.toUpperCase()
ハッシュ生成(優先度: 低)
機能概要:
- テキストからハッシュ値を計算
- 対応アルゴリズム: MD5, SHA-1, SHA-256, SHA-512
- ファイルからのハッシュ計算
UI構成案:
- 入力テキストエリア または ファイルドロップエリア
- アルゴリズム選択(ラジオボタンまたはドロップダウン)
- 出力: ハッシュ値(コピーボタン付き)
使用ライブラリ候補:
- Web Crypto API:
crypto.subtle.digest()(SHA系) - js-md5: MD5用(Web Crypto APIにMD5はない)
- crypto-js: 複数アルゴリズム対応
実装メモ:
- Web Crypto APIの例:
const buffer = new TextEncoder().encode(text); const hashBuffer = await crypto.subtle.digest('SHA-256', buffer); const hashArray = Array.from(new Uint8Array(hashBuffer)); const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); - MD5は非推奨だが需要はあるので一応対応
JWTデコーダー(優先度: 低)
機能概要:
- JWTトークンをデコードして中身を表示
- ヘッダー、ペイロード、署名を分けて表示
- 有効期限(exp)のタイムスタンプを人間が読める形式に変換
- 署名の検証はしない(秘密鍵がないため)
UI構成案:
- 入力: JWTトークン(テキストエリア)
- 出力: ヘッダー(JSON)、ペイロード(JSON)、署名(Base64)
- 有効期限があれば「期限切れ」「あと○日」などを表示
使用ライブラリ候補:
- ライブラリ不要: Base64デコードのみで可能
実装メモ:
- JWTは
header.payload.signatureの形式(ドット区切り) - ヘッダーとペイロードはBase64URLエンコード
- Base64URLのデコード:
function base64UrlDecode(str) { const base64 = str.replace(/-/g, '+').replace(/_/g, '/'); return decodeURIComponent(escape(atob(base64))); } expフィールドはUNIXタイムスタンプ(秒)
.envエディター(優先度: 低)
機能概要:
- .envファイルの整形(KEY=value形式)
- 重複キーの検出
- コメント行の保持
- 値のクォート有無の統一
UI構成案:
- 入力テキストエリア(.env形式)
- 出力: テーブル表示(キー/値の一覧)
- オプション: ソート(アルファベット順)、クォート統一
使用ライブラリ候補:
- dotenv: 定番だがNode.js向け
- 自前パース: ブラウザで使うなら簡易パーサーで十分
実装メモ:
- 基本的なパース:
function parseEnv(text) { const result = {}; for (const line of text.split('\n')) { if (line.startsWith('#') || !line.includes('=')) continue; const [key, ...valueParts] = line.split('='); result[key.trim()] = valueParts.join('=').trim(); } return result; } - クォートの除去:
value.replace(/^["']|["']$/g, '') - 複数行の値(heredoc形式)は対応しない方がシンプル
INIエディター(優先度: 低)
機能概要:
- INIファイルの整形
- セクション
[section]とキー=値のパース - バリデーション(構文エラー検出)
- コメント行の保持
UI構成案:
- 入力テキストエリア(INI形式)
- 出力: ツリー表示(セクション > キー/値)
- オプション: ソート、JSON変換
使用ライブラリ候補:
- ini: Node.js向けだがブラウザでも使える
- 自前パース: セクションとキー=値の単純な構造なので自前でも可
実装メモ:
- 基本的なパース:
function parseIni(text) { const result = {}; let currentSection = ''; for (const line of text.split('\n')) { const trimmed = line.trim(); if (trimmed.startsWith(';') || trimmed.startsWith('#')) continue; if (trimmed.startsWith('[') && trimmed.endsWith(']')) { currentSection = trimmed.slice(1, -1); result[currentSection] = {}; } else if (trimmed.includes('=')) { const [key, ...valueParts] = trimmed.split('='); const target = currentSection ? result[currentSection] : result; target[key.trim()] = valueParts.join('=').trim(); } } return result; } - セクションなしのキーも許容(ルートレベル)
実装方針
カテゴリの追加
現在のカテゴリ定義(src/lib/lab-tools.ts):
export type LabToolCategory =
| 'image-convert'
| 'image-transform'
| 'image-edit'
| 'image-effect'
| 'viewer'
| 'nlp'
| 'utility';
テキスト処理専用のカテゴリを追加する案:
text-process: テキスト処理(JSON, Base64, URL, ハッシュなど)developer: 開発者ツール(より広い範囲)
あるいは、既存のutilityに含めてしまう案もある。ツールが増えてきたらカテゴリを分ける。
ツール登録の手順
src/pages/lab/に新しいAstroファイルを作成src/lib/lab-tools.tsのtools配列にエントリを追加- 一覧ページ(
src/pages/lab/index.astro)に自動反映される
共通コンポーネント
テキスト処理系ツールは似たUIになるため、共通コンポーネントを作ると効率的:
TextArea: コピーボタン付きテキストエリアConvertButton: 変換ボタンOptionToggle: オプション切り替え
とはいえ実装するのもまあまあ暇がないと……気が向いたらって感じで