preview markdown working
This commit is contained in:
59
MLPApi.py
59
MLPApi.py
@ -3,9 +3,20 @@
|
|||||||
import sublime
|
import sublime
|
||||||
import sublime_plugin
|
import sublime_plugin
|
||||||
|
|
||||||
|
import os.path
|
||||||
|
from html.parser import HTMLParser
|
||||||
|
|
||||||
|
from .lib import markdown2
|
||||||
|
from .escape_amp import *
|
||||||
from .functions import *
|
from .functions import *
|
||||||
from .setting_names import *
|
from .setting_names import *
|
||||||
|
|
||||||
|
__folder__ = os.path.dirname(__file__)
|
||||||
|
|
||||||
|
STYLE_FILE = os.path.join(os.path.dirname(__folder__), 'User',
|
||||||
|
'MarkdownLivePreview.css')
|
||||||
|
DEFAULT_STYLE_FILE = os.path.join(__folder__, 'default.css')
|
||||||
|
|
||||||
def get_preview_name(md_view):
|
def get_preview_name(md_view):
|
||||||
name = md_view.name() \
|
name = md_view.name() \
|
||||||
or os.path.basename(md_view.file_name()) \
|
or os.path.basename(md_view.file_name()) \
|
||||||
@ -40,3 +51,51 @@ def hide_preview(md_view):
|
|||||||
psettings = preview.settings()
|
psettings = preview.settings()
|
||||||
psettings.set(IS_HIDDEN, True)
|
psettings.set(IS_HIDDEN, True)
|
||||||
sublime.set_timeout(preview.close(), 250)
|
sublime.set_timeout(preview.close(), 250)
|
||||||
|
|
||||||
|
def get_style():
|
||||||
|
if os.path.exists(STYLE_FILE):
|
||||||
|
with open(STYLE_FILE) as fp:
|
||||||
|
return fp.read()
|
||||||
|
|
||||||
|
with open(DEFAULT_STYLE_FILE) as fp:
|
||||||
|
content = fp.read()
|
||||||
|
content = ''.join([line.strip() for line in content.splitlines()])
|
||||||
|
return content + "pre code .space {color: var(--light-bg)}"
|
||||||
|
|
||||||
|
def show_html(md_view, preview):
|
||||||
|
html = '<style>{}</style>\n{}'.format(get_style(),
|
||||||
|
pre_with_br(markdown2.markdown(get_view_content(md_view),
|
||||||
|
extras=['fenced-code-blocks',
|
||||||
|
'no-code-highlighting'])))
|
||||||
|
|
||||||
|
# the option no-code-highlighting does not exists
|
||||||
|
# in the official version of markdown2 for now
|
||||||
|
# I personaly edited the file (markdown2.py:1743)
|
||||||
|
|
||||||
|
html = html.replace(' ', ' espace;') # save where are the spaces
|
||||||
|
|
||||||
|
html = HTMLParser().unescape(html)
|
||||||
|
|
||||||
|
html = escape_amp(html)
|
||||||
|
|
||||||
|
# exception, again, because <pre> aren't supported by the phantoms
|
||||||
|
html = html.replace(' espace;', '<i class="space">.</i>')
|
||||||
|
html = replace_img_src_base64(html)
|
||||||
|
preview.erase_phantoms('markdown_preview')
|
||||||
|
preview.add_phantom('markdown_preview',
|
||||||
|
sublime.Region(-1),
|
||||||
|
html,
|
||||||
|
sublime.LAYOUT_BLOCK,
|
||||||
|
lambda href: sublime.run_command('open_url',
|
||||||
|
{'url': href}))
|
||||||
|
|
||||||
|
# set viewport position
|
||||||
|
|
||||||
|
# 0 < y < 1
|
||||||
|
y = md_view.text_to_layout(md_view.sel()[0].begin())[1] / md_view.layout_extent()[1]
|
||||||
|
vector = [0, y * preview.layout_extent()[1]]
|
||||||
|
# remove half of the viewport_extent.y to center it on the screen (verticaly)
|
||||||
|
vector[1] -= preview.viewport_extent()[1] / 2
|
||||||
|
vector[1] = mini(vector[1], 0)
|
||||||
|
vector[1] += preview.line_height()
|
||||||
|
preview.set_viewport_position(vector, animate=False)
|
||||||
|
|||||||
@ -27,12 +27,17 @@ class MarkdownLivePreviewListener(sublime_plugin.EventListener):
|
|||||||
md_view_settings = md_view.settings()
|
md_view_settings = md_view.settings()
|
||||||
if md_view_settings.get(PREVIEW_ENABLED) is not True:
|
if md_view_settings.get(PREVIEW_ENABLED) is not True:
|
||||||
return
|
return
|
||||||
|
id = md_view_settings.get(PREVIEW_ID)
|
||||||
if not md_view_settings.get(PREVIEW_ID):
|
if not id:
|
||||||
MarkdownLivePreviewListener.md_view = md_view
|
MarkdownLivePreviewListener.md_view = md_view
|
||||||
create_preview(md_view)
|
create_preview(md_view)
|
||||||
MarkdownLivePreviewListener.has_preview = True
|
MarkdownLivePreviewListener.has_preview = True
|
||||||
window.focus_view(md_view)
|
window.focus_view(md_view)
|
||||||
|
else:
|
||||||
|
preview = get_view_from_id(window, id)
|
||||||
|
if preview is None:
|
||||||
|
raise ValueError('Getting preview from id: got None')
|
||||||
|
show_html(md_view, preview)
|
||||||
|
|
||||||
def on_pre_close(self, view):
|
def on_pre_close(self, view):
|
||||||
vsettings = view.settings()
|
vsettings = view.settings()
|
||||||
|
|||||||
43
default.css
Normal file
43
default.css
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
:root, html, body {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
html {
|
||||||
|
--light-bg: color(var(--background) blend(#999 85%))
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
padding:10px;
|
||||||
|
padding-top: 0px;
|
||||||
|
font-family: "Open Sans", sans-serif;
|
||||||
|
background-color: var(--background);
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
font-style: italic;
|
||||||
|
display: block;
|
||||||
|
margin-left: 30px;
|
||||||
|
border: 1px solid red;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
padding-left: 0.2rem;
|
||||||
|
padding-right: 0.2rem;
|
||||||
|
background-color: var(--light-bg);
|
||||||
|
margin: 0;
|
||||||
|
border-radius: 3px;
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
display: block;
|
||||||
|
margin-top: 20px;
|
||||||
|
line-height: 1.7;
|
||||||
|
background-color: var(--light-bg);
|
||||||
|
padding-left: 10px;
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
pre code {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
@ -7,6 +7,7 @@ import os.path
|
|||||||
class MLPDevListener(sublime_plugin.EventListener):
|
class MLPDevListener(sublime_plugin.EventListener):
|
||||||
|
|
||||||
def on_post_save(self, view):
|
def on_post_save(self, view):
|
||||||
|
return
|
||||||
if not (os.path.dirname(__file__) in view.file_name() and
|
if not (os.path.dirname(__file__) in view.file_name() and
|
||||||
view.file_name().endswith('.py')):
|
view.file_name().endswith('.py')):
|
||||||
return
|
return
|
||||||
|
|||||||
42
functions.py
42
functions.py
@ -2,9 +2,36 @@
|
|||||||
import base64
|
import base64
|
||||||
import os.path
|
import os.path
|
||||||
import sublime
|
import sublime
|
||||||
|
import re
|
||||||
|
from .image_manager import ImageManager
|
||||||
|
|
||||||
file404 = os.path.join(os.path.dirname(__file__), '404.png')
|
file404 = os.path.join(os.path.dirname(__file__), '404.png')
|
||||||
|
|
||||||
|
|
||||||
|
def replace_img_src_base64(html):
|
||||||
|
"""Really messy, but it works (should be updated)"""
|
||||||
|
index = -1
|
||||||
|
tag_start = '<img src="'
|
||||||
|
shtml, html = html, list(html)
|
||||||
|
while True:
|
||||||
|
index = shtml.find(tag_start, index + 1)
|
||||||
|
if index == -1:
|
||||||
|
break
|
||||||
|
path, end = get_content_till(html, '"', start=index + len(tag_start))
|
||||||
|
if ''.join(path).startswith('data:image/'):
|
||||||
|
continue
|
||||||
|
if ''.join(path).startswith(tuple(get_settings().get('load_from_internet'
|
||||||
|
'_when_starts'))):
|
||||||
|
image = ImageManager.get(''.join(path))
|
||||||
|
image = image or to_base64('loading.png')
|
||||||
|
|
||||||
|
else:
|
||||||
|
# local image
|
||||||
|
image = to_base64(''.join(path))
|
||||||
|
html[index+len(tag_start):end] = image
|
||||||
|
shtml = ''.join(html)
|
||||||
|
return ''.join(html)
|
||||||
|
|
||||||
def is_markdown_view(view):
|
def is_markdown_view(view):
|
||||||
return 'markdown' in view.scope_name(0)
|
return 'markdown' in view.scope_name(0)
|
||||||
|
|
||||||
@ -51,3 +78,18 @@ def get_view_from_id(window, id):
|
|||||||
|
|
||||||
def get_settings():
|
def get_settings():
|
||||||
return sublime.load_settings('MarkdownLivePreview.sublime-settings')
|
return sublime.load_settings('MarkdownLivePreview.sublime-settings')
|
||||||
|
|
||||||
|
def pre_with_br(html):
|
||||||
|
"""Because the phantoms of sublime text does not support <pre> blocks
|
||||||
|
this function replaces every \n with a <br> in a <pre>"""
|
||||||
|
|
||||||
|
while True:
|
||||||
|
obj = re.search(r'<pre>(.*?)</pre>', html, re.DOTALL)
|
||||||
|
if not obj:
|
||||||
|
break
|
||||||
|
html = list(html)
|
||||||
|
html[obj.start(0):obj.end(0)] = '<pre >' + ''.join(html[obj.start(1):obj.end(1)]) \
|
||||||
|
.replace('\n', '<br>') \
|
||||||
|
.replace(' ', ' ') + '</pre>'
|
||||||
|
html = ''.join(html)
|
||||||
|
return html
|
||||||
|
|||||||
Reference in New Issue
Block a user