Evernote Web HTML editor

This scripts adds a button to edit the HTML code of a note in Evernote Web

目前为 2017-12-02 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Evernote Web HTML editor
  3. // @namespace http://andrealazzarotto.com/
  4. // @version 3.2.3
  5. // @description This scripts adds a button to edit the HTML code of a note in Evernote Web
  6. // @match http://www.evernote.com/*Home.action*
  7. // @match https://www.evernote.com/*Home.action*
  8. // @copyright 2015, Seb Maynard, Andrea Lazzarotto
  9. // @license Apache License, Version 2.0
  10. // @require http://code.jquery.com/jquery-latest.min.js
  11. // @grant GM_setValue
  12. // @grant GM_getValue
  13. // ==/UserScript==
  14.  
  15. /*
  16. This program is a modified version of the Evernote HTML Editor bookmarklet
  17. created by Seb Maynard and released as open source software under the
  18. Apache 2.0 license. You can download the original software here:
  19.  
  20. https://gist.github.com/sebmaynard/8f9f6b33247ab2f4bc85
  21. http://seb.so/html-source-editor-for-evernote-web-a-bookmarklet/
  22. */
  23.  
  24. /*
  25. Copyright 2015 Seb Maynard, Andrea Lazzarotto
  26.  
  27. Licensed under the Apache License, Version 2.0 (the "License");
  28. you may not use this file except in compliance with the License.
  29. You may obtain a copy of the License at
  30.  
  31. http://www.apache.org/licenses/LICENSE-2.0
  32.  
  33. Unless required by applicable law or agreed to in writing, software
  34. distributed under the License is distributed on an "AS IS" BASIS,
  35. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  36. See the License for the specific language governing permissions and
  37. limitations under the License.
  38. */
  39.  
  40. var icon_old = "iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAzUExURUxpcYiIiIiIiExpcYiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiNINviEAAAAQdFJOUwCqZgDdzBEiuzNVRJl3/4jEJrZZAAAAhUlEQVQY05WPwQ7DIAxDDQokAdr5/7+2gVbrusOkWbnwYmwAfiizfqNkj2NVYM/1tvnYN3Rq4/AFWiHNMQSayJIDGUtcg7xmgFHeLmW/XWfWtseSqX80WgL08bDKjD8VP5PoZKKj0DmRQtRt1oEXEqF2QzbGnMirLJQK+4Uiy5erMVIo5QACmwWhG+ikMQAAAABJRU5ErkJggg==";
  41. var icon_new = "iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAnUExURUxpcQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK/XnHYAAAAMdFJOUwBEuzPMd2aZIt2I7sVV9wMAAABUSURBVBjTpY7bCsAgDEOjzOvy/9+7por6NBg7SmhCWwr8orbThQjkgissrzKGWRhM0luSuHs0uHp8T8k+eNDqp8uoT6OjU24kCpO9kRieYCveE/IBzfcCeIwe7AAAAAAASUVORK5CYII=";
  42.  
  43. var wrapper, editor;
  44.  
  45. var theme = GM_getValue("editor_theme", "ace/theme/tomorrow_night");
  46. var size = GM_getValue("editor_size", 16);
  47.  
  48. var basic_html_formatter = function(code) {
  49. var block_tags = "p|div|ol|ul|li|pre|blockquote|h[1-6]|table|thead|tbody|tr|td";
  50. code = code.replace(new RegExp("([^\n])(<[\/]?("+block_tags+")[^>]*>)", "g"), "$1\n$2");
  51. for (var i = 0; i<2; i++)
  52. code = code.replace(new RegExp("(<[\/]?("+block_tags+")[^>]*>)([^\n])", "g"), "$1\n$3");
  53. return code;
  54. };
  55.  
  56. var getCurrentContent = function() {
  57. var content = $("#tinymce, #en-note", $("#en-common-editor-iframe, .RichTextArea-entinymce").contents()).first().clone();
  58. content.find("*").removeAttr("data-mce-style").removeAttr("data-mce-src").removeAttr("data-mce-href");
  59. return basic_html_formatter(content.html());
  60. };
  61. var setCurrentContent = function(content) {
  62. if(!$("table:has(input)").first().is(":visible")) // Activate the note editing mode again
  63. $("iframe.gwt-Frame").first().contents().find("body").click();
  64. $("#tinymce, #en-note", $("#en-common-editor-iframe, .RichTextArea-entinymce").contents()).first().html(content);
  65. $(".ennote", $("#en-common-editor-iframe, .RichTextArea-entinymce").contents()).first().html(content);
  66. };
  67. var toolbarTheme = function() {
  68. var style = {
  69. 'Bright': {
  70. 'text': '#404040',
  71. 'border': '#ececec',
  72. 'background': '#f8f8f8'
  73. },
  74. 'Dark': {
  75. 'text': '#c0c0c0',
  76. 'border': '#404040',
  77. 'background': '#202020'
  78. },
  79. };
  80.  
  81. var label = $('#html_theme :selected').parent().attr('label');
  82. var colors = style[label];
  83. var toolbar = $("#html_code_toolbar");
  84. toolbar.find('#left_side input, #left_side select').css({
  85. 'background': colors.background,
  86. 'border': 0,
  87. 'border-bottom': '2px solid ' + colors.border,
  88. 'padding': '.25rem',
  89. 'height': '2rem',
  90. 'box-sizing': 'border-box'
  91. });
  92. toolbar.find("#btn_reset").css({
  93. 'border-left': '1px solid ' + colors.border,
  94. 'background': "transparent"
  95. });
  96. toolbar.find('*:not(.material-icons)').css({
  97. 'color': colors.text,
  98. 'font-family': 'gotham, helvetica, arial, sans-serif',
  99. 'font-size': '.9rem',
  100. 'outline': 'none'
  101. });
  102. toolbar.find('.material-icons').css({
  103. 'color': colors.text,
  104. 'font-size': '1.25rem',
  105. 'vertical-align': 'middle'
  106. });
  107. toolbar.find('#html_icons').css('height', '3rem');
  108. toolbar.find('#btn_submit').css('color', 'white');
  109. toolbar.find('#left_side > *').css('margin-left', '1rem');
  110. toolbar.css({
  111. 'border-bottom': '1px solid ' + colors.border,
  112. 'background': colors.background
  113. });
  114. toolbar.find('input, select, i.material-icons').css('cursor', 'pointer');
  115. };
  116. var prepareTextArea = function() {
  117. wrapper = $(
  118. "<div id='html_code_editor'>" +
  119. "<div id='html_code_toolbar'>" +
  120. "<div id='left_side' style='float: left'>" +
  121. "<select id='html_theme'>" +
  122. "<optgroup label='Bright'>" +
  123. "<option value='ace/theme/chrome'>Chrome</option>" +
  124. "<option value='ace/theme/clouds'>Clouds</option>" +
  125. "<option value='ace/theme/crimson_editor'>Crimson Editor</option>" +
  126. "<option value='ace/theme/dawn'>Dawn</option>" +
  127. "<option value='ace/theme/dreamweaver'>Dreamweaver</option>" +
  128. "<option value='ace/theme/eclipse'>Eclipse</option>" +
  129. "<option value='ace/theme/github'>GitHub</option>" +
  130. "<option value='ace/theme/iplastic'>IPlastic</option>" +
  131. "<option value='ace/theme/solarized_light'>Solarized Light</option>" +
  132. "<option value='ace/theme/textmate'>TextMate</option>" +
  133. "<option value='ace/theme/tomorrow'>Tomorrow</option>" +
  134. "<option value='ace/theme/xcode'>XCode</option>" +
  135. "<option value='ace/theme/kuroir'>Kuroir</option>" +
  136. "<option value='ace/theme/katzenmilch'>KatzenMilch</option>" +
  137. "<option value='ace/theme/sqlserver'>SQL Server</option>" +
  138. "</optgroup>" +
  139. "<optgroup label='Dark'>" +
  140. "<option value='ace/theme/ambiance'>Ambiance</option>" +
  141. "<option value='ace/theme/chaos'>Chaos</option>" +
  142. "<option value='ace/theme/clouds_midnight'>Clouds Midnight</option>" +
  143. "<option value='ace/theme/cobalt'>Cobalt</option>" +
  144. "<option value='ace/theme/idle_fingers'>idle Fingers</option>" +
  145. "<option value='ace/theme/kr_theme'>krTheme</option>" +
  146. "<option value='ace/theme/merbivore'>Merbivore</option>" +
  147. "<option value='ace/theme/merbivore_soft'>Merbivore Soft</option>" +
  148. "<option value='ace/theme/mono_industrial'>Mono Industrial</option>" +
  149. "<option value='ace/theme/monokai'>Monokai</option>" +
  150. "<option value='ace/theme/pastel_on_dark'>Pastel on dark</option>" +
  151. "<option value='ace/theme/solarized_dark'>Solarized Dark</option>" +
  152. "<option value='ace/theme/terminal'>Terminal</option>" +
  153. "<option value='ace/theme/tomorrow_night'>Tomorrow Night</option>" +
  154. "<option value='ace/theme/tomorrow_night_blue'>Tomorrow Night Blue</option>" +
  155. "<option value='ace/theme/tomorrow_night_bright'>Tomorrow Night Bright</option>" +
  156. "<option value='ace/theme/tomorrow_night_eighties'>Tomorrow Night 80s</option>" +
  157. "<option value='ace/theme/twilight'>Twilight</option>" +
  158. "<option value='ace/theme/vibrant_ink'>Vibrant Ink</option>" +
  159. "</optgroup>" +
  160. "</select>" +
  161. "<span><input type='number' id='html_size' min='8' max='24' style='text-align: right'> px</span>" +
  162. "<span id='html_icons'>" +
  163. "<i class='material-icons' id='btn_find'>search</i>&nbsp;" +
  164. "<i class='material-icons' id='btn_replace'>find_replace</i>" +
  165. "</span>" +
  166. "</div>" +
  167. "<div id='right_side' style='float: right'>" +
  168. "<a target='_blank' style='margin-right: 2em' href='https://lazza.me/EvernotePremium20USD'>Get Premium for €20/$22 a year</a>" +
  169. "<input id='btn_reset' type='reset'/>" +
  170. "<input id='btn_submit' type='submit'/>" +
  171. "</div>" +
  172. "</div>" +
  173. " <div id='html_code_area' />" +
  174. "</div>");
  175. wrapper.css({
  176. "z-index": "10000",
  177. "position": "fixed",
  178. "top": "0",
  179. "left": "0",
  180. "right": "0",
  181. "bottom": "0"
  182. });
  183. $("body").append(wrapper);
  184.  
  185. $("#html_code_toolbar").css({
  186. 'height': '3rem',
  187. 'line-height': '3rem',
  188. 'box-sizing': 'border-box',
  189. 'border-bottom': '1px solid #404040',
  190. 'background': '#080808'
  191. });
  192. $("#html_code_area").css({
  193. "width": "100%",
  194. "height": "calc(100% - 3rem)",
  195. "box-sizing": "border-box",
  196. "outline": 0
  197. });
  198. $("#html_theme").val(theme);
  199. $("#html_theme").change(function() {
  200. theme = $("#html_theme").val();
  201. GM_setValue("editor_theme", theme);
  202. editor.setTheme(theme);
  203. toolbarTheme();
  204. });
  205. $("#html_size").val(size);
  206. $("#html_size").change(function() {
  207. size = $("#html_size").val();
  208. GM_setValue("editor_size", size);
  209. editor.setOptions(cloneInto({fontSize: size + "px"}, unsafeWindow));
  210. });
  211. $("#right_side input").css({
  212. "border": 0,
  213. "background": "transparent",
  214. "height": "3rem",
  215. "min-width": "8rem",
  216. "display": "inline-block",
  217. });
  218. $("#btn_submit").css({
  219. "font-weight": "bold",
  220. "background": "#2dbe60",
  221. "color": "white"
  222. });
  223. $("#btn_find").click(function() { editor.execCommand("find"); });
  224. $("#btn_replace").click(function() { editor.execCommand("replace"); });
  225. toolbarTheme();
  226.  
  227. editor = unsafeWindow.ace.edit("html_code_area");
  228. editor.setTheme(theme);
  229. editor.getSession().setMode("ace/mode/html");
  230. editor.setOptions(cloneInto({
  231. fontSize: size + "px",
  232. wrap: "free",
  233. enableBasicAutocompletion: true,
  234. scrollPastEnd: true,
  235. showPrintMargin: false,
  236. enableSnippets: true,
  237. enableLiveAutocompletion: true
  238. }, unsafeWindow));
  239.  
  240. $("#btn_submit").click(function() {
  241. setCurrentContent(editor.getValue());
  242. wrapper.hide();
  243. });
  244. $("#btn_reset").click(function() {
  245. wrapper.hide();
  246. });
  247.  
  248. wrapper.hide();
  249. };
  250.  
  251. var placeButton = function() {
  252. // old Evernote Web
  253. var prev = $("table:has(input)").first().find("td:nth-of-type(9)");
  254. var code = "<td id='html_edit'></td>";
  255. var icon = icon_old;
  256. // new Evernote Web
  257. if(!prev.length) {
  258. prev = $("#gwt-debug-FormattingBar-strikeButton").parent();
  259. code = "<div id='html_edit'></div>";
  260. icon = icon_new;
  261. }
  262. if(!prev.length)
  263. return false;
  264.  
  265. prepareTextArea();
  266. prev.after(code);
  267. var btn = $("#html_edit");
  268. btn.addClass(prev.attr('class'));
  269. btn.attr("style", prev.attr("style"));
  270. prev.find("div").first().clone().appendTo(btn);
  271. btn.find("input").remove();
  272. btn.find("div").attr("title", "HTML");
  273. btn.find("div").css("background-image", "url('data:image/png;base64,"+icon+"')");
  274. btn.click(function() {
  275. editor.setValue(getCurrentContent(), -1);
  276. wrapper.show();
  277. });
  278. return true;
  279. };
  280.  
  281. $(document).ready(function() {
  282. $.getScript("https://cdn.rawgit.com/ajaxorg/ace-builds/v1.2.5/src-min-noconflict/ace.js").done(function(){
  283. $.getScript("https://cdn.rawgit.com/ajaxorg/ace-builds/v1.2.5/src-min-noconflict/ext-language_tools.js").done(function(){
  284. // Place the button at the end of the formatting options
  285. setTimeout(function() {
  286. if(!placeButton())
  287. setTimeout(arguments.callee, 400);
  288. }, 400);
  289. });
  290. });
  291.  
  292. $('<link/>', {
  293. rel: 'stylesheet',
  294. href: 'https://fonts.googleapis.com/icon?family=Material+Icons'
  295. }).appendTo('head');
  296. });