-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Add customizable Markdown preview keybindings #4423
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b42be41
0924e87
c80a1d0
c875fd8
9b9881f
28f6d73
4b58f65
4674503
a664427
1304246
2c72885
08d9328
58c4ce0
2f47c95
341d2b0
e4c3439
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -1089,11 +1089,13 @@ | |||||||||||||||||||
|
|
||||||||||||||||||||
| function restoreMarkdownScrollState(state) { | ||||||||||||||||||||
| if (!state) { return; } | ||||||||||||||||||||
| if (state.nearTop) { | ||||||||||||||||||||
| setMarkdownScrollY(0); | ||||||||||||||||||||
| return; | ||||||||||||||||||||
| } | ||||||||||||||||||||
| function apply() { | ||||||||||||||||||||
| var targetY; | ||||||||||||||||||||
| if (state.nearTop) { | ||||||||||||||||||||
| targetY = 0; | ||||||||||||||||||||
| } else if (state.nearBottom) { | ||||||||||||||||||||
| if (state.nearBottom) { | ||||||||||||||||||||
| targetY = markdownMaxScrollY(); | ||||||||||||||||||||
| } else if (state.anchor && state.anchor.id) { | ||||||||||||||||||||
| var anchor = document.getElementById(state.anchor.id); | ||||||||||||||||||||
|
|
@@ -1417,6 +1419,98 @@ | |||||||||||||||||||
| openMarkdownCandidate(rawPath); | ||||||||||||||||||||
| }, true); | ||||||||||||||||||||
|
|
||||||||||||||||||||
| var markdownPreviewSearchQuery = ''; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| function markdownPreviewScroller() { | ||||||||||||||||||||
| return document.scrollingElement || document.documentElement || document.body; | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| function markdownPreviewScrollBy(deltaX, deltaY) { | ||||||||||||||||||||
| var scroller = markdownPreviewScroller(); | ||||||||||||||||||||
| var nextLeft = Math.max(0, (window.scrollX || scroller.scrollLeft || 0) + deltaX); | ||||||||||||||||||||
| var nextTop = clampScrollY((window.scrollY || scroller.scrollTop || 0) + deltaY); | ||||||||||||||||||||
| try { | ||||||||||||||||||||
| window.scrollTo({ left: nextLeft, top: nextTop, behavior: 'smooth' }); | ||||||||||||||||||||
| } catch (e) { | ||||||||||||||||||||
| window.scrollTo(nextLeft, nextTop); | ||||||||||||||||||||
| } | ||||||||||||||||||||
| return true; | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| function markdownPreviewScrollSelectionIntoView() { | ||||||||||||||||||||
| if (!window.getSelection) { return; } | ||||||||||||||||||||
| var selection = window.getSelection(); | ||||||||||||||||||||
| if (!selection || selection.rangeCount < 1) { return; } | ||||||||||||||||||||
| var range = selection.getRangeAt(0); | ||||||||||||||||||||
| var rect = range.getBoundingClientRect(); | ||||||||||||||||||||
| if (!rect || (!rect.top && !rect.bottom)) { return; } | ||||||||||||||||||||
| var targetY = markdownScrollY() + rect.top - Math.max(24, Math.round(window.innerHeight * 0.25)); | ||||||||||||||||||||
| try { | ||||||||||||||||||||
| window.scrollTo({ | ||||||||||||||||||||
| left: window.scrollX || markdownPreviewScroller().scrollLeft || 0, | ||||||||||||||||||||
| top: clampScrollY(targetY), | ||||||||||||||||||||
| behavior: 'smooth' | ||||||||||||||||||||
| }); | ||||||||||||||||||||
| } catch (e) { | ||||||||||||||||||||
| setMarkdownScrollY(targetY); | ||||||||||||||||||||
| } | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| function markdownPreviewPromptSearch(backwards) { | ||||||||||||||||||||
| var promptKey = backwards ? 'searchPromptBackward' : 'searchPromptForward'; | ||||||||||||||||||||
| var fallback = backwards ? 'Search Markdown backward' : 'Search Markdown'; | ||||||||||||||||||||
| var query = window.prompt(cmuxString(promptKey, fallback), markdownPreviewSearchQuery); | ||||||||||||||||||||
|
cubic-dev-ai[bot] marked this conversation as resolved.
|
||||||||||||||||||||
| if (query == null) { return false; } | ||||||||||||||||||||
| query = String(query); | ||||||||||||||||||||
| if (query) { markdownPreviewSearchQuery = query; } | ||||||||||||||||||||
| return markdownPreviewSearch(markdownPreviewSearchQuery, backwards); | ||||||||||||||||||||
|
Comment on lines
+1462
to
+1466
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| function markdownPreviewSearch(query, backwards) { | ||||||||||||||||||||
| var value = String(query == null ? '' : query); | ||||||||||||||||||||
| if (!value) { return false; } | ||||||||||||||||||||
| markdownPreviewSearchQuery = value; | ||||||||||||||||||||
| if (typeof window.find !== 'function') { return false; } | ||||||||||||||||||||
| var found = !!window.find(value, false, !!backwards, true, false, false, false); | ||||||||||||||||||||
| if (found) { | ||||||||||||||||||||
| markdownPreviewScrollSelectionIntoView(); | ||||||||||||||||||||
| } | ||||||||||||||||||||
| return found; | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| window.__cmuxMarkdownPreviewSearch = markdownPreviewSearch; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| window.__cmuxMarkdownPreviewHandleKeyCommand = function(command) { | ||||||||||||||||||||
| switch (command) { | ||||||||||||||||||||
| case 'scrollLeft': | ||||||||||||||||||||
| return markdownPreviewScrollBy(-72, 0); | ||||||||||||||||||||
| case 'scrollDown': | ||||||||||||||||||||
| return markdownPreviewScrollBy(0, 72); | ||||||||||||||||||||
| case 'scrollUp': | ||||||||||||||||||||
| return markdownPreviewScrollBy(0, -72); | ||||||||||||||||||||
| case 'scrollRight': | ||||||||||||||||||||
| return markdownPreviewScrollBy(72, 0); | ||||||||||||||||||||
| case 'pageUp': | ||||||||||||||||||||
| return markdownPreviewScrollBy(0, -Math.max(120, Math.round(window.innerHeight * 0.5))); | ||||||||||||||||||||
| case 'pageDown': | ||||||||||||||||||||
| return markdownPreviewScrollBy(0, Math.max(120, Math.round(window.innerHeight * 0.5))); | ||||||||||||||||||||
| case 'findForward': | ||||||||||||||||||||
| return markdownPreviewPromptSearch(false); | ||||||||||||||||||||
| case 'findBackward': | ||||||||||||||||||||
| return markdownPreviewPromptSearch(true); | ||||||||||||||||||||
| case 'findNext': | ||||||||||||||||||||
| return markdownPreviewSearchQuery | ||||||||||||||||||||
| ? markdownPreviewSearch(markdownPreviewSearchQuery, false) | ||||||||||||||||||||
| : markdownPreviewPromptSearch(false); | ||||||||||||||||||||
| case 'findPrevious': | ||||||||||||||||||||
| return markdownPreviewSearchQuery | ||||||||||||||||||||
| ? markdownPreviewSearch(markdownPreviewSearchQuery, true) | ||||||||||||||||||||
| : markdownPreviewPromptSearch(true); | ||||||||||||||||||||
| default: | ||||||||||||||||||||
| return false; | ||||||||||||||||||||
| } | ||||||||||||||||||||
| }; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| window.__cmuxRenderMarkdown = function(md) { | ||||||||||||||||||||
| try { | ||||||||||||||||||||
| headingSlugCounts = Object.create(null); | ||||||||||||||||||||
|
|
||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: Per-keystroke scrolling uses smooth animation, which can drop/flatten repeated scroll steps when keys are pressed quickly.
Prompt for AI agents