Search code examples
pythonjupyter-notebookmarkdownjupyter

inlining svg image in a markdown cell


My question is related to the wish of publishing a self contained notebook

I have a Markdown cell in a notebook of mine that references an external image file

so far

![](example.svg "Example")

so good

Is it possible to inline the file content in the MD cell?


Solution

  • I'd like to distill some wisdom from the answers and the comments I've received. The answer from Shammel Lee is the closest to an accettable answer, the idea behind that answer is the correct idea, but too many details make me think that I cannot accept it.

    1. The recourse to external sites, it's true that I'm going to publish the notebooks but my files and other details of my digital identity are not the business of anyone (as far as possible :), especially when Python standard library is perfectly up to the task.

    2. The usually unnecessary step of uuencoding the SVG string.

    3. The missing distinction between the header for a not-uuencoded string and the uuencoded one, as noted in this comment by Aristide.

    I have written a Python script that copies the quoted SVG content, plus the headers etc, to the clipboard

    $ python3 svg2clip figure03.svg
    

    so that you can paste (Ctrl-V) the required stuff into a markdown cell.

    from sys import argv
    from urllib import parse
    from subprocess import PIPE, Popen, TimeoutExpired
    
    svg = open(argv[1]).read()
    inlined = ('![svg image](data:image/svg+xml,' +
               parse.quote(svg) +
               ')'
               ).encode('utf8')
    p = Popen(["xclip", "-selection", "clipboard"],
              stdin=PIPE, stdout=PIPE)
    try:
        p.communicate(inlined, timeout=0.020)
    except TimeoutExpired:
        pass
    

    PS1 — if someone knows how to terminate command execution in a simpler way, please comment...
    PS2 — the script works on Linux, where xclip is usually present or can be easily installed, but afaict similar utilities are available also for different environments, just modify the Popen first argument.


    UPDATE

    When I wrote my answer in 2017, I was not aware of the pyperclip Python package.

    Using pyperclip my script can be rewritten and simplified as follows

    from sys import argv
    from urllib import parse
    from pyperclip import copy as copy2clip
    
    svg = open(argv[1]).read()
    inlined = ('![svg image](data:image/svg+xml,' +
               parse.quote(svg) +
               ')'
               ).encode('utf8')
    copy2clip(inlined)