diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..3d3a110 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,4 @@ +# Markdown Editor Optimized (MEO) +--- +## 0.1.0 +- Initial build of the Markdown Editor Optimized (MEO) VSCode extension. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8aa2645 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) [year] [fullname] + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 34aa73a..0a96f3a 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,15 @@ -# MEO - Markdown Editor Optimized - -A native VS Code custom editor for Markdown files powered by CodeMirror 6 with live preview mode. +# Markdown Editor Optimized (MEO) +WYSIWYG editor for markdown files with live edit mode. ## Features -- Custom editor for `.md` files with live preview and modern toolbar -- Uses VS Code color tokens and layout guidance -- Live mode hides markdown syntax markers outside active blocks -- Source mode with full syntax highlighting - -## Development - -Install dependencies: - -```bash -bun install:all -``` - -Build the extension and webview: - -```bash -bun run build -``` - -Run extension in development mode: - -``` -FN+F5 (or F5) in VS Code to launch the extension in a new window with the webview. -``` +- Toggle between live and source modes seamlessly in a single tab. +- Syntax highlighting with Monokai inspired color scheme. +- Rendering of mermaid diagrams and other markdown features. +- Easy management of markdown tables with a dedicated table editor. +- Tasks list support with interactive checkboxes. +- Auto save of markdown files as you edit. +- Content outline view for easy navigation through document structure. ## Usage -- Open a `.md` file. -- Run the command `Markdown Editor Optimized: Open With Editor`. -- Set as default editor if desired. +- Open a `.md` or `.markdown` files with the Markdown Editor Optimized by right-clicking the file in the explorer and selecting `Open with Markdown Editor Optimized`. +- Set the editor as default by running command `Markdown Editor Optimized: Set as Default`. diff --git a/logo.png b/logo.png new file mode 100644 index 0000000..676f3f3 Binary files /dev/null and b/logo.png differ diff --git a/package.json b/package.json index 087cf9e..1fb9c34 100644 --- a/package.json +++ b/package.json @@ -1,24 +1,41 @@ { "name": "markdown-editor-optimized", "displayName": "Markdown Editor Optimized", - "description": "VS Code custom editor for Markdown files with live preview mode powered by CodeMirror 6.", + "description": "WYSIWYG editor for markdown files with live edit mode.", "version": "0.1.0", + "publisher": "vadimmelnicuk", + "private": true, + "icon": "logo.png", "engines": { "vscode": "^1.97.0" }, "categories": [ + "Programming Languages", "Other" ], + "keywords": [ + "markdown", + "editor", + "live-edit", + "wysiwyg", + "markdown-editor", + "markdown-preview" + ], "main": "./dist/extension.js", "activationEvents": [ "onLanguage:markdown" ], - "contributes": { + "contributes": { "commands": [ { "command": "markdownEditorOptimized.open", - "title": "Markdown Editor Optimized: Open With Editor", + "title": "Open With Markdown Editor Optimized", "icon": "$(book)" + }, + { + "command": "markdownEditorOptimized.setDefaultEditor", + "title": "Markdown Editor Optimized: Set as Default", + "icon": "$(check)" } ], "customEditors": [ @@ -35,7 +52,33 @@ ], "priority": "default" } - ] + ], + "menus": { + "explorer/context": [ + { + "command": "markdownEditorOptimized.open", + "when": "resourceFilename =~ /\\.(md|markdown)$/", + "group": "navigation" + } + ], + "editor/title/context": [ + { + "command": "markdownEditorOptimized.open", + "when": "resourceFilename =~ /\\.(md|markdown)$/", + "group": "navigation" + } + ] + }, + "configuration": { + "title": "Markdown Editor Optimized", + "properties": { + "markdownEditorOptimized.useAsDefault": { + "type": "boolean", + "default": true, + "description": "Use Markdown Editor Optimized as the default editor for Markdown files" + } + } + } }, "scripts": { "install:all": "bun install && (cd webview && bun install)", diff --git a/src/extension.ts b/src/extension.ts index faf9c25..a657f3c 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -70,12 +70,30 @@ export function activate(context: vscode.ExtensionContext): void { ); context.subscriptions.push( - vscode.commands.registerCommand('markdownEditorOptimized.open', async () => { - const active = vscode.window.activeTextEditor; - if (!active || active.document.languageId !== 'markdown') { + vscode.commands.registerCommand('markdownEditorOptimized.open', async (uri?: vscode.Uri) => { + let targetUri = uri; + if (!targetUri) { + const active = vscode.window.activeTextEditor; + if (!active) { + return; + } + targetUri = active.document.uri; + } + if (!targetUri.fsPath.endsWith('.md') && !targetUri.fsPath.endsWith('.markdown')) { return; } - await vscode.commands.executeCommand('vscode.openWith', active.document.uri, VIEW_TYPE); + await vscode.commands.executeCommand('vscode.openWith', targetUri, VIEW_TYPE); + }) + ); + + context.subscriptions.push( + vscode.commands.registerCommand('markdownEditorOptimized.setDefaultEditor', async () => { + const config = vscode.workspace.getConfiguration('workbench'); + const associations = config.get>('editorAssociations') || {}; + associations['*.md'] = VIEW_TYPE; + associations['*.markdown'] = VIEW_TYPE; + await config.update('editorAssociations', associations, vscode.ConfigurationTarget.Global); + void vscode.window.showInformationMessage('Markdown Editor Optimized is now set as the default editor for Markdown files.'); }) ); } @@ -106,7 +124,7 @@ class MarkdownWebviewProvider implements vscode.CustomTextEditorProvider { panel.webview.html = this.getWebviewHtml(panel.webview); - let mode: EditorMode = 'source'; + let mode: EditorMode = 'live'; let applyQueue: Promise = Promise.resolve(); let initDelivered = false; let isApplyingOwnChange = false; diff --git a/webview/src/helpers/tables.js b/webview/src/helpers/tables.js index ad7b924..7ca9c85 100644 --- a/webview/src/helpers/tables.js +++ b/webview/src/helpers/tables.js @@ -404,6 +404,23 @@ class HtmlTableWidget extends WidgetType { event.clipboardData?.setData('text/plain', text); }; + const onKeyDown = (event) => { + if (this.selectedCellCount() <= 1) return; + if (event.key !== 'Backspace' && event.key !== 'Delete') return; + if (!this.selectionRange || !this.domRefs) return; + event.preventDefault(); + for (let row = this.selectionRange.fromRow; row <= this.selectionRange.toRow; row++) { + for (let col = this.selectionRange.fromCol; col <= this.selectionRange.toCol; col++) { + const input = this.domRefs.allRowInputs[row][col]; + if (input.value !== '') { + input.value = ''; + this.hasPendingCellEdits = true; + } + } + } + this.scheduleLayout({ resizeRows: true }); + }; + const onFocusOut = (event) => { const nextTarget = event.relatedTarget; if (nextTarget instanceof Node && table.contains(nextTarget)) return; @@ -457,6 +474,7 @@ class HtmlTableWidget extends WidgetType { table.addEventListener('pointerup', endPointerSelection); table.addEventListener('pointercancel', endPointerSelection); table.addEventListener('copy', onCopy); + table.addEventListener('keydown', onKeyDown); table.addEventListener('focusout', onFocusOut); document.addEventListener('pointerdown', onDocumentPointerDown, true); this.cleanupFns.push(() => { @@ -466,6 +484,7 @@ class HtmlTableWidget extends WidgetType { table.removeEventListener('pointerup', endPointerSelection); table.removeEventListener('pointercancel', endPointerSelection); table.removeEventListener('copy', onCopy); + table.removeEventListener('keydown', onKeyDown); table.removeEventListener('focusout', onFocusOut); document.removeEventListener('pointerdown', onDocumentPointerDown, true); }); diff --git a/webview/src/index.js b/webview/src/index.js index e9c2494..99d4495 100644 --- a/webview/src/index.js +++ b/webview/src/index.js @@ -312,7 +312,7 @@ let syncedText = ''; let inFlight = false; let inFlightText = null; let saveAfterSync = false; -let currentMode = 'source'; +let currentMode = 'live'; let hasLocalModePreference = false; const updateModeUI = () => {