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