Viewing images works for local files
We have to make sure that everything is converted to base64 (and replaced in the src attribute) because otherwise ST3 messes up the height of the images
This commit is contained in:
@ -1,7 +1,10 @@
|
|||||||
|
import os.path
|
||||||
import sublime
|
import sublime
|
||||||
import sublime_plugin
|
import sublime_plugin
|
||||||
|
|
||||||
from .lib.markdown2 import Markdown
|
from functools import partial
|
||||||
|
|
||||||
|
from .markdown2html import markdown2html
|
||||||
from .utils import *
|
from .utils import *
|
||||||
|
|
||||||
def plugin_loaded():
|
def plugin_loaded():
|
||||||
@ -85,8 +88,6 @@ class OpenMarkdownPreviewCommand(sublime_plugin.TextCommand):
|
|||||||
|
|
||||||
class MarkdownLivePreviewListener(sublime_plugin.EventListener):
|
class MarkdownLivePreviewListener(sublime_plugin.EventListener):
|
||||||
|
|
||||||
markdowner = Markdown()
|
|
||||||
|
|
||||||
phantom_sets = {
|
phantom_sets = {
|
||||||
# markdown_view.id(): phantom set
|
# markdown_view.id(): phantom set
|
||||||
}
|
}
|
||||||
@ -161,17 +162,23 @@ class MarkdownLivePreviewListener(sublime_plugin.EventListener):
|
|||||||
self._update_preview(markdown_view)
|
self._update_preview(markdown_view)
|
||||||
|
|
||||||
def _update_preview(self, markdown_view):
|
def _update_preview(self, markdown_view):
|
||||||
print('update markdown view', markdown_view.is_loading())
|
# if the buffer id is 0, that means that the markdown_view has been closed
|
||||||
|
# This check is needed since a this function is used as a callback for when images
|
||||||
|
# are loaded from the internet (ie. it could finish loading *after* the user
|
||||||
|
# closes the markdown_view)
|
||||||
|
if markdown_view.buffer_id() == 0:
|
||||||
|
return
|
||||||
|
|
||||||
total_region = sublime.Region(0, markdown_view.size())
|
total_region = sublime.Region(0, markdown_view.size())
|
||||||
markdown = markdown_view.substr(total_region)
|
markdown = markdown_view.substr(total_region)
|
||||||
|
|
||||||
html = self.markdowner.convert(markdown)
|
basepath = os.path.dirname(markdown_view.file_name())
|
||||||
print(html)
|
html = markdown2html(markdown, basepath, partial(self._update_preview,
|
||||||
|
markdown_view))
|
||||||
# FIXME: replace images
|
|
||||||
|
|
||||||
self.phantom_sets[markdown_view.id()].update([
|
self.phantom_sets[markdown_view.id()].update([
|
||||||
sublime.Phantom(sublime.Region(0), html, sublime.LAYOUT_BLOCK,
|
sublime.Phantom(sublime.Region(0), html, sublime.LAYOUT_BLOCK,
|
||||||
lambda href: sublime.run_command('open_url', {'url': href}))
|
lambda href: sublime.run_command('open_url', {'url': href}))
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
7
dependencies.json
Normal file
7
dependencies.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"*": {
|
||||||
|
"*": [
|
||||||
|
"bs4"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
live-testing/sublime_text.png
Normal file
BIN
live-testing/sublime_text.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
20
live-testing/test.md
Normal file
20
live-testing/test.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# hello world
|
||||||
|
|
||||||
|
This is a *test*.
|
||||||
|
|
||||||
|
I'm not sure that it **actually** going to work, but it seems nicer than the [previous version][prev]
|
||||||
|
|
||||||
|
This is the first image from the local file system (absolute path, sorry):
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
This is the first image from the local file system, *relative* path!
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
This is the first image from the internet!
|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
[prev]: https://github.com/math2001/MarkdownLivePreview/tree/d4c477749ce7e77b8e9fc85464a2488f003c45bc
|
||||||
69
markdown2html.py
Normal file
69
markdown2html.py
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import base64
|
||||||
|
import os.path
|
||||||
|
from functools import lru_cache
|
||||||
|
from .lib.markdown2 import Markdown
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
|
__all__ = ('markdown2html', )
|
||||||
|
|
||||||
|
markdowner = Markdown()
|
||||||
|
|
||||||
|
# FIXME: put a nice picture please :^)
|
||||||
|
BASE64_LOADING_IMAGE = 'loading image!'
|
||||||
|
BASE64_404_IMAGE = '404 not found :-('
|
||||||
|
|
||||||
|
class LoadingError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def markdown2html(markdown, basepath, re_render):
|
||||||
|
""" converts the markdown to html, loads the images and puts in base64 for sublime
|
||||||
|
to understand them correctly. That means that we are responsible for loading the
|
||||||
|
images from the internet. Hence, we take in re_render, which is just a function we
|
||||||
|
call when an image has finished loading to retrigger a render (see #90)
|
||||||
|
"""
|
||||||
|
html = markdowner.convert(markdown)
|
||||||
|
|
||||||
|
soup = BeautifulSoup(html, "html.parser")
|
||||||
|
for img_element in soup.find_all('img'):
|
||||||
|
src = img_element['src']
|
||||||
|
# already in base64, or something of the like
|
||||||
|
# FIXME: what other types are possible? Are they handled by ST? If not, could we
|
||||||
|
# convert it into base64? is it worth the effort?
|
||||||
|
if src.startswith('data:image/'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if src.startswith('http://') or src.startswith('https://'):
|
||||||
|
path = src
|
||||||
|
elif src.startswith('file://'):
|
||||||
|
path = src[len('file://'):]
|
||||||
|
else:
|
||||||
|
# expanduser: ~ -> /home/math2001
|
||||||
|
# realpath: simplify that paths so that we don't have duplicated caches
|
||||||
|
path = os.path.realpath(os.path.expanduser(os.path.join(basepath, src)))
|
||||||
|
|
||||||
|
try:
|
||||||
|
base64 = get_base64_image(path)
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
print("{!r} not found {!r}".format(path, e))
|
||||||
|
base64 = BASE64_404_IMAGE
|
||||||
|
except LoadingError:
|
||||||
|
# the image is loading
|
||||||
|
base64 = BASE64_LOADING_IMAGE
|
||||||
|
|
||||||
|
img_element['src'] = base64
|
||||||
|
|
||||||
|
# FIXME: how do tables look? should we use ascii tables?
|
||||||
|
|
||||||
|
return str(soup)
|
||||||
|
|
||||||
|
# FIXME: This is an in memory cache. 20 seems like a fair bit of images... Should it be
|
||||||
|
# bigger? Should the user be allowed to chose? There definitely should be a limit
|
||||||
|
# because we don't wanna use to much memory, we're a simple markdown preview plugin
|
||||||
|
@lru_cache(maxsize=20)
|
||||||
|
def get_base64_image(path):
|
||||||
|
if path.startswith('http://') or path.startswith('https://'):
|
||||||
|
return 'loading of the internet!'
|
||||||
|
|
||||||
|
with open(path, 'rb') as fp:
|
||||||
|
return 'data:image/png;base64,' + base64.b64encode(fp.read()).decode('utf-8')
|
||||||
|
|
||||||
Reference in New Issue
Block a user