diff --git a/.gitignore b/.gitignore index 668cce1..4c99b5d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ Thumbs.db __pycache__/ +cache.txt diff --git a/image_manager.py b/image_manager.py new file mode 100644 index 0000000..72e38e0 --- /dev/null +++ b/image_manager.py @@ -0,0 +1,83 @@ +# -*- encoding: utf-8 -*- + +import os.path +from threading import Thread +import urllib.request +import base64 +import sublime + +CACHE_FILE = os.path.join(os.path.dirname(__file__), 'cache.txt') +TIMEOUT = 20 + +SEPARATOR = '---%cache%--' + +class InternalError(Exception): pass + +def to_base64(path=None, content=None): + if content is None and path is not None: + try: + with open(path, 'rb') as fp: + content = fp.read() + except FileNotFoundError: + return to_base64(os.path.join(os.path.dirname(__file__), '404.png')) + + return 'data:image/png;base64,' + ''.join([chr(el) for el in list(base64.standard_b64encode(content))]) + +def load_and_save_image(url, user_callback): + def callback(content): + content = to_base64(content=content) + with open(CACHE_FILE, 'a') as fp: + fp.write(url + SEPARATOR + content) + user_callback(content) + thread = ImageLoader(url, callback) + thread.start() + sublime.set_timeout_async(lambda: thread.join(), TIMEOUT) + +class ImageLoader(Thread): + + def __init__(self, url, callback): + Thread.__init__(self) + self.url = url + self.callback = callback + + def run(self): + page = urllib.request.urlopen(self.url, None, TIMEOUT) + self.callback(page.read()) + + +class ImageManager(object): + + currently_loading = [] + + @staticmethod + def get(imageurl, user_callback): + if imageurl in ImageManager.currently_loading: + return None + def callback(content): + try: + ImageManager.currently_loading.remove(imageurl) + except ValueError: + sublime.error_message('Internal error: Trying to remove an URL' + 'from loading_url, but not found. Please' + 'report to the issue tracker.') + sublime.run_command('open_url', { + 'url': 'https://github.com/math2001/MarkdownLivePreview/' + 'issues/new' + }) + + user_callback(content) + + ImageManager.currently_loading.append(imageurl) + try: + with open(CACHE_FILE, 'r') as fp: + lines = fp.readlines() + except FileNotFoundError: + pass + else: + for line in lines: + url, base64 = line.split(SEPARATOR, 1) + if url == imageurl: + return callback(base64) + else: + print(url + '\n' + imageurl) + load_and_save_image(imageurl, callback) diff --git a/md_in_popup.py b/md_in_popup.py index f1ea835..1ff429a 100644 --- a/md_in_popup.py +++ b/md_in_popup.py @@ -6,6 +6,8 @@ import os.path import re import base64 +from .image_manager import ImageManager + from .escape_amp import * from html.parser import HTMLParser @@ -39,7 +41,7 @@ def to_base64(path): with open(path, 'rb') as fp: content = fp.read() - return base64.standard_b64encode(content) + return 'data:image/png;base64,' + ''.join([chr(el) for el in list(base64.standard_b64encode(content))]) def replace_img_src_base64(html): """Really messy, but it works (should be updated)""" @@ -57,7 +59,7 @@ def replace_img_src_base64(html): if index == -1: return ''.join(html) path, end = get_content_till(html, '"', start=index + len(tag_start)) - html[index+len(tag_start):end] = 'data:image/png;base64,' + ''.join([chr(el) for el in list(to_base64(''.join(path)))]) + html[index+len(tag_start):end] = to_base64(''.join(path)) return ''.join(html) @@ -246,3 +248,22 @@ class MarkdownInPopupCommand(sublime_plugin.EventListener): md_view_settings.erase('markdown_preview_enabled') md_view_settings.erase('markdown_preview_id') sublime.set_timeout_async(callback, 250) + +class LoadImageCommand(sublime_plugin.ApplicationCommand): + + def run(self): + ImageManager.get('https://images.duckduckgo.com/iu/?u=http%3A%2F%2Fi82.photobucket.com%2Falbums%2Fj261%2FOrestesElVerdadero%2Favatar-fenix-100.jpg&f=1', + lambda content: print('got content', len(content))) + +class MLPDevListener(sublime_plugin.EventListener): + + def on_post_save(self, view): + if not (os.path.dirname(__file__) in view.file_name() and + view.file_name().endswith('.py')): + return + sublime.run_command('reload_plugin', { + 'main': os.path.join(sublime.packages_path(), 'MarkdownLivePreview', + 'md_in_popup.py'), + 'scripts': ['image_manager'], + 'quiet': True + })