-
Notifications
You must be signed in to change notification settings - Fork 92
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
Add support for markdown cells in positron notebooks #2563
Conversation
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.
(Partial review since I had to head out, will complete tomorrow.)
Very nice! It mostly worked well in my testing. A few rough edges I encountered and some thoughts below, but happy to get :
- For some reason the "Hide Editor" button didn't initially work for me, but then started working and I'm not sure what changed.
- I also managed to make my notebook tab go blank although I'm not sure how. I think I tried to close the tab (but it didn't actually close) then created a markdown cell and added an image to it.
- Links are not yet clickable.
- We'll want to decide which approach we take in terms of showing a side-by-side preview versus previewing when the user tries to "run" the cell, but we can handle that in future.
We can address some of these in follow-ups of course.
src/vs/workbench/contrib/positronNotebook/browser/AddCellButtons.tsx
Outdated
Show resolved
Hide resolved
src/vs/workbench/contrib/positronNotebook/browser/notebookCells/interfaces.ts
Outdated
Show resolved
Hide resolved
src/vs/workbench/contrib/positronNotebook/browser/PositronNotebookInstance.ts
Show resolved
Hide resolved
src/vs/workbench/contrib/positronNotebook/browser/notebookCells/DeferredImage.tsx
Outdated
Show resolved
Hide resolved
src/vs/workbench/contrib/positronNotebook/browser/notebookCells/DeferredImage.tsx
Show resolved
Hide resolved
src/vs/workbench/contrib/positronNotebook/browser/notebookCells/DeferredImage.tsx
Outdated
Show resolved
Hide resolved
src/vs/workbench/contrib/positronNotebook/browser/notebookCells/DeferredImage.tsx
Outdated
Show resolved
Hide resolved
src/vs/workbench/contrib/positronNotebook/browser/notebookCells/Markdown.tsx
Outdated
Show resolved
Hide resolved
b8b36df
to
f2fcdfb
Compare
|
||
React.useEffect(() => { | ||
const timeoutMs = 3000; | ||
const convertCommand = commandWithTimeout<unknown>( |
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.
Does the onError
part of this work i.e. can you catch errors in the extension host by try-catching executeCommand
?
I'm still able to see errors in the console if they aren't caught in the command.
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.
Something weird also happens if I use a URL e.g. https://posit.co/wp-content/uploads/2023/03/home-hero-connect-e1689269684616.jpg. It displays in the preview, but also shows an error in the console:
Error: ENOENT: no such file or directory, open '/Users/seem/posit/demos/https:/posit.co/wp-content/uploads/2023/03/home-hero-connect-e1689269684616.jpg'
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.
Errors thrown in the extension context don't seem to trigger errors in the ui-thread. So in that case onError()
really only catches errors where no data is returned. Probably worth renaming or consolidating that logic.
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.
Cleaned up this logic in b7402a8 to make it more obvious what was going on. Unhandled errors in the extension will now most likely trigger a timeout now, which seems reasonable.
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.
ff2afc6 Lets remote images pass through (Based on if it starts with http
or https
which I think is safe enough.
…rvable renderedHtml field for the markup cells.
…ontent and double-click status
…ed markup view. Also fix distracting action button outlines.
…ld that is used for image loading. Also update modalDialogs to use this new approach.
Co-authored-by: Jonathan <[email protected]> Signed-off-by: Nick Strayer <[email protected]>
Co-authored-by: Jonathan <[email protected]> Signed-off-by: Nick Strayer <[email protected]>
…y passing info about failure as object
…and also added a timeout.
…and utilize in the markdown and image rendering.
…led after timeout
62800ce
to
0d5a5e3
Compare
…ack to being more typical promise format
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.
I found just one small thing.
src/vs/workbench/contrib/positronNotebook/browser/PositronNotebookComponent.tsx
Outdated
Show resolved
Hide resolved
export function promiseWithTimeout<T>(promise: Promise<T>, timeoutMs: number, cancelToken: CancellationToken): Promise<T> { | ||
|
||
return new Promise((resolve, reject) => { | ||
cancelToken.onCancellationRequested(() => { | ||
reject(new Error('Promise cancelled')); | ||
}); | ||
|
||
const timeout = setTimeout(() => { | ||
reject(new Error(`Promise timed out after ${timeoutMs}ms`)); | ||
}, timeoutMs); | ||
|
||
promise.then((res) => { | ||
clearTimeout(timeout); | ||
resolve(res); | ||
}).catch((err) => { | ||
clearTimeout(timeout); | ||
reject(err); | ||
}); | ||
}); | ||
} |
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.
@jmcphers Is this reinventing a wheel from somewhere in the codebase already?
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.
It is. I think you want raceTimeout
here.
export function promiseWithTimeout<T>(promise: Promise<T>, timeoutMs: number, cancelToken: CancellationToken): Promise<T> { | ||
|
||
return new Promise((resolve, reject) => { | ||
cancelToken.onCancellationRequested(() => { | ||
reject(new Error('Promise cancelled')); | ||
}); | ||
|
||
const timeout = setTimeout(() => { | ||
reject(new Error(`Promise timed out after ${timeoutMs}ms`)); | ||
}, timeoutMs); | ||
|
||
promise.then((res) => { | ||
clearTimeout(timeout); | ||
resolve(res); | ||
}).catch((err) => { | ||
clearTimeout(timeout); | ||
reject(err); | ||
}); | ||
}); | ||
} |
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.
It is. I think you want raceTimeout
here.
Intent
Add the ability to create and edit markdown cells in notebooks.
Approach
Leveraged existing markdown parser from the
markdown-language-features
extension.Added new component for displaying images (
DeferredImage
) from the local file-system in react-land.positron-notebooks
to do so with the'positronNotebookHelpers.convertImageToBase64'
command that converts image to data-url.renderHtml()
function to allow for the usage of custom components for a tag type. This is used to pass<DeferredImage/>
component instead of plain<img/>
.Added
<Markdown/>
component that takes a string of markdown text and renders it into react land with images done using the<DeferredImage/>
componentMarkup cells default to closed but can be opened via double-clicking or a "show editor" button.
Addresses #2350