Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 30d75f159d | |||
| 52e4b917e5 | |||
| 48a68b2a79 | |||
| 8eb0172eb4 | |||
| 52e35fb610 | |||
| 84f809e57f | |||
| 351e8bd355 | |||
| 5babc862b4 | |||
| dc7139fbe7 | |||
| bbbeae6fe9 | |||
| 271c7c619a | |||
| 8cc6b2b263 | |||
| c7961ce94c | |||
| eae91fa428 | |||
| 6f18e8e4a2 | |||
| 48c1800065 | |||
| bad1cb74c6 | |||
| 4198504fd1 | |||
| 1bef00de14 | |||
| d707cf7a47 | |||
| c27cd5f210 | |||
| 41bbc3d03d |
@ -7,6 +7,13 @@
|
||||
"caption": "MarkdownLivePreview: Clear the cache",
|
||||
"command": "markdown_live_preview_clear_cache"
|
||||
},
|
||||
{
|
||||
"caption": "MarkdownLivePreview: Edit Custom CSS File",
|
||||
"command": "open_file",
|
||||
"args": {
|
||||
"file": "$packages/User/MarkdownLivePreview.css"
|
||||
}
|
||||
},
|
||||
{
|
||||
"caption": "Preferences: MarkdownLivePreview Settings",
|
||||
"command": "edit_settings",
|
||||
|
||||
@ -1,4 +1,12 @@
|
||||
{
|
||||
// As soon as you open a markdown file, it opens the window preview
|
||||
"markdown_live_preview_on_open": false,
|
||||
"load_from_internet_when_starts": ["http://", "https://"]
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
82
MLPApi.py
82
MLPApi.py
@ -7,6 +7,7 @@ import os.path
|
||||
from html.parser import HTMLParser
|
||||
|
||||
from .lib import markdown2 as md2
|
||||
from .lib.pre_tables import pre_tables
|
||||
from .escape_amp import *
|
||||
from .functions import *
|
||||
from .setting_names import *
|
||||
@ -15,23 +16,20 @@ from random import randint as rnd
|
||||
|
||||
__folder__ = os.path.dirname(__file__)
|
||||
|
||||
STYLE_FILE = os.path.join(os.path.dirname(__folder__), 'User',
|
||||
'MarkdownLivePreview.css')
|
||||
USER_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
|
||||
if os.path.exists(os.path.join(__folder__, 'default.css')):
|
||||
with open(os.path.join(__folder__, 'default.css')) as fp:
|
||||
DEFAULT_STYLE_FILE = fp.read()
|
||||
else:
|
||||
DEFAULT_STYLE_FILE = sublime.load_resource('Packages/MarkdownLivePreview/default.css')
|
||||
|
||||
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 create_preview(window, file_name):
|
||||
preview = window.new_file()
|
||||
|
||||
@ -44,37 +42,53 @@ def create_preview(window, file_name):
|
||||
|
||||
def get_style():
|
||||
content = ''.join([line.strip() + ' ' for line in DEFAULT_STYLE_FILE.splitlines()])
|
||||
return content + "pre code .space {color: var(--light-bg)}"
|
||||
if os.path.exists(USER_STYLE_FILE):
|
||||
with open(USER_STYLE_FILE) as fp:
|
||||
content += '\n' + fp.read() + '\n'
|
||||
return content
|
||||
|
||||
def markdown2html(md, basepath):
|
||||
html = '<style>\n{}\n</style>\n'.format(get_style())
|
||||
|
||||
# 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', 'no-code-highlighting', 'tables'])
|
||||
|
||||
# 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)
|
||||
|
||||
# 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)
|
||||
|
||||
# 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
|
||||
# so, because this is monosaped font, I just replace it with a '.' and make transparent ;)
|
||||
html = html.replace(' ', '<i class="space">.</i>')
|
||||
|
||||
# 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=os.path.dirname(basepath))
|
||||
|
||||
# BeautifulSoup uses the <br/> but the sublime phantoms do not support them...
|
||||
html = html.replace('<br/>', '<br />')
|
||||
|
||||
return html
|
||||
|
||||
def show_html(md_view, preview):
|
||||
global windows_phantom_set
|
||||
html = []
|
||||
html.append('<style>\n{}\n</style>'.format(get_style()))
|
||||
html.append(pre_with_br(md2.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 = '\n'.join(html)
|
||||
|
||||
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, basepath=os.path.dirname(
|
||||
md_view.file_name()))
|
||||
html = markdown2html(get_view_content(md_view), os.path.dirname(md_view.file_name()))
|
||||
|
||||
phantom_set = windows_phantom_set.setdefault(preview.window().id(),
|
||||
sublime.PhantomSet(preview,
|
||||
'markdown_live_preview'))
|
||||
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}))])
|
||||
|
||||
# lambda href: sublime.run_command('open_url', {'url': href})
|
||||
# get the "ratio" of the markdown view's position.
|
||||
|
||||
@ -15,6 +15,7 @@ class NewMarkdownLivePreviewCommand(sublime_plugin.ApplicationCommand):
|
||||
|
||||
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 '
|
||||
|
||||
@ -1,21 +1,22 @@
|
||||
Fast:
|
||||
☐ sync scroll @needsUpdate(because of images)
|
||||
☐ cache image in object when used, so that it's faster @needsTest
|
||||
☐ add settings to keep md view open #13
|
||||
|
||||
Medium:
|
||||
☐ auto refresh preview if loading images
|
||||
☐ use alt attribute for 404 error
|
||||
☐ fix custom css @bug
|
||||
|
||||
Long:
|
||||
☐ support hanchor (TOC) @big
|
||||
☐ support anchor (TOC) @big
|
||||
|
||||
Unknown:
|
||||
☐ check how many times is the show_html function called
|
||||
|
||||
|
||||
___________________
|
||||
Archive:
|
||||
✔ 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)
|
||||
|
||||
76
README.md
76
README.md
@ -4,44 +4,65 @@ 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
|
||||
|
||||
MarkdownLivePreview is available on the default channel of [PackageControl](http://packagecontrol.io), which means you just have to
|
||||
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>
|
||||
|
||||
to have MarkdownLivePreview working on your computer. Cool right? You can [thank package control](https://packagecontrol.io/say_thanks) for this.
|
||||
to have MarkdownLivePreview working on your computer. Cool right? You can
|
||||
[thank package control](https://packagecontrol.io/say_thanks) for this.
|
||||
|
||||
### Usage
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
*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*
|
||||
*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*
|
||||
|
||||
### Settings
|
||||
|
||||
- `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](https://github.com/ooing) for its [suggestion](https://github.com/math2001/MarkdownLivePreview/issues/7#issue-199464852)). 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://"]`
|
||||
- `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](https://github.com/ooing) for its
|
||||
[suggestion](https://github.com/math2001/MarkdownLivePreview/issues/7#issue-199464852)). 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://"]`
|
||||
|
||||
Note: To edit your settings, search up in the command palette `Preferences: MarkdownLivePreview Settings`, or by using the menu: `Preferences → Packages Settings → MarkdownLivePreview → Settings` ;. It's not your global settings, but only the `MarkdownLivePreview`'s one
|
||||
Note: To edit your settings, search up in the command palette
|
||||
`Preferences: MarkdownLivePreview Settings`, or by using the menu:
|
||||
*Preferences → Packages Settings → MarkdownLivePreview → Settings*;. It's not your global settings,
|
||||
but only the `MarkdownLivePreview`'s one
|
||||
|
||||
### Syntax Specific Settings
|
||||
|
||||
This in an other "type" of setting. :laughing: If you have a look at the syntax of the preview file (not the markdown one, really the preview), you'll see that the syntax is `MarkdownLivePreviewSyntax`. This mean that you can specify specific settings for this specific syntax (such as `word_wrap: true`, `rulers: []`, etc).
|
||||
This in an other "type" of setting. :laughing: If you have a look at the syntax of the preview file
|
||||
(not the markdown one, really the preview), you'll see that the syntax is
|
||||
`MarkdownLivePreviewSyntax`. This mean that you can specify specific settings for this specific
|
||||
syntax (such as `word_wrap: true`, `rulers: []`, etc).
|
||||
|
||||
To do so, you can
|
||||
|
||||
1. focus the *preview* (<kbd>ctrl+2</kbd> to focus the second group, so, by default, the preview's group)
|
||||
2. search up in the command palette `Preferences: Settings Syntax Specific`. It's in the *right* file that you can add the settings you want (not the left one).
|
||||
1. focus the *preview* (<kbd>ctrl+2</kbd> to focus the second group, so, by default, the
|
||||
preview's group)
|
||||
2. search up in the command palette `Preferences: Settings Syntax Specific`. It's in the *right*
|
||||
file that you can add the settings you want (not the left one).
|
||||
|
||||
Note: MarkdownLivePreview will actualy look in this file for settings that aren't supported by default. Here they are:
|
||||
Note: MarkdownLivePreview will actualy look in this file for settings that aren't supported by
|
||||
default. Here they are:
|
||||
|
||||
- `show_tabs`
|
||||
- `show_minimap`
|
||||
@ -49,7 +70,9 @@ Note: MarkdownLivePreview will actualy look in this file for settings that aren'
|
||||
- `show_sidebar`
|
||||
- `show_menus`
|
||||
|
||||
They talk for themself, don't they? All of them takes a boolean (`true` or `false`). Note that those settings are *window* specific, not just view specific (that's why they aren't supported). It means that they'll affect the entire window, and every view in it.
|
||||
They talk for themself, don't they? All of them takes a boolean (`true` or `false`). Note that those
|
||||
settings are *window* specific, not just view specific (that's why they aren't supported). It means
|
||||
that they'll affect the entire window, and every view in it.
|
||||
|
||||
Here is an example of syntax specific settings for MarkdownLivePreviewSyntax:
|
||||
|
||||
@ -72,7 +95,9 @@ And here's what you'll get:
|
||||
|
||||
### Clear the cache
|
||||
|
||||
MarkdownLivePreview caches every images it loads from internet (otherwise, you'd never see your images, or you'd need to have a *really* fast internet connection :smile:). So, if for some reason you want to clear the cache (a simple file), you can do so from the command palette by running `
|
||||
MarkdownLivePreview caches every images it loads from internet (otherwise, you'd never see your
|
||||
images, or you'd need to have a *really* fast internet connection :smile:). So, if for some reason
|
||||
you want to clear the cache (a simple file), you can do so from the command palette by running `
|
||||
|
||||
### Demo
|
||||
|
||||
@ -80,17 +105,26 @@ MarkdownLivePreview caches every images it loads from internet (otherwise, you'd
|
||||
|
||||
### Custom css
|
||||
|
||||
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 → Style - CSS`. 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.
|
||||
It is possible to set your own css. But, be carefull, you have to respect
|
||||
[those rules][st-css-rules]. Just go to
|
||||
`Preferences → Package Settings → MarkdownLivePreview → Style - CSS`. 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.
|
||||
|
||||
### Somethings wrong!!
|
||||
|
||||
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)
|
||||
|
||||
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).
|
||||
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][]
|
||||
|
||||
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
|
||||
|
||||
34
default.css
34
default.css
@ -1,6 +1,8 @@
|
||||
html {
|
||||
--light-bg: color(var(--background) blend(#999 85%));
|
||||
--very-light-bg: color(var(--background) blend(#999 92%));
|
||||
}
|
||||
|
||||
body {
|
||||
padding: 10px;
|
||||
padding-top: 0px;
|
||||
@ -13,7 +15,6 @@ blockquote {
|
||||
font-style: italic;
|
||||
display: block;
|
||||
margin-left: 30px;
|
||||
border: 1px solid red;
|
||||
}
|
||||
|
||||
code {
|
||||
@ -22,28 +23,41 @@ code {
|
||||
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;
|
||||
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 .29412em;
|
||||
border-radius: .2rem;
|
||||
background-color: #f5f5f5;
|
||||
color: #555;
|
||||
box-shadow: 0 0.1rem 0 #b0b0b0;
|
||||
word-break: break-word;
|
||||
padding: 0 5px;
|
||||
background-color: var(--very-light-bg);
|
||||
font-family: "Roboto Mono","Courier New",Courier,monospace;
|
||||
}
|
||||
|
||||
7
dependencies.json
Normal file
7
dependencies.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"*": {
|
||||
"*": [
|
||||
"bs4"
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -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
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
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 |
@ -1,4 +1,7 @@
|
||||
Welcome to MarkdownLivePreview's documentation!
|
||||
# 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!
|
||||
@ -56,7 +59,26 @@ As told in the introduction, MarkdownLivePreview is very easy to use:
|
||||
!!! tip
|
||||
[Markdown Extended][] is supported too!
|
||||
|
||||
That's it.
|
||||
That's it. That's all you need to do to preview your markdown!
|
||||
|
||||
### 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
|
||||
|
||||
@ -112,18 +134,19 @@ Here's what I'd recommend (and use):
|
||||
}
|
||||
```
|
||||
|
||||
!!! note
|
||||
!!! tip
|
||||
On Windows at least, you can press <kbd>alt</kbd> to focus (so show) the menu, 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
|
||||
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" width="160px" height="30px"></iframe>!
|
||||
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
|
||||
[pck-con-ins]: https://packagecontrol.io/installation
|
||||
[install-pck-con]: https://packagecontrol.io/installation
|
||||
[tweet]: https://twitter.com/_math2001
|
||||
[GitHub repo]: https://github.com/math2001/MarkdownLivePreview/issues
|
||||
|
||||
24
docs/license.md
Normal file
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.
|
||||
64
functions.py
64
functions.py
@ -4,38 +4,41 @@ import os.path
|
||||
import sublime
|
||||
import re
|
||||
from .image_manager import ImageManager
|
||||
from bs4 import BeautifulSoup, Comment as html_comment
|
||||
|
||||
def plugin_loaded():
|
||||
global error404, loading
|
||||
loading = sublime.load_resource('Packages/MarkdownLivePreview/loading.txt')
|
||||
error404 = sublime.load_resource('Packages/MarkdownLivePreview/404.txt')
|
||||
|
||||
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 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):
|
||||
"""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/'):
|
||||
soup = BeautifulSoup(html)
|
||||
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, src))
|
||||
|
||||
else:
|
||||
# local image
|
||||
path = ''.join(path)
|
||||
path = os.path.join(basepath, path)
|
||||
image = to_base64(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)
|
||||
@ -89,14 +92,9 @@ def get_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
|
||||
soup = BeautifulSoup(html)
|
||||
for pre in soup.find_all('pre'):
|
||||
code = pre.find('code')
|
||||
code.replaceWith(BeautifulSoup(''.join(str(node) for node in pre.contents) \
|
||||
.replace('\n', '<br/>').replace(' ', '<i class="space">.</i>'), 'html.parser'))
|
||||
return str(soup)
|
||||
|
||||
52
lib/pre_tables.py
Normal file
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)
|
||||
@ -24,6 +24,7 @@ markdown_extensions:
|
||||
- codehilite
|
||||
|
||||
extra:
|
||||
logo: imgs/MarkdownLivePreview-opposite.svg
|
||||
palette:
|
||||
primary: Blue
|
||||
accent: Indigo
|
||||
|
||||
31
sample.md
31
sample.md
@ -1,11 +1,40 @@
|
||||
# Hello world
|
||||
|
||||
<!-- supports comments -->
|
||||
|
||||
And `<!-- vicious ones ;) -->`
|
||||
|
||||
Some `inline code` with *italic* and **bold** text.
|
||||
|
||||
```python
|
||||
import this
|
||||
if you('are', 'curious'):
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user