-
Notifications
You must be signed in to change notification settings - Fork 71
/
note_support.py
125 lines (109 loc) · 4.6 KB
/
note_support.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import sublime, sublime_plugin
import webbrowser
import urllib.request
import base64
import io
import struct
ST3072 = int(sublime.version()) >= 3072
def is_enabled_for_view(view):
valid_syntax = ['Note.tmLanguage', 'Note.sublime-syntax']
syntax = view.settings().get("syntax")
return any(syntax.endswith(s) for s in valid_syntax)
class NoteOpenUrlCommand(sublime_plugin.TextCommand):
def run(self, edit):
v = self.view
s = v.sel()[0]
link_region = v.extract_scope(s.a)
url = v.substr(link_region)
webbrowser.open_new_tab(url)
def is_enabled(self):
return is_enabled_for_view(self.view)
if ST3072:
class NotePreviewImageCommand(sublime_plugin.TextCommand):
def run(self, edit):
v = self.view
s = v.sel()[0]
link_region = v.extract_scope(s.a)
url = v.substr(link_region)
req = urllib.request.Request(url, headers={"Range": "5000"})
r = urllib.request.urlopen(req)
mime, w, h = self.getImageInfo(r.read())
max_w, max_h = v.viewport_extent()
print(mime, w, h, max_w, max_h)
if 'image' in mime:
response = urllib.request.urlopen(url)
data = response.read()
b64 = base64.b64encode(data)
win_w, win_h = self.getPreviewDimensions(w, h, max_w, max_h)
print(win_w, win_h)
style = '<style>body, html {margin: 0; padding: 0}</style>'
html = style + '<img height="' + str(win_h) + '" width="' + str(win_w) + '" src="data:image/png;base64,' + b64.decode('utf-8') + '">'
v.show_popup(html, max_width=win_w, max_height=win_h, location=link_region.a)
def getPreviewDimensions(self, w, h, max_w, max_h):
margin = 100
if w > (max_h - margin) or h > (max_h - margin):
ratio = w / (h * 1.0)
if max_w >= max_h:
height = (max_h - margin)
width = height * ratio
else:
width = (max_w - margin)
height = width / ratio
return (width, height)
else:
return (w, h)
def getImageInfo(self, data):
data = data
size = len(data)
height = -1
width = -1
content_type = ''
# handle GIFs
if (size >= 10) and data[:6] in (b'GIF87a', b'GIF89a'):
# Check to see if content_type is correct
content_type = 'image/gif'
w, h = struct.unpack(b"<HH", data[6:10])
width = int(w)
height = int(h)
# See PNG 2. Edition spec (http://www.w3.org/TR/PNG/)
# Bytes 0-7 are below, 4-byte chunk length, then 'IHDR'
# and finally the 4-byte width, height
elif ((size >= 24) and data.startswith(b'\211PNG\r\n\032\n') and
(data[12:16] == b'IHDR')):
content_type = 'image/png'
w, h = struct.unpack(b">LL", data[16:24])
width = int(w)
height = int(h)
# Maybe this is for an older PNG version.
elif (size >= 16) and data.startswith(b'\211PNG\r\n\032\n'):
# Check to see if we have the right content type
content_type = 'image/png'
w, h = struct.unpack(b">LL", data[8:16])
width = int(w)
height = int(h)
# handle JPEGs
elif (size >= 2) and data.startswith(b'\377\330'):
content_type = 'image/jpeg'
jpeg = io.BytesIO(data)
jpeg.read(2)
b = jpeg.read(1)
try:
while (b and ord(b) != 0xDA):
while (ord(b) != 0xFF): b = jpeg.read(1)
while (ord(b) == 0xFF): b = jpeg.read(1)
if (ord(b) >= 0xC0 and ord(b) <= 0xC3):
jpeg.read(3)
h, w = struct.unpack(b">HH", jpeg.read(4))
break
else:
jpeg.read(int(struct.unpack(b">H", jpeg.read(2))[0])-2)
b = jpeg.read(1)
width = int(w)
height = int(h)
except struct.error:
pass
except ValueError:
pass
return content_type, width, height
def is_enabled(self):
return is_enabled_for_view(self.view)