- Finalized PROJECT.md incorporating 'Zero-Pollution' constraints - Enforced native Git portability (git pull sync only) - Generated ARCHITECTURE.md and STACK.md maps - Deleted .agent/skills/.gitignore to physically track flattened skills
245 lines
7.4 KiB
Markdown
245 lines
7.4 KiB
Markdown
---
|
|
name: json-canvas
|
|
description: JSON Canvas 형식의 시각적 마인드맵, 노드, 다이어그램, 플로우차트 파일(.canvas)을 생성하고 편집합니다.
|
|
---
|
|
|
|
# JSON Canvas Skill
|
|
|
|
## File Structure
|
|
|
|
A canvas file (`.canvas`) contains two top-level arrays following the [JSON Canvas Spec 1.0](https://jsoncanvas.org/spec/1.0/):
|
|
|
|
```json
|
|
{
|
|
"nodes": [],
|
|
"edges": []
|
|
}
|
|
```
|
|
|
|
- `nodes` (optional): Array of node objects
|
|
- `edges` (optional): Array of edge objects connecting nodes
|
|
|
|
## Common Workflows
|
|
|
|
### 1. Create a New Canvas
|
|
|
|
1. Create a `.canvas` file with the base structure `{"nodes": [], "edges": []}`
|
|
2. Generate unique 16-character hex IDs for each node (e.g., `"6f0ad84f44ce9c17"`)
|
|
3. Add nodes with required fields: `id`, `type`, `x`, `y`, `width`, `height`
|
|
4. Add edges referencing valid node IDs via `fromNode` and `toNode`
|
|
5. **Validate**: Parse the JSON to confirm it is valid. Verify all `fromNode`/`toNode` values exist in the nodes array
|
|
|
|
### 2. Add a Node to an Existing Canvas
|
|
|
|
1. Read and parse the existing `.canvas` file
|
|
2. Generate a unique ID that does not collide with existing node or edge IDs
|
|
3. Choose position (`x`, `y`) that avoids overlapping existing nodes (leave 50-100px spacing)
|
|
4. Append the new node object to the `nodes` array
|
|
5. Optionally add edges connecting the new node to existing nodes
|
|
6. **Validate**: Confirm all IDs are unique and all edge references resolve to existing nodes
|
|
|
|
### 3. Connect Two Nodes
|
|
|
|
1. Identify the source and target node IDs
|
|
2. Generate a unique edge ID
|
|
3. Set `fromNode` and `toNode` to the source and target IDs
|
|
4. Optionally set `fromSide`/`toSide` (top, right, bottom, left) for anchor points
|
|
5. Optionally set `label` for descriptive text on the edge
|
|
6. Append the edge to the `edges` array
|
|
7. **Validate**: Confirm both `fromNode` and `toNode` reference existing node IDs
|
|
|
|
### 4. Edit an Existing Canvas
|
|
|
|
1. Read and parse the `.canvas` file as JSON
|
|
2. Locate the target node or edge by `id`
|
|
3. Modify the desired attributes (text, position, color, etc.)
|
|
4. Write the updated JSON back to the file
|
|
5. **Validate**: Re-check all ID uniqueness and edge reference integrity after editing
|
|
|
|
## Nodes
|
|
|
|
Nodes are objects placed on the canvas. Array order determines z-index: first node = bottom layer, last node = top layer.
|
|
|
|
### Generic Node Attributes
|
|
|
|
| Attribute | Required | Type | Description |
|
|
|-----------|----------|------|-------------|
|
|
| `id` | Yes | string | Unique 16-char hex identifier |
|
|
| `type` | Yes | string | `text`, `file`, `link`, or `group` |
|
|
| `x` | Yes | integer | X position in pixels |
|
|
| `y` | Yes | integer | Y position in pixels |
|
|
| `width` | Yes | integer | Width in pixels |
|
|
| `height` | Yes | integer | Height in pixels |
|
|
| `color` | No | canvasColor | Preset `"1"`-`"6"` or hex (e.g., `"#FF0000"`) |
|
|
|
|
### Text Nodes
|
|
|
|
| Attribute | Required | Type | Description |
|
|
|-----------|----------|------|-------------|
|
|
| `text` | Yes | string | Plain text with Markdown syntax |
|
|
|
|
```json
|
|
{
|
|
"id": "6f0ad84f44ce9c17",
|
|
"type": "text",
|
|
"x": 0,
|
|
"y": 0,
|
|
"width": 400,
|
|
"height": 200,
|
|
"text": "# Hello World\n\nThis is **Markdown** content."
|
|
}
|
|
```
|
|
|
|
**Newline pitfall**: Use `\n` for line breaks in JSON strings. Do **not** use the literal `\\n` -- Obsidian renders that as the characters `\` and `n`.
|
|
|
|
### File Nodes
|
|
|
|
| Attribute | Required | Type | Description |
|
|
|-----------|----------|------|-------------|
|
|
| `file` | Yes | string | Path to file within the system |
|
|
| `subpath` | No | string | Link to heading or block (starts with `#`) |
|
|
|
|
```json
|
|
{
|
|
"id": "a1b2c3d4e5f67890",
|
|
"type": "file",
|
|
"x": 500,
|
|
"y": 0,
|
|
"width": 400,
|
|
"height": 300,
|
|
"file": "Attachments/diagram.png"
|
|
}
|
|
```
|
|
|
|
### Link Nodes
|
|
|
|
| Attribute | Required | Type | Description |
|
|
|-----------|----------|------|-------------|
|
|
| `url` | Yes | string | External URL |
|
|
|
|
```json
|
|
{
|
|
"id": "c3d4e5f678901234",
|
|
"type": "link",
|
|
"x": 1000,
|
|
"y": 0,
|
|
"width": 400,
|
|
"height": 200,
|
|
"url": "https://obsidian.md"
|
|
}
|
|
```
|
|
|
|
### Group Nodes
|
|
|
|
Groups are visual containers for organizing other nodes. Position child nodes inside the group's bounds.
|
|
|
|
| Attribute | Required | Type | Description |
|
|
|-----------|----------|------|-------------|
|
|
| `label` | No | string | Text label for the group |
|
|
| `background` | No | string | Path to background image |
|
|
| `backgroundStyle` | No | string | `cover`, `ratio`, or `repeat` |
|
|
|
|
```json
|
|
{
|
|
"id": "d4e5f6789012345a",
|
|
"type": "group",
|
|
"x": -50,
|
|
"y": -50,
|
|
"width": 1000,
|
|
"height": 600,
|
|
"label": "Project Overview",
|
|
"color": "4"
|
|
}
|
|
```
|
|
|
|
## Edges
|
|
|
|
Edges connect nodes via `fromNode` and `toNode` IDs.
|
|
|
|
| Attribute | Required | Type | Default | Description |
|
|
|-----------|----------|------|---------|-------------|
|
|
| `id` | Yes | string | - | Unique identifier |
|
|
| `fromNode` | Yes | string | - | Source node ID |
|
|
| `fromSide` | No | string | - | `top`, `right`, `bottom`, or `left` |
|
|
| `fromEnd` | No | string | `none` | `none` or `arrow` |
|
|
| `toNode` | Yes | string | - | Target node ID |
|
|
| `toSide` | No | string | - | `top`, `right`, `bottom`, or `left` |
|
|
| `toEnd` | No | string | `arrow` | `none` or `arrow` |
|
|
| `color` | No | canvasColor | - | Line color |
|
|
| `label` | No | string | - | Text label |
|
|
|
|
```json
|
|
{
|
|
"id": "0123456789abcdef",
|
|
"fromNode": "6f0ad84f44ce9c17",
|
|
"fromSide": "right",
|
|
"toNode": "a1b2c3d4e5f67890",
|
|
"toSide": "left",
|
|
"toEnd": "arrow",
|
|
"label": "leads to"
|
|
}
|
|
```
|
|
|
|
## Colors
|
|
|
|
The `canvasColor` type accepts either a hex string or a preset number:
|
|
|
|
| Preset | Color |
|
|
|--------|-------|
|
|
| `"1"` | Red |
|
|
| `"2"` | Orange |
|
|
| `"3"` | Yellow |
|
|
| `"4"` | Green |
|
|
| `"5"` | Cyan |
|
|
| `"6"` | Purple |
|
|
|
|
Preset color values are intentionally undefined -- applications use their own brand colors.
|
|
|
|
## ID Generation
|
|
|
|
Generate 16-character lowercase hexadecimal strings (64-bit random value):
|
|
|
|
```
|
|
"6f0ad84f44ce9c17"
|
|
"a3b2c1d0e9f8a7b6"
|
|
```
|
|
|
|
## Layout Guidelines
|
|
|
|
- Coordinates can be negative (canvas extends infinitely)
|
|
- `x` increases right, `y` increases down; position is the top-left corner
|
|
- Space nodes 50-100px apart; leave 20-50px padding inside groups
|
|
- Align to grid (multiples of 10 or 20) for cleaner layouts
|
|
|
|
| Node Type | Suggested Width | Suggested Height |
|
|
|-----------|-----------------|------------------|
|
|
| Small text | 200-300 | 80-150 |
|
|
| Medium text | 300-450 | 150-300 |
|
|
| Large text | 400-600 | 300-500 |
|
|
| File preview | 300-500 | 200-400 |
|
|
| Link preview | 250-400 | 100-200 |
|
|
|
|
## Validation Checklist
|
|
|
|
After creating or editing a canvas file, verify:
|
|
|
|
1. All `id` values are unique across both nodes and edges
|
|
2. Every `fromNode` and `toNode` references an existing node ID
|
|
3. Required fields are present for each node type (`text` for text nodes, `file` for file nodes, `url` for link nodes)
|
|
4. `type` is one of: `text`, `file`, `link`, `group`
|
|
5. `fromSide`/`toSide` values are one of: `top`, `right`, `bottom`, `left`
|
|
6. `fromEnd`/`toEnd` values are one of: `none`, `arrow`
|
|
7. Color presets are `"1"` through `"6"` or valid hex (e.g., `"#FF0000"`)
|
|
8. JSON is valid and parseable
|
|
|
|
If validation fails, check for duplicate IDs, dangling edge references, or malformed JSON strings (especially unescaped newlines in text content).
|
|
|
|
## Complete Examples
|
|
|
|
See [references/EXAMPLES.md](references/EXAMPLES.md) for full canvas examples including mind maps, project boards, research canvases, and flowcharts.
|
|
|
|
## References
|
|
|
|
- [JSON Canvas Spec 1.0](https://jsoncanvas.org/spec/1.0/)
|
|
- [JSON Canvas GitHub](https://github.com/obsidianmd/jsoncanvas)
|