908 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			908 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import sublime
 | |
| import sublime_plugin
 | |
| from os import path
 | |
| import tempfile
 | |
| import sys
 | |
| import time
 | |
| import webbrowser
 | |
| import re
 | |
| from HtmlAnnotations import get_annotations
 | |
| import ExportHtmlLib.desktop as desktop
 | |
| import json
 | |
| 
 | |
| PACKAGE_SETTINGS = "ExportHtml.sublime-settings"
 | |
| JS_DIR = path.join(sublime.packages_path(), 'ExportHtml', "js")
 | |
| CSS_DIR = path.join(sublime.packages_path(), 'ExportHtml', "css")
 | |
| 
 | |
| if sublime.platform() == "linux":
 | |
|     # Try and load Linux Python2.6 lib.  Default path is for Ubuntu.
 | |
|     linux_lib = sublime.load_settings(PACKAGE_SETTINGS).get("linux_python2.6_lib", "/usr/lib/python2.6/lib-dynload")
 | |
|     if not linux_lib in sys.path and path.exists(linux_lib):
 | |
|         sys.path.append(linux_lib)
 | |
| from plistlib import readPlist
 | |
| from ExportHtmlLib.rgba.rgba import RGBA
 | |
| 
 | |
| FILTER_MATCH = re.compile(r'^(?:(brightness|saturation|hue|colorize)\((-?[\d]+|[\d]*\.[\d]+)\)|(sepia|grayscale|invert))$')
 | |
| 
 | |
| # HTML Code
 | |
| HTML_HEADER = \
 | |
| '''<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
 | |
| <html>
 | |
| <head>
 | |
| <title>%(title)s</title>
 | |
| <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
 | |
| <meta http-equiv="Pragma" content="no-cache" />
 | |
| <meta http-equiv="Expires" content="0" />
 | |
| <style type="text/css">
 | |
| %(css)s
 | |
| </style>
 | |
| %(js)s
 | |
| </head>
 | |
| '''
 | |
| 
 | |
| TOOL_GUTTER = '''<img onclick="toggle_gutter();" alt="" title="Toggle Gutter" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3AofFg8FBLseHgAAAAxpVFh0Q29tbWVudAAAAAAAvK6ymQAAAM5JREFUOMvdjzFqAlEQhuephZWNYEq9wJ4kt7C08AiyhWCXQI6xh5CtUqVJEbAU1kA6i92VzWPnmxR5gUUsfAQbf5himPm+YURumSzLetFQWZZj4Bn45DcHYFMUxfAqAbA1MwO+gHeA0L9cJfDeJ6q6yvO8LyKiqosgOKVp6qJf8t4nQfD9J42Kqi6D4DUabppmBhzNzNq2fYyC67p+AHbh+iYKrqpqAnwE+Ok/8Dr6b+AtwArsu6Wq8/P9wQXHTETEOdcTkWl3YGYjub/8ANrnvguZ++ozAAAAAElFTkSuQmCC" />'''
 | |
| 
 | |
| TOOL_PLAIN_TEXT = '''<img onclick="toggle_plain_text();" alt="" title="Toggle Plain" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3AofFg8dF9eGSAAAAAxpVFh0Q29tbWVudAAAAAAAvK6ymQAAANRJREFUOMvdkTFOgkEQhResaeQScAsplIRGDgKttnsIOYIUm1hQa/HfQiMFcIBt9k/UTWa/sRkbspKfzviS7eZ7M/uec39WbdsOgU/gI6V0ebZBKeVeTaWUu7PgpmkugD3wZW8XQuh3NhCRuaoq8AisVVVF5LazAfBi0JWITMzsuROccx4b8O6cc977HrAFyDmPumxfHQf3EyjwcBKOMQ6ApL8ISDHGwanqljb4VLlsY5ctqrD99c3Cm1aamZn5q/e+V6vuxgb2tc5DCH3gYAuu3f/RNzmJ99G3cZ53AAAAAElFTkSuQmCC" />'''
 | |
| 
 | |
| TOOL_PRINT = '''<img onclick="page_print();" alt="" title="Print" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3AofFhAl8o8wSAAAAAxpVFh0Q29tbWVudAAAAAAAvK6ymQAAAQZJREFUOMulkzFSgjEUhL8X/xJ/iBegkAtQ6A08gIUehFthYykOw9BzBmwcaxGoZW1eZjIx/sC4TTJv8ja7mxfDIcmAAWDUIeDLzJQXm2w/AFZOkB8yoAU+gHtJ7yVJUnAlaS1pJOm6WN8kjSUtJQ1dLQChIvMATIEXXw9e3wMT4NnV/rKQsAcegAvgG9g5wcwv7OU51QgugSegD2yBO+DWmyLw+leINQXyW5VeoQj4qIIcW+CxPFwjSLKtEnAZOkGSSYruL3QMUxq0AERJUZKl5pV7bjsmMR+qHfAJ3DReDB4cwKLiv0R0S5Yy6ANz37ecgSZ7nui1zYm9G0B2wi+k63fyX/wA0b9vjF8iB3oAAAAASUVORK5CYII=" />'''
 | |
| 
 | |
| TOOL_ANNOTATION = '''<img onclick="toggle_annotations();" alt="" title="Toggle Annotations" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3AofFhAIt1BsPQAAAAxpVFh0Q29tbWVudAAAAAAAvK6ymQAAALVJREFUOMvNkkESgjAUQ/Or+8IN9A7ewHN7FRgvwIB7eW6+WGsRRjZm05n+Jn+aRNoIyy8Ak1QVZkjqzYyiQEKsJF0kxUxgkHSW1Eu6mdn9bStwABqgA0Y+MfqsBU7ALie3M8SS0NU5JqD2zWvIqUgD1MF9iCVDF8yPkixsjTF4PIOfa/Hi/GhiO5mYJHH0mL4ROzdvIu+TAoW8ddm30iJNjTQgevOqpMLPx8NilWe6X3z8n3gAfmBJ5rRJVyQAAAAASUVORK5CYII=" />'''
 | |
| 
 | |
| TOOL_DUMP_THEME = '''<img onclick="dump_theme();" alt="" title="Download" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3AofFhAWTV9RXgAAAAxpVFh0Q29tbWVudAAAAAAAvK6ymQAAAJtJREFUOMvdk9ENwyAQQ5+rDBA6QZbI/gN0h3YE2gXi/lykhABN1b9aQkh3+CEwiEK2BYyAyhbwlORtceCoEbgBqahnYI65C1CYr43eThd+1B8Ahkp0qXZZa8/2LlIFIG2i676DmDMwS8pDcZzW7tt4DbwOr8/2ZPthe3FbS6yZ4thfQdrmE5DP5g7kvLkCucdomtWDRJzUvvGqN6JK1cOooSjlAAAAAElFTkSuQmCC" />'''
 | |
| 
 | |
| TOOL_WRAPPING = '''<img onclick="toggle_wrapping();" alt="" title="Toggle Wrapping" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3AsBFiYl9jWoIQAAAAxpVFh0Q29tbWVudAAAAAAAvK6ymQAAAP1JREFUOMudk0FuwkAMRZ+jbCGZXADlKvS8HKG9Qa8Q1K5LSLpG+ixwUmdKQMLSSDOeb/v7e8bITJIBNWD5FTCYmaLT7gTWwDtQZQlG4A0YYiILwTvgwxNsgV+vOuEm3wDsga+ZjaQkqZN0kdT7vpXU+Grd1zumk5Rm6g44STr6PjmriEl+d3RsK8li9T/nimXFOkmp8P4mwcZc5YXit7vRjxVgBQ/MK1aPWBWu9Jw1A9c+mZ0nW7AFdLevwKCR9BPE/SdiaWaSNADntdb9jXz6eQt8L15lGFM+vsarRevjtMqg7pkXrHghZiFs+QS8xmwDHIC9PXsHK197/t5XQswlGeOCYgkAAAAASUVORK5CYII=" />'''
 | |
| 
 | |
| TOOLBAR = '''<div id="toolbarhide"><div id="toolbar">%(options)s</div></div>'''
 | |
| 
 | |
| ANNOTATE_OPEN = '''<span onclick="toggle_annotations();" class="tooltip_hotspot" onmouseover="tooltip.show(%(comment)s);" onmouseout="tooltip.hide();">%(code)s'''
 | |
| 
 | |
| ANNOTATE_CLOSE = '''</span>'''
 | |
| 
 | |
| BODY_START = '''<body class="code_page code_text"><pre class="code_page">'''
 | |
| 
 | |
| FILE_INFO = '''<tr><td colspan="2"><div id="file_info"><span style="color: %(color)s">%(date_time)s %(file)s\n\n</span></div></td></tr>'''
 | |
| 
 | |
| TABLE_START = '''<table cellspacing="0" cellpadding="0" class="code_page">'''
 | |
| 
 | |
| LINE = (
 | |
|     '<tr>' +
 | |
|     '<td valign="top" id="L_%(table)d_%(line_id)d" class="code_text code_gutter">' +
 | |
|     '<span style="color: %(color)s;">%(line)s </span>' +
 | |
|     '</td>' +
 | |
|     '<td valign="top" class="code_text code_line" style="background-color: %(pad_color)s;">' +
 | |
|     '<div id="C_%(table)d_%(code_id)d">%(code)s\n</div>' +
 | |
|     '</td>' +
 | |
|     '</tr>'
 | |
| )
 | |
| 
 | |
| CODE = '''<span class="%(class)s" style="background-color: %(highlight)s; color: %(color)s;">%(content)s</span>'''
 | |
| ANNOTATION_CODE = '''<span style="background-color: %(highlight)s;"><a href="javascript:void();" class="annotation"><span class="%(class)s annotation" style="color: %(color)s;">%(content)s</span></a></span>'''
 | |
| 
 | |
| TABLE_END = '''</table>'''
 | |
| 
 | |
| ROW_START = '''<tr><td>'''
 | |
| 
 | |
| ROW_END = '''</td></tr>'''
 | |
| 
 | |
| DIVIDER = '''<span style="color: %(color)s">\n...\n\n</span>'''
 | |
| 
 | |
| ANNOTATION_TBL_START = (
 | |
|     '<div id="comment_list" style="display:none"><div id="comment_wrapper">' +
 | |
|     '<table id="comment_table">' +
 | |
|     '<tr><th>Line/Col</th><th>Comments' +
 | |
|     '<a href="javascript:void(0)" class="table_close" onclick="toggle_annotations();return false;">(close)</a>'
 | |
|     '</th></tr>'
 | |
| )
 | |
| 
 | |
| ANNOTATION_TBL_END = '''</table></div></div>'''
 | |
| 
 | |
| ANNOTATION_ROW = (
 | |
|     '<tr>' +
 | |
|     '<td class="annotation_link">' +
 | |
|     '<a href="javascript:void(0)" onclick="scroll_to_line(\'C_%(table)d_%(row)d\');return false;">%(link)s</a>' +
 | |
|     '</td>' +
 | |
|     '<td class="annotation_comment"><div class="annotation_comment">%(comment)s</div></td>' +
 | |
|     '<tr>'
 | |
| )
 | |
| 
 | |
| ANNOTATION_FOOTER = (
 | |
|     '<tr><td colspan=2>' +
 | |
|     '<div class="table_footer"><label>Position </label>' +
 | |
|     '<select id="dock" size="1" onchange="dock_table();">' +
 | |
|     '<option value="0" selected="selected">center</option>' +
 | |
|     '<option value="1">top</option>' +
 | |
|     '<option value="2">bottom</option>' +
 | |
|     '<option value="3">left</option>' +
 | |
|     '<option value="4">right</option>' +
 | |
|     '<option value="5">top left</option>' +
 | |
|     '<option value="6">top right</option>' +
 | |
|     '<option value="7">bottom left</option>' +
 | |
|     '<option value="8">bottom right</option>' +
 | |
|     '</select>' +
 | |
|     '</div>' +
 | |
|     '</td></tr>'
 | |
| )
 | |
| 
 | |
| BODY_END = '''</pre>%(toolbar)s\n%(js)s\n</body>\n</html>\n'''
 | |
| 
 | |
| INCLUDE_THEME = \
 | |
| '''
 | |
| <script type="text/javascript">
 | |
| %(jscode)s
 | |
| plist.color_scheme = %(theme)s;
 | |
| 
 | |
| function dump_theme() {
 | |
|     extract_theme('%(name)s');
 | |
| }
 | |
| </script>
 | |
| '''
 | |
| 
 | |
| TOGGLE_LINE_OPTIONS = \
 | |
| '''
 | |
| <script type="text/javascript">
 | |
| %(jscode)s
 | |
| 
 | |
| page_line_info.wrap      = false;
 | |
| page_line_info.ranges    = [%(ranges)s];
 | |
| page_line_info.wrap_size = %(wrap_size)d;
 | |
| page_line_info.tables    = %(tables)s;
 | |
| page_line_info.header    = %(header)s;
 | |
| page_line_info.gutter    = %(gutter)s;
 | |
| </script>
 | |
| '''
 | |
| 
 | |
| AUTO_PRINT = \
 | |
| '''
 | |
| <script type="text/javascript">
 | |
| document.getElementsByTagName('body')[0].onload = function (e) { page_print(); self.onload = null; };
 | |
| </script>
 | |
| '''
 | |
| 
 | |
| WRAP = \
 | |
| '''
 | |
| <script type="text/javascript">
 | |
| toggle_wrapping();
 | |
| </script>
 | |
| '''
 | |
| 
 | |
| HTML_JS_WRAP = \
 | |
| '''
 | |
| <script type="text/javascript">
 | |
| %(jscode)s
 | |
| </script>
 | |
| '''
 | |
| 
 | |
| 
 | |
| def getjs(file_name):
 | |
|     code = ""
 | |
|     try:
 | |
|         with open(path.join(JS_DIR, file_name), "r") as f:
 | |
|             code = f.read()
 | |
|     except:
 | |
|         pass
 | |
|     return code
 | |
| 
 | |
| 
 | |
| def getcss(file_name, options):
 | |
|     code = ""
 | |
|     final_code = ""
 | |
|     last_pt = 0
 | |
|     keys = '|'.join(options.keys())
 | |
|     replace = re.compile("/\\* *%(" + keys + ")% * \\*/")
 | |
| 
 | |
|     try:
 | |
|         with open(path.join(CSS_DIR, file_name), "r") as f:
 | |
|             code = f.read()
 | |
|             for m in replace.finditer(code):
 | |
|                 final_code += code[last_pt:m.start()] + options[m.group(1)]
 | |
|                 last_pt = m.end()
 | |
|             final_code += code[last_pt:]
 | |
|     except:
 | |
|         pass
 | |
| 
 | |
|     return final_code
 | |
| 
 | |
| 
 | |
| class ExportHtmlPanelCommand(sublime_plugin.WindowCommand):
 | |
|     def execute(self, value):
 | |
|         if value >= 0:
 | |
|             view = self.window.active_view()
 | |
|             if view != None:
 | |
|                 ExportHtml(view).run(**self.args[value])
 | |
| 
 | |
|     def run(self):
 | |
|         options = sublime.load_settings(PACKAGE_SETTINGS).get("html_panel", {})
 | |
|         menu = []
 | |
|         self.args = []
 | |
|         for opt in options:
 | |
|             k, v = opt.items()[0]
 | |
|             menu.append(k)
 | |
|             self.args.append(v)
 | |
| 
 | |
|         if len(menu):
 | |
|             self.window.show_quick_panel(
 | |
|                 menu,
 | |
|                 self.execute
 | |
|             )
 | |
| 
 | |
| 
 | |
| class ExportHtmlCommand(sublime_plugin.WindowCommand):
 | |
|     def run(self, **kwargs):
 | |
|         view = self.window.active_view()
 | |
|         if view != None:
 | |
|             ExportHtml(view).run(**kwargs)
 | |
| 
 | |
| 
 | |
| class ExportHtml(object):
 | |
|     def __init__(self, view):
 | |
|         self.view = view
 | |
| 
 | |
|     def process_inputs(self, **kwargs):
 | |
|         return {
 | |
|             "numbers": bool(kwargs.get("numbers", False)),
 | |
|             "highlight_selections": bool(kwargs.get("highlight_selections", False)),
 | |
|             "browser_print": bool(kwargs.get("browser_print", False)),
 | |
|             "color_scheme": kwargs.get("color_scheme", None),
 | |
|             "wrap": kwargs.get("wrap", None),
 | |
|             "multi_select": bool(kwargs.get("multi_select", False)),
 | |
|             "style_gutter": bool(kwargs.get("style_gutter", True)),
 | |
|             "no_header": bool(kwargs.get("no_header", False)),
 | |
|             "date_time_format": kwargs.get("date_time_format", "%m/%d/%y %I:%M:%S"),
 | |
|             "show_full_path": bool(kwargs.get("show_full_path", True)),
 | |
|             "toolbar": kwargs.get("toolbar", ["plain_text", "gutter", "wrapping", "print", "annotation", "theme"]),
 | |
|             "save_location": kwargs.get("save_location", None),
 | |
|             "time_stamp": kwargs.get("time_stamp", "_%m%d%y%H%M%S"),
 | |
|             "clipboard_copy": bool(kwargs.get("clipboard_copy", False)),
 | |
|             "view_open": bool(kwargs.get("view_open", False)),
 | |
|             "shift_brightness": bool(kwargs.get("shift_brightness", False)),
 | |
|             "filter": kwargs.get("filter", "")
 | |
|         }
 | |
| 
 | |
|     def setup(self, **kwargs):
 | |
|         path_packages = sublime.packages_path()
 | |
| 
 | |
|         # Get get general document preferences from sublime preferences
 | |
|         eh_settings = sublime.load_settings(PACKAGE_SETTINGS)
 | |
|         settings = sublime.load_settings('Preferences.sublime-settings')
 | |
|         alternate_font_size = eh_settings.get("alternate_font_size", False)
 | |
|         alternate_font_face = eh_settings.get("alternate_font_face", False)
 | |
|         self.font_size = settings.get('font_size', 10) if alternate_font_size == False else alternate_font_size
 | |
|         self.font_face = settings.get('font_face', 'Consolas') if alternate_font_face == False else alternate_font_face
 | |
|         self.tab_size = settings.get('tab_size', 4)
 | |
|         self.padd_top = settings.get('line_padding_top', 0)
 | |
|         self.padd_bottom = settings.get('line_padding_bottom', 0)
 | |
|         self.char_limit = int(eh_settings.get("valid_selection_size", 4))
 | |
|         self.bground = ''
 | |
|         self.fground = ''
 | |
|         self.gbground = ''
 | |
|         self.gfground = ''
 | |
|         self.sbground = ''
 | |
|         self.sfground = ''
 | |
|         self.numbers = kwargs["numbers"]
 | |
|         self.date_time_format = kwargs["date_time_format"]
 | |
|         self.time = time.localtime()
 | |
|         self.show_full_path = kwargs["show_full_path"]
 | |
|         self.highlight_selections = kwargs["highlight_selections"]
 | |
|         self.browser_print = kwargs["browser_print"]
 | |
|         self.auto_wrap = kwargs["wrap"] != None and int(kwargs["wrap"]) > 0
 | |
|         self.wrap = 900 if not self.auto_wrap else int(kwargs["wrap"])
 | |
|         self.hl_continue = None
 | |
|         self.curr_hl = None
 | |
|         self.sels = []
 | |
|         self.multi_select = self.check_sel() if kwargs["multi_select"] and not kwargs["highlight_selections"] else False
 | |
|         self.size = self.view.size()
 | |
|         self.pt = 0
 | |
|         self.end = 0
 | |
|         self.curr_row = 0
 | |
|         self.tables = 0
 | |
|         self.curr_annot = None
 | |
|         self.curr_comment = None
 | |
|         self.annotations = self.get_annotations()
 | |
|         self.annot_num = -1
 | |
|         self.new_annot = False
 | |
|         self.open_annot = False
 | |
|         self.no_header = kwargs["no_header"]
 | |
|         self.annot_tbl = []
 | |
|         self.toolbar = kwargs["toolbar"]
 | |
|         self.toolbar_orientation = "block" if eh_settings.get("toolbar_orientation", "horizontal") == "vertical" else "inline-block"
 | |
|         self.matched = {}
 | |
|         self.ebground = self.bground
 | |
|         self.dark_lumens = None
 | |
|         self.lumens_limit = float(eh_settings.get("bg_min_lumen_threshold", 62))
 | |
|         self.filter = []
 | |
|         for f in kwargs["filter"].split(";"):
 | |
|             m = FILTER_MATCH.match(f)
 | |
|             if m:
 | |
|                 if m.group(1):
 | |
|                     self.filter.append((m.group(1), float(m.group(2))))
 | |
|                 else:
 | |
|                     self.filter.append((m.group(3), 0.0))
 | |
| 
 | |
|         fname = self.view.file_name()
 | |
|         if fname == None or not path.exists(fname):
 | |
|             fname = "Untitled"
 | |
|         self.file_name = fname
 | |
| 
 | |
|         # Get color scheme
 | |
|         if kwargs["color_scheme"] != None:
 | |
|             alt_scheme = kwargs["color_scheme"]
 | |
|         else:
 | |
|             alt_scheme = eh_settings.get("alternate_scheme", False)
 | |
|         scheme_file = settings.get('color_scheme') if alt_scheme == False else alt_scheme
 | |
|         colour_scheme = path.normpath(scheme_file)
 | |
|         self.scheme_file = path.basename(colour_scheme)
 | |
|         self.plist_file = self.apply_filters(readPlist(path_packages + colour_scheme.replace('Packages', '')))
 | |
|         colour_settings = self.plist_file["settings"][0]["settings"]
 | |
| 
 | |
|         # Get general theme colors from color scheme file
 | |
|         self.bground = self.strip_transparency(colour_settings.get("background", '#FFFFFF'), True, True)
 | |
|         self.fground = self.strip_transparency(colour_settings.get("foreground", '#000000'))
 | |
|         self.sbground = self.strip_transparency(colour_settings.get("selection", self.fground), True)
 | |
|         self.sfground = self.strip_transparency(colour_settings.get("selectionForeground", None))
 | |
|         self.gbground = self.strip_transparency(colour_settings.get("gutter", self.bground)) if kwargs["style_gutter"] else self.bground
 | |
|         self.gfground = self.strip_transparency(colour_settings.get("gutterForeground", self.fground), True) if kwargs["style_gutter"] else self.fground
 | |
| 
 | |
|         self.highlights = []
 | |
|         if self.highlight_selections:
 | |
|             for sel in self.view.sel():
 | |
|                 if not sel.empty():
 | |
|                     self.highlights.append(sel)
 | |
| 
 | |
|         # Create scope colors mapping from color scheme file
 | |
|         self.colours = {self.view.scope_name(self.end).split(' ')[0]: {"color": self.fground, "bgcolor": None, "style": None}}
 | |
|         for item in self.plist_file["settings"]:
 | |
|             scope = item.get('scope', None)
 | |
|             colour = None
 | |
|             style = []
 | |
|             if 'scope' in item:
 | |
|                 scope = item['scope']
 | |
|             if 'settings' in item:
 | |
|                 colour = item['settings'].get('foreground', None)
 | |
|                 bgcolour = item['settings'].get('background', None)
 | |
|                 if 'fontStyle' in item['settings']:
 | |
|                     for s in item['settings']['fontStyle'].split(' '):
 | |
|                         if s == "bold" or s == "italic":  # or s == "underline":
 | |
|                             style.append(s)
 | |
| 
 | |
|             if scope != None and (colour != None or bgcolour != None):
 | |
|                 self.colours[scope] = {
 | |
|                     "color": self.strip_transparency(colour),
 | |
|                     "bgcolor": self.strip_transparency(bgcolour, True),
 | |
|                     "style": style
 | |
|                 }
 | |
| 
 | |
|         self.shift_brightness = kwargs["shift_brightness"] and self.dark_lumens is not None and self.dark_lumens < self.lumens_limit
 | |
|         if self.shift_brightness:
 | |
|             self.color_adjust()
 | |
| 
 | |
|     def apply_filters(self, tmtheme):
 | |
|         def filter_color(color):
 | |
|             rgba = RGBA(color)
 | |
|             for f in self.filter:
 | |
|                 name = f[0]
 | |
|                 value = f[1]
 | |
|                 if name == "grayscale":
 | |
|                     rgba.grayscale()
 | |
|                 elif name == "sepia":
 | |
|                     rgba.sepia()
 | |
|                 elif name == "saturation":
 | |
|                     rgba.saturation(value)
 | |
|                 elif name == "invert":
 | |
|                     rgba.invert()
 | |
|                 elif name == "brightness":
 | |
|                     rgba.brightness(value)
 | |
|                 elif name == "hue":
 | |
|                     rgba.hue(value)
 | |
|                 elif name == "colorize":
 | |
|                     rgba.colorize(value)
 | |
|             return rgba.get_rgba()
 | |
| 
 | |
|         if len(self.filter):
 | |
|             general_settings_read = False
 | |
|             for settings in tmtheme["settings"]:
 | |
|                 if not general_settings_read:
 | |
|                     for k, v in settings["settings"].items():
 | |
|                         try:
 | |
|                             settings["settings"][k] = filter_color(v)
 | |
|                         except:
 | |
|                             pass
 | |
|                     general_settings_read = True
 | |
|                     continue
 | |
| 
 | |
|                 try:
 | |
|                     settings["settings"]["foreground"] = filter_color(settings["settings"]["foreground"])
 | |
|                 except:
 | |
|                     pass
 | |
|                 try:
 | |
|                     settings["settings"]["background"] = filter_color(settings["settings"]["background"])
 | |
|                 except:
 | |
|                     pass
 | |
|         return tmtheme
 | |
| 
 | |
|     def color_adjust(self):
 | |
|         factor = 1 + ((self.lumens_limit - self.dark_lumens) / 255.0) if self.shift_brightness else None
 | |
|         for k, v in self.colours.items():
 | |
|             fg, bg = v["color"], v["bgcolor"]
 | |
|             if v["color"] is not None:
 | |
|                 self.colours[k]["color"] = self.apply_color_change(v["color"], factor)
 | |
|             if v["bgcolor"] is not None:
 | |
|                 self.colours[k]["bgcolor"] = self.apply_color_change(v["bgcolor"], factor)
 | |
|         self.bground = self.apply_color_change(self.bground, factor)
 | |
|         self.fground = self.apply_color_change(self.fground, factor)
 | |
|         self.sbground = self.apply_color_change(self.sbground, factor)
 | |
|         if self.sfground is not None:
 | |
|             self.sfground = self.apply_color_change(self.sfground, factor)
 | |
|         self.gbground = self.apply_color_change(self.gbground, factor)
 | |
|         self.gfground = self.apply_color_change(self.gfground, factor)
 | |
| 
 | |
|     def apply_color_change(self, color, shift_factor):
 | |
|         rgba = RGBA(color)
 | |
|         if shift_factor is not None:
 | |
|             rgba.brightness(shift_factor)
 | |
|         return rgba.get_rgb()
 | |
| 
 | |
|     def get_tools(self, tools, use_annotation, use_wrapping):
 | |
|         toolbar_options = {
 | |
|             "gutter": TOOL_GUTTER,
 | |
|             "print": TOOL_PRINT,
 | |
|             "plain_text": TOOL_PLAIN_TEXT,
 | |
|             "annotation": TOOL_ANNOTATION if use_annotation else "",
 | |
|             "theme": TOOL_DUMP_THEME,
 | |
|             "wrapping": TOOL_WRAPPING if use_wrapping else ""
 | |
|         }
 | |
|         t_opt = ""
 | |
|         toolbar_element = ""
 | |
| 
 | |
|         if len(tools):
 | |
|             for t in tools:
 | |
|                 if t in toolbar_options:
 | |
|                     t_opt += toolbar_options[t]
 | |
|             toolbar_element = TOOLBAR % {"options": t_opt}
 | |
|         return toolbar_element
 | |
| 
 | |
|     def strip_transparency(self, color, track_darkness=False, simple_strip=False):
 | |
|         if color is None:
 | |
|             return color
 | |
|         rgba = RGBA(color.replace(" ", ""))
 | |
|         if not simple_strip:
 | |
|             rgba.apply_alpha(self.bground if self.bground != "" else "#FFFFFF")
 | |
|         if track_darkness:
 | |
|             lumens = rgba.luminance()
 | |
|             if self.dark_lumens is None or lumens < self.dark_lumens:
 | |
|                 self.dark_lumens = lumens
 | |
|         return rgba.get_rgb()
 | |
| 
 | |
|     def setup_print_block(self, curr_sel, multi=False):
 | |
|         # Determine start and end points and whether to parse whole file or selection
 | |
|         if not multi and (curr_sel.empty() or self.highlight_selections or curr_sel.size() <= self.char_limit):
 | |
|             self.size = self.view.size()
 | |
|             self.pt = 0
 | |
|             self.end = 1
 | |
|             self.curr_row = 1
 | |
|         else:
 | |
|             self.size = curr_sel.end()
 | |
|             self.pt = curr_sel.begin()
 | |
|             self.end = self.pt + 1
 | |
|             self.curr_row = self.view.rowcol(self.pt)[0] + 1
 | |
|         self.start_line = self.curr_row
 | |
| 
 | |
|         self.gutter_pad = len(str(self.view.rowcol(self.size)[0])) + 1
 | |
| 
 | |
|     def check_sel(self):
 | |
|         multi = False
 | |
|         for sel in self.view.sel():
 | |
|             if not sel.empty() and sel.size() >= self.char_limit:
 | |
|                 multi = True
 | |
|                 self.sels.append(sel)
 | |
|         return multi
 | |
| 
 | |
|     def print_line(self, line, num):
 | |
|         html_line = LINE % {
 | |
|             "line_id": num,
 | |
|             "color": self.gfground,
 | |
|             "line": str(num).rjust(self.gutter_pad).replace(" ", ' '),
 | |
|             "code_id": num,
 | |
|             "code": line,
 | |
|             "table": self.tables,
 | |
|             "pad_color": self.ebground or self.bground
 | |
|         }
 | |
| 
 | |
|         return html_line
 | |
| 
 | |
|     def guess_colour(self, pt, the_key):
 | |
|         the_colour = self.fground
 | |
|         the_bgcolour = None
 | |
|         the_style = set([])
 | |
|         if the_key in self.matched:
 | |
|             the_colour = self.matched[the_key]["color"]
 | |
|             the_style = self.matched[the_key]["style"]
 | |
|             the_bgcolour = self.matched[the_key]["bgcolor"]
 | |
|         else:
 | |
|             best_match_bg = 0
 | |
|             best_match_fg = 0
 | |
|             best_match_style = 0
 | |
|             for key in self.colours:
 | |
|                 match = self.view.score_selector(pt, key)
 | |
|                 if self.colours[key]["color"] is not None and match > best_match_fg:
 | |
|                     best_match_fg = match
 | |
|                     the_colour = self.colours[key]["color"]
 | |
|                 if self.colours[key]["style"] is not None and match > best_match_style:
 | |
|                     best_match_style = match
 | |
|                     for s in self.colours[key]["style"]:
 | |
|                         the_style.add(s)
 | |
|                 if self.colours[key]["bgcolor"] is not None and match > best_match_bg:
 | |
|                     best_match_bg = match
 | |
|                     the_bgcolour = self.colours[key]["bgcolor"]
 | |
|             self.matched[the_key] = {"color": the_colour, "bgcolor": the_bgcolour, "style": the_style}
 | |
|         if len(the_style) == 0:
 | |
|             the_style = "normal"
 | |
|         else:
 | |
|             the_style = ' '.join(the_style)
 | |
|         return the_colour, the_style, the_bgcolour
 | |
| 
 | |
|     def write_header(self, the_html):
 | |
|         header = HTML_HEADER % {
 | |
|             "title": path.basename(self.file_name),
 | |
|             "css":   getcss(
 | |
|                 'export.css',
 | |
|                 {
 | |
|                     "font_size":           str(self.font_size),
 | |
|                     "font_face":           '"' + self.font_face + '"',
 | |
|                     "page_bg":             self.bground,
 | |
|                     "gutter_bg":           self.gbground,
 | |
|                     "body_fg":             self.fground,
 | |
|                     "display_mode":        'table-cell' if self.numbers else 'none',
 | |
|                     "dot_color":           self.fground,
 | |
|                     "toolbar_orientation": self.toolbar_orientation
 | |
|                 }
 | |
|             ),
 | |
|             "js": INCLUDE_THEME % {
 | |
|                 "jscode": getjs('plist.js'),
 | |
|                 "theme": json.dumps(self.plist_file, sort_keys=True, indent=4, separators=(',', ': ')).encode('raw_unicode_escape'),
 | |
|                 "name": self.scheme_file,
 | |
|             }
 | |
|         }
 | |
|         the_html.write(header)
 | |
| 
 | |
|     def convert_view_to_html(self, the_html):
 | |
|         for line in self.view.split_by_newlines(sublime.Region(self.pt, self.size)):
 | |
|             self.size = line.end()
 | |
|             empty = not bool(line.size())
 | |
|             line = self.convert_line_to_html(the_html, empty)
 | |
|             the_html.write(self.print_line(line, self.curr_row))
 | |
|             self.curr_row += 1
 | |
| 
 | |
|     def html_encode(self, text):
 | |
|         # Format text to HTML
 | |
|         encode_table = {
 | |
|             '&':  '&',
 | |
|             '>':  '>',
 | |
|             '<':  '<',
 | |
|             '\t': ' ' * self.tab_size,
 | |
|             ' ':  ' ',
 | |
|             '\n': ''
 | |
|         }
 | |
| 
 | |
|         return ''.join(encode_table.get(c, c) for c in text).encode('ascii', 'xmlcharrefreplace')
 | |
| 
 | |
|     def get_annotations(self):
 | |
|         annotations = get_annotations(self.view)
 | |
|         comments = []
 | |
|         for x in range(0, int(annotations["count"])):
 | |
|             region = annotations["annotations"]["html_annotation_%d" % x]["region"]
 | |
|             comments.append((region, annotations["annotations"]["html_annotation_%d" % x]["comment"]))
 | |
|         comments.sort()
 | |
|         return comments
 | |
| 
 | |
|     def annotate_text(self, line, the_colour, the_bgcolour, the_style, empty):
 | |
|         pre_text = None
 | |
|         annot_text = None
 | |
|         post_text = None
 | |
|         start = None
 | |
| 
 | |
|         # Pretext Check
 | |
|         if self.pt >= self.curr_annot.begin():
 | |
|             # Region starts with an annotation
 | |
|             start = self.pt
 | |
|         else:
 | |
|             # Region has text before annoation
 | |
|             pre_text = self.html_encode(self.view.substr(sublime.Region(self.pt, self.curr_annot.begin())))
 | |
|             start = self.curr_annot.begin()
 | |
| 
 | |
|         if self.end == self.curr_annot.end():
 | |
|             # Region ends annotation
 | |
|             annot_text = self.html_encode(self.view.substr(sublime.Region(start, self.end)))
 | |
|             self.curr_annot = None
 | |
|         elif self.end > self.curr_annot.end():
 | |
|             # Region has text following annotation
 | |
|             annot_text = self.html_encode(self.view.substr(sublime.Region(start, self.curr_annot.end())))
 | |
|             post_text = self.html_encode(self.view.substr(sublime.Region(self.curr_annot.end(), self.end)))
 | |
|             self.curr_annot = None
 | |
|         else:
 | |
|             # Region ends but annotation is not finished
 | |
|             annot_text = self.html_encode(self.view.substr(sublime.Region(start, self.end)))
 | |
|             self.curr_annot = sublime.Region(self.end, self.curr_annot.end())
 | |
| 
 | |
|         # Print the separate parts pre text, annotation, post text
 | |
|         if pre_text != None:
 | |
|             self.format_text(line, pre_text, the_colour, the_bgcolour, the_style, empty)
 | |
|         if annot_text != None:
 | |
|             self.format_text(line, annot_text, the_colour, the_bgcolour, the_style, empty, annotate=True)
 | |
|             if self.curr_annot == None:
 | |
|                 self.curr_comment = None
 | |
|         if post_text != None:
 | |
|             self.format_text(line, post_text, the_colour, the_bgcolour, the_style, empty)
 | |
| 
 | |
|     def add_annotation_table_entry(self):
 | |
|         row, col = self.view.rowcol(self.annot_pt)
 | |
|         self.annot_tbl.append(
 | |
|             (
 | |
|                 self.tables, self.curr_row, "Line %d Col %d" % (row + 1, col + 1),
 | |
|                 self.curr_comment.encode('ascii', 'xmlcharrefreplace')
 | |
|             )
 | |
|         )
 | |
|         self.annot_pt = None
 | |
| 
 | |
|     def format_text(self, line, text, the_colour, the_bgcolour, the_style, empty, annotate=False):
 | |
|         if empty:
 | |
|             text = ' '
 | |
|         else:
 | |
|             the_style += " real_text"
 | |
| 
 | |
|         if the_bgcolour is None:
 | |
|             the_bgcolour = self.bground
 | |
| 
 | |
|         if annotate:
 | |
|             code = ANNOTATION_CODE % {"highlight": the_bgcolour, "color": the_colour, "content": text, "class": the_style}
 | |
|         else:
 | |
|             code = CODE % {"highlight": the_bgcolour, "color": the_colour, "content": text, "class": the_style}
 | |
| 
 | |
|         if annotate:
 | |
|             if self.curr_annot != None and not self.open_annot:
 | |
|                 # Open an annotation
 | |
|                 if self.annot_pt != None:
 | |
|                     self.add_annotation_table_entry()
 | |
|                 if self.new_annot:
 | |
|                     self.annot_num += 1
 | |
|                     self.new_annot = False
 | |
|                 code = ANNOTATE_OPEN % {"code": code, "comment": str(self.annot_num)}
 | |
|                 self.open_annot = True
 | |
|             elif self.curr_annot == None:
 | |
|                 if self.open_annot:
 | |
|                     # Close an annotation
 | |
|                     code += ANNOTATE_CLOSE
 | |
|                     self.open_annot = False
 | |
|                 else:
 | |
|                     # Do a complete annotation
 | |
|                     if self.annot_pt != None:
 | |
|                         self.add_annotation_table_entry()
 | |
|                     if self.new_annot:
 | |
|                         self.annot_num += 1
 | |
|                         self.new_annot = False
 | |
|                     code = (
 | |
|                         ANNOTATE_OPEN % {"code": code, "comment": str(self.annot_num)} +
 | |
|                         ANNOTATE_CLOSE
 | |
|                     )
 | |
|         line.append(code)
 | |
| 
 | |
|     def convert_line_to_html(self, the_html, empty):
 | |
|         line = []
 | |
|         hl_done = False
 | |
| 
 | |
|         # Continue highlight form last line
 | |
|         if self.hl_continue != None:
 | |
|             self.curr_hl = self.hl_continue
 | |
|             self.hl_continue = None
 | |
| 
 | |
|         while self.end <= self.size:
 | |
|             # Get next highlight region
 | |
|             if self.highlight_selections and self.curr_hl == None and len(self.highlights) > 0:
 | |
|                 self.curr_hl = self.highlights.pop(0)
 | |
| 
 | |
|             # See if we are starting a highlight region
 | |
|             if self.curr_hl != None and self.pt == self.curr_hl.begin():
 | |
|                 # Get text of like scope up to a highlight
 | |
|                 scope_name = self.view.scope_name(self.pt)
 | |
|                 while self.view.scope_name(self.end) == scope_name and self.end < self.size:
 | |
|                     # Kick out if we hit a highlight region
 | |
|                     if self.end == self.curr_hl.end():
 | |
|                         break
 | |
|                     self.end += 1
 | |
|                 if self.end < self.curr_hl.end():
 | |
|                     if self.end >= self.size:
 | |
|                         self.hl_continue = sublime.Region(self.end, self.curr_hl.end())
 | |
|                     else:
 | |
|                         self.curr_hl = sublime.Region(self.end, self.curr_hl.end())
 | |
|                 else:
 | |
|                     hl_done = True
 | |
|                 if hl_done and empty:
 | |
|                     the_colour, the_style, the_bgcolour = self.guess_colour(self.pt, scope_name)
 | |
|                 elif self.sfground is None:
 | |
|                     the_colour, the_style, _ = self.guess_colour(self.pt, scope_name)
 | |
|                     the_bgcolour = self.sbground
 | |
|                 else:
 | |
|                     the_colour, the_style = self.sfground, "normal"
 | |
|                     the_bgcolour = self.sbground
 | |
|             else:
 | |
|                 # Get text of like scope up to a highlight
 | |
|                 scope_name = self.view.scope_name(self.pt)
 | |
|                 while self.view.scope_name(self.end) == scope_name and self.end < self.size:
 | |
|                     # Kick out if we hit a highlight region
 | |
|                     if self.curr_hl != None and self.end == self.curr_hl.begin():
 | |
|                         break
 | |
|                     self.end += 1
 | |
|                 the_colour, the_style, the_bgcolour = self.guess_colour(self.pt, scope_name)
 | |
| 
 | |
|             # Get new annotation
 | |
|             if (self.curr_annot == None or self.curr_annot.end() < self.pt) and len(self.annotations):
 | |
|                 self.curr_annot, self.curr_comment = self.annotations.pop(0)
 | |
|                 self.annot_pt = self.curr_annot[0]
 | |
|                 while self.pt > self.curr_annot[1]:
 | |
|                     if len(self.annotations):
 | |
|                         self.curr_annot, self.curr_comment = self.annotations.pop(0)
 | |
|                         self.annot_pt = self.curr_annot[0]
 | |
|                     else:
 | |
|                         self.curr_annot = None
 | |
|                         self.curr_comment = None
 | |
|                         break
 | |
|                 self.new_annot = True
 | |
|                 self.curr_annot = sublime.Region(self.curr_annot[0], self.curr_annot[1])
 | |
| 
 | |
|             region = sublime.Region(self.pt, self.end)
 | |
|             if self.curr_annot != None and region.intersects(self.curr_annot):
 | |
|                 # Apply annotation within the text and format the text
 | |
|                 self.annotate_text(line, the_colour, the_bgcolour, the_style, empty)
 | |
|             else:
 | |
|                 # Normal text formatting
 | |
|                 tidied_text = self.html_encode(self.view.substr(region))
 | |
|                 self.format_text(line, tidied_text, the_colour, the_bgcolour, the_style, empty)
 | |
| 
 | |
|             if hl_done:
 | |
|                 # Clear highlight flags and variables
 | |
|                 hl_done = False
 | |
|                 self.curr_hl = None
 | |
| 
 | |
|             # Continue walking through line
 | |
|             self.pt = self.end
 | |
|             self.end = self.pt + 1
 | |
| 
 | |
|         # Close annotation if open at end of line
 | |
|         if self.open_annot:
 | |
|             line.append(ANNOTATE_CLOSE % {"comment": self.curr_comment})
 | |
|             self.open_annot = False
 | |
| 
 | |
|         # Get the color for the space at the end of a line
 | |
|         if self.end < self.view.size():
 | |
|             end_key = self.view.scope_name(self.pt)
 | |
|             _, _, self.ebground = self.guess_colour(self.pt, end_key)
 | |
| 
 | |
|         # Join line segments
 | |
|         return ''.join(line)
 | |
| 
 | |
|     def write_body(self, the_html):
 | |
|         processed_rows = ""
 | |
|         the_html.write(BODY_START)
 | |
| 
 | |
|         the_html.write(TABLE_START)
 | |
|         if not self.no_header:
 | |
|             # Write file name
 | |
|             date_time = time.strftime(self.date_time_format, self.time)
 | |
|             the_html.write(
 | |
|                 FILE_INFO % {
 | |
|                     "color": self.fground,
 | |
|                     "date_time": date_time,
 | |
|                     "file": self.file_name if self.show_full_path else path.basename(self.file_name)
 | |
|                 }
 | |
|             )
 | |
| 
 | |
|         the_html.write(ROW_START)
 | |
|         the_html.write(TABLE_START)
 | |
|         # Convert view to HTML
 | |
|         if self.multi_select:
 | |
|             count = 0
 | |
|             total = len(self.sels)
 | |
|             for sel in self.sels:
 | |
|                 self.setup_print_block(sel, multi=True)
 | |
|                 processed_rows += "[" + str(self.curr_row) + ","
 | |
|                 self.convert_view_to_html(the_html)
 | |
|                 count += 1
 | |
|                 self.tables = count
 | |
|                 processed_rows += str(self.curr_row) + "],"
 | |
| 
 | |
|                 if count < total:
 | |
|                     the_html.write(TABLE_END)
 | |
|                     the_html.write(ROW_END)
 | |
|                     the_html.write(ROW_START)
 | |
|                     the_html.write(DIVIDER % {"color": self.fground})
 | |
|                     the_html.write(ROW_END)
 | |
|                     the_html.write(ROW_START)
 | |
|                     the_html.write(TABLE_START)
 | |
|         else:
 | |
|             self.setup_print_block(self.view.sel()[0])
 | |
|             processed_rows += "[" + str(self.curr_row) + ","
 | |
|             self.convert_view_to_html(the_html)
 | |
|             processed_rows += str(self.curr_row) + "],"
 | |
|             self.tables += 1
 | |
| 
 | |
|         the_html.write(TABLE_END)
 | |
|         the_html.write(ROW_END)
 | |
|         the_html.write(TABLE_END)
 | |
| 
 | |
|         js_options = []
 | |
|         if len(self.annot_tbl):
 | |
|             self.add_comments_table(the_html)
 | |
|             js_options.append(HTML_JS_WRAP % {"jscode": getjs('annotation.js')})
 | |
| 
 | |
|         # Write javascript snippets
 | |
|         js_options.append(HTML_JS_WRAP % {"jscode": getjs('print.js')})
 | |
|         js_options.append(HTML_JS_WRAP % {"jscode": getjs('plaintext.js')})
 | |
|         js_options.append(TOGGLE_LINE_OPTIONS % {
 | |
|                 "jscode":    getjs('lines.js'),
 | |
|                 "wrap_size": self.wrap,
 | |
|                 "ranges":    processed_rows.rstrip(','),
 | |
|                 "tables":    self.tables,
 | |
|                 "header":    ("false" if self.no_header else "true"),
 | |
|                 "gutter":    ('true' if self.numbers else 'false')
 | |
|             }
 | |
|         )
 | |
|         if self.auto_wrap:
 | |
|             js_options.append(WRAP)
 | |
| 
 | |
|         if self.browser_print:
 | |
|             js_options.append(AUTO_PRINT)
 | |
| 
 | |
|         # Write empty line to allow copying of last line and line number without issue
 | |
|         the_html.write(BODY_END % {"js": ''.join(js_options), "toolbar": self.get_tools(self.toolbar, len(self.annot_tbl), self.auto_wrap)})
 | |
| 
 | |
|     def add_comments_table(self, the_html):
 | |
|         the_html.write(ANNOTATION_TBL_START)
 | |
|         the_html.write(''.join([ANNOTATION_ROW % {"table": t, "row": r, "link": l, "comment": c} for t, r, l, c in self.annot_tbl]))
 | |
|         the_html.write(ANNOTATION_FOOTER)
 | |
|         the_html.write(ANNOTATION_TBL_END)
 | |
| 
 | |
|     def run(self, **kwargs):
 | |
|         inputs = self.process_inputs(**kwargs)
 | |
|         self.setup(**inputs)
 | |
| 
 | |
|         save_location = inputs["save_location"]
 | |
|         time_stamp = inputs["time_stamp"]
 | |
| 
 | |
|         if save_location is not None:
 | |
|             fname = self.view.file_name()
 | |
|             if (
 | |
|                 ((fname == None or not path.exists(fname)) and save_location == ".") or
 | |
|                 not path.exists(save_location)
 | |
|                 or not path.isdir(save_location)
 | |
|             ):
 | |
|                 html_file = ".html"
 | |
|                 save_location = None
 | |
|             elif save_location == ".":
 | |
|                 html_file = "%s%s.html" % (fname, time.strftime(time_stamp, self.time))
 | |
|             elif fname is None or not path.exists(fname):
 | |
|                 html_file = path.join(save_location, "Untitled%s.html" % time.strftime(time_stamp, self.time))
 | |
|             else:
 | |
|                 html_file = path.join(save_location, "%s%s.html" % (path.basename(fname), time.strftime(time_stamp, self.time)))
 | |
|         else:
 | |
|             html_file = ".html"
 | |
| 
 | |
|         if save_location is not None:
 | |
|             open_html = lambda x: open(x, "w")
 | |
|         else:
 | |
|             open_html = lambda x: tempfile.NamedTemporaryFile(delete=False, suffix=x)
 | |
| 
 | |
|         with open_html(html_file) as the_html:
 | |
|             self.write_header(the_html)
 | |
|             self.write_body(the_html)
 | |
|             if inputs["clipboard_copy"]:
 | |
|                 the_html.seek(0)
 | |
|                 sublime.set_clipboard(the_html.read())
 | |
|                 sublime.status_message("Export to HTML: copied to clipboard")
 | |
| 
 | |
|         if inputs["view_open"]:
 | |
|             self.view.window().open_file(the_html.name)
 | |
|         else:
 | |
|             # Open in web browser; check return code, if failed try webbrowser
 | |
|             status = desktop.open(the_html.name, status=True)
 | |
|             if not status:
 | |
|                 webbrowser.open(the_html.name, new=2)
 |