From bae26fc45277f9bbdb363b0e17bcaf6836896c11 Mon Sep 17 00:00:00 2001 From: Mathieu PATUREL Date: Thu, 14 Nov 2019 17:28:02 +1100 Subject: [PATCH] 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 --- MarkdownLivePreview.py | 23 ++++++++---- dependencies.json | 7 ++++ live-testing/sublime_text.png | Bin 0 -> 38950 bytes live-testing/test.md | 20 ++++++++++ markdown2html.py | 69 ++++++++++++++++++++++++++++++++++ test.md | 8 ---- 6 files changed, 111 insertions(+), 16 deletions(-) create mode 100644 dependencies.json create mode 100644 live-testing/sublime_text.png create mode 100644 live-testing/test.md create mode 100644 markdown2html.py delete mode 100644 test.md diff --git a/MarkdownLivePreview.py b/MarkdownLivePreview.py index 6b10aa2..3f5ae64 100644 --- a/MarkdownLivePreview.py +++ b/MarkdownLivePreview.py @@ -1,7 +1,10 @@ +import os.path import sublime import sublime_plugin -from .lib.markdown2 import Markdown +from functools import partial + +from .markdown2html import markdown2html from .utils import * def plugin_loaded(): @@ -85,8 +88,6 @@ class OpenMarkdownPreviewCommand(sublime_plugin.TextCommand): class MarkdownLivePreviewListener(sublime_plugin.EventListener): - markdowner = Markdown() - phantom_sets = { # markdown_view.id(): phantom set } @@ -161,17 +162,23 @@ class MarkdownLivePreviewListener(sublime_plugin.EventListener): self._update_preview(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()) markdown = markdown_view.substr(total_region) - html = self.markdowner.convert(markdown) - print(html) - - # FIXME: replace images + basepath = os.path.dirname(markdown_view.file_name()) + html = markdown2html(markdown, basepath, partial(self._update_preview, + markdown_view)) self.phantom_sets[markdown_view.id()].update([ sublime.Phantom(sublime.Region(0), html, sublime.LAYOUT_BLOCK, lambda href: sublime.run_command('open_url', {'url': href})) ]) + \ No newline at end of file diff --git a/dependencies.json b/dependencies.json new file mode 100644 index 0000000..d0b3031 --- /dev/null +++ b/dependencies.json @@ -0,0 +1,7 @@ +{ + "*": { + "*": [ + "bs4" + ] + } +} diff --git a/live-testing/sublime_text.png b/live-testing/sublime_text.png new file mode 100644 index 0000000000000000000000000000000000000000..8be1c1f54bb1cc00a66d363c395576862de35851 GIT binary patch literal 38950 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

c&4>L8(g*C0w9g6zf;Wv3zwDlA(0 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 /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') + diff --git a/test.md b/test.md deleted file mode 100644 index 59ff640..0000000 --- a/test.md +++ /dev/null @@ -1,8 +0,0 @@ -# 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] - - -[prev]: https://github.com/math2001/MarkdownLivePreview/tree/d4c477749ce7e77b8e9fc85464a2488f003c45bc \ No newline at end of file