Package: nb2medium
nb2mediumPython package and Jupyter extension that enables submitting Medium drafts elegantly from a Jupyter Notebooknb2medium main assets are:Written usingnbdevand therefore easy to maintainSimple pythonic implementation of Medium APIMakes use ofnbconvertand custom preprocessors to turn notebooks to Markdown documentsSupports uploading blocks as GitHub gists with simple in-cell tagsSupports hiding of cells sources, cells outputs or cellsComes with Jupyter extension and CLI for ease-of-usenb2medium represents a simple yet sufficient framework to upload Jupyter notebook to Medium. Its main strenghts are that it makes use of great existing tools such asnbconvertor therequestspackage for its main functionality. Moreover the package is developed usingnbdevfrom Jeremy Howard and the fastai team, which is claimed to accelerate development an debugging time.Installpip install nb2mediumThen enable the notebook extension by running:jupyternotebookinstallnb2medium--py
jupyternotebookenablenb2medium--pyAdd--userto these commands if you want to activate the extension only for the current user.Add--sys-prefixto these commands if you want to activate the extension only in current virtual environment.SetupYou will need a Medium Integration token to be able to upload your articles to Medium. If you wish to upload some code blocks as gists, you will need a GitHub token too.
Both token should be available as environment variables, hence we recommend you add these 2 lines to your shell configuration file (~/.bashrcor~/.zshrcare the most common ones):exportMEDIUM_TOKEN=<your-medium-token>exportGITHUB_TOKEN=<your-github-token>Obtain an Medium Integration Token fromyour Medium settings pageObtain a GitHub token by followingGitHub's docsHow to useYou may choose to use nb2medium as a command line tool, directly from python or using the Jupyter notebook extension button or menu.Note:nb2medium uploads Jupyter notebooks as they are, the notebooks do not get executed before being rendered.From the Jupyter notebookYou may choose to use thenb2mediumunder file or the button on the top toolbarFrom the CLIFrom the shell (bash, zsh, sh):nb2medium"My article"path/to/notebook.ipynbUsenb2medium --helpto see all the different optionsFrom pythonfrom nb2medium.upload import nb2medium

nb2medium(title = 'My First Article', notebook = '../samples/test-notebook.ipynb');converter:INFO - Found a hide-source tag in cell #35.
converter:INFO - Found a hide-output tag in cell #36.
converter:INFO - Found a hide-cell tag in cell #37.
converter:INFO - Gist notebooktest.py from cell 26 succesfully uploaded!
converter:INFO - Gist print.py from cell 27 succesfully uploaded!
converter:INFO - Gist pandas.py from cell 30 succesfully uploaded!
converter:INFO - Gist pandas.py.csv from cell 30 succesfully uploaded!
converter:INFO - Gist pandas-doubleupload.py from cell 33 succesfully uploaded!
converter:INFO - Gist pandas-doubleupload.py.csv from cell 33 succesfully uploaded!
converter:INFO - Detected 4 plots and 2 local images in notebook.
converter:INFO - Markdown document written to ../samples/test-notebook/test-notebook.md
uploader:INFO - Draft of 'My First Article' from test-notebook.ipynb notebook uploaded to Medium: https://medium.com/@lucha6/946f9176365bImages, code cells and tablesImagesImages usually come from a local file, online site or are the result of a plot.nb2mediumcan handle these 3 situations. If an image correspond to a local file in markdown cell (e.g.![](path/to/image.png))The image is uploaded to the Medium end point and the path to the image is swapped for the newly generated image URL.
If the image is the result of a plot, such as:importnumpyasnpimportmatplotlib.pyplotaspltx=np.arange(0,10,0.1)y=np.sin(x)plt.plot(x,y)The result of the image is uploaded to the Medium endpoint (without being written to memory) and the corresponding plot is replaced by the plot's URL.If the image is already online, nothing changes to it, as Medium can access it directly from the internet when loading the articleCode cells as GitHub gistsBy default a code cell is rendered without syntax highlighting or anything fancy like:import pandas as pd
pd.DataFrame({'a': [1,2,3], 'b': [2,4,6]})Though if a GitHub token is available and the user includes the following header in a cell:# %gist gistname: pandas.pyimportpandasaspdpd.DataFrame({'a':[1,2,3],'b':[2,4,6]})The code block will be uploaded to the user's GitHub as a private gist (by default - can be changed to be made public) and the respective code cell will be replaced by the gist URL. The user can also use thedescription:and thepublic:flags in the#gistheader, wherepublic:maybe either True or False and description can just be a string (no single or double quotes required - just avoid using the keywordsgistname, public or description)Hiding cellsIt is often convenient to hide either a cell's source (i.e. the code), a cell's output (the result of evaluating the code) or the whole cell altogether. To achieve this the user can place the following header at the start of the relevant cells.To hide a cell's source:# %hide-sourceprint("This code won't be shown, but it's output will")To hide a cell's output:# %hide-outputprint("This code will be shown, but it's output won't")To hide a cell completely (source and output):# %hide-cellprint("This cell won't make it to the final document")Note:all tags (%hide-*and%gist) were not designed with the idea to be combined so such usage has not been tested. In general there should be no need for such behaviour.TablesMedium does not have good support for HTML nor Markdown tables. My preferred existing option for tables isgist. If a cell outputs a pandas dataframe and you choose the#%gistoption with the value of theupload:flag set tobothoroutput,nd2mediumwill detect your table and upload it as a CSV to your GitHub gist repo.#% gist gistname: pandas.py upload: bothimportpandasaspdpd.DataFrame({'a':[1,2,3],'b':[0,0,0],'c':['One','Two','Three']})DocumentationThe docs are available athttps://lucharo.github.io/nb2mediumand are rendered automatically from thenbdevnotebooks so they are always up to date with the package source codeContributingIf you find a bug or think of an enhancement feel free to raise issues or submit pull requests. If you want to contribute to open source projects such as this one have a look at the issues with the label/taghelp neededin particular.