Skip to content

Commit a6af8b8

Browse files
authored
Merge pull request #40 from openpatch/copilot/add-vscode-extension-learningmap
Add VS Code extension platform for editing .learningmap files (with browser support and fully configurable keyboard shortcuts)
2 parents 8875689 + 24dde25 commit a6af8b8

27 files changed

Lines changed: 3241 additions & 95 deletions

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ explore learning pathways. It is developed by
99
- **Repository:** https://github.com/openpath/learningmap
1010
- **Community**: https://matrix.to/#/#openpatch:matrix.org
1111

12+
## Platforms
13+
14+
- **Web App**: Create and share learningmaps at [learningmap.app](https://learningmap.app)
15+
- **VS Code Extension**: Edit `.learningmap` files locally in VS Code (see [platforms/vscode](platforms/vscode))
16+
- **React Component**: Integrate learningmap into your own React app (see [packages/learningmap](packages/learningmap))
17+
- **Web Component**: Use learningmap in any web application (see [packages/web-component](packages/web-component))
18+
1219
## Documentation
1320

1421
If you want to work on the documentation, run the

docs/book/development.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ learningmap/
4040
│ ├── learningmap/ # Core React component library
4141
│ └── web-component/ # Web component wrapper
4242
├── platforms/
43-
│ └── web/ # Web application (learningmap.app)
43+
│ ├── web/ # Web application (learningmap.app)
44+
│ └── vscode/ # VS Code extension
4445
├── docs/ # Documentation (Hyperbook)
4546
└── scripts/ # Build and development scripts
4647
```
@@ -88,6 +89,23 @@ pnpm docs:dev
8889

8990
The documentation is built with [Hyperbook](https://hyperbook.openpatch.org) and is located in the `docs/` directory.
9091

92+
### VS Code Extension
93+
94+
To develop the VS Code extension:
95+
96+
1. Build the extension:
97+
```bash
98+
pnpm --filter learningmap-vscode build
99+
```
100+
101+
2. Open the `platforms/vscode` directory in VS Code
102+
103+
3. Press F5 to launch the Extension Development Host
104+
105+
4. Open or create a `.learningmap` file to test the editor
106+
107+
See [platforms/vscode/DEVELOPMENT.md](../../platforms/vscode/DEVELOPMENT.md) for more details.
108+
91109
## Testing Your Changes
92110

93111
1. **Type-check**: `pnpm lint`

docs/book/react/index.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,65 @@ function App() {
4646
| `roadmapData` | `string \| RoadmapData` | `undefined` | Initial roadmap data (JSON string or object) |
4747
| `language` | `string` | `"en"` | UI language (`"en"` or `"de"`) |
4848
| `jsonStore` | `string` | `"https://json.openpatch.org"` | URL for JSON storage service |
49+
| `disableSharing` | `boolean` | `false` | Hide the share button (useful in environments without external sharing) |
50+
| `disableFileOperations` | `boolean` | `false` | Hide open and download buttons (useful when file operations are handled externally) |
51+
| `keyBindings` | `Partial<KeyBindings>` | `undefined` | Custom keyboard shortcuts (see [Keyboard Shortcuts](#keyboard-shortcuts)) |
52+
53+
#### Keyboard Shortcuts
54+
55+
The editor includes many keyboard shortcuts for efficient editing. You can customize these shortcuts by providing a `keyBindings` prop:
56+
57+
```tsx
58+
import { LearningMapEditor, KeyBindings } from '@learningmap/learningmap';
59+
60+
const customKeyBindings: Partial<KeyBindings> = {
61+
save: undefined, // Disable save shortcut
62+
addTaskNode: { key: 't', ctrl: true }, // Change from Ctrl+1 to Ctrl+T
63+
};
64+
65+
<LearningMapEditor keyBindings={customKeyBindings} />
66+
```
67+
68+
**Default Keyboard Shortcuts:**
69+
70+
| Action | Default Shortcut | KeyBinding Property |
71+
|--------|-----------------|-------------------|
72+
| Add Task Node | `Ctrl+1` | `addTaskNode` |
73+
| Add Topic Node | `Ctrl+2` | `addTopicNode` |
74+
| Add Image Node | `Ctrl+3` | `addImageNode` |
75+
| Add Text Node | `Ctrl+4` | `addTextNode` |
76+
| Save | `Ctrl+S` | `save` |
77+
| Undo | `Ctrl+Z` | `undo` |
78+
| Redo | `Ctrl+Y` | `redo` |
79+
| Toggle Preview | `Ctrl+P` | `togglePreview` |
80+
| Toggle Debug | `Ctrl+D` | `toggleDebug` |
81+
| Zoom In | `Ctrl++` | `zoomIn` |
82+
| Zoom Out | `Ctrl+-` | `zoomOut` |
83+
| Reset Zoom | `Ctrl+0` | `resetZoom` |
84+
| Toggle Grid | `Ctrl+'` | `toggleGrid` |
85+
| Reset Map | `Ctrl+Delete` | `resetMap` |
86+
| Cut | `Ctrl+X` | `cut` |
87+
| Copy | `Ctrl+C` | `copy` |
88+
| Paste | `Ctrl+V` | `paste` |
89+
| Select All | `Ctrl+A` | `selectAll` |
90+
| Fit View | `Shift+!` | `fitView` |
91+
| Zoom to Selection | `Shift+@` | `zoomToSelection` |
92+
| Delete Selected | `Delete` | `deleteSelected` |
93+
| Help | `Ctrl+?` | `help` |
94+
95+
**KeyBinding Type:**
96+
97+
```typescript
98+
interface KeyBinding {
99+
key: string;
100+
ctrl?: boolean;
101+
shift?: boolean;
102+
alt?: boolean;
103+
meta?: boolean;
104+
}
105+
```
106+
107+
To disable a shortcut, set it to `undefined`. To customize, provide a `KeyBinding` object with the desired key combination.
49108

50109
#### Features
51110

docs/book/web-component/index.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,22 @@ Interactive editor for creating and editing learning maps.
9696
|-----------|------|---------|-------------|
9797
| `roadmap-data` | `string` | `undefined` | JSON string of roadmap data |
9898
| `language` | `string` | `"en"` | UI language (`"en"` or `"de"`) |
99+
| `json-store` | `string` | `"https://json.openpatch.org"` | URL for JSON storage service |
100+
| `disable-sharing` | `boolean` | `false` | Hide the share button (useful in environments without external sharing) |
101+
| `disable-file-operations` | `boolean` | `false` | Hide open and download buttons (useful when file operations are handled externally) |
102+
| `key-bindings` | `string` | `undefined` | JSON string of custom keyboard shortcuts (see React docs for KeyBindings type) |
103+
104+
#### Customizing Keyboard Shortcuts
105+
106+
You can customize keyboard shortcuts by passing a JSON string to the `key-bindings` attribute:
107+
108+
```html
109+
<hyperbook-learningmap-editor
110+
key-bindings='{"save": null, "addTaskNode": {"key": "t", "ctrl": true}}'
111+
></hyperbook-learningmap-editor>
112+
```
113+
114+
This example disables the save shortcut and changes the "add task" shortcut from `Ctrl+1` to `Ctrl+T`. See the React package documentation for a complete list of available shortcuts and the KeyBindings type definition.
99115

100116
#### Events
101117

packages/learningmap/src/EditorToolbar.tsx

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import React from "react";
22
import { Menu, MenuButton, MenuDivider, MenuItem, SubMenu } from "@szhsin/react-menu";
3-
import "@szhsin/react-menu/dist/index.css";
4-
import '@szhsin/react-menu/dist/transitions/zoom.css';
53
import { Plus, Bug, Settings, Eye, Menu as MenuI, FolderOpen, Download, ImageDown, ExternalLink, Share2, RotateCcw } from "lucide-react";
64
import { getTranslations } from "./translations";
75
import { useEditorStore } from "./editorStore";
@@ -13,10 +11,14 @@ import { getZIndexForNodeType } from "./zIndexHelper";
1311

1412
interface EditorToolbarProps {
1513
defaultLanguage?: string;
14+
disableSharing?: boolean;
15+
disableFileOperations?: boolean;
1616
}
1717

1818
export const EditorToolbar: React.FC<EditorToolbarProps> = ({
1919
defaultLanguage = "en",
20+
disableSharing = false,
21+
disableFileOperations = false,
2022
}) => {
2123
const { screenToFlowPosition } = useReactFlow();
2224

@@ -112,15 +114,21 @@ export const EditorToolbar: React.FC<EditorToolbarProps> = ({
112114
</div>
113115
<div className="toolbar-group">
114116
<Menu menuButton={<MenuButton className="toolbar-button"><MenuI /></MenuButton>}>
115-
<MenuItem onClick={openRoadmap}>
116-
<FolderOpen size={16} /> <span>{t.open}</span>
117-
</MenuItem>
118-
<MenuItem onClick={downloadRoadmap}>
119-
<Download size={16} /> <span>{t.download}</span>
120-
</MenuItem>
121-
<MenuItem onClick={postToJsonStore}>
122-
<Share2 size={16} /> <span>{t.share}</span>
123-
</MenuItem>
117+
{!disableFileOperations && (
118+
<MenuItem onClick={openRoadmap}>
119+
<FolderOpen size={16} /> <span>{t.open}</span>
120+
</MenuItem>
121+
)}
122+
{!disableFileOperations && (
123+
<MenuItem onClick={downloadRoadmap}>
124+
<Download size={16} /> <span>{t.download}</span>
125+
</MenuItem>
126+
)}
127+
{!disableSharing && (
128+
<MenuItem onClick={postToJsonStore}>
129+
<Share2 size={16} /> <span>{t.share}</span>
130+
</MenuItem>
131+
)}
124132
<MenuDivider />
125133
<MenuItem onClick={onReset}>
126134
<RotateCcw size={16} /> <span>{t.reset}</span>

0 commit comments

Comments
 (0)