Skip to content

Render .md files in Jupyter #2485

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

Closed
lspvic opened this issue May 6, 2017 · 19 comments
Closed

Render .md files in Jupyter #2485

lspvic opened this issue May 6, 2017 · 19 comments

Comments

@lspvic
Copy link

lspvic commented May 6, 2017

Are there any ways to open .md markdown files in jupyter? As there are many .ipynb notebooks cloned from git repositories containing many .md files like README.md. It is very inconvenient to read these .md files. Currently, clicking the .md in tree view will open the source of the markdown, not the rendered view.

I notice ViewHandler in v5.0 is introduced. Is there a .md ViewHandler to render markdown files? thanks

@ddulic
Copy link

ddulic commented May 16, 2017

Same "problem".

@juhasch
Copy link

juhasch commented May 16, 2017

There is an MD renderer in the nbextensions_configurator.

You can render any MD file like this (here README.md in the notebook root directory:
http://127.0.0.1:8888/nbextensions/nbextensions_configurator/rendermd/files/README.md

@ddulic
Copy link

ddulic commented May 16, 2017

Installed that by following the instruction, it just installed 2 extensions. Also installed https://github.com/ipython-contrib/jupyter_contrib_nbextensions but I can't seem to find the renderer. Could you explain a bit more how to set it up?
Sorry if I am not understanding something, new to jupyter :)

Maybe an example will help. Going to https://try.jupyter.org/ and creating a new .md file, typing something in it and going back to tree view & then clicking on the .md file opens the editor - this is the correct behavior. Doing it locally shows the source :/

Thanks in advance @juhasch :)

@ostrokach
Copy link

ostrokach commented May 18, 2017

Agreed that this would be a killer feature.

If the README.md file was rendered below the list of files in a directory view, it would give us a way to document all the notebooks. For example, I have many repositories with the following structure. After getting so used to GitHub, I really miss the README.md not being rendered.

selection_013

@gnestor
Copy link
Contributor

gnestor commented Jun 2, 2017

JupyterLab supports real-time rendering of Markdown documents:

image

@gnestor gnestor added this to the JupyterLab milestone Jun 2, 2017
@oysteijo
Copy link

@juhasch You suggested solution works fine. Can you please tell me how to configure Jupyter such that this open when I click the file in the Jupyter file listing? Thanks!

@juhasch
Copy link

juhasch commented Jul 22, 2017

There is no simple way to do this, I think. One would have to change the notebook code, and as @gnestor has written this is already possible with JupyterLab, so there is little incentive to add this to the "classic" notebook, I guess.

It would be possible to write a server extension implementing a custom Jupyter file listing with additional features like markdown rendering.

@Faur
Copy link

Faur commented Aug 17, 2017

Just to make sure I understand. The feature by @ostrokach will be added to JupyterLab, but not the current Jupyter UI? I.e. it will take a while before this is rolled out.

It would seem to me that this would be a relatively simple feature to add that would greatly enhance the user experience for many (I am a TA and would love this feature!).

@takluyver
Copy link
Member

There isn't currently any mechanism for rendering a file other than a notebook - we can display text files in a simple editor, or send them to the browser raw to let it render/download them.

If you can come up with a non-invasive PR which adds the feature without interfering with the mechanisms and UI already there, I think we'd be happy to merge that. But I don't have a clear idea where I'd add that to the existing framework.

@Sbelletier
Copy link

This may be a stupid suggestion, but couldn't we consider .md files as a special "markdown notebook" containing only one cell ? We could then almost reuse almost all of the python notebook UI couldn't we ?

The renderer exists for basic notebooks, and markdown is pretty much a standard for writing non-code text in jupyter so it does seem a good idea to make a markdown editor+renderer as the basis for writing formatted natural langage text in jupyter.

I don't think cells, the way are defined, are invasive in markdown syntax so both should be able to function together. This way we may even be able to support splitting the markdown files in several cells when editing with jupyter to avoid rendering the whole file in one go.

@Faur
Copy link

Faur commented Oct 12, 2017

@Sbelletier I like the idea of special 'markdown notebooks' but adding multicell support would require adding content to the .md file (as far as I understand), and thus break it in other interpreters, but automatically rendering all .md as special limited notebooks sounds reasonable to me.

@gnestor
Copy link
Contributor

gnestor commented Oct 12, 2017

@Sbelletier It would not be trivial to implement something like this. JupyterLab is designed with this use case in mind (e.g. you can edit a markdown file and render the same markdown file in another panel and the 2 representation stay in sync) whereas the notebook isn't. If you can't use JupyterLab for some reason, then you can always edit your markdown in a cell of a notebook and copy/paste it over to a markdown file when you're done. We unfortunately have limited resources and the majority of those resources dedicated to JupyterLab, so for that reason I'm going to close this issue.

@gnestor gnestor closed this as completed Oct 12, 2017
@fuyw
Copy link

fuyw commented Apr 4, 2018

notedown may help.

@jshtaway
Copy link

jshtaway commented Jun 8, 2018

Here's some code I wrote from something else that does something similar.

It looks through a given folder and creates an ipynb file with all readme files as markdown cells.

#---- Merge with readme ---- ---- ---- ---- ---- --- ---- ---- ---- ----
import nbformat; import os; import re
newMergedCells = nbformat.v4.new_notebook()
oneTime = False; readmeLines = ''; resources = ''
folderToWalkThrough = os.path.join('.','06-Python-APIs')
for root, dirs, files in os.walk(folderToWalkThrough, topdown=True):
    for name in files: #Only care about the files
        #print (os.path.join(root,name))
        if re.search('\.md', name):
            with open (os.path.join(root,name)) as readme:
                readmeLines = readme.read()
                newCell = nbformat.v4.new_markdown_cell(str(readmeLines))
                merged.cells.insert(-1,newCell)


newMergedCells.metadata.name = folderToWalkThrough.replace('.','').replace('/','_').lstrip('_')
nbformat.write(merged, '{0}_Merged.ipynb'.format(newMergedCells.metadata.name))

@jshtaway
Copy link

jshtaway commented Jun 8, 2018

This code alternatively loops through all files in a given directory and merges all ipynb and readme files into a single ipynb file.

#---- Merge with readme ---- ---- ---- ---- ---- --- ---- ---- ---- ----
import nbformat; import os; import re
merged = None; oneTime = False; readmeLines = ''; resources = ''
folderToWalkThrough = os.path.join('.','06-Python-APIs')
for root, dirs, files in os.walk(folderToWalkThrough, topdown=True):
    for name in files: #Only care about the files
        #print (os.path.join(root,name))
        if re.search('\.md', name):
            with open (os.path.join(root,name)) as readme:
                readmeLines = readme.read()
            
        if re.search('\.ipynb', name): #Make sure its a ipython notebook file
            with open(os.path.join(root, name) ) as f:
                nb = nbformat.read(f, as_version=4)
            if merged == None:
                merged = nb
            else:
                if readmeLines: 
                    newCell = nbformat.v4.new_markdown_cell(str(readmeLines))
                    merged.cells.insert(-1,newCell)
                    readmeLines = ''
                
                    path = os.path.join(root,name)
                    resources = path.split('Unsolved')[0] if re.search('Unsolved', root) else ''
                    #print(resources)
                    resources = path.split('Solved')[0] if re.search('Solved', root) and not(resources) else resources
                    #print(resources)
                    resources = os.path.join(resources, 'Resources')
                    resources = os.path.join(root,'Resources') if not(os.path.isdir(resources)) else resources
                    #print(resources)
                    if os.path.isdir(resources):
                        csvCode= 'import os\nimport re\nimport pandas as pd'
                        csvCode+='\ncsvData=dict()\nfor root, dirs, files in os.walk(\'{0}\', topdown=True):'.format(resources)
                        csvCode+='\n    for name in files: #Only care about the files\n        if re.search(\'.csv\',name):'
                        csvCode+='\n            csvData[name.split(\'.\')[0]] = pd.read_csv(open(os.path.join(root,name)))'
                        csvCode+='\ncsvData'
                        newCodeCell = nbformat.v4.new_code_cell(csvCode)
                        merged.cells.insert(-1,newCodeCell)
                
                merged.cells.insert(-1, nbformat.v4.new_markdown_cell(str(os.path.join(root, name))))
                merged.cells.extend(nb.cells)

newMergedCells = nbformat.v4.new_notebook()
newMergedCells.metadata.name = folderToWalkThrough.replace('.','').replace('/','_').lstrip('_')
nbformat.write(merged, '{0}_Merged.ipynb'.format(newMergedCells.metadata.name))
```

@carlosmarin
Copy link

@zen-gineer - thanks for the share!
Crazy coincidence that I stumbled into this snippet while (also) prepping to teach bootcamp class =) (06-Python-APIs was the giveaway).

Fixed by renaming merged in the first code.

import nbformat; import os; import re
newMergedCells = nbformat.v4.new_notebook()
oneTime = False; readmeLines = ''; resources = ''
folderToWalkThrough = os.path.join('.')
for root, dirs, files in os.walk(folderToWalkThrough, topdown=True):
    for name in files: #Only care about the files
        print (os.path.join(root,name))
        if re.search('\.md', name):
            with open (os.path.join(root,name)) as readme:
                readmeLines = readme.read()
                newCell = nbformat.v4.new_markdown_cell(str(readmeLines))
                newMergedCells.cells.insert(-1,newCell)

newMergedCells.metadata.name = folderToWalkThrough.replace('.','').replace('/','_').lstrip('_')
nbformat.write(newMergedCells, '{0}_Merged.ipynb'.format(newMergedCells.metadata.name))

@Hiyorimi
Copy link

So, anyone working on this? I would love to implement Readme.md display and support preview of MD files in separate tab, if someone would provide occasional support and point me where to start. I never committed to jupyter before.

@toonijn toonijn mentioned this issue Mar 20, 2020
@LGR3
Copy link

LGR3 commented Jul 22, 2020

What the ... ??? ( Can I Develop and pull request it ?? )

@kevin-bates
Copy link
Member

@LGR3 - thank you for your interest. However, I believe this issue may have been addressed by #5299 - which was closed in favor of #5488 due to refactoring efforts. If there's no further work for it, perhaps you could take it for a spin - which would be a big help.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 24, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests