cd6a94f(相対座標・回転中心なし)と 1a9a2a0(KLE往復は照合)の反映漏れを直す。 - position を $defs/transform (x, y, rotation) に置き換え、rotationOrigin を削除 - size を width/height から w/h に揃え、親の変換を受けないことを明記 - elements を root / children に改名 - kleCompatibility.originalIndex を削除(KLEは保存時にキーを並べ替える) - 使用例を新しい形に更新し、スキーマで検証が通ることを確認 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
12 KiB
12 KiB
Phase 1: JSON Schema仕様策定
レイヤー間データフロー
PHY (物理配置) → IDX (キー識別) → ELC (電気配線) + MAP (キーマップ)
↓ ↓
ファームウェア生成 VIA/Remap出力
1. PHYレイヤー JSON Schema
座標・回転・サイズの意味は PHYレイヤー.md を正とする。
基本構造
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://beyond-kle.org/schemas/phy-layer.json",
"title": "PHY Layer - Physical Key Layout",
"description": "Physical positioning and sizing of keys",
"type": "object",
"required": ["version", "metadata", "profiles", "root"],
"properties": {
"version": {
"type": "string",
"pattern": "^\\d+\\.\\d+\\.\\d+$",
"description": "Schema version (semver)"
},
"metadata": {
"type": "object",
"properties": {
"name": { "type": "string" },
"author": { "type": "string" },
"description": { "type": "string" },
"created": { "type": "string", "format": "date-time" },
"modified": { "type": "string", "format": "date-time" }
}
},
"compatibility": {
"type": "object",
"description": "Information for external tool compatibility",
"properties": {
"kleJson": {
"type": "object",
"properties": {
"source": { "type": "string" },
"checksum": { "type": "string" },
"preservedFields": { "type": "array", "items": { "type": "string" } }
}
},
"originalFormat": {
"type": "string",
"enum": ["kle", "via", "qmk", "native"]
}
}
},
"profiles": {
"type": "array",
"minItems": 1,
"items": {
"$ref": "#/$defs/profile"
}
},
"root": {
"type": "array",
"items": {
"oneOf": [
{ "$ref": "#/$defs/key" },
{ "$ref": "#/$defs/cluster" }
]
}
}
},
"$defs": {
"transform": {
"type": "object",
"description": "Placement relative to the parent: rotate by rotation around the local origin, then translate by (x, y)",
"required": ["x", "y", "rotation"],
"properties": {
"x": { "type": "number" },
"y": { "type": "number" },
"rotation": { "type": "number", "description": "Degrees" }
}
},
"profile": {
"type": "object",
"required": ["id", "name", "unitSize"],
"properties": {
"id": { "type": "string" },
"name": { "type": "string" },
"unitSize": {
"type": "object",
"required": ["x", "y"],
"properties": {
"x": { "type": "number", "minimum": 0 },
"y": { "type": "number", "minimum": 0 }
}
},
"visualOffset": {
"type": "object",
"properties": {
"x": { "type": "number" },
"y": { "type": "number" },
"radius": { "type": "number", "minimum": 0 }
}
}
}
},
"key": {
"type": "object",
"required": ["type", "id", "profile", "transform", "size"],
"properties": {
"type": {
"type": "string",
"const": "key"
},
"id": {
"type": "string",
"description": "Unique key identifier"
},
"profile": {
"type": "string",
"description": "Reference to profile ID"
},
"transform": { "$ref": "#/$defs/transform" },
"size": {
"type": "object",
"description": "Local size. Not affected by the parent transform",
"required": ["w", "h"],
"properties": {
"w": { "type": "number", "minimum": 0 },
"h": { "type": "number", "minimum": 0 }
}
},
"metadata": {
"type": "object",
"properties": {
"label": { "type": "string" },
"color": { "type": "string" },
"textColor": { "type": "string" },
"kleCompatibility": {
"type": "object",
"description": "Original KLE fields for round-trip compatibility",
"properties": {
"labels": { "type": "array", "items": { "type": "string" } },
"textSizes": { "type": "array", "items": { "type": "number" } },
"decalData": { "type": "object" }
}
}
}
}
}
},
"cluster": {
"type": "object",
"required": ["type", "id", "name", "transform", "children"],
"properties": {
"type": {
"type": "string",
"const": "cluster"
},
"id": { "type": "string" },
"name": { "type": "string" },
"transform": { "$ref": "#/$defs/transform" },
"children": {
"type": "array",
"items": {
"oneOf": [
{ "$ref": "#/$defs/key" },
{ "$ref": "#/$defs/cluster" }
]
}
}
}
}
}
}
使用例
{
"version": "1.0.0",
"metadata": {
"name": "Split Keyboard Layout",
"author": "John Doe",
"description": "Ergonomic split keyboard with rotated thumb clusters",
"created": "2025-01-01T00:00:00Z"
},
"profiles": [
{
"id": "standard",
"name": "Standard Cherry MX",
"unitSize": { "x": 19.05, "y": 19.05 },
"visualOffset": { "x": 1, "y": 1, "radius": 1 }
}
],
"root": [
{
"type": "cluster",
"id": "left_main",
"name": "Left Main Block",
"transform": { "x": 0, "y": 0, "rotation": 0 },
"children": [
{
"type": "key",
"id": "k00",
"profile": "standard",
"transform": { "x": 0, "y": 0, "rotation": 0 },
"size": { "w": 1, "h": 1 },
"metadata": { "label": "Q" }
},
{
"type": "key",
"id": "k01",
"profile": "standard",
"transform": { "x": 1, "y": 0, "rotation": 0 },
"size": { "w": 1, "h": 1 },
"metadata": { "label": "W" }
}
]
},
{
"type": "cluster",
"id": "left_thumb",
"name": "Left Thumb Cluster",
"transform": { "x": 2, "y": 3, "rotation": 15 },
"children": [
{
"type": "key",
"id": "k30",
"profile": "standard",
"transform": { "x": 0, "y": 0, "rotation": 0 },
"size": { "w": 1.25, "h": 1 },
"metadata": { "label": "Space" }
},
{
"type": "key",
"id": "k31",
"profile": "standard",
"transform": { "x": 1.25, "y": 0, "rotation": 0 },
"size": { "w": 1, "h": 1 },
"metadata": { "label": "Enter" }
}
]
}
]
}
2. IDXレイヤー JSON Schema
基本構造
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://beyond-kle.org/schemas/idx-layer.json",
"title": "IDX Layer - Key Identification",
"description": "Mapping between physical keys and logical identifiers",
"type": "object",
"required": ["version", "phyReference", "keyMap"],
"properties": {
"version": { "type": "string" },
"phyReference": {
"type": "object",
"required": ["source", "checksum"],
"properties": {
"source": { "type": "string" },
"checksum": { "type": "string" }
}
},
"keyMap": {
"type": "array",
"items": {
"$ref": "#/$defs/keyMapping"
}
}
},
"$defs": {
"keyMapping": {
"type": "object",
"required": ["physicalId", "logicalId"],
"properties": {
"physicalId": {
"type": "string",
"description": "Reference to PHY layer key ID"
},
"logicalId": {
"type": "object",
"required": ["index"],
"properties": {
"index": { "type": "integer", "minimum": 0 },
"matrix": {
"type": "object",
"properties": {
"row": { "type": "integer", "minimum": 0 },
"col": { "type": "integer", "minimum": 0 }
}
},
"label": { "type": "string" }
}
}
}
}
}
}
3. ELCレイヤー JSON Schema
基本構造
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://beyond-kle.org/schemas/elc-layer.json",
"title": "ELC Layer - Electrical Configuration",
"description": "Electrical wiring and pin mapping",
"type": "object",
"required": ["version", "idxReference", "microcontroller", "matrix"],
"properties": {
"version": { "type": "string" },
"idxReference": {
"type": "object",
"required": ["source", "checksum"],
"properties": {
"source": { "type": "string" },
"checksum": { "type": "string" }
}
},
"microcontroller": {
"type": "object",
"required": ["type", "pinMapping"],
"properties": {
"type": { "type": "string" },
"pinMapping": {
"type": "object",
"properties": {
"rows": {
"type": "array",
"items": { "type": "string" }
},
"cols": {
"type": "array",
"items": { "type": "string" }
}
}
}
}
},
"matrix": {
"type": "object",
"required": ["type", "dimensions"],
"properties": {
"type": {
"type": "string",
"enum": ["standard", "charlieplexing", "direct"]
},
"dimensions": {
"type": "object",
"required": ["rows", "cols"],
"properties": {
"rows": { "type": "integer", "minimum": 1 },
"cols": { "type": "integer", "minimum": 1 }
}
}
}
}
}
}
4. MAPレイヤー JSON Schema
基本構造
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://beyond-kle.org/schemas/map-layer.json",
"title": "MAP Layer - Keymap Configuration",
"description": "Key code assignments and layers",
"type": "object",
"required": ["version", "idxReference", "layers"],
"properties": {
"version": { "type": "string" },
"idxReference": {
"type": "object",
"required": ["source", "checksum"],
"properties": {
"source": { "type": "string" },
"checksum": { "type": "string" }
}
},
"layers": {
"type": "array",
"items": {
"$ref": "#/$defs/layer"
}
}
},
"$defs": {
"layer": {
"type": "object",
"required": ["id", "name", "keymap"],
"properties": {
"id": { "type": "integer", "minimum": 0 },
"name": { "type": "string" },
"keymap": {
"type": "array",
"items": {
"$ref": "#/$defs/keyAssignment"
}
}
}
},
"keyAssignment": {
"type": "object",
"required": ["keyIndex", "keycode"],
"properties": {
"keyIndex": { "type": "integer" },
"keycode": { "type": "string" }
}
}
}
}
変換フロー設計
PHY → IDX変換
- PHYレイヤーから物理キーリストを取得
- 各キーに論理IDを割り当て
- マトリックス座標の自動生成(行列最適化)
IDX → ELC変換
- マトリックス次元を算出
- ピン配置の最適化提案
- 配線効率の検証
IDX + ELC → MAP変換
- キーインデックス配列の生成
- デフォルトキーマップの提案
- VIA/QMK形式への出力
次のステップ
- TypeScriptでの型定義作成
- 変換ロジックのプロトタイプ実装
- テストケース(60%、Split等)での検証
- 既存KLE JSONからの変換機能