Compare commits
68 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 119acbb092 | |||
| 7c4354fb2e | |||
| b93aea6698 | |||
| b3fb5779d3 | |||
| 7bdda5f5c7 | |||
| 7257cb467e | |||
| 40a563fb1e | |||
| 3e0d6ad265 | |||
| f65a068b4e | |||
| bc328642e7 | |||
| d2053be41e | |||
| eb48b1c79f | |||
| 8317fa738c | |||
| 3be12b0539 | |||
| c92d78fb20 | |||
| 30d75f159d | |||
| 52e4b917e5 | |||
| 48a68b2a79 | |||
| 8eb0172eb4 | |||
| 52e35fb610 | |||
| 84f809e57f | |||
| 351e8bd355 | |||
| 5babc862b4 | |||
| dc7139fbe7 | |||
| bbbeae6fe9 | |||
| 271c7c619a | |||
| 8cc6b2b263 | |||
| c7961ce94c | |||
| eae91fa428 | |||
| 6f18e8e4a2 | |||
| 48c1800065 | |||
| bad1cb74c6 | |||
| 4198504fd1 | |||
| 1bef00de14 | |||
| d707cf7a47 | |||
| c27cd5f210 | |||
| 41bbc3d03d | |||
| 1e651bebc6 | |||
| ea309f2323 | |||
| 3306d6ad5e | |||
| 0505ca30bc | |||
| c49ae26720 | |||
| c2618ead1d | |||
| 6e113fef6e | |||
| e5378e2300 | |||
| caf932b536 | |||
| fa106c8206 | |||
| 0ac9fd9aaa | |||
| 5bbfb4606d | |||
| 37703e9bab | |||
| 3b920f4336 | |||
| abe151fdb7 | |||
| acc8beb3be | |||
| 9206b6de62 | |||
| cda4532833 | |||
| ff8c94bda5 | |||
| ded9c28096 | |||
| 0e6660a331 | |||
| 0143428114 | |||
| f48ef63956 | |||
| a4e670de43 | |||
| d466a29cd4 | |||
| 0f0e53ff34 | |||
| 30ac30082f | |||
| e4e7c44c3c | |||
| 75a8cf53f9 | |||
| 3dcaed0ede | |||
| c605ffb3db |
2
.gitignore
vendored
@ -1,3 +1,5 @@
|
||||
Thumbs.db
|
||||
__pycache__/
|
||||
cache.txt
|
||||
venv/
|
||||
site/
|
||||
|
||||
@ -1,10 +1,7 @@
|
||||
[
|
||||
{
|
||||
"keys": ["alt+m"],
|
||||
"command": "toggle_setting",
|
||||
"args": {
|
||||
"setting": "markdown_live_preview_enabled"
|
||||
},
|
||||
"command": "new_markdown_live_preview",
|
||||
"context": [
|
||||
{
|
||||
"key": "selector",
|
||||
|
||||
@ -7,11 +7,24 @@
|
||||
"children": [
|
||||
{
|
||||
"caption": "MarkdownLivePreview",
|
||||
"command": "open_file",
|
||||
"args": {
|
||||
"file": "$packages/User/MarkdownLivePreview.css",
|
||||
"contents": "/* See http://www.sublimetext.com/docs/3/minihtml.html#css to know which property you're able to use */\n\n$0"
|
||||
}
|
||||
"children": [
|
||||
{
|
||||
"caption": "Settings",
|
||||
"command": "edit_settings",
|
||||
"args": {
|
||||
"base_file": "$packages/MarkdownLivePreview/.sublime/MarkdownLivePreview.sublime-settings",
|
||||
"default": "// Your settings for MarkdownLivePreview. See the default file to see the different options. \n{\n\t\n}\n"
|
||||
}
|
||||
},
|
||||
{
|
||||
"caption": "Style - CSS",
|
||||
"command": "open_file",
|
||||
"args": {
|
||||
"file": "$packages/User/MarkdownLivePreview.css",
|
||||
"contents": "/* See http://www.sublimetext.com/docs/3/minihtml.html#css to know which property you're able to use */\n\n$0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -1,9 +1,25 @@
|
||||
[
|
||||
{
|
||||
"caption": "MarkdownLivePreview: Toggle",
|
||||
"command": "toggle_setting",
|
||||
"caption": "MarkdownLivePreview: Edit Current File",
|
||||
"command": "new_markdown_live_preview"
|
||||
},
|
||||
{
|
||||
"caption": "MarkdownLivePreview: Clear the cache",
|
||||
"command": "markdown_live_preview_clear_cache"
|
||||
},
|
||||
{
|
||||
"caption": "MarkdownLivePreview: Edit Custom CSS File",
|
||||
"command": "open_file",
|
||||
"args": {
|
||||
"setting": "markdown_live_preview_enabled"
|
||||
"file": "$packages/User/MarkdownLivePreview.css"
|
||||
}
|
||||
},
|
||||
{
|
||||
"caption": "Preferences: MarkdownLivePreview Settings",
|
||||
"command": "edit_settings",
|
||||
"args": {
|
||||
"base_file": "${packages}/MarkdownLivePreview/.sublime/MarkdownLivePreview.sublime-settings",
|
||||
"default": "// Your settings for MarkdownLivePreview. See the default file to see the different options. \n{\n\t$0\n}\n"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -1,3 +1,16 @@
|
||||
{
|
||||
"load_from_internet_when_starts": ["http://", "https://"]
|
||||
// As soon as you open a markdown file, it opens the window preview
|
||||
"markdown_live_preview_on_open": false,
|
||||
|
||||
// If an image starts with one of those strings, then it will be loaded from internet
|
||||
"load_from_internet_when_starts": ["http://", "https://"],
|
||||
|
||||
// When the preview is opened, the markdown file is closed in the origin window and reopend in
|
||||
// the preview window. If this option is set to 'true', then the markdown file will NOT be
|
||||
// closed in the origin window
|
||||
"keep_open_when_opening_preview": false,
|
||||
|
||||
// Choose what to do with YAML/TOML (---/+++ respectively) headers
|
||||
// Valid values: "wrap_in_pre", "remove".
|
||||
"header_action": "wrap_in_pre"
|
||||
}
|
||||
|
||||
14
.sublime/MarkdownLivePreviewSyntax.hidden-tmLanguage
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>MarkdownLivePreviewSyntax</string>
|
||||
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
</array>
|
||||
<key>scopeName</key>
|
||||
<string>text.markdown-live-preview</string>
|
||||
</dict>
|
||||
</plist>
|
||||
7
LICENSE
Normal file
@ -0,0 +1,7 @@
|
||||
Copyright 2017 Mathieu PATUREL
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
169
MLPApi.py
@ -6,139 +6,102 @@ import sublime_plugin
|
||||
import os.path
|
||||
from html.parser import HTMLParser
|
||||
|
||||
from .lib import markdown2
|
||||
from .lib import markdown2 as md2
|
||||
from .lib.pre_tables import pre_tables
|
||||
|
||||
from .escape_amp import *
|
||||
from .functions import *
|
||||
from .setting_names import *
|
||||
from .image_manager import CACHE_FILE
|
||||
from random import randint as rnd
|
||||
|
||||
__folder__ = os.path.dirname(__file__)
|
||||
|
||||
STYLE_FILE = os.path.join(os.path.dirname(__folder__), 'User',
|
||||
'MarkdownLivePreview.css')
|
||||
|
||||
# used to store the phantom's set
|
||||
windows_phantom_set = {}
|
||||
|
||||
|
||||
def plugin_loaded():
|
||||
global DEFAULT_STYLE_FILE
|
||||
DEFAULT_STYLE_FILE = sublime.load_resource('Packages/MarkdownLivePreview/'
|
||||
'default.css')
|
||||
|
||||
def get_preview_name(md_view):
|
||||
name = md_view.name() \
|
||||
or os.path.basename(md_view.file_name()) \
|
||||
or 'Untitled'
|
||||
return name + ' - Preview'
|
||||
|
||||
def find_preview(window):
|
||||
for view in window.views():
|
||||
vsettings = view.settings()
|
||||
if vsettings.get(IS_PREVIEW):
|
||||
yield view, vsettings
|
||||
|
||||
def create_preview(md_view):
|
||||
window = md_view.window()
|
||||
md_view_settings = md_view.settings()
|
||||
md_view_settings.set(JUST_CREATED, True)
|
||||
|
||||
def create_preview(window, file_name):
|
||||
preview = window.new_file()
|
||||
|
||||
psettings = preview.settings()
|
||||
psettings.set(IS_PREVIEW, True)
|
||||
psettings.set(MD_VIEW_ID, md_view.id())
|
||||
preview.set_name(get_preview_name(md_view))
|
||||
preview.set_name(get_preview_name(file_name))
|
||||
preview.set_scratch(True)
|
||||
md_view_settings.set(PREVIEW_ID, preview.id())
|
||||
def move_and_focus_md_view():
|
||||
window.run_command('new_pane')
|
||||
sublime.set_timeout_async(lambda: window.focus_view(md_view), 250)
|
||||
sublime.set_timeout_async(move_and_focus_md_view, 250)
|
||||
preview.set_syntax_file('Packages/MarkdownLivePreview/.sublime/' + \
|
||||
'MarkdownLivePreviewSyntax.hidden-tmLanguage')
|
||||
|
||||
return preview
|
||||
|
||||
def hide_preview(view):
|
||||
window = view.window()
|
||||
vsettings = view.settings()
|
||||
if vsettings.get(IS_PREVIEW):
|
||||
preview = view
|
||||
psettings = vsettings
|
||||
md_view_id = vsettings.get(MD_VIEW_ID)
|
||||
md_view = get_view_from_id(window, md_view_id)
|
||||
if md_view is None:
|
||||
raise ValueError('Tried to get md_view from id {} but got None'.format(md_view_id))
|
||||
mdvsettings = md_view.settings()
|
||||
def markdown2html(md, basepath, color_scheme):
|
||||
|
||||
elif vsettings.get(PREVIEW_ENABLED):
|
||||
md_view = view
|
||||
preview_id = vsettings.get(PREVIEW_ID)
|
||||
preview = get_view_from_id(window, preview_id)
|
||||
mdvsettings = vsettings
|
||||
if preview is None:
|
||||
raise ValueError('Tried to get preview from id {} but got None'.format(preview_id))
|
||||
psettings = preview.settings()
|
||||
else:
|
||||
raise ValueError('Call hide_preview with a view which is not the preview or the md_view')
|
||||
psettings.set(IS_HIDDEN, True)
|
||||
mdvsettings.erase(PREVIEW_ID)
|
||||
sublime.set_timeout(lambda: preview.close(), 250)
|
||||
return
|
||||
# removes/format the YAML/TOML header.
|
||||
md = manage_header(md, get_settings().get('header_action'))
|
||||
|
||||
html = '<style>\n{}\n</style>\n'.format(get_style(color_scheme))
|
||||
|
||||
|
||||
|
||||
window = md_view.window()
|
||||
if window is None:
|
||||
return
|
||||
mdvsettings = md_view.settings()
|
||||
preview_id = mdvsettings.get(PREVIEW_ID)
|
||||
if not preview_id:
|
||||
return
|
||||
mdvsettings.erase(PREVIEW_ID)
|
||||
preview = get_view_from_id(window, preview_id)
|
||||
if preview is None:
|
||||
raise ValueError('Tried to get view from id {} but got None'.format(preview_id))
|
||||
psettings = preview.settings()
|
||||
psettings.set(IS_HIDDEN, True)
|
||||
sublime.set_timeout(preview.close(), 250)
|
||||
|
||||
def get_style():
|
||||
content = ''.join([line.strip() for line in DEFAULT_STYLE_FILE.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
|
||||
# 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 += md2.markdown(md, extras=['fenced-code-blocks', 'tables'])
|
||||
|
||||
html = html.replace(' ', ' espace;') # save where are the spaces
|
||||
# tables aren't supported by the Phantoms
|
||||
# This function transforms them into aligned ASCII tables and displays them in a <pre> block
|
||||
# (the ironic thing is that they aren't supported either :D)
|
||||
html = pre_tables(html)
|
||||
|
||||
html = HTMLParser().unescape(html)
|
||||
# pre block are not supported by the Phantoms.
|
||||
# This functions replaces the \n in them with <br> so that it does (1/2)
|
||||
html = pre_with_br(html)
|
||||
|
||||
html = escape_amp(html)
|
||||
# comments aren't supported by the Phantoms
|
||||
# Simply removes them using bs4, so you can be sadic and type `<!-- hey hey! -->`, these one
|
||||
# won't be stripped!
|
||||
html = strip_html_comments(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}))
|
||||
# so, because this is monosaped font, I just replace it with a '.' and make transparent ;)
|
||||
html = html.replace(' ', '<i class="space">.</i>')
|
||||
|
||||
# set viewport position
|
||||
# Phantoms have problem with images size when they're loaded from an url/path
|
||||
# So, the solution is to convert them to base64
|
||||
html = replace_img_src_base64(html, basepath=basepath)
|
||||
|
||||
# sublime.set_clipboard(html)
|
||||
# BeautifulSoup uses the <br/> but the sublime phantoms do not support them...
|
||||
html = html.replace('<br/>', '<br />').replace('<hr/>', '<hr />')
|
||||
|
||||
return
|
||||
return html
|
||||
|
||||
def show_html(md_view, preview):
|
||||
global windows_phantom_set
|
||||
html = markdown2html(get_view_content(md_view), os.path.dirname(md_view.file_name()),
|
||||
os.path.join(sublime.packages_path(), '..', md_view.settings().get('color_scheme')))
|
||||
|
||||
phantom_set = windows_phantom_set.setdefault(preview.window().id(),
|
||||
sublime.PhantomSet(preview, 'markdown_live_preview'))
|
||||
phantom_set.update([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})
|
||||
# get the "ratio" of the markdown view's position.
|
||||
# 0 < y < 1
|
||||
y = md_view.text_to_layout(md_view.sel()[0].begin())[1] / md_view.layout_extent()[1]
|
||||
# set the vector (position) for the preview
|
||||
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)
|
||||
# make sure the minimum is 0
|
||||
vector[1] = 0 if vector[1] < 0 else vector[1]
|
||||
# the hide the first line
|
||||
vector[1] += preview.line_height()
|
||||
preview.set_viewport_position(vector, animate=False)
|
||||
|
||||
def clear_cache():
|
||||
"""Removes the cache file"""
|
||||
os.remove(CACHE_FILE)
|
||||
|
||||
def release_phantoms_set(view_id=None):
|
||||
global windows_phantom_set
|
||||
if view_id is None:
|
||||
windows_phantom_set = {}
|
||||
else:
|
||||
del windows_phantom_set[view_id]
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
import os.path
|
||||
import sublime
|
||||
import sublime_plugin
|
||||
|
||||
@ -9,43 +7,109 @@ from .MLPApi import *
|
||||
from .setting_names import *
|
||||
from .functions import *
|
||||
|
||||
class NewMarkdownLivePreviewCommand(sublime_plugin.ApplicationCommand):
|
||||
|
||||
def run(self):
|
||||
|
||||
"""Inspired by the edit_settings command"""
|
||||
|
||||
current_view = sublime.active_window().active_view()
|
||||
file_name = current_view.file_name()
|
||||
if get_settings().get('keep_open_when_opening_preview') is False:
|
||||
current_view.close()
|
||||
if file_name is None:
|
||||
return sublime.error_message('MarkdownLivePreview: Not supporting '
|
||||
'unsaved file for now')
|
||||
|
||||
sublime.run_command('new_window')
|
||||
self.window = sublime.active_window()
|
||||
self.window.settings().set(PREVIEW_WINDOW, True)
|
||||
self.window.run_command('set_layout', {
|
||||
'cols': [0.0, 0.5, 1.0],
|
||||
'rows': [0.0, 1.0],
|
||||
'cells': [[0, 0, 1, 1], [1, 0, 2, 1]]
|
||||
})
|
||||
self.window.focus_group(1)
|
||||
preview = create_preview(self.window, current_view)
|
||||
|
||||
self.window.focus_group(0)
|
||||
md_view = self.window.open_file(file_name)
|
||||
mdsettings = md_view.settings()
|
||||
|
||||
mdsettings.set(PREVIEW_ENABLED, True)
|
||||
mdsettings.set(PREVIEW_ID, preview.id())
|
||||
|
||||
def is_enabled(self):
|
||||
return is_markdown_view(sublime.active_window().active_view())
|
||||
|
||||
class MarkdownLivePreviewListener(sublime_plugin.EventListener):
|
||||
|
||||
def update(self, view):
|
||||
vsettings = view.settings()
|
||||
if not vsettings.get(PREVIEW_ENABLED):
|
||||
return
|
||||
id = vsettings.get(PREVIEW_ID)
|
||||
if id is None:
|
||||
raise ValueError('The preview id is None')
|
||||
preview = get_view_from_id(view.window(), id)
|
||||
if preview is None:
|
||||
raise ValueError('The preview is None (id: {})'.format(id))
|
||||
|
||||
show_html(view, preview)
|
||||
return view, preview
|
||||
|
||||
def on_modified(self, view):
|
||||
window = view.window()
|
||||
if not is_markdown_view(view): # faster than getting the settings
|
||||
return
|
||||
self.update(view)
|
||||
|
||||
def on_window_command(self, window, command, args):
|
||||
if command == 'close' and window.settings().get(PREVIEW_WINDOW):
|
||||
release_phantoms_set(window.id())
|
||||
return 'close_window', {}
|
||||
|
||||
def on_activated_async(self, view):
|
||||
vsettings = view.settings()
|
||||
if vsettings.get(PREVIEW_ENABLED):
|
||||
id = vsettings.get(PREVIEW_ID)
|
||||
preview = get_view_from_id(window, id)
|
||||
if id is None or preview is None:
|
||||
preview = create_preview(view)
|
||||
sublime.set_timeout_async(lambda: show_html(view, preview), 1000)
|
||||
else:
|
||||
show_html(view, preview)
|
||||
|
||||
return
|
||||
if (is_markdown_view(view) and get_settings().get(ON_OPEN)
|
||||
and not vsettings.get(PREVIEW_ENABLED)
|
||||
and vsettings.get('syntax') != 'Packages/MarkdownLivePreview/' + \
|
||||
'.sublime/MarkdownLivePreviewSyntax' + \
|
||||
'.hidden-tmLanguage'
|
||||
and not any(filter(lambda window: window.settings().get(PREVIEW_WINDOW) is True,
|
||||
sublime.windows()))):
|
||||
# print("MarkdownLivePreview.py:81", 'open window')
|
||||
sublime.run_command('new_markdown_live_preview')
|
||||
|
||||
def on_activated(self, view):
|
||||
# if view is md_view and has no preview
|
||||
# -> create preview
|
||||
window = view.window()
|
||||
vsettings = view.settings()
|
||||
if vsettings.get(PREVIEW_ENABLED):
|
||||
id = vsettings.get(PREVIEW_ID)
|
||||
preview = get_view_from_id(window, id)
|
||||
if id is None or preview is None:
|
||||
preview = create_preview(view)
|
||||
sublime.set_timeout(lambda: show_html(view, preview), 1000)
|
||||
else:
|
||||
show_html(view, preview)
|
||||
return
|
||||
|
||||
# if view is preview
|
||||
# -> do nothing
|
||||
if vsettings.get(IS_PREVIEW):
|
||||
def on_load_async(self, view):
|
||||
"""Check the settings to hide menu, minimap, etc"""
|
||||
try:
|
||||
md_view, preview = self.update(view)
|
||||
except TypeError:
|
||||
# the function update has returned None
|
||||
return
|
||||
# if view is not the md_view or the preview
|
||||
# remove preview if any
|
||||
for view, settings in find_preview(window):
|
||||
settings.set(IS_HIDDEN, True)
|
||||
view.close()
|
||||
window = preview.window()
|
||||
psettings = preview.settings()
|
||||
|
||||
show_tabs = psettings.get('show_tabs')
|
||||
show_minimap = psettings.get('show_minimap')
|
||||
show_status_bar = psettings.get('show_status_bar')
|
||||
show_sidebar = psettings.get('show_sidebar')
|
||||
show_menus = psettings.get('show_menus')
|
||||
|
||||
if show_tabs is not None:
|
||||
window.set_tabs_visible(show_tabs)
|
||||
if show_minimap is not None:
|
||||
window.set_minimap_visible(show_minimap)
|
||||
if show_status_bar is not None:
|
||||
window.set_status_bar_visible(show_status_bar)
|
||||
if show_sidebar is not None:
|
||||
window.set_sidebar_visible(show_sidebar)
|
||||
if show_menus is not None:
|
||||
window.set_menu_visible(show_menus)
|
||||
|
||||
class MarkdownLivePreviewClearCacheCommand(sublime_plugin.ApplicationCommand):
|
||||
|
||||
def run(self):
|
||||
clear_cache()
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
Fast:
|
||||
|
||||
☐ sync scroll @needsUpdate(because of images)
|
||||
☐ cache image in object when used, so that it's faster @needsTest
|
||||
☐ call settings listener on_new too - might be too heavy
|
||||
☐ add clear cache command
|
||||
|
||||
Medium:
|
||||
☐ auto refresh preview if loading images
|
||||
☐ use alt attribute for 404 error
|
||||
☐ use MarkdownLivePreview syntax, so we can use syntax's settings
|
||||
☐ listen for settings to change
|
||||
|
||||
Long:
|
||||
☐ fix #4 @high
|
||||
☐ support hanchor (TOC) @big
|
||||
|
||||
Unknown:
|
||||
☐ check how many times is the show_html function called
|
||||
|
||||
|
||||
___________________
|
||||
Archive:
|
||||
✔ regive focus to the right markdown view @done Mon 02 Jan 2017 at 18:34 @project(Fast)
|
||||
✔ try/except for 404 @done Mon 02 Jan 2017 at 18:03 @project(Fast)
|
||||
✔ fix bug when empty `src` @done Mon 02 Jan 2017 at 17:15 @project(Fast)
|
||||
✔ preview.set_scratch(True) @done Mon 02 Jan 2017 at 16:58
|
||||
✔ set the title of the preview @done Mon 02 Jan 2017 at 16:58
|
||||
✔ preview.wordWrap => True @done Mon 02 Jan 2017 at 16:58
|
||||
✔ clean the code (syntax) @done Mon 02 Jan 2017 at 16:58
|
||||
✔ add 404 image @done Mon 02 Jan 2017 at 16:57
|
||||
✔ load images from internet (`https:`) @done Mon 02 Jan 2017 at 16:57
|
||||
48
README.md
@ -4,44 +4,54 @@ This is a sublime text **3** plugin that allows you to preview your markdown ins
|
||||
|
||||
### Dependencies
|
||||
|
||||
**None**! There is no dependency! It uses [markdown2](https://github.com/trentm/python-markdown2) but it's a one file plugin, so it's included in the package.
|
||||
**None! There is no dependency!** It uses [markdown2](https://github.com/trentm/python-markdown2) but it's a one file plugin, so it's included in the package.
|
||||
|
||||
## Installation
|
||||
|
||||
Although MarkdownLivePreview is not available on the default channel of [PackageControl](http://packagecontrol.io), you can still use it to download this little package.
|
||||
|
||||
1. Open the command palette (`ctrl+shift+p`)
|
||||
2. Search for: `Package Control: Add Repository`
|
||||
3. Enter in the input at the bottom of ST the path to this repo: <https://github.com/math2001/MarkdownLivePreview> (tip: just drag the link in)
|
||||
4. Hit <kbd>enter</kbd>
|
||||
|
||||
What this does is simply adding this repo to the list of packages you get when you install a package using PC.
|
||||
|
||||
So, as you probably understood, now you just need to install MarkdownLivePreview as if it was available on the default channel:
|
||||
MarkdownLivePreview is available on the default channel of
|
||||
[PackageControl](http://packagecontrol.io), which means you just have to
|
||||
|
||||
1. Open the command palette (`ctrl+shift+p`)
|
||||
2. Search for: `Package Control: Install Package`
|
||||
3. Search for: `MarkdownLivePreview`
|
||||
4. hit <kbd>enter</kbd>
|
||||
|
||||
Done!
|
||||
to have MarkdownLivePreview working on your computer. Cool right? You can
|
||||
[thank package control](https://packagecontrol.io/say_thanks) for this. :wink:
|
||||
|
||||
### Usage
|
||||
|
||||
Sometimes, you just want to open a markdown file to edit it quickly, you don't care about the preview, and even worse, **you don't want it**. So, if you want to have the preview, press `alt+m`, edit your file, and you'll get a nice preview.
|
||||
You can choose to enable MarkdownLivePreview by pressing <kbd>alt+m</kbd> or selecting in the
|
||||
command palette `MarkdownLivePreview: Edit Current File`. Note that you need to be editing (simply
|
||||
having the focus on) a markdown file. Because [Markdown Extended][markdown-extended] did a good job,
|
||||
it's compatible with this plugin.
|
||||
|
||||
### In dev
|
||||
So, once you've run it, it will open a new window, with only your markdown file, with the preview.
|
||||
Once you're done, close whichever file and it'll close the entire window.
|
||||
|
||||
This plugin is not finished, there's still some things to fix (custom css, focus, etc). So, don't run away if you have any trouble, just submit an issue [here](http://github.com/math2001/MarkdownLivePreview/issues).
|
||||
*Notice that it will close the entire window if you close __whichever__ file. It means that if you*
|
||||
*open a random file in this window, and then close it, it'll close the entire window still*
|
||||
|
||||
For further infos, please [read the docs](https://math2001.github.io/MarkdownLivePreview/)!
|
||||
|
||||
### Demo
|
||||
|
||||

|
||||
|
||||
### Custom css
|
||||
### Somethings wrong!!
|
||||
|
||||
It is possible to set your own css. But, be carefull, you have to respect [those rules](http://www.sublimetext.com/docs/3/minihtml.html#css). Just go to `Preferences -> Package Settings -> MarkdownLivePreview`. It will open a css file, here: `$packages/User/MarkdownLivePreview.css`. Just save it and it will automatically use it instead of the default one.
|
||||
If you find that something's wrong with this package, you can let me know by raising an issue on the
|
||||
[GitHub issue tracker][github-issue-tracker]
|
||||
|
||||
### How to open the [README](http://github.com/math2001/MarkdownLivePreview/README.md)
|
||||
### How to open the [README][]
|
||||
|
||||
Some of the package add a command in the menus, others in the command palette, or other nowhere. None of those options are really good, especially the last one on ST3 because the packages are compressed. But, fortunately, there is plugin that exists and **will solve this problem** for us (and he has a really cute name, don't you think?): [ReadmePlease](https://packagecontrol.io/packages/ReadmePlease).
|
||||
Some of the package add a command in the menus, others in the command palette, or other nowhere.
|
||||
None of those options are really good, especially the last one on ST3 because the packages are
|
||||
compressed. But, fortunately, there is plugin that exists and **will solve this problem** for us
|
||||
(and he has a really cute name, don't you think?):
|
||||
[ReadmePlease](https://packagecontrol.io/packages/ReadmePlease).
|
||||
|
||||
[markdown-extended]: https://packagecontrol.io/packages/Markdown%20Extended
|
||||
[github-issue-tracker]: https://github.com/math2001/MarkdownLivePreview/issues
|
||||
[st-css-rules]: http://www.sublimetext.com/docs/3/minihtml.html#css
|
||||
[README]: http://github.com/math2001/MarkdownLivePreview/README.md
|
||||
|
||||
42
default.css
@ -1,12 +1,10 @@
|
||||
:root, html, body {
|
||||
height: 100%;
|
||||
}
|
||||
html {
|
||||
--light-bg: color(var(--background) blend(#999 85%))
|
||||
height: 100%;
|
||||
--light-bg: color(var(--background) blend(#999 85%));
|
||||
--very-light-bg: color(var(--background) blend(#999 92%));
|
||||
}
|
||||
|
||||
body {
|
||||
padding:10px;
|
||||
padding: 10px;
|
||||
padding-top: 0px;
|
||||
font-family: "Open Sans", sans-serif;
|
||||
background-color: var(--background);
|
||||
@ -17,7 +15,6 @@ blockquote {
|
||||
font-style: italic;
|
||||
display: block;
|
||||
margin-left: 30px;
|
||||
border: 1px solid red;
|
||||
}
|
||||
|
||||
code {
|
||||
@ -26,18 +23,41 @@ code {
|
||||
background-color: var(--light-bg);
|
||||
margin: 0;
|
||||
border-radius: 3px;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
pre {
|
||||
div.codehilite {
|
||||
display: block;
|
||||
margin-top: 20px;
|
||||
line-height: 1.7;
|
||||
background-color: var(--light-bg);
|
||||
padding-left: 10px;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
width: 100%;
|
||||
border-radius: 3px;
|
||||
}
|
||||
pre code {
|
||||
padding-left: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
pre code .space {
|
||||
color: var(--light-bg);
|
||||
}
|
||||
|
||||
pre.table {
|
||||
background-color: var(--background);
|
||||
}
|
||||
pre.table code {
|
||||
background-color: var(--background);
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
pre.table code .space {
|
||||
color: var(--background);
|
||||
}
|
||||
|
||||
|
||||
kbd {
|
||||
padding: 0 5px;
|
||||
background-color: var(--very-light-bg);
|
||||
font-family: "Roboto Mono","Courier New",Courier,monospace;
|
||||
}
|
||||
|
||||
8
dependencies.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"*": {
|
||||
"*": [
|
||||
"bs4",
|
||||
"pygments"
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -7,14 +7,14 @@ import os.path
|
||||
class MLPDevListener(sublime_plugin.EventListener):
|
||||
|
||||
def on_post_save(self, view):
|
||||
return
|
||||
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'),
|
||||
'main': os.path.join(sublime.packages_path(), 'MarkdownLivePreview',
|
||||
'MarkdownLivePreview.py'),
|
||||
'scripts': ['image_manager', 'functions', 'MLPApi',
|
||||
'setting_names'],
|
||||
'folders': ['lib'],
|
||||
'quiet': True
|
||||
})
|
||||
|
||||
92
docs/imgs/MarkdownLivePreview-opposite.svg
Normal file
@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="100"
|
||||
height="100"
|
||||
viewBox="0 0 99.999996 100"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="MarkdownLivePreview.svg">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#2196f3"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="2.8"
|
||||
inkscape:cx="36.574985"
|
||||
inkscape:cy="6.9424003"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
showborder="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1018"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:showpageshadow="false"
|
||||
units="px"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:snap-global="false" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-349.87364,-434.14672)">
|
||||
<g
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:59.90521622px;font-family:Candal;-inkscape-font-specification:Candal;text-align:start;text-anchor:start;opacity:1;fill:#e1ecff;fill-opacity:1;stroke:#ef524f;stroke-width:3.75156426;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="text7027"
|
||||
transform="translate(-0.13506381,-12.064395)">
|
||||
<path
|
||||
d="m 352.04084,461.61747 12.16825,0 10.2962,16.08783 10.29621,-16.08783 12.46076,0 0,41.36034 -13.39678,0 0,-22.46445 -9.65269,16.35108 -2.83731,0 -9.97445,-16.35108 0,22.46445 -9.36019,0 0,-41.36034 z"
|
||||
style="fill:#e1ecff;fill-opacity:1;stroke:none"
|
||||
id="path7039"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(-1,0,0,1,-0.13506381,-12.064395)"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:59.90521622px;font-family:Candal;-inkscape-font-specification:Candal;text-align:start;text-anchor:start;opacity:1;fill:#b9d5ff;fill-opacity:1;stroke:#ef524f;stroke-width:3.75156426;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="text7031">
|
||||
<path
|
||||
d="m -447.97656,461.61747 12.16825,0 10.29621,16.08783 10.29621,-16.08783 12.46075,0 0,41.36034 -13.39677,0 0,-22.46445 -9.6527,16.35108 -2.8373,0 -9.97446,-16.35108 0,22.46445 -9.36019,0 0,-41.36034 z"
|
||||
style="fill:#b9d5ff;fill-opacity:1;stroke:none"
|
||||
id="path7036"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<path
|
||||
style="opacity:0.75;fill:#cde0ff;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 375.63144,496.36803 24.28571,14.02137 24.28572,-14.02137 14.46428,0 -38.75,22.37233 -38.75,-22.37233 z"
|
||||
id="path7081"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
92
docs/imgs/MarkdownLivePreview.svg
Normal file
@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="100"
|
||||
height="100"
|
||||
viewBox="0 0 99.999996 100"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="MarkdownLivePreview.svg">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="2.8"
|
||||
inkscape:cx="36.574985"
|
||||
inkscape:cy="6.9424003"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
showborder="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1018"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:showpageshadow="false"
|
||||
units="px"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:snap-global="false" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-349.87364,-434.14672)">
|
||||
<g
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:59.90521622px;font-family:Candal;-inkscape-font-specification:Candal;text-align:start;text-anchor:start;opacity:1;fill:#5599ff;fill-opacity:1;stroke:#ef524f;stroke-width:3.75156426;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="text7027"
|
||||
transform="translate(-0.13506381,-12.064395)">
|
||||
<path
|
||||
d="m 352.04084,461.61747 12.16825,0 10.2962,16.08783 10.29621,-16.08783 12.46076,0 0,41.36034 -13.39678,0 0,-22.46445 -9.65269,16.35108 -2.83731,0 -9.97445,-16.35108 0,22.46445 -9.36019,0 0,-41.36034 z"
|
||||
style="fill:#5599ff;fill-opacity:1;stroke:none"
|
||||
id="path7039"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(-1,0,0,1,-0.13506381,-12.064395)"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:59.90521622px;font-family:Candal;-inkscape-font-specification:Candal;text-align:start;text-anchor:start;opacity:0.75;fill:#5599ff;fill-opacity:1;stroke:#ef524f;stroke-width:3.75156426;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="text7031">
|
||||
<path
|
||||
d="m -447.97656,461.61747 12.16825,0 10.29621,16.08783 10.29621,-16.08783 12.46075,0 0,41.36034 -13.39677,0 0,-22.46445 -9.6527,16.35108 -2.8373,0 -9.97446,-16.35108 0,22.46445 -9.36019,0 0,-41.36034 z"
|
||||
style="fill:#5599ff;fill-opacity:1;stroke:none"
|
||||
id="path7036"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<path
|
||||
style="opacity:0.75;fill:#aaccff;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 375.63144,496.36803 24.28571,14.02137 24.28572,-14.02137 14.46428,0 -38.75,22.37233 -38.75,-22.37233 z"
|
||||
id="path7081"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
BIN
docs/imgs/syntax-specific-settings.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
184
docs/index.md
Normal file
@ -0,0 +1,184 @@
|
||||
# Welcome to MarkdownLivePreview's documentation!
|
||||
|
||||
<img src="imgs/MarkdownLivePreview.svg" alt="MarkdownLivePreview's logo"
|
||||
style="width: 400px; margin: auto; display: block;">
|
||||
|
||||
MarkdownLivePreview is a [Sublime Text 3][st] plugin to preview your markdown as you type,
|
||||
*right in Sublime Text itself*, without *any* dependency!
|
||||
|
||||
It's very easy to use, but there's a few things that you might want to be aware of... So, let's
|
||||
get started
|
||||
|
||||
## Installation
|
||||
|
||||
### Using Package Control
|
||||
|
||||
You can really easily install MarkdownLivePreview by using [Package Control][pck-con].
|
||||
|
||||
If it's not already, you need to [install it][install-pck-con] first.
|
||||
|
||||
!!! note
|
||||
If you're using the latest build of Sublime Text 3, you can just do
|
||||
*Tools → Install Package Control…*
|
||||
|
||||
- Open up the command palette (<kbd>ctrl+shift+p</kbd>)
|
||||
- Search up `Package Control: Install Package` (might take a few seconds)
|
||||
- In the panel that just showed up, search for `MarkdownLivePreview`
|
||||
|
||||
Done! You have now access to every single features of MarkdownLivePreview! :wink:
|
||||
|
||||
### Using `git`
|
||||
|
||||
```sh
|
||||
$ cd "%APPDATA%\Sublime Text 3\Packages" # on Windows
|
||||
$ cd ~/Library/Application\ Support/Sublime\ Text\ 3 # on Mac
|
||||
$ cd ~/.config/sublime-text-3 # on Linux
|
||||
|
||||
$ git clone "https://github.com/math2001/MarkdownLivePreview"
|
||||
```
|
||||
|
||||
> So, which one do I pick?!
|
||||
|
||||
I depends of what you want to do. If you want to just use MarkdownLivePreview, pick the first
|
||||
solution, you'll get every update automatically. But if you want to contribute, then choose the
|
||||
second solution.
|
||||
|
||||
## Usage
|
||||
|
||||
### Previewing
|
||||
|
||||
As told in the introduction, MarkdownLivePreview is very easy to use:
|
||||
|
||||
- open a markdown file
|
||||
- press <kbd>alt+m</kbd>
|
||||
- or select in the command palette `MarkdownLivePreview: Edit Current File`
|
||||
|
||||
!!! note
|
||||
The preview of unsaved markdown files is currently not supported. It should be fixed soon.
|
||||
|
||||
!!! tip
|
||||
[Markdown Extended][] is supported too!
|
||||
|
||||
That's it. That's all you need to do to preview your markdown!
|
||||
|
||||
### Settings
|
||||
|
||||
To edit MarkdownLivePreview's settings, you just need to search in the command palette
|
||||
`Preferences: MarkdownLivePreview Settings`, or from the menus:
|
||||
*Preferences → Package Settings → MarkdownLivePreview → Settings*
|
||||
|
||||
Do not edit the left file (by default, you cannot), but the right one. This right file will
|
||||
override the default one (on the left), and will be saved in your `User` folder, which makes it easy
|
||||
to back up.
|
||||
|
||||
- `markdown_live_preview_on_open`: if set to `true`, as soon as you open a markdown file, the
|
||||
preview window will popup (thanks to[@ooing][] for its [suggestion][@ooing suggestion]). Default to
|
||||
`false`
|
||||
- `load_from_internet_when_starts`: every images that starts with any of the string specified in
|
||||
this list will be loaded from internet. Default to `["http://", "https://"]`
|
||||
- `header_action`: If you're writing a blog with some markdown and a static website generator, you
|
||||
probably have a YAML header. By default, this header will be displayed in a `pre` block. If you want
|
||||
to hide it, then just change the value to `remove`. Thanks to [@tanhanjay][] for
|
||||
[letting me know][front-matter-issue]!
|
||||
- `keep_open_when_opening_preview`: Each time the preview window is opened, the original markdown
|
||||
view is closed. If you want to keep it opened, just set this setting to `true`
|
||||
|
||||
### Custom CSS
|
||||
|
||||
If you want to, you can add custom `CSS` to the MarkdownLivePreview's default stylesheet.
|
||||
|
||||
Just search for `MarkdownLivePreview: Edit Custom CSS File` in the command palette
|
||||
(<kbd>ctrl+shift+p</kbd>). It will open a file in which you can add some CSS that will be *added* to
|
||||
the normal CSS.
|
||||
|
||||
!!! bug
|
||||
Comments in the CSS is interpreted weirdly by Sublime Text's phantoms. After a few tests, I
|
||||
think that everything that is bellow a comment is ignored.
|
||||
|
||||
If you want to be sure that your CSS works, don't put any comments in it
|
||||
|
||||
#### Share your tweaks!
|
||||
|
||||
If you think that other users would enjoy your added CSS, then raise an issue, or PR the
|
||||
[GitHub repo][] to share your tweaks!
|
||||
|
||||
### Clearing the cache
|
||||
|
||||
MarkdownLivePreview has a cache system to store images you load from internet. You can clear this
|
||||
cache by searching up in the command palette `MarkdownLivePreview: Clear the cache`.
|
||||
|
||||
!!! tip
|
||||
The cache is one simple file called `MarkdownLivePreviewCache`, which is located in your temp
|
||||
folder. To know where it is, you can open the Sublime Text console (<kbd>ctrl+`</kbd> or
|
||||
*View → Show Console*), and paste this in:
|
||||
|
||||
```python
|
||||
import tempfile; print(tempfile.gettempdir())
|
||||
```
|
||||
|
||||
### Custom settings for the preview
|
||||
|
||||
Sublime Text makes it easy to set custom settings for a specific *type* of view. For example,
|
||||
`markdown`, `python`, etc. MarkdownLivePreview takes advantage of that: the preview view (the view
|
||||
on the right) is a specific syntax (called — sorry for the originality —
|
||||
`MarkdownLivePreviewSyntax`). So, to change this, you can focus the right view, open up the command
|
||||
palette (<kbd>ctrl+shift+p</kbd>), and search up `Preferences: Settings — Syntax Specific`. In here,
|
||||
you can specify any settings that is going to be applied only to this view.
|
||||
|
||||
### The hacky part
|
||||
|
||||
In fact, MarkdownLivePreview parses those settings, and looks for specific ones:
|
||||
|
||||
- `show_tabs`
|
||||
- `show_minimap`
|
||||
- `show_status_bar`
|
||||
- `show_sidebar`
|
||||
- `show_menus`
|
||||
|
||||
Those settings aren't supported by default because they affect the entire *window* instead of just
|
||||
the view. But MarkdownLivePreview will look for them in your *preview*'s settings, and hide/show the
|
||||
tabs, the minimap, etc...
|
||||
|
||||
As you probably guessed those settings takes a bool for value (`true` or `false`).
|
||||
|
||||
### Recommendation
|
||||
|
||||
Here's what I'd recommend for your MarkdownLivePreviewSyntax's settings (and what I use):
|
||||
|
||||
```json
|
||||
{
|
||||
"show_menus": false,
|
||||
"show_tabs": false,
|
||||
"show_minimap": false,
|
||||
"gutter": false,
|
||||
"rulers": [],
|
||||
"word_wrap": true
|
||||
}
|
||||
```
|
||||
|
||||
And here's what you'll get (With the awesome [Boxy Theme][] and its [Monokai Color Scheme][]):
|
||||
|
||||

|
||||
|
||||
!!! tip
|
||||
On Windows at least, you can press <kbd>alt</kbd> to focus (so show) the menus, even if they're
|
||||
originally hidden.
|
||||
|
||||
That's it! I hope you'll enjoy using this package! If it's the case, please let your friends know
|
||||
about it, and even myself by sending me a [tweet][] or staring the repo!
|
||||
<iframe
|
||||
src="https://ghbtns.com/github-btn.html?user=math2001&repo=MarkdownLivePreview&type=star&count=true&size=large"
|
||||
frameborder="0" scrolling="0" style="width: 120px; height: 30px; vertical-align: bottom"></iframe>
|
||||
|
||||
[st]: https://sublimetext.com
|
||||
[Markdown Extended]: https://packagecontrol.io/packages/Markdown%20Extended
|
||||
[pck-con]: https://packagecontrol.io
|
||||
[install-pck-con]: https://packagecontrol.io/installation
|
||||
[tweet]: https://twitter.com/_math2001
|
||||
[GitHub repo]: https://github.com/math2001/MarkdownLivePreview/issues
|
||||
[@ooing]: https://github.com/ooing
|
||||
[@ooing suggestion]: https://github.com/math2001/MarkdownLivePreview/issues/7#issue-199464852
|
||||
[@tanhanjay]: https://github.com/tanhanjay
|
||||
[front-matter-issue]: https://github.com/math2001/MarkdownLivePreview/issues/17
|
||||
[Boxy Theme]: https://packagecontrol.io/packages/Boxy%20Theme
|
||||
[Monokai Color Scheme]: https://github.com/ihodev/sublime-boxy#boxy-monokai--predawn
|
||||
24
docs/license.md
Normal file
@ -0,0 +1,24 @@
|
||||
This project is published under MIT license.
|
||||
|
||||
> The MIT License is a permissive license that is short and to the point. It lets people do anything
|
||||
> they want with your code as long as they provide attribution back to you and don’t hold you
|
||||
> liable.
|
||||
>
|
||||
> — *from [choosealicense.com](http://choosealicense.com), by [GitHub](https://github.com)*
|
||||
|
||||
Copyright 2017 Mathieu PATUREL
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
andassociated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial
|
||||
portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@ -2,9 +2,7 @@
|
||||
|
||||
import re
|
||||
|
||||
__all__ = [
|
||||
'escape_amp'
|
||||
]
|
||||
__all__ = ['escape_amp']
|
||||
|
||||
RE_REPLACE_AMPERSAND = re.compile(r'&(\w*)(;)?')
|
||||
|
||||
@ -27,11 +25,14 @@ def run_tests():
|
||||
fails = 0
|
||||
for i, (subject, result) in enumerate(tests):
|
||||
if RE_REPLACE_AMPERSAND.sub(replace, subject) != result:
|
||||
# CSW: ignore
|
||||
print('TEST FAIL ({i}): {subject!r} escaped did not match {result!r}'.format(**locals()))
|
||||
fails += 1
|
||||
if fails == 0:
|
||||
# CSW: ignore
|
||||
print("SUCCESS: every tests ({}) passed successfully!".format(len(tests)))
|
||||
else:
|
||||
# CSW: ignore
|
||||
print("{} test{} failed".format(fails, 's' if fails > 1 else ''))
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
47
example.md
Normal file
@ -0,0 +1,47 @@
|
||||
---
|
||||
title: Demo
|
||||
description: Preview your markdown right in Sublime Text!
|
||||
hope: You'll enjoy using it!
|
||||
---
|
||||
|
||||
# Hello world
|
||||
|
||||
<!-- supports comments -->
|
||||
|
||||
And `<!-- vicious ones ;) -->`
|
||||
|
||||
Some `inline code` with *italic* and **bold** text.
|
||||
|
||||
```python
|
||||
import this
|
||||
if you is moods.curious:
|
||||
print('then do it!')
|
||||
```
|
||||
|
||||
<kbd>ctrl+\`</kbd> or *View → Show Console* and paste `import this`!
|
||||
|
||||
> Perfect programmers do NOT need comments.
|
||||
|
||||
- to be efficient
|
||||
- you need
|
||||
- todos
|
||||
|
||||
|
||||
| ID | Name |
|
||||
|-----------|-------|
|
||||
| 56 | Matt |
|
||||
| 42 | Colin |
|
||||
| 23 | Lisa |
|
||||
| 45 | John |
|
||||
| `<table>` | `><` |
|
||||
|
||||

|
||||
|
||||
Some plugin I just *need*:
|
||||
|
||||
- [PackageResourceReviewer](https://packagecontrol.io/packages/PackageResourceViewer)
|
||||
- [Boxy Theme](https://packagecontrol.io/packages/Boxy%20Theme)
|
||||
- [Markdown Preview](https://packagecontrol.io/packages/Markdown%20Preview)
|
||||
- [FileManager](https://packagecontrol.io/packages/FileManager)
|
||||
- [PlainTasks](https://packagecontrol.io/packages/PlainTasks)
|
||||
- [JSONComma](https://packagecontrol.io/packages/JSONComma)
|
||||
100
functions.py
@ -4,39 +4,61 @@ import os.path
|
||||
import sublime
|
||||
import re
|
||||
from .image_manager import ImageManager
|
||||
from .lib.pygments_from_theme import pygments_from_theme
|
||||
from bs4 import BeautifulSoup, Comment as html_comment
|
||||
|
||||
def plugin_loaded():
|
||||
global error404, loading
|
||||
global error404, loading, DEFAULT_STYLE, USER_STYLE_FILE
|
||||
loading = sublime.load_resource('Packages/MarkdownLivePreview/loading.txt')
|
||||
error404 = sublime.load_resource('Packages/MarkdownLivePreview/404.txt')
|
||||
|
||||
DEFAULT_STYLE = sublime.load_resource('Packages/MarkdownLivePreview/default.css')
|
||||
USER_STYLE_FILE = os.path.join(sublime.packages_path(), 'User', "MarkdownLivePreview.css")
|
||||
|
||||
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/'):
|
||||
MATCH_YAML_HEADER = re.compile(r'^([\-\+])\1{2}\n(?P<content>.+)\n\1{3}\n', re.DOTALL)
|
||||
|
||||
def strip_html_comments(html):
|
||||
soup = BeautifulSoup(html, 'html.parser')
|
||||
for element in soup.find_all(text=lambda text: isinstance(text, html_comment)):
|
||||
element.extract()
|
||||
return str(soup)
|
||||
|
||||
def manage_header(md, action):
|
||||
matchobj = MATCH_YAML_HEADER.match(md)
|
||||
if not matchobj:
|
||||
return md
|
||||
if action == 'remove':
|
||||
return md[len(matchobj.group(0)):]
|
||||
elif action == 'wrap_in_pre':
|
||||
return '<pre><code>' + matchobj.group('content') + '</code></pre>' \
|
||||
+ md[len(matchobj.group(0)):]
|
||||
|
||||
raise ValueError('Got an unknown action: "{}"'.format(action))
|
||||
|
||||
def get_preview_name(md_view):
|
||||
file_name = md_view.file_name()
|
||||
name = md_view.name() \
|
||||
or os.path.basename(file_name) if file_name else None \
|
||||
or 'Untitled'
|
||||
return name + ' - Preview'
|
||||
|
||||
def replace_img_src_base64(html, basepath):
|
||||
soup = BeautifulSoup(html, 'html.parser')
|
||||
load_from_internet_starters = get_settings().get('load_from_internet_when_starts')
|
||||
for img in soup.find_all('img'):
|
||||
if img['src'].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 loading
|
||||
elif img['src'].startswith(tuple(load_from_internet_starters)):
|
||||
image = ImageManager.get(img['src']) or loading
|
||||
else: # this is a local image
|
||||
image = to_base64(os.path.join(basepath, img['src']))
|
||||
|
||||
else:
|
||||
# local image
|
||||
image = to_base64(''.join(path))
|
||||
html[index+len(tag_start):end] = image
|
||||
shtml = ''.join(html)
|
||||
return ''.join(html)
|
||||
img['src'] = image
|
||||
|
||||
return str(soup)
|
||||
|
||||
def is_markdown_view(view):
|
||||
return 'markdown' in view.scope_name(0)
|
||||
return 'markdown' in view.scope_name(0)
|
||||
|
||||
def to_base64(path=None, content=None):
|
||||
if path is None and content is None:
|
||||
@ -75,6 +97,8 @@ def get_view_content(view):
|
||||
return view.substr(sublime.Region(0, view.size()))
|
||||
|
||||
def get_view_from_id(window, id):
|
||||
if not isinstance(id, int):
|
||||
return
|
||||
for view in window.views():
|
||||
if view.id() == id:
|
||||
return view
|
||||
@ -82,17 +106,27 @@ def get_view_from_id(window, id):
|
||||
def get_settings():
|
||||
return sublime.load_settings('MarkdownLivePreview.sublime-settings')
|
||||
|
||||
|
||||
def _pre_with_spaces(code):
|
||||
for tag in code.find_all(text=True):
|
||||
tag.replace_with(BeautifulSoup(str(tag).replace('\t', ' ' * 4).replace(' ', '<i class="space">.</i>').replace('\n', '<br />'), 'html.parser'))
|
||||
return code
|
||||
|
||||
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>"""
|
||||
soup = BeautifulSoup(html, 'html.parser')
|
||||
for pre in soup.find_all('pre'):
|
||||
code = pre.find('code')
|
||||
code.replace_with(_pre_with_spaces(code))
|
||||
return str(soup)
|
||||
|
||||
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
|
||||
|
||||
def get_style(color_scheme):
|
||||
css = DEFAULT_STYLE
|
||||
if os.path.exists(USER_STYLE_FILE):
|
||||
with open(USER_STYLE_FILE) as fp:
|
||||
css += '\n' + fp.read() + '\n'
|
||||
if color_scheme:
|
||||
css += pygments_from_theme(color_scheme)
|
||||
return ''.join([line.strip() + ' ' for line in css.splitlines()])
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
import os.path
|
||||
import tempfile
|
||||
import sublime
|
||||
from threading import Thread
|
||||
import urllib.request, urllib.error
|
||||
import sublime
|
||||
from .functions import *
|
||||
import tempfile
|
||||
|
||||
CACHE_FILE = os.path.join(tempfile.gettempdir(),
|
||||
'MarkdownLivePreviewCache.txt')
|
||||
|
||||
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
1
imgs/README.md
Normal file
@ -0,0 +1 @@
|
||||
There is images here, allthough they aren't of any use for the plugin. They're just the image that I used to generate the base64 (404.txt and loading.txt)
|
||||
|
Before Width: | Height: | Size: 953 B After Width: | Height: | Size: 953 B |
52
lib/pre_tables.py
Normal file
@ -0,0 +1,52 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
"""
|
||||
'pre_tables' transform *html* tables into markdown tables, and put them in some <pre><code> tags
|
||||
"""
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
def python_table(s_table):
|
||||
"""Transform BeautifulSoup table into list of list"""
|
||||
rows = []
|
||||
for row in s_table.find_all('tr'):
|
||||
# rows.append(list(map( lambda td: td.text, row.find_all(['th', 'td']) )))
|
||||
rows.append(row.find_all(['th', 'td']))
|
||||
return rows
|
||||
|
||||
def pre_table(s_table):
|
||||
rows = python_table(s_table)
|
||||
cols_width = [len(cell) for cell in rows[0]]
|
||||
for j, row in enumerate(rows):
|
||||
for i, cell in enumerate(row):
|
||||
if cols_width[i] < len(cell.text):
|
||||
cols_width[i] = len(cell.text)
|
||||
text = '<pre class="table"><code>'
|
||||
for i, row in enumerate(rows):
|
||||
if i == 1:
|
||||
for j, cell in enumerate(row):
|
||||
text += '|' + '-' * (cols_width[j] + 2)
|
||||
text += '|\n'
|
||||
|
||||
for j, cell in enumerate(row):
|
||||
text += '| '
|
||||
if cell.name == 'th':
|
||||
title = ' ' * ((cols_width[j] - len(cell.text)) // 2) \
|
||||
+ ''.join(str(node) for node in cell.contents) \
|
||||
+ ' ' * int(round((cols_width[j] - len(cell.text)) / 2 ) + 1)
|
||||
# + 1 because of the added space before the closing | of each cell
|
||||
if cols_width[j] + 1 != len(title):
|
||||
title += ' '
|
||||
text += title
|
||||
else:
|
||||
text += ''.join(str(node) for node in cell.contents) \
|
||||
+ ' ' * (cols_width[j] - len(cell.text) + 1)
|
||||
text += '|\n'
|
||||
text += '</pre></code>'
|
||||
return text
|
||||
|
||||
def pre_tables(html):
|
||||
soup = BeautifulSoup(html, 'html.parser')
|
||||
for table in soup.find_all('table'):
|
||||
table.replace_with(BeautifulSoup(pre_table(table), 'html.parser'))
|
||||
return str(soup)
|
||||
167
lib/pygments_from_theme.py
Normal file
@ -0,0 +1,167 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
from xml.dom.minidom import parse
|
||||
from collections import defaultdict
|
||||
|
||||
class Style:
|
||||
# .highlight is the wrapper class for highlighting therefore
|
||||
# all css rules are prefixed with .highlight
|
||||
PREFIX = '.codehilite'
|
||||
|
||||
# -----------------------------------------
|
||||
# Params
|
||||
# name: the name of the class
|
||||
# args: each argument is an array.
|
||||
# Each array consists of css properties
|
||||
# that is either a color or font style
|
||||
# ----------------------------------------
|
||||
|
||||
def __init__(self, name, *args):
|
||||
self.name = name # Name of the class
|
||||
self.rules = {} # The css rules
|
||||
for arr in args:
|
||||
for value in arr:
|
||||
# Only define properties if they are already not defined
|
||||
# This allows "cascading" if rules to be applied
|
||||
if value.startswith('#') and 'color' not in self.rules:
|
||||
self.rules['color'] = value
|
||||
else:
|
||||
if 'italic' in value and 'font-style' not in self.rules:
|
||||
self.rules['font-style'] = 'italic'
|
||||
if 'underline' in value and 'text-decoration' not in self.rules:
|
||||
self.rules['text-decoration'] = 'underline'
|
||||
if 'bold' in value and 'font-weight' not in self.rules:
|
||||
self.rules['font-weight'] = 'bold'
|
||||
|
||||
# Helper method for creating the css rule
|
||||
def _join_attr(self):
|
||||
temp = []
|
||||
if(len(self.rules) == 0):
|
||||
return ''
|
||||
for key in self.rules:
|
||||
temp.append(key + ': ' + self.rules[key])
|
||||
return '; '.join(temp) + ';'
|
||||
|
||||
def toString(self):
|
||||
joined = self._join_attr()
|
||||
if joined:
|
||||
return "%s .%s { %s }" % (Style.PREFIX, self.name, joined)
|
||||
return ''
|
||||
|
||||
|
||||
# Crappy xml parsing function for getting the
|
||||
# colors and font styles from colortheme file
|
||||
|
||||
|
||||
def get_settings(file_name):
|
||||
settings = defaultdict(lambda: [])
|
||||
dom = parse(file_name)
|
||||
arr = dom.getElementsByTagName('array')[0]
|
||||
editor_cfg = arr.getElementsByTagName('dict')[0].getElementsByTagName('dict')[0]
|
||||
editor_vals = editor_cfg.getElementsByTagName('string')
|
||||
background = editor_vals[0].firstChild.nodeValue
|
||||
text_color = editor_vals[2].firstChild.nodeValue
|
||||
settings['editor_bg'] = background
|
||||
settings['text_color'] = text_color
|
||||
for node in arr.childNodes:
|
||||
if node.nodeName == "dict":
|
||||
try:
|
||||
setting = node.getElementsByTagName('string')[1].firstChild.nodeValue
|
||||
attrs = []
|
||||
values = node.getElementsByTagName('dict')[0].getElementsByTagName('string')
|
||||
for v in values:
|
||||
if v.firstChild:
|
||||
a = str(v.firstChild.nodeValue).strip()
|
||||
attrs.append(a)
|
||||
for s in setting.split(', '):
|
||||
settings[s] = attrs
|
||||
except:
|
||||
continue
|
||||
return settings
|
||||
|
||||
|
||||
def pygments_from_theme(file):
|
||||
settings = get_settings(file)
|
||||
styles = []
|
||||
|
||||
#Generic
|
||||
styles.append(Style('ge', ['italic']))
|
||||
styles.append(Style('gs', ['bold']))
|
||||
|
||||
# Comments
|
||||
styles.append(Style('c', settings['comment']))
|
||||
styles.append(Style('cp', settings['comment']))
|
||||
styles.append(Style('c1', settings['comment']))
|
||||
styles.append(Style('cs', settings['comment']))
|
||||
styles.append(Style('cm', settings['comment.block'], settings['comment']))
|
||||
|
||||
# Constants
|
||||
styles.append(Style('m', settings['constant.numeric'], settings['constant.other'], settings['constant'], settings['support.constant']))
|
||||
styles.append(Style('mf', settings['constant.numeric'], settings['constant.other'], settings['constant'], settings['support.constant']))
|
||||
styles.append(Style('mi', settings['constant.numeric'], settings['constant.other'], settings['constant'], settings['support.constant']))
|
||||
styles.append(Style('mo', settings['constant.numeric'], settings['constant.other'], settings['constant'], settings['support.constant']))
|
||||
styles.append(Style('se', settings['constant.language'], settings['constant.other'], settings['constant'], settings['support.constant']))
|
||||
styles.append(Style('kc', settings['constant.language'], settings['constant.other'], settings['constant'], settings['support.constant']))
|
||||
|
||||
#Keywords
|
||||
styles.append(Style('k', settings['entity.name.type'], settings['support.type'], settings['keyword']))
|
||||
styles.append(Style('kd', settings['storage.type'], settings['storage']))
|
||||
styles.append(Style('kn', settings['support.function.construct'], settings['keyword.control'], settings['keyword']))
|
||||
styles.append(Style('kt', settings['entity.name.type'], settings['support.type'], settings['support.constant']))
|
||||
|
||||
#String
|
||||
styles.append(Style('settings', settings['string.quoted.double'], settings['string.quoted'], settings['string']))
|
||||
styles.append(Style('sb', settings['string.quoted.double'], settings['string.quoted'], settings['string']))
|
||||
styles.append(Style('sc', settings['string.quoted.single'], settings['string.quoted'], settings['string']))
|
||||
styles.append(Style('sd', settings['string.quoted.double'], settings['string.quoted'], settings['string']))
|
||||
styles.append(Style('s2', settings['string.quoted.double'], settings['string.quoted'], settings['string']))
|
||||
styles.append(Style('sh', settings['string']))
|
||||
styles.append(Style('si', settings['string.interpolated'], settings['string']))
|
||||
styles.append(Style('sx', settings['string.other'], settings['string']))
|
||||
styles.append(Style('sr', settings['string.regexp'], settings['string']))
|
||||
styles.append(Style('s1', settings['string.quoted.single'], settings['string']))
|
||||
styles.append(Style('ss', settings['string']))
|
||||
|
||||
#Name
|
||||
styles.append(Style('na', settings['entity.other.attribute-name'], settings['entity.other']))
|
||||
styles.append(Style('bp', settings['variable.language'], settings['variable']))
|
||||
styles.append(Style('nc', settings['entity.name.class'], settings['entity.other.inherited-class'], settings['support.class']))
|
||||
styles.append(Style('no', settings['constant.language'], settings['constant']))
|
||||
styles.append(Style('nd', settings['entity.name.class']))
|
||||
styles.append(Style('ne', settings['entity.name.class']))
|
||||
styles.append(Style('nf', settings['entity.name.function'], settings['support.function']))
|
||||
styles.append(Style('nt', settings['entity.name.tag'], settings['keyword']))
|
||||
styles.append(Style('nv', settings['variable'], [settings['text_color']]))
|
||||
styles.append(Style('vc', settings['variable.language']))
|
||||
styles.append(Style('vg', settings['variable.language']))
|
||||
styles.append(Style('vi', settings['variable.language']))
|
||||
|
||||
#Operator
|
||||
styles.append(Style('ow', settings['keyword.operator'], settings['keyword.operator'], settings['keyword']))
|
||||
styles.append(Style('o', settings['keyword.operator'], settings['keyword.operator'], settings['keyword']))
|
||||
|
||||
# Text
|
||||
styles.append(Style('n', [settings['text_color']]))
|
||||
styles.append(Style('nl', [settings['text_color']]))
|
||||
styles.append(Style('nn', [settings['text_color']]))
|
||||
styles.append(Style('nx', [settings['text_color']]))
|
||||
styles.append(Style('bp', settings['variable.language'], settings['variable'], [settings['text_color']]))
|
||||
styles.append(Style('p', [settings['text_color']]))
|
||||
|
||||
css = '{} {{ background-color: {}; color: {}; }}\n'.format(Style.PREFIX, settings['editor_bg'], settings['text_color'])
|
||||
for st in styles:
|
||||
css_style = st.toString()
|
||||
if css_style:
|
||||
css += css_style + '\n'
|
||||
|
||||
return css
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = sys.argv[1:]
|
||||
if len(args) < 1:
|
||||
print("Please provide the .tmTheme file!", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
print(pygments_from_theme(args[0]))
|
||||
7
messages.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"install": "messages/install.txt",
|
||||
"1.1.2": "messages/1.1.2.txt",
|
||||
"2.0.1": "messages/2.0.1.txt",
|
||||
"2.2.1": "messages/2.2.0.txt",
|
||||
"2.4.1": "messages/2.4.txt"
|
||||
}
|
||||
12
messages/1.1.2.txt
Normal file
@ -0,0 +1,12 @@
|
||||
Sorry to interrupt you... :(
|
||||
|
||||
Small changes occured on MarkdownLivePreview.
|
||||
|
||||
Changes:
|
||||
~~~~~~~~
|
||||
|
||||
Main callback is now async (prevent ST from crashing)
|
||||
|
||||
|
||||
Tip of the day: Delete all the content till the end of the line: Ctrl+k, Ctrl+k
|
||||
You'll use it much more than you think ;)
|
||||
22
messages/2.0.1.txt
Normal file
@ -0,0 +1,22 @@
|
||||
Sorry to interrupt you... :(
|
||||
|
||||
Some quite important changes have occured on MarkdownLivePreview.
|
||||
|
||||
The first version was quite buggy: it made Sublime Text 3 crash. So I released
|
||||
a whole new version, which is working differently.
|
||||
|
||||
When you active MarkdownLivePreview, it'll open a new window with the markdown
|
||||
view on the left, and the preview on the right.
|
||||
|
||||
When you'll close any file in this window, it'll close the *entire* window.
|
||||
|
||||
I hope you'll still enjoy using MarkdownLivePreview. If you have any request,
|
||||
just let me know by raising an issue here:
|
||||
|
||||
github.com/math2001/MarkdownLivePreview/issues
|
||||
|
||||
Tip of the day: you can duplicate a line by pressing 'ctrl+d'
|
||||
remove a line by pressing 'ctrl+shift+k'
|
||||
join lines by pressing 'ctrl+j'
|
||||
get use to use these few shortcuts, and you'll speed up
|
||||
significantly.
|
||||
8
messages/2.1.0.txt
Normal file
@ -0,0 +1,8 @@
|
||||
Sorry to interrupt you... :(
|
||||
|
||||
A settings is now available: `markdown_live_preview_on_open`. If set to true,
|
||||
it opens the window preview as soon as you open a markdown file. See the
|
||||
README for more infos.
|
||||
|
||||
Tip of the day: `ctrl+w`: closes the current file
|
||||
`ctrl+shift+w`: closes the current window
|
||||
8
messages/2.2.0.txt
Normal file
@ -0,0 +1,8 @@
|
||||
Sorry to interrupt you... :(
|
||||
|
||||
Something changed on MarkdownLivePreview: the preview is now scrolled to where
|
||||
you are editing your markdown file! It doesn't scroll back up all the time any
|
||||
more!
|
||||
|
||||
Tip of the day: You can center the screen on your cursor by pressing:
|
||||
`ctrl+k, ctrl+v` (on OSX `cmd+k, cmd+v`)
|
||||
10
messages/2.4.txt
Normal file
@ -0,0 +1,10 @@
|
||||
Sorry to interrupt you... :(
|
||||
|
||||
Some stuff changed on MarkdownLivePreview. It now supports YAML/TOML front matters. You can hide it,
|
||||
or show it in a pre block (edit your settings for this).
|
||||
|
||||
Hope you'll enjoy it!
|
||||
|
||||
Tip of the day: If you want a VIM-like search feature, then just press 'ctrl/cmd+i'
|
||||
(Find → Incremental find). You can still go the next match by pressing 'f3', and to
|
||||
the previous one by pressing 'shift+f3'
|
||||
42
messages/install.txt
Normal file
@ -0,0 +1,42 @@
|
||||
__ __ _ _ _ _ _____ _
|
||||
| \/ | | | | | | | (_) | __ \ (_)
|
||||
| \ / | __ _ _ __| | ____| | _____ ___ __ | | ___ _____| |__) | __ _____ ___ _____ __
|
||||
| |\/| |/ _` | '__| |/ / _` |/ _ \ \ /\ / / '_ \| | | \ \ / / _ \ ___/ '__/ _ \ \ / / |/ _ \ \ /\ / /
|
||||
| | | | (_| | | | < (_| | (_) \ V V /| | | | |____| |\ V / __/ | | | | __/\ V /| | __/\ V V /
|
||||
|_| |_|\__,_|_| |_|\_\__,_|\___/ \_/\_/ |_| |_|______|_| \_/ \___|_| |_| \___| \_/ |_|\___| \_/\_/
|
||||
|
||||
Thanks for installing MarkdownLivePreview! I hope you'll enjoy using it!
|
||||
|
||||
Quick Start:
|
||||
~~~~~~~~~~~~
|
||||
|
||||
To enable MarkdownLivePreview, you need to be on a markdown view (works with
|
||||
Markdown Extended). Then just press `alt+m`, or search up in the command
|
||||
palette: 'MarkdownLivePreview: Toggle'. Hit enter and you're done. As soon as
|
||||
you type anything in, it'll show up with the preview in a new group.
|
||||
|
||||
Say thanks:
|
||||
~~~~~~~~~~~
|
||||
|
||||
Just letting me know you're enjoying this plugin is a great way to say thanks!
|
||||
|
||||
You can do so by staring the GitHub repo, or sending a tweet (@_math2001) for
|
||||
example!
|
||||
|
||||
Troubles?
|
||||
~~~~~~~~~
|
||||
|
||||
If you have any kind of trouble with it, just let me now by raising an issue on
|
||||
the GitHub issue tracker here:
|
||||
|
||||
https://github.com/math2001/MarkdownLivePreview/issues
|
||||
|
||||
Tip of the day: Right click on a URL and choose 'Open <the url>' to open it in
|
||||
your default browser.
|
||||
|
||||
Credits:
|
||||
~~~~~~~~
|
||||
|
||||
The ASCII MLP has been generated using the ASCII Decorator.
|
||||
|
||||
https://github.com/viisual/ASCII-Decorator
|
||||
35
mkdocs.yml
Normal file
@ -0,0 +1,35 @@
|
||||
site_name: MarkdownLivePreview
|
||||
theme: material
|
||||
repo_name: math2001/MarkdownLivePreview
|
||||
repo_url: https://github.com/math2001/MarkdownLivePreview
|
||||
site_description: Sublime Text 3 Plugin MarkdownLivePreview's documentation
|
||||
site_author: math2001
|
||||
|
||||
markdown_extensions:
|
||||
- toc(permalink=true)
|
||||
- pymdownx.arithmatex
|
||||
- pymdownx.betterem(smart_enable=all)
|
||||
- pymdownx.caret
|
||||
- pymdownx.critic
|
||||
- pymdownx.emoji:
|
||||
emoji_generator: !!python/name:pymdownx.emoji.to_svg
|
||||
- pymdownx.inlinehilite
|
||||
- pymdownx.magiclink
|
||||
- pymdownx.mark
|
||||
- pymdownx.smartsymbols
|
||||
- pymdownx.superfences
|
||||
- pymdownx.tasklist(custom_checkbox=true)
|
||||
- pymdownx.tilde
|
||||
- admonition
|
||||
- codehilite
|
||||
|
||||
extra:
|
||||
logo: imgs/MarkdownLivePreview-opposite.svg
|
||||
palette:
|
||||
primary: Blue
|
||||
accent: Indigo
|
||||
social:
|
||||
- type: github
|
||||
link: https://github.com/math2001
|
||||
- type: twitter
|
||||
link: https://twitter.com/_math2001
|
||||
13
sample.md
@ -1,13 +0,0 @@
|
||||
# DuckDuckGo - The Search engine you'll fall in love with this is a test.
|
||||
|
||||
This is a test, and this is pretty cool!
|
||||
|
||||

|
||||
|
||||
Hope you'll enjoy using MarkdownLivePreview!
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
this is a tets
|
||||
@ -5,4 +5,5 @@ PREVIEW_ID = 'markdown_live_preview_id'
|
||||
IS_PREVIEW = 'is_markdown_live_preview'
|
||||
IS_HIDDEN = 'is_hidden_markdown_live_preview'
|
||||
MD_VIEW_ID = 'markdown_live_preview_md_id'
|
||||
JUST_CREATED = 'markdown_live_preview_just_created'
|
||||
PREVIEW_WINDOW = 'markdown_live_preview_window'
|
||||
ON_OPEN = 'markdown_live_preview_on_open'
|
||||
|
||||
12
test.md
Normal file
@ -0,0 +1,12 @@
|
||||
```python
|
||||
import this
|
||||
|
||||
if you.are('new'):
|
||||
print('Welcome!')
|
||||
if you.are('brand new'):
|
||||
print("You'll see, python's just awesome")
|
||||
else:
|
||||
print('Hello!')
|
||||
```
|
||||
|
||||

|
||||
38
todo
Normal file
@ -0,0 +1,38 @@
|
||||
Fast:
|
||||
☐ cache image in object when used, so that it's faster @needsTest
|
||||
|
||||
Medium:
|
||||
☐ auto refresh preview if loading images
|
||||
☐ use alt attribute for 404 error
|
||||
☐ optimize usage of BeautifulSoup
|
||||
|
||||
Long:
|
||||
☐ support anchor (TOC) @big
|
||||
|
||||
Unknown:
|
||||
☐ properly convert tmtheme to css
|
||||
|
||||
___________________
|
||||
Archive:
|
||||
✔ add settings to keep md view open #13 @done Sat 11 Feb 2017 at 09:10 @project(Fast)
|
||||
✔ fix custom css @bug @done Sun 22 Jan 2017 at 18:40 @project(Medium)
|
||||
✘ check how many times is the show_html function called @cancelled Sun 22 Jan 2017 at 18:40 @project(Unknown)
|
||||
✔ sync scroll @needsUpdate(because of images) @done Sun 22 Jan 2017 at 18:39 @project(Fast)
|
||||
✔ fix #4 @high @done Mon 09 Jan 2017 at 18:42 @project(Long)
|
||||
✔ use MarkdownLivePreview syntax, so we can use syntax's settings @done Mon 09 Jan 2017 at 18:41 @project(Medium)
|
||||
✔ add clear cache command @done Mon 09 Jan 2017 at 18:41 @project(Fast)
|
||||
✔ update README for settings in view @done Mon 09 Jan 2017 at 18:41 @project(Fast)
|
||||
✔ add edit settings @done Mon 09 Jan 2017 at 18:41 @project(Fast)
|
||||
✘ listen for settings to change @cancelled Mon 09 Jan 2017 at 18:41 @project(Medium)
|
||||
✘ call settings listener on_new too - might be too heavy @cancelled Sun 08 Jan 2017 at 19:33 @project(Fast)
|
||||
✔ fix relative source @done Sun 08 Jan 2017 at 19:22 @project(Medium)
|
||||
✔ add settings for the preview @done Sun 08 Jan 2017 at 17:36 @project(Fast)
|
||||
✔ regive focus to the right markdown view @done Mon 02 Jan 2017 at 18:34 @project(Fast)
|
||||
✔ try/except for 404 @done Mon 02 Jan 2017 at 18:03 @project(Fast)
|
||||
✔ fix bug when empty `src` @done Mon 02 Jan 2017 at 17:15 @project(Fast)
|
||||
✔ preview.set_scratch(True) @done Mon 02 Jan 2017 at 16:58
|
||||
✔ set the title of the preview @done Mon 02 Jan 2017 at 16:58
|
||||
✔ preview.wordWrap => True @done Mon 02 Jan 2017 at 16:58
|
||||
✔ clean the code (syntax) @done Mon 02 Jan 2017 at 16:58
|
||||
✔ add 404 image @done Mon 02 Jan 2017 at 16:57
|
||||
✔ load images from internet (`https:`) @done Mon 02 Jan 2017 at 16:57
|
||||