From 060435bcaa01773d213acffecf5958c92f46b8c9 Mon Sep 17 00:00:00 2001 From: life Date: Sun, 3 May 2015 16:27:51 +0800 Subject: [PATCH] =?UTF-8?q?needle=E9=87=8D=E8=BF=9E,=20night=E4=B8=BB?= =?UTF-8?q?=E9=A2=98=E7=BE=8E=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 + src/data/version | 2 +- src/node_modules/api.js | 14 +- src/node_modules/needle/lib/needle.js | 28 +- src/note.html | 10 +- src/public/config.js | 2 +- src/public/js/app/note.js | 3 +- src/public/js/common.js | 4 +- src/public/themes/basic.less | 2 + src/public/themes/default.css | 2 + src/public/themes/themes/night/theme.css | 46 +- src/public/themes/themes/night/theme.less | 25 +- .../themes/themes/pebbles_night/theme.css | 30 +- src/public/themes/themes/volumn/theme.css | 30 +- .../themes/themes/water_night/theme.css | 30 +- .../tinymce/plugins/paste/plugin.min.js | 1136 +++++++++++++++++ src/test2.js | 61 +- 17 files changed, 1340 insertions(+), 88 deletions(-) create mode 100644 src/public/tinymce/plugins/paste/plugin.min.js diff --git a/.gitignore b/.gitignore index 45485974..fbb5f086 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ config.codekit sqlite* /test tinymce_old +src/node_modules/request +src/test*.js +/updates diff --git a/src/data/version b/src/data/version index ada873b0..f3a965ba 100644 --- a/src/data/version +++ b/src/data/version @@ -1 +1 @@ -{"version":"0.4.1","updatedTime":"2015-03-24T07:11:51.505Z"} \ No newline at end of file +{"version":"electron-0.4","updatedTime":"2015-03-24T07:11:51.505Z"} \ No newline at end of file diff --git a/src/node_modules/api.js b/src/node_modules/api.js index b795ca73..558f2c70 100644 --- a/src/node_modules/api.js +++ b/src/node_modules/api.js @@ -20,7 +20,7 @@ function log(o) { // timeout 0无限等待, 60,000 1分钟 needle.defaults({ - timeout: 5*60000 + timeout: 60000 }); // 远程数据服务 @@ -94,7 +94,7 @@ var Api = { // log({emai: email, pwd: pwd}); // console.log(this.getUrl('auth/login', {email: email, pwd: pwd})); // console.log('????????????') - needle.post(this.getUrl('auth/login'), {email: email, pwd: pwd}, function(error, response) { + needle.post(this.getUrl('auth/login'), {email: email, pwd: pwd}, {timeout: 10000}, function(error, response) { me.checkError(error, response); if(error) { return callback && callback(false); @@ -217,7 +217,9 @@ var Api = { getLastSyncState: function(callback) { var me = this; var url = this.getUrl('user/getSyncState'); - needle.get(url, function(error, response) { + console.log(url); + needle.get(url, {timeout: 10000}, function(error, response) { + // console.log('user/getSyncState ret'); me.checkError(error, response); if(error) { return callback && callback(false); @@ -439,7 +441,7 @@ var Api = { var me = this; var data = {notebookId: notebook.ServerNotebookId, usn: notebook.Usn}; log('delete notebook'); - needle.post(me.getUrl('notebook/deleteNotebook'), data, {}, function(err, resp) { + needle.post(me.getUrl('notebook/deleteNotebook'), data, {timeout: 10000}, function(err, resp) { me.checkError(err, resp); if(err) { return callback(false); @@ -633,7 +635,7 @@ var Api = { log('delete note'); // 这里要重新require下, 不然为{} Note = require('note'); - needle.post(me.getUrl('note/deleteTrash'), data, {}, function(err, resp) { + needle.post(me.getUrl('note/deleteTrash'), data, {timeout: 10000}, function(err, resp) { me.checkError(err, resp); if(err) { return callback(false); @@ -728,7 +730,7 @@ var Api = { // 删除标签 deleteTag: function(tag, callback) { var me = this; - needle.post(me.getUrl('tag/deleteTag'), {tag: tag.Tag, usn: tag.Usn}, {}, function(err, resp) { + needle.post(me.getUrl('tag/deleteTag'), {tag: tag.Tag, usn: tag.Usn}, {timeout: 10000}, function(err, resp) { me.checkError(err, resp); if(err) { return callback && callback(false); diff --git a/src/node_modules/needle/lib/needle.js b/src/node_modules/needle/lib/needle.js index e34dc568..7ca51fd5 100644 --- a/src/node_modules/needle/lib/needle.js +++ b/src/node_modules/needle/lib/needle.js @@ -21,8 +21,8 @@ var fs = require('fs'), ////////////////////////////////////////// var version = JSON.parse(fs.readFileSync(__dirname + '/../package.json').toString()).version, - debugging = !!process.env.DEBUG, - debug = debugging ? console.log : function() { /* noop */ }; + debugging = !!process.env.DEBUG, // life 开始debug模式 + debug = debugging ? console : {'log': function() { /* noop */ }}; var user_agent = 'Needle/' + version; user_agent += ' (Node.js ' + process.version + '; ' + process.platform + ' ' + process.arch + ')'; @@ -37,7 +37,7 @@ var decompressors = {}; try { - var zlib = require('zlib') + var zlib = require('zlib'); decompressors['x-deflate'] = zlib.Inflate; decompressors['deflate'] = zlib.Inflate; @@ -199,6 +199,7 @@ var Needle = { } }, + // 发送请求 send_request: function(count, method, uri, config, post_data, out, callback) { var timer, @@ -216,11 +217,11 @@ var Needle = { out.emit('end', err, resp, body); } - debug('Making request #' + count, request_opts); + // console.log('Making request #' + count, request_opts); var request = protocol.request(request_opts, function(resp) { - + // 没有收到 var headers = resp.headers; - debug('Got response', headers); + // console.log('Got response', headers); if (timer) clearTimeout(timer); // if redirect code is found, send a GET request to that location if enabled via 'follow' option @@ -348,7 +349,7 @@ var Needle = { }); // end request call // unless timeout was disabled, set a timeout to abort the request - console.log('needle timeout' + config.timeout); + // console.log('needle timeout' + config.timeout); if (config.timeout > 0) { timer = setTimeout(function() { console.error('needle timeout' + config.timeout); @@ -356,10 +357,21 @@ var Needle = { }, config.timeout); } + // request.abort()会触发error + // { [Error: socket hang up] code: 'ECONNRESET' } request.on('error', function(err) { - debug('Request error', err); if (timer) clearTimeout(timer); + // 再重新请求一次 + if(err && err.code == 'ECONNRESET' && count == 1) { + setTimeout(function() { + console.log('重连连一次'); + self.send_request(count+1, method, uri, config, post_data, out, callback); + }, Math.random() * 1000); + return; + } + + console.log('Request error', err); done(err || new Error('Unknown error when making request.')); }); diff --git a/src/note.html b/src/note.html index 4b74bef7..0624fc12 100755 --- a/src/note.html +++ b/src/note.html @@ -21,12 +21,13 @@ - - + + + diff --git a/src/public/config.js b/src/public/config.js index 3cc239e6..63777e52 100644 --- a/src/public/config.js +++ b/src/public/config.js @@ -20,5 +20,5 @@ var Config = { } ], "lang": "zh-hk", - "theme": "" + "theme": "night" }; \ No newline at end of file diff --git a/src/public/js/app/note.js b/src/public/js/app/note.js index 63774796..b5526ff5 100644 --- a/src/public/js/app/note.js +++ b/src/public/js/app/note.js @@ -383,7 +383,8 @@ Note.genDesc = function(content) { // 避免其它的").html(content).text(); - + + content = $.trim(content); // pre下text()会将< => < > => > content = content.replace(/]+src=\"data:image[^>]+>/g, ''); + } + + args = editor.fire('BeforePastePreProcess', {content: html}); // Internal event used by Quirks + args = editor.fire('PastePreProcess', args); + html = args.content; + + if (!args.isDefaultPrevented()) { + // User has bound PastePostProcess events then we need to pass it through a DOM node + // This is not ideal but we don't want to let the browser mess up the HTML for example + // some browsers add   to P tags etc + if (editor.hasEventListeners('PastePostProcess') && !args.isDefaultPrevented()) { + // We need to attach the element to the DOM so Sizzle selectors work on the contents + var tempBody = dom.add(editor.getBody(), 'div', {style: 'display:none'}, html); + args = editor.fire('PastePostProcess', {node: tempBody}); + dom.remove(tempBody); + html = args.node.innerHTML; + } + + if (!args.isDefaultPrevented()) { + // life + var node = editor.selection.getNode(); + if(node.nodeName == "PRE") { + if(!text) { + try { + text = $(html).text(); + } catch(e) { + } + } + // HTML不能粘贴 + // 其它有错误.... TODO + // 若有HTML, paste到其它地方有js错误 + // 貼html时自动会删除 + // 纯HTML编辑也会 + text = text.replace(//g, ">"); + // firefox下必须这个 + editor.insertRawContent(text); + // 之前用insertRawContent()有问题, ace paste下, TODO + // editor.insertContent(text); + } else { + // life 这里得到图片img, 复制到leanote下 + if(!self.copyImage) { + editor.insertContent(html); + } else { + var urlPrefix = UrlPrefix; + var needCopyImages = {}; // src => [id1,id2] + var time = (new Date()).getTime(); + try { + var $html = $("
" + html + " + var forcedRootBlockName = editor.settings.forced_root_block; + var forcedRootBlockStartHtml; + if (forcedRootBlockName) { + forcedRootBlockStartHtml = editor.dom.createHTML(forcedRootBlockName, editor.settings.forced_root_block_attrs); + forcedRootBlockStartHtml = forcedRootBlockStartHtml.substr(0, forcedRootBlockStartHtml.length - 3) + '>'; + } + + if ((startBlock && /^(PRE|DIV)$/.test(startBlock.nodeName)) || !forcedRootBlockName) { + text = Utils.filter(text, [ + [/\n/g, "
"] + ]); + } else { + text = Utils.filter(text, [ + [/\n\n/g, "

" + forcedRootBlockStartHtml], + [/^(.*<\/p>)(

)$/, forcedRootBlockStartHtml + '$1'], + [/\n/g, "
"] + ]); + + if (text.indexOf('

') != -1) { + text = forcedRootBlockStartHtml + text; + } + } + + pasteHtml(text, text2); + } + + /** + * Creates a paste bin element and moves the selection into that element. It will also move the element offscreen + * so that resize handles doesn't get produced on IE or Drag handles or Firefox. + */ + function createPasteBin() { + var dom = editor.dom, body = editor.getBody(), viewport = editor.dom.getViewPort(editor.getWin()); + var scrollY = editor.inline ? body.scrollTop : viewport.y, height = editor.inline ? body.clientHeight : viewport.h; + + removePasteBin(); + + // Create a pastebin + pasteBinElm = dom.add(editor.getBody(), 'div', { + id: "mcepastebin", + contentEditable: true, + "data-mce-bogus": "1", + style: 'position: absolute; top: ' + (scrollY + 20) + 'px;' + + 'width: 10px; height: ' + (height - 40) + 'px; overflow: hidden; opacity: 0' + }, pasteBinDefaultContent); + + // Move paste bin out of sight since the controlSelection rect gets displayed otherwise + dom.setStyle(pasteBinElm, 'left', dom.getStyle(body, 'direction', true) == 'rtl' ? 0xFFFF : -0xFFFF); + + // Prevent focus events from bubbeling fixed FocusManager issues + dom.bind(pasteBinElm, 'beforedeactivate focusin focusout', function(e) { + e.stopPropagation(); + }); + + lastRng = editor.selection.getRng(); + pasteBinElm.focus(); + editor.selection.select(pasteBinElm, true); + } + + /** + * Removes the paste bin if it exists. + */ + function removePasteBin() { + if (pasteBinElm) { + editor.dom.unbind(pasteBinElm); + editor.dom.remove(pasteBinElm); + + if (lastRng) { + editor.selection.setRng(lastRng); + } + } + + keyboardPastePlainTextState = false; + pasteBinElm = lastRng = null; + } + + /** + * Returns the contents of the paste bin as a HTML string. + * + * @return {String} Get the contents of the paste bin. + */ + function getPasteBinHtml() { + return pasteBinElm ? pasteBinElm.innerHTML : pasteBinDefaultContent; + } + + /** + * Gets various content types out of the Clipboard API. It will also get the + * plain text using older IE and WebKit API:s. + * + * @param {ClipboardEvent} clipboardEvent Event fired on paste. + * @return {Object} Object with mime types and data for those mime types. + */ + function getClipboardContent(clipboardEvent) { + var data = {}, clipboardData = clipboardEvent.clipboardData || editor.getDoc().dataTransfer; + + if (clipboardData && clipboardData.types) { + data['text/plain'] = clipboardData.getData('Text'); + + for (var i = 0; i < clipboardData.types.length; i++) { + var contentType = clipboardData.types[i]; + data[contentType] = clipboardData.getData(contentType); + } + } + + return data; + } + + function inAcePrevent() { + // 这个事件是从哪触发的? 浏览器自带的 + // life ace 如果在pre中, 直接返回 TODO + var ace = LeaAce.nowIsInAce(); + if(ace) { + // log("in aceEdiotr 2 paste"); + // 原来这里focus了 + setTimeout(function() { + ace[0].focus(); + }); + return true; + } + return false; + } + + editor.on('keydown', function(e) { + if (e.isDefaultPrevented()) { + return; + } + + // Ctrl+V or Shift+Insert + if ((VK.metaKeyPressed(e) && e.keyCode == 86) || (e.shiftKey && e.keyCode == 45)) { + + if(inAcePrevent()) { + return; + } + + keyboardPastePlainTextState = e.shiftKey && e.keyCode == 86; + + // Prevent undoManager keydown handler from making an undo level with the pastebin in it + e.stopImmediatePropagation(); + + keyboardPasteTimeStamp = new Date().getTime(); + + // IE doesn't support Ctrl+Shift+V and it doesn't even produce a paste event + // so lets fake a paste event and let IE use the execCommand/dataTransfer methods + if (Env.ie && keyboardPastePlainTextState) { + e.preventDefault(); + editor.fire('paste', {ieFake: true}); + return; + } + + createPasteBin(); + } + }); + + // 当url改变时, 得到图片的大小 copy from leanote_image + function getImageSize(url, callback) { + var img = document.createElement('img'); + + function done(width, height) { + img.parentNode.removeChild(img); + callback({width: width, height: height}); + } + + img.onload = function() { + done(img.clientWidth, img.clientHeight); + }; + + img.onerror = function() { + done(); + }; + + img.src = url; + + var style = img.style; + style.visibility = 'hidden'; + style.position = 'fixed'; + style.bottom = style.left = 0; + style.width = style.height = 'auto'; + + document.body.appendChild(img); + } + + editor.on('paste', function(e) { + if(inAcePrevent()) { + return; + } + + var clipboardContent = getClipboardContent(e); + var isKeyBoardPaste = new Date().getTime() - keyboardPasteTimeStamp < 100; + var plainTextMode = self.pasteFormat == "text" || keyboardPastePlainTextState; + + // Not a keyboard paste prevent default paste and try to grab the clipboard contents using different APIs + if (!isKeyBoardPaste) { + e.preventDefault(); + } + + // Try IE only method if paste isn't a keyboard paste + if (Env.ie && (!isKeyBoardPaste || e.ieFake)) { + createPasteBin(); + + editor.dom.bind(pasteBinElm, 'paste', function(e) { + e.stopPropagation(); + }); + + editor.getDoc().execCommand('Paste', false, null); + clipboardContent["text/html"] = getPasteBinHtml(); + removePasteBin(); + } + + setTimeout(function() { + var html = getPasteBinHtml(); + + // WebKit has a nice bug where it clones the paste bin if you paste from for example notepad + if (pasteBinElm && pasteBinElm.firstChild && pasteBinElm.firstChild.id === 'mcepastebin') { + plainTextMode = true; + } + + removePasteBin(); + + if (html == pasteBinDefaultContent || !isKeyBoardPaste) { + html = clipboardContent['text/html'] || clipboardContent['text/plain'] || pasteBinDefaultContent; + + if (html == pasteBinDefaultContent) { + if (!isKeyBoardPaste) { + // editor.windowManager.alert('Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents.'); + } + return; + } + } + + if (plainTextMode) { + pasteText(clipboardContent['text/plain'] || Utils.innerText(html)); + } else { + // life + pasteHtml(html, clipboardContent['text/plain']); + } + }, 0); + + //----------- + // paste image + try { + // common.js + pasteImage(); + return; + /* + if(pasteImage(e)) { + return; + } + */ + } catch(e) {}; + + }); + + + + self.pasteHtml = pasteHtml; + self.pasteText = pasteText; + }; +}); + +// Included from: js/tinymce/plugins/paste/classes/WordFilter.js + +/** + * WordFilter.js + * + * Copyright, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://www.tinymce.com/license + * Contributing: http://www.tinymce.com/contributing + */ + +/** + * This class parses word HTML into proper TinyMCE markup. + * + * @class tinymce.pasteplugin.Quirks + * @private + */ +define("tinymce/pasteplugin/WordFilter", [ + "tinymce/util/Tools", + "tinymce/html/DomParser", + "tinymce/html/Schema", + "tinymce/html/Serializer", + "tinymce/html/Node", + "tinymce/pasteplugin/Utils" +], function(Tools, DomParser, Schema, Serializer, Node, Utils) { + function isWordContent(content) { + return (/class="?Mso|style="[^"]*\bmso-|style='[^'']*\bmso-|w:WordDocument/i).test(content); + } + + function WordFilter(editor) { + var settings = editor.settings; + + editor.on('BeforePastePreProcess', function(e) { + var content = e.content, retainStyleProperties, validStyles; + + retainStyleProperties = settings.paste_retain_style_properties; + if (retainStyleProperties) { + validStyles = Tools.makeMap(retainStyleProperties); + } + + /** + * Converts fake bullet and numbered lists to real semantic OL/UL. + * + * @param {tinymce.html.Node} node Root node to convert children of. + */ + function convertFakeListsToProperLists(node) { + var currentListNode, prevListNode, lastLevel = 1; + + function convertParagraphToLi(paragraphNode, listStartTextNode, listName, start) { + var level = paragraphNode._listLevel || lastLevel; + + // Handle list nesting + if (level != lastLevel) { + if (level < lastLevel) { + // Move to parent list + if (currentListNode) { + currentListNode = currentListNode.parent.parent; + } + } else { + // Create new list + prevListNode = currentListNode; + currentListNode = null; + } + } + + if (!currentListNode || currentListNode.name != listName) { + prevListNode = prevListNode || currentListNode; + currentListNode = new Node(listName, 1); + + if (start > 1) { + currentListNode.attr('start', '' + start); + } + + paragraphNode.wrap(currentListNode); + } else { + currentListNode.append(paragraphNode); + } + + paragraphNode.name = 'li'; + listStartTextNode.value = ''; + + var nextNode = listStartTextNode.next; + if (nextNode && nextNode.type == 3) { + nextNode.value = nextNode.value.replace(/^\u00a0+/, ''); + } + + // Append list to previous list if it exists + if (level > lastLevel && prevListNode) { + prevListNode.lastChild.append(currentListNode); + } + + lastLevel = level; + } + + var paragraphs = node.getAll('p'); + + for (var i = 0; i < paragraphs.length; i++) { + node = paragraphs[i]; + + if (node.name == 'p' && node.firstChild) { + // Find first text node in paragraph + var nodeText = ''; + var listStartTextNode = node.firstChild; + + while (listStartTextNode) { + nodeText = listStartTextNode.value; + if (nodeText) { + break; + } + + listStartTextNode = listStartTextNode.firstChild; + } + + // Detect unordered lists look for bullets + if (/^\s*[\u2022\u00b7\u00a7\u00d8\u25CF]\s*$/.test(nodeText)) { + convertParagraphToLi(node, listStartTextNode, 'ul'); + continue; + } + + // Detect ordered lists 1., a. or ixv. + if (/^\s*\w+\.$/.test(nodeText)) { + // Parse OL start number + var matches = /([0-9])\./.exec(nodeText); + var start = 1; + if (matches) { + start = parseInt(matches[1], 10); + } + + convertParagraphToLi(node, listStartTextNode, 'ol', start); + continue; + } + + currentListNode = null; + } + } + } + + function filterStyles(node, styleValue) { + // Parse out list indent level for lists + if (node.name === 'p') { + var matches = /mso-list:\w+ \w+([0-9]+)/.exec(styleValue); + + if (matches) { + node._listLevel = parseInt(matches[1], 10); + } + } + + if (editor.getParam("paste_retain_style_properties", "none")) { + var outputStyle = ""; + + Tools.each(editor.dom.parseStyle(styleValue), function(value, name) { + // Convert various MS styles to W3C styles + switch (name) { + case "horiz-align": + name = "text-align"; + return; + + case "vert-align": + name = "vertical-align"; + return; + + case "font-color": + case "mso-foreground": + name = "color"; + return; + + case "mso-background": + case "mso-highlight": + name = "background"; + break; + } + + // Output only valid styles + if (retainStyleProperties == "all" || (validStyles && validStyles[name])) { + outputStyle += name + ':' + value + ';'; + } + }); + + if (outputStyle) { + return outputStyle; + } + } + + return null; + } + + if (settings.paste_enable_default_filters === false) { + return; + } + + // Detect is the contents is Word junk HTML + if (isWordContent(e.content)) { + e.wordContent = true; // Mark it for other processors + + // Remove basic Word junk + content = Utils.filter(content, [ + // Word comments like conditional comments etc + //gi, + + // Remove comments, scripts (e.g., msoShowComment), XML tag, VML content, + // MS Office namespaced tags, and a few other tags + /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi, + + // Convert into for line-though + [/<(\/?)s>/gi, "<$1strike>"], + + // Replace nsbp entites to char since it's easier to handle + [/ /gi, "\u00a0"], + + // Convert ___ to string of alternating + // breaking/non-breaking spaces of same length + [/([\s\u00a0]*)<\/span>/gi, + function(str, spaces) { + return (spaces.length > 0) ? + spaces.replace(/./, " ").slice(Math.floor(spaces.length/2)).split("").join("\u00a0") : ""; + } + ] + ]); + + var validElements = settings.paste_word_valid_elements; + if (!validElements) { + validElements = '@[style],-strong/b,-em/i,-span,-p,-ol,-ul,-li,-h1,-h2,-h3,-h4,-h5,-h6,' + + '-table,-tr,-td[colspan|rowspan],-th,-thead,-tfoot,-tbody,-a[!href],sub,sup,strike,br'; + } + + // Setup strict schema + var schema = new Schema({ + valid_elements: validElements + }); + + // Parse HTML into DOM structure + var domParser = new DomParser({}, schema); + + // Filte element style attributes + domParser.addAttributeFilter('style', function(nodes) { + var i = nodes.length, node; + + while (i--) { + node = nodes[i]; + node.attr('style', filterStyles(node, node.attr('style'))); + + // Remove pointess spans + if (node.name == 'span' && !node.attributes.length) { + node.unwrap(); + } + } + }); + + // Parse into DOM structure + var rootNode = domParser.parse(content); + + // Process DOM + convertFakeListsToProperLists(rootNode); + + // Serialize DOM back to HTML + e.content = new Serializer({}, schema).serialize(rootNode); + } + }); + } + + WordFilter.isWordContent = isWordContent; + + return WordFilter; +}); + +// Included from: js/tinymce/plugins/paste/classes/Quirks.js + +/** + * Quirks.js + * + * Copyright, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://www.tinymce.com/license + * Contributing: http://www.tinymce.com/contributing + */ + +/** + * This class contains various fixes for browsers. These issues can not be feature + * detected since we have no direct control over the clipboard. However we might be able + * to remove some of these fixes once the browsers gets updated/fixed. + * + * @class tinymce.pasteplugin.Quirks + * @private + */ +define("tinymce/pasteplugin/Quirks", [ + "tinymce/Env", + "tinymce/util/Tools", + "tinymce/pasteplugin/WordFilter", + "tinymce/pasteplugin/Utils" +], function(Env, Tools, WordFilter, Utils) { + "use strict"; + + return function(editor) { + function addPreProcessFilter(filterFunc) { + editor.on('BeforePastePreProcess', function(e) { + e.content = filterFunc(e.content); + }); + } + + /** + * Removes WebKit fragment comments and converted-space spans. + * + * This: + * a b + * + * Becomes: + * a b + */ + function removeWebKitFragments(html) { + html = Utils.filter(html, [ + /^[\s\S]*|[\s\S]*$/g, // WebKit fragment + [/\u00a0<\/span>/g, '\u00a0'], // WebKit   + /
$/ // Traling BR elements + ]); + + return html; + } + + /** + * Removes BR elements after block elements. IE9 has a nasty bug where it puts a BR element after each + * block element when pasting from word. This removes those elements. + * + * This: + *

a


b

+ * + * Becomes: + *

a

b

+ */ + function removeExplorerBrElementsAfterBlocks(html) { + // Only filter word specific content + if (!WordFilter.isWordContent(html)) { + return html; + } + + // Produce block regexp based on the block elements in schema + var blockElements = []; + + Tools.each(editor.schema.getBlockElements(), function(block, blockName) { + blockElements.push(blockName); + }); + + var explorerBlocksRegExp = new RegExp( + '(?:
 [\\s\\r\\n]+|
)*(<\\/?(' + blockElements.join('|') + ')[^>]*>)(?:
 [\\s\\r\\n]+|
)*', + 'g' + ); + + // Remove BR:s from: X
+ html = Utils.filter(html, [ + [explorerBlocksRegExp, '$1'] + ]); + + // IE9 also adds an extra BR element for each soft-linefeed and it also adds a BR for each word wrap break + html = Utils.filter(html, [ + [/

/g, '

'], // Replace multiple BR elements with uppercase BR to keep them intact + [/
/g, ' '], // Replace single br elements with space since they are word wrap BR:s + [/

/g, '
'] // Replace back the double brs but into a single BR + ]); + + return html; + } + + /** + * WebKit has a nasty bug where the all runtime styles gets added to style attributes when copy/pasting contents. + * This fix solves that by simply removing the whole style attribute. + * + * Todo: This can be made smarter. Keeping styles that override existing ones etc. + * + * @param {String} content Content that needs to be processed. + * @return {String} Processed contents. + */ + function removeWebKitStyles(content) { + if (editor.settings.paste_remove_styles || editor.settings.paste_remove_styles_if_webkit !== false) { + content = content.replace(/ style=\"[^\"]+\"/g, ''); + } + + return content; + } + + // Sniff browsers and apply fixes since we can't feature detect + if (Env.webkit) { + addPreProcessFilter(removeWebKitStyles); + addPreProcessFilter(removeWebKitFragments); + } + + if (Env.ie) { + addPreProcessFilter(removeExplorerBrElementsAfterBlocks); + } + }; +}); + +// Included from: js/tinymce/plugins/paste/classes/Plugin.js + +/** + * Plugin.js + * + * Copyright, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://www.tinymce.com/license + * Contributing: http://www.tinymce.com/contributing + */ + +/** + * This class contains the tinymce plugin logic for the paste plugin. + * + * @class tinymce.pasteplugin.Plugin + * @private + */ +define("tinymce/pasteplugin/Plugin", [ + "tinymce/PluginManager", + "tinymce/pasteplugin/Clipboard", + "tinymce/pasteplugin/WordFilter", + "tinymce/pasteplugin/Quirks" +], function(PluginManager, Clipboard, WordFilter, Quirks) { + var userIsInformed; + var userIsInformed2; + + PluginManager.add('paste', function(editor) { + var self = this, clipboard, settings = editor.settings; + + function togglePlainTextPaste() { + if (clipboard.pasteFormat == "text") { + this.active(false); + clipboard.pasteFormat = "html"; + } else { + clipboard.pasteFormat = "text"; + this.active(true); + + if (!userIsInformed) { + editor.windowManager.alert( + 'Paste is now in plain text mode. Contents will now ' + + 'be pasted as plain text until you toggle this option off.' + ); + + userIsInformed = true; + } + } + } + + function togglePasteCopyImage() { + if (clipboard.copyImage) { + this.active(false); + clipboard.copyImage = false + } else { + clipboard.copyImage = true; + this.active(true); + if (!userIsInformed2) { + editor.windowManager.alert( + "When copy other site's images (not in leanote) into editor, it will copy the image into your album." + ); + userIsInformed2 = true; + } + } + } + + self.clipboard = clipboard = new Clipboard(editor); + self.quirks = new Quirks(editor); + self.wordFilter = new WordFilter(editor); + + if (editor.settings.paste_as_text) { + self.clipboard.pasteFormat = "text"; + } + + if (settings.paste_preprocess) { + editor.on('PastePreProcess', function(e) { + settings.paste_preprocess.call(self, self, e); + }); + } + + if (settings.paste_postprocess) { + editor.on('PastePostProcess', function(e) { + settings.paste_postprocess.call(self, self, e); + }); + } + + editor.addCommand('mceInsertClipboardContent', function(ui, value) { + if (value.content) { + self.clipboard.pasteHtml(value.content); + } + + if (value.text) { + self.clipboard.pasteText(value.text); + } + }); + + // Block all drag/drop events + if (editor.paste_block_drop) { + editor.on('dragend dragover draggesture dragdrop drop drag', function(e) { + e.preventDefault(); + e.stopPropagation(); + }); + } + + // Prevent users from dropping data images on Gecko + if (!editor.settings.paste_data_images) { + editor.on('drop', function(e) { + var dataTransfer = e.dataTransfer; + + if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) { + e.preventDefault(); + } + }); + } + + editor.addButton('pastetext', { + icon: 'pastetext', + tooltip: 'Paste as text', + onclick: togglePlainTextPaste, + active: self.clipboard.pasteFormat == "text" + }); + + editor.addButton('pasteCopyImage', { + icon: 'copy', + tooltip: "When Paste other site's image, copy it into my album as public image", + onclick: togglePasteCopyImage, + active: self.clipboard.copyImage === true + }); + + editor.addMenuItem('pastetext', { + text: 'Paste as text', + selectable: true, + active: clipboard.pasteFormat, + onclick: togglePlainTextPaste + }); + }); +}); + +expose(["tinymce/pasteplugin/Utils","tinymce/pasteplugin/WordFilter"]); +})(this); \ No newline at end of file diff --git a/src/test2.js b/src/test2.js index 055be242..48a00a88 100755 --- a/src/test2.js +++ b/src/test2.js @@ -1,53 +1,10 @@ +var needle = require('needle'); -var fs = require('fs'); - -var common = require('common'); - -/* -var AdmZip = require('adm-zip'); -// https://github.com/cthackers/adm-zip -var filePath = './a.zip'; -var zip = new AdmZip(filePath); -zip.extractAllTo('./cc', true); -fs.readdir('./cc', function(err, files) { - console.log(files); -}); -*/ - -var scanFolder = function (path) { - var fileList = []; - var folderList = []; - var walk = function(path, fileList, folderList) { - files = fs.readdirSync(path); - files.forEach(function(item) { - var tmpPath = path + '/' + item; - var stats = fs.statSync(tmpPath); - - if (stats.isDirectory() && item.indexOf('_') == -1) { - walk(tmpPath, fileList, folderList); - folderList.push(tmpPath); - } - else if (item.indexOf('_') == -1) { - fileList.push(tmpPath); - } - }); - }; - - - walk(path, fileList, folderList); - - console.log('scan foler end....'); - console.log(fileList); - - return fileList; -}; - -// scanFolder('/Users/life/Documents/kuaipan/leanote/desktop-app/src/data/1.1'); -// console.log(process.platform.toLowerCase().indexOf('window')); - -// var s = fs.existsSync('/Users/life/Library/Application Support/leanote/data/5368c1aa99c37b029d000001/images/1428148081216_2.pdf'); -// console.log(s); - -for(var i = 0; i < 10; ++i) { - console.log(common.objectId()); -} +var m = 100; +var j = 0; +for(var i = 0; i < m; ++i) { + needle.get('http://leanote.com/api/user/getSyncState?token=554576a438f4113d3a000962&', function(err, resp) { + j++; + console.log(j); + }); +} \ No newline at end of file