<commit_before>$.Redactor.prototype.WoltLabPaste = function() {
	"use strict";

	var _environment = null;

	return {
		init: function () {
			var clipboardData = null;
			var isKbd = false;

			// IE 11
			var isIe = (document.documentMode && typeof window.clipboardData === 'object');

			var pastedHtml = null, pastedPlainText = null;

			// special `init()` implementation for Chrome on Android which seems to have
			// some serious issues with `setTimeout()` during a `paste` event
			var mpInitChromeOnAndroid = (function (e) {
				this.rtePaste = true;
				var pre = !!(this.opts.type === 'pre' || this.utils.isCurrentOrParent('pre'));

				this.utils.saveScroll();
				this.selection.save();
				this.paste.createPasteBox(pre);

				var html = this.paste.getPasteBoxCode(pre);

				// buffer
				this.buffer.set();
				this.selection.restore();

				this.utils.restoreScroll();

				// paste info
				var data = this.clean.getCurrentType(html);

				// clean
				html = this.clean.onPaste(html, data);

				// callback
				var returned = this.core.callback('paste', html);
				html = (typeof returned === 'undefined') ? html : returned;

				this.paste.insert(html, data);
				this.rtePaste = false;

				// clean pre breaklines
				if (pre) this.clean.cleanPre();
			}).bind(this);

			var mpInit = this.paste.init;
			this.paste.init = (function (e) {
				pastedPlainText = pastedHtml = null;

				var isCode = (this.opts.type === 'pre' || this.utils.isCurrentOrParent('pre'));
				isKbd = (!isCode && this.utils.isCurrentOrParent('kbd'));
				if (isCode || isKbd) {
					if (isIe) {
						clipboardData = window.clipboardData.getData('Text');
					}
					else {
						clipboardData = e.originalEvent.clipboardData.getData('text/plain');
					}

					var mpCleanEncodeEntities = this.clean.encodeEntities;
					this.clean.encodeEntities = (function(str) {
						// revert to original method
						this.clean.encodeEntities = mpCleanEncodeEntities;

						return WCF.String.escapeHTML(str);
					}).bind(this);
				}
				else if (!isIe) {
					var types = e.originalEvent.clipboardData.types;
					if (types.length === 1 && types[0] === 'text/plain') {
						var tmp = WCF.String.escapeHTML(e.originalEvent.clipboardData.getData('text/plain'));

						pastedPlainText = '';
						var lines = tmp.split("\n");
						if (lines.length === 1) {
							// paste single-line content as real plain text
							pastedPlainText = tmp;
						}
						else {
							// plain newline characters do not work out well, mimic HTML instead
							lines.forEach(function (line) {
								line = line.trim();
								if (line === '') line = '
';

								pastedPlainText += '
' + line + '
';
							});
						}
					}
					else if (types.indexOf('text/html') !== -1) {
						// handles all major browsers except iOS Safari which does not expose `text/html`,
						// but instead gives us `public.rtf` (which of course is completely useless)
						// https://bugs.webkit.org/show_bug.cgi?id=19893
						pastedHtml = e.originalEvent.clipboardData.getData('text/html');

						// remove document fragments
						if (pastedHtml.trim().match(/^]*>[\s\S]*?]*>([\s\S]+)<\/body>[\s\S]*?<\/html>$/)) {
							pastedHtml = RegExp.$1.replace(/^\s*(?:)(.+)(?:)?\s*$/, '$1');
						}
					}
				}

				if (pastedPlainText !== null || pastedHtml !== null) {
					e.preventDefault();
				}

				if (_environment.platform() === 'android' && _environment.browser() === 'chrome') {
					mpInitChromeOnAndroid(e);
				}
				else {
					mpInit.call(this, e);
				}
			}).bind(this);

			require(['Environment'], (function(Environment) {
				_environment = Environment;

				if (_environment.platform() === 'ios') {
					var mpAppendPasteBox = this.paste.appendPasteBox;
					this.paste.appendPasteBox = (function() {
						// iOS doesn't like `position: fixed` and font-sizes below 16px that much
						this.$pasteBox.css({
							fontSize: '16px',
							height: '1px',
							left: '1px',
							overflow: 'hidden',
							position: 'absolute',
							top: (~~(window.innerHeight / 4) + window.pageYOffset) + 'px',
							width: '1px'
						});

						mpAppendPasteBox.call(this);
					}).bind(this);
				}
			}).bind(this));

			var mpCreatePasteBox = this.paste.createPasteBox;
			this.paste.createPasteBox = (function (pre) {
				if (pastedHtml === null && pastedPlainText === null) {
					mpCreatePasteBox.call(this, pre);
				}

				// do nothing
			}).bind(this);

			var mpGetPasteBoxCode = this.paste.getPasteBoxCode;
			this.paste.getPasteBoxCode = (function (pre) {
				if (pastedHtml !== null || pastedPlainText !== null) {
					// prevent page scrolling
					this.tmpScrollTop = undefined;

					return pastedHtml || pastedPlainText;
				}

				var returnValue = mpGetPasteBoxCode.call(this, pre);

				if (isKbd) {
					return clipboardData;
				}

				// use clipboard data if paste box is flawed or when
				// pasting in IE 11 where clipboard data is more reliable
				if (pre && (!returnValue || isIe)) {
					return clipboardData;
				}

				return returnValue;
			}).bind(this);

			// rebind paste event
			this.core.editor().off('paste.redactor').on('paste.redactor', this.paste.init.bind(this));

			this.paste.detectClipboardUpload = (function (e) {
				e = e.originalEvent || e;

				var file = null;
				if (isIe) {
					if (!window.clipboardData.files.length) {
						return false;
					}

					file = window.clipboardData.files.item(0);
				}
				else if (this.detect.isFirefox()) {
					return false;
				}
				else {
					var clipboard = e.clipboardData;

					// Safari
					var types = clipboard.types;
					if (Array.isArray(types) && types.indexOf('public.tiff') !== -1) {
						if (clipboard.files.length === 0) {
							// pasted an `<img>` element from clipboard
							return;
						}
						else if (clipboard.files.length === 1) {
							// This may not work if the file was copied from Finder for whatever
							// reasons and it is not possible to try/catch this error (wow!).
							//
							// It does not have any side-effects when failing other than canceling
							// out the `paste` event, which is pretty much what we're looking for
							// anyway. It does work from certain apps, but Safari exposes too little
							// information to tell them apart, so we just have to try it.
							//
							// See https://bugs.webkit.org/show_bug.cgi?id=171504
							file = clipboard.files[0];
							cancelPaste = true;

							if (file !== null) {
								e.preventDefault();
							}
						}
						else {
							e.preventDefault();
							return false;
						}
					}

					if (file === null) {
						if (!clipboard.items || !clipboard.items.length) {
							return;
						}

						if (this.detect.isWebkit()) {
							var item, hasFile = false, hasHtml = false;
							for (var i = 0, length = clipboard.items.length; i < length; i++) {
								item = clipboard.items[i];
								if (item.kind === 'string' && item.type === 'text/html') hasHtml = true;
								else if (item.kind === 'file') hasFile = true;
							}

							// pasted an `<img>` element from clipboard
							if (hasFile && hasHtml) {
								return false;
							}
						}

						var cancelPaste = false;
						file = clipboard.items[0].getAsFile();
						if (file === null) {
							if (this.detect.isWebkit() && clipboard.items.length > 1) {
								file = clipboard.items[1].getAsFile();
								cancelPaste = true;

								if (file !== null) {
									e.preventDefault();
								}
							}

							if (file === null) {
								return false;
							}
						}
					}
				}

				var reader = new FileReader();
				reader.readAsDataURL(file);
				reader.onload = this.paste.insertFromClipboard.bind(this);

				return (cancelPaste === false);
			}).bind(this);

			this.paste.insertFromClipboard = (function (e) {
				if (!window.FormData) {
					return;
				}

				this.buffer.set();

				WCF.System.Event.fireEvent('com.woltlab.wcf.redactor2', 'pasteFromClipboard_' + this.$element[0].id, {
					blob: this.utils.dataURItoBlob(e.target.result)
				});

				this.rtePaste = false;
			}).bind(this);

			var transparentGif = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
			var mpInsert = this.paste.insert;
			this.paste.insert = (function(html, data) {
				if (isKbd) data.pre = true;

				if (this.utils.isCurrentOrParent('kbd')) {
					mpInsert.call(this, html, data);

					var current = this.selection.current();
					if (current.nodeType === Node.TEXT_NODE) current = current.parentNode;
					var kbd = current.closest('kbd');
					var paragraphs = elByTag('p', kbd);
					while (paragraphs.length) {
						paragraphs[0].outerHTML = paragraphs[0].innerHTML;
					}

					var parts = kbd.innerHTML.split(/
/);
					if (parts.length > 1) {
						var lastParent = this.selection.block();

						for (var i = 1, length = parts.length; i < length; i++) {
							var newParent = elCreate(lastParent.nodeName);
							newParent.innerHTML = '' + parts[i] + (i === length - 1 ? this.marker.html() : '') + '';
							lastParent.parentNode.insertBefore(newParent, lastParent.nextSibling);

							lastParent = newParent;
						}

						kbd.innerHTML = parts[0];

						this.selection.restore();

					}

					return;
				}
				else if (data.pre) {
					return mpInsert.call(this, html, data);
				}

				var div = elCreate('div');
				div.innerHTML = html;

				var pastedImages = [];
				if (!data.pre && !data.text) {
					elBySelAll('img', div, (function(img) {
						var src = img.src;
						if (src.indexOf('data:image') === 0 && src !== transparentGif) {
							img.src = transparentGif;

							var uuid = WCF.getUUID();
							elData(img, 'uuid', uuid);
							pastedImages.push({
								src: src,
								uuid: uuid
							});

							elHide(img);
						}
					}).bind(this));
				}

				mpInsert.call(this, div.innerHTML, data);

				// check if the caret is now inside an  element, but at
				// the very last position
				var selection = window.getSelection();
				if (selection.rangeCount && selection.anchorNode.nodeName === 'A' && selection.anchorOffset === selection.anchorNode.childNodes.length) {
					this.caret.after(selection.anchorNode);
				}

				if (pastedImages.length) {
					window.setTimeout((function () {
						var imgData, img;
						for (var i = 0, length = pastedImages.length; i < length; i++) {
							imgData = pastedImages[i];
							img = elBySel('img[data-uuid="' + imgData.uuid + '"]', this.$editor[0]);

							if (img) {
								if (isIe) {
									// Internet Explorer 11 triggers both the event *and* insert the image
									img.parentNode.removeChild(img);
								}
								else {
									WCF.System.Event.fireEvent('com.woltlab.wcf.redactor2', 'pasteFromClipboard_' + this.$element[0].id, {
										blob: this.utils.dataURItoBlob(imgData.src),
										replace: img
									});
								}
							}
						}
					}).bind(this), 50);
				}

				// cleanup any stray text fragments caused by paragraphs
				// being replaced by the clipboard contents
				var node, badNodes = [];
				var editor = this.core.editor()[0];
				for (i = 0, length = editor.childNodes.length; i < length; i++) {
					node = editor.childNodes[i];
					if (node.nodeType === Node.TEXT_NODE && node.textContent === '\u200B') {
						badNodes.push(node);
					}
				}
				badNodes.forEach(elRemove);

				this.rtePaste = false;
			}).bind(this);

			this.paste.clipboardUpload = function () { /* not required, images are handled in `paste.insert()` below */ };
		}
	};
};
<commit_msg>Fall-back to plain text if clipboard html was empty<commit_after>$.Redactor.prototype.WoltLabPaste = function() {
	"use strict";

	var _environment = null;

	return {
		init: function () {
			var clipboardData = null;
			var isKbd = false;

			// IE 11
			var isIe = (document.documentMode && typeof window.clipboardData === 'object');

			var pastedHtml = null, pastedPlainText = null;

			// special `init()` implementation for Chrome on Android which seems to have
			// some serious issues with `setTimeout()` during a `paste` event
			var mpInitChromeOnAndroid = (function (e) {
				this.rtePaste = true;
				var pre = !!(this.opts.type === 'pre' || this.utils.isCurrentOrParent('pre'));

				this.utils.saveScroll();
				this.selection.save();
				this.paste.createPasteBox(pre);

				var html = this.paste.getPasteBoxCode(pre);

				// buffer
				this.buffer.set();
				this.selection.restore();

				this.utils.restoreScroll();

				// paste info
				var data = this.clean.getCurrentType(html);

				// clean
				html = this.clean.onPaste(html, data);

				// callback
				var returned = this.core.callback('paste', html);
				html = (typeof returned === 'undefined') ? html : returned;

				this.paste.insert(html, data);
				this.rtePaste = false;

				// clean pre breaklines
				if (pre) this.clean.cleanPre();
			}).bind(this);

			var mpInit = this.paste.init;
			this.paste.init = (function (e) {
				pastedPlainText = pastedHtml = null;

				var isCode = (this.opts.type === 'pre' || this.utils.isCurrentOrParent('pre'));
				isKbd = (!isCode && this.utils.isCurrentOrParent('kbd'));
				if (isCode || isKbd) {
					if (isIe) {
						clipboardData = window.clipboardData.getData('Text');
					}
					else {
						clipboardData = e.originalEvent.clipboardData.getData('text/plain');
					}

					var mpCleanEncodeEntities = this.clean.encodeEntities;
					this.clean.encodeEntities = (function(str) {
						// revert to original method
						this.clean.encodeEntities = mpCleanEncodeEntities;

						return WCF.String.escapeHTML(str);
					}).bind(this);
				}
				else if (!isIe) {
					var types = e.originalEvent.clipboardData.types;
					var hasContent = false;
					if (types.indexOf('text/html') !== -1) {
						// handles all major browsers except iOS Safari which does not expose `text/html`,
						// but instead gives us `public.rtf` (which of course is completely useless)
						// https://bugs.webkit.org/show_bug.cgi?id=19893
						pastedHtml = e.originalEvent.clipboardData.getData('text/html');

						// remove document fragments
						if (pastedHtml.trim().match(/^]*>[\s\S]*?]*>([\s\S]+)<\/body>[\s\S]*?<\/html>$/)) {
							pastedHtml = RegExp.$1.replace(/^\s*(?:)(.+)(?:)?\s*$/, '$1');
						}

						hasContent = (pastedHtml.trim().length !== 0);
					}

					if (!hasContent && types.indexOf('text/plain') !== -1) {
						var tmp = WCF.String.escapeHTML(e.originalEvent.clipboardData.getData('text/plain'));

						pastedPlainText = '';
						var lines = tmp.split("\n");
						if (lines.length === 1) {
							// paste single-line content as real plain text
							pastedPlainText = tmp;
						}
						else {
							// plain newline characters do not work out well, mimic HTML instead
							lines.forEach(function (line) {
								line = line.trim();
								if (line === '') line = '
';

								pastedPlainText += '
' + line + '
';
							});
						}
					}
				}

				if (pastedPlainText !== null || pastedHtml !== null) {
					e.preventDefault();
				}

				if (_environment.platform() === 'android' && _environment.browser() === 'chrome') {
					mpInitChromeOnAndroid(e);
				}
				else {
					mpInit.call(this, e);
				}
			}).bind(this);

			require(['Environment'], (function(Environment) {
				_environment = Environment;

				if (_environment.platform() === 'ios') {
					var mpAppendPasteBox = this.paste.appendPasteBox;
					this.paste.appendPasteBox = (function() {
						// iOS doesn't like `position: fixed` and font-sizes below 16px that much
						this.$pasteBox.css({
							fontSize: '16px',
							height: '1px',
							left: '1px',
							overflow: 'hidden',
							position: 'absolute',
							top: (~~(window.innerHeight / 4) + window.pageYOffset) + 'px',
							width: '1px'
						});

						mpAppendPasteBox.call(this);
					}).bind(this);
				}
			}).bind(this));

			var mpCreatePasteBox = this.paste.createPasteBox;
			this.paste.createPasteBox = (function (pre) {
				if (pastedHtml === null && pastedPlainText === null) {
					mpCreatePasteBox.call(this, pre);
				}

				// do nothing
			}).bind(this);

			var mpGetPasteBoxCode = this.paste.getPasteBoxCode;
			this.paste.getPasteBoxCode = (function (pre) {
				if (pastedHtml !== null || pastedPlainText !== null) {
					// prevent page scrolling
					this.tmpScrollTop = undefined;

					return pastedHtml || pastedPlainText;
				}

				var returnValue = mpGetPasteBoxCode.call(this, pre);

				if (isKbd) {
					return clipboardData;
				}

				// use clipboard data if paste box is flawed or when
				// pasting in IE 11 where clipboard data is more reliable
				if (pre && (!returnValue || isIe)) {
					return clipboardData;
				}

				return returnValue;
			}).bind(this);

			// rebind paste event
			this.core.editor().off('paste.redactor').on('paste.redactor', this.paste.init.bind(this));

			this.paste.detectClipboardUpload = (function (e) {
				e = e.originalEvent || e;

				var file = null;
				if (isIe) {
					if (!window.clipboardData.files.length) {
						return false;
					}

					file = window.clipboardData.files.item(0);
				}
				else if (this.detect.isFirefox()) {
					return false;
				}
				else {
					var clipboard = e.clipboardData;

					// Safari
					var types = clipboard.types;
					if (Array.isArray(types) && types.indexOf('public.tiff') !== -1) {
						if (clipboard.files.length === 0) {
							// pasted an `<img>` element from clipboard
							return;
						}
						else if (clipboard.files.length === 1) {
							// This may not work if the file was copied from Finder for whatever
							// reasons and it is not possible to try/catch this error (wow!).
							//
							// It does not have any side-effects when failing other than canceling
							// out the `paste` event, which is pretty much what we're looking for
							// anyway. It does work from certain apps, but Safari exposes too little
							// information to tell them apart, so we just have to try it.
							//
							// See https://bugs.webkit.org/show_bug.cgi?id=171504
							file = clipboard.files[0];
							cancelPaste = true;

							if (file !== null) {
								e.preventDefault();
							}
						}
						else {
							e.preventDefault();
							return false;
						}
					}

					if (file === null) {
						if (!clipboard.items || !clipboard.items.length) {
							return;
						}

						if (this.detect.isWebkit()) {
							var item, hasFile = false, hasHtml = false;
							for (var i = 0, length = clipboard.items.length; i < length; i++) {
								item = clipboard.items[i];
								if (item.kind === 'string' && item.type === 'text/html') hasHtml = true;
								else if (item.kind === 'file') hasFile = true;
							}

							// pasted an `<img>` element from clipboard
							if (hasFile && hasHtml) {
								return false;
							}
						}

						var cancelPaste = false;
						file = clipboard.items[0].getAsFile();
						if (file === null) {
							if (this.detect.isWebkit() && clipboard.items.length > 1) {
								file = clipboard.items[1].getAsFile();
								cancelPaste = true;

								if (file !== null) {
									e.preventDefault();
								}
							}

							if (file === null) {
								return false;
							}
						}
					}
				}

				var reader = new FileReader();
				reader.readAsDataURL(file);
				reader.onload = this.paste.insertFromClipboard.bind(this);

				return (cancelPaste === false);
			}).bind(this);

			this.paste.insertFromClipboard = (function (e) {
				if (!window.FormData) {
					return;
				}

				this.buffer.set();

				WCF.System.Event.fireEvent('com.woltlab.wcf.redactor2', 'pasteFromClipboard_' + this.$element[0].id, {
					blob: this.utils.dataURItoBlob(e.target.result)
				});

				this.rtePaste = false;
			}).bind(this);

			var transparentGif = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
			var mpInsert = this.paste.insert;
			this.paste.insert = (function(html, data) {
				if (isKbd) data.pre = true;

				if (this.utils.isCurrentOrParent('kbd')) {
					mpInsert.call(this, html, data);

					var current = this.selection.current();
					if (current.nodeType === Node.TEXT_NODE) current = current.parentNode;
					var kbd = current.closest('kbd');
					var paragraphs = elByTag('p', kbd);
					while (paragraphs.length) {
						paragraphs[0].outerHTML = paragraphs[0].innerHTML;
					}

					var parts = kbd.innerHTML.split(/
/);
					if (parts.length > 1) {
						var lastParent = this.selection.block();

						for (var i = 1, length = parts.length; i < length; i++) {
							var newParent = elCreate(lastParent.nodeName);
							newParent.innerHTML = '' + parts[i] + (i === length - 1 ? this.marker.html() : '') + '';
							lastParent.parentNode.insertBefore(newParent, lastParent.nextSibling);

							lastParent = newParent;
						}

						kbd.innerHTML = parts[0];

						this.selection.restore();

					}

					return;
				}
				else if (data.pre) {
					return mpInsert.call(this, html, data);
				}

				var div = elCreate('div');
				div.innerHTML = html;

				var pastedImages = [];
				if (!data.pre && !data.text) {
					elBySelAll('img', div, (function(img) {
						var src = img.src;
						if (src.indexOf('data:image') === 0 && src !== transparentGif) {
							img.src = transparentGif;

							var uuid = WCF.getUUID();
							elData(img, 'uuid', uuid);
							pastedImages.push({
								src: src,
								uuid: uuid
							});

							elHide(img);
						}
					}).bind(this));
				}

				mpInsert.call(this, div.innerHTML, data);

				// check if the caret is now inside an  element, but at
				// the very last position
				var selection = window.getSelection();
				if (selection.rangeCount && selection.anchorNode.nodeName === 'A' && selection.anchorOffset === selection.anchorNode.childNodes.length) {
					this.caret.after(selection.anchorNode);
				}

				if (pastedImages.length) {
					window.setTimeout((function () {
						var imgData, img;
						for (var i = 0, length = pastedImages.length; i < length; i++) {
							imgData = pastedImages[i];
							img = elBySel('img[data-uuid="' + imgData.uuid + '"]', this.$editor[0]);

							if (img) {
								if (isIe) {
									// Internet Explorer 11 triggers both the event *and* insert the image
									img.parentNode.removeChild(img);
								}
								else {
									WCF.System.Event.fireEvent('com.woltlab.wcf.redactor2', 'pasteFromClipboard_' + this.$element[0].id, {
										blob: this.utils.dataURItoBlob(imgData.src),
										replace: img
									});
								}
							}
						}
					}).bind(this), 50);
				}

				// cleanup any stray text fragments caused by paragraphs
				// being replaced by the clipboard contents
				var node, badNodes = [];
				var editor = this.core.editor()[0];
				for (i = 0, length = editor.childNodes.length; i < length; i++) {
					node = editor.childNodes[i];
					if (node.nodeType === Node.TEXT_NODE && node.textContent === '\u200B') {
						badNodes.push(node);
					}
				}
				badNodes.forEach(elRemove);

				this.rtePaste = false;
			}).bind(this);

			this.paste.clipboardUpload = function () { /* not required, images are handled in `paste.insert()` below */ };
		}
	};
};
<|endoftext|>


<commit_before>(function(root) {

    var hyve = (typeof require == 'function' && !(typeof define == 'function' && define.amd)) ? require('../src/hyve.core.js') : root.hyve

    hyve.feeds['instagram'] = {
        methods : ['friends'],
        interval : 3000,
        interval_friends : 10000,
        access_token : '',
        feed_urls : {
            friends: 'https://api.instagram.com/v1/users/self/feed?limit=25&type=post{{ access_token }}{{ since }}{{#&callback=#callback}}'
        },
        format_url : function(query){
            var since_arg = ''
            if (this.since){
                since_arg = '&since='+this.since
            }
            return {
                      query: query
                    , since: since_arg
                    , access_token: '&access_token=' + this.access_token
            }
        },
        parsers : {
            friends: function(data, query, callback){
                if (data.data.length > 0){
                    data.data.forEach(function(item){

                        console.log('instagram item',item)

                        hyve.process({
                            'service' : 'instagram',
                            'type' : 'image',
                            'query' : query,
                            'user' : {
                                'id' : item.user.id,
                                'name' : item.user.username,
                                'real_name' : item.user.full_name,
                                'avatar' : item.user.profile_picture
                            },
                            'id' : item.id,
                            'date' : item.created_time,
                            'text' : item.caption,
                            'thumbnail' : item.images.standard_resolution,
                            'comments' : item.comments.count,
                            'source' : item.link,
                            'likes' : item.likes.count,
                            'weight' : item.likes.count + item.comments.count
                        },callback)

                    },this)
                }
            }
        }
    }

})(this)
<commit_msg>remove log line<commit_after>(function(root) {

    var hyve = (typeof require == 'function' && !(typeof define == 'function' && define.amd)) ? require('../src/hyve.core.js') : root.hyve

    hyve.feeds['instagram'] = {
        methods : ['friends'],
        interval : 3000,
        interval_friends : 10000,
        access_token : '',
        feed_urls : {
            friends: 'https://api.instagram.com/v1/users/self/feed?limit=25&type=post{{ access_token }}{{ since }}{{#&callback=#callback}}'
        },
        format_url : function(query){
            var since_arg = ''
            if (this.since){
                since_arg = '&since='+this.since
            }
            return {
                      query: query
                    , since: since_arg
                    , access_token: '&access_token=' + this.access_token
            }
        },
        parsers : {
            friends: function(data, query, callback){
                if (data.data.length > 0){
                    data.data.forEach(function(item){

                        hyve.process({
                            'service' : 'instagram',
                            'type' : 'image',
                            'query' : query,
                            'user' : {
                                'id' : item.user.id,
                                'name' : item.user.username,
                                'real_name' : item.user.full_name,
                                'avatar' : item.user.profile_picture
                            },
                            'id' : item.id,
                            'date' : item.created_time,
                            'text' : item.caption,
                            'thumbnail' : item.images.standard_resolution,
                            'comments' : item.comments.count,
                            'source' : item.link,
                            'likes' : item.likes.count,
                            'weight' : item.likes.count + item.comments.count
                        },callback)

                    },this)
                }
            }
        }
    }

})(this)
<|endoftext|>


<commit_before>/*
 * https://nutty.io
 * Copyright (c) 2014 krishna.srinivas@gmail.com All rights reserved.
 * GPLv3 License <http://www.gnu.org/licenses/gpl.txt>
 */

angular.module('nuttyapp')
    .factory('Termdevice', ['$rootScope', 'NuttySession', 'Compatibility', '$timeout', 'alertBox', '$location',
        function($rootScope, NuttySession, Compatibility, $timeout, alertBox, $location) {
            var inputcbk;
            var autoreload = false;
            var port;
            var extid = "ooelecakcjobkpmbdnflfneaalbhejmk";
            // var extid = "jboablmfecefcaedlpaaciooecbgjbhl";

            function postMessage(msg) {
                if (port) {
                    port.postMessage(msg)
                } else {
                    msg.type = '_nutty_fromwebpage';
                    window.postMessage(msg, window.location.origin);
                }
            }

            var retobj = {
                extension: false,
                nativehost: false,
                ondata: function(cbk) {
                    inputcbk = cbk;
                },
                write: function(msg) {
                    if (!msg) {
                        console.log("Termdevice.write(): msg is null")
                        return;
                    }
                    if (msg.newtmuxsession) {
                        retobj.newtmuxsession();
                        return;
                    }
                    postMessage(msg);
                },
                newtmuxsession: function() {
                    if (!NuttySession.sessionid)
                        return;
                    postMessage({
                        unsetsessionid: true
                    });
                    postMessage({
                        setsessionid: NuttySession.sessionid
                    });
                    postMessage({
                        rowcol: 1,
                        row: NuttySession.rowcol.row,
                        col: NuttySession.rowcol.col
                    });
                }
            }

            if (window.chrome && chrome.runtime && chrome.runtime.connect)
                port = chrome.runtime.connect(extid);
            if (port) {
                retobj.extension = true;
                port.onMessage.addListener(function(msg) {
                    if (!msg) {
                        log.console("msg from extension is undefined");
                        return;
                    }
                    if (msg.nativehost === "connected") {
                        retobj.nativehost = true;
                        safeApply($rootScope);
                        return;
                    }
                    else if (msg.nativehost === "disconnected") {
                        retobj.nativehost = false;
                        safeApply($rootScope);
                        return;
                    }
                    if (inputcbk)
                        inputcbk(msg);
                });
                port.onDisconnect.addListener (function() {
                    retobj.extension = false;
                    port = undefined;
                    console.log ("nutty extension disconnected");
                });
            }

            Meteor._reload.onMigrate("onMigrate", function() {
                autoreload = true;
                return [true];
            });
            window.addEventListener('beforeunload', function(e) {
                if (!autoreload) {
                    postMessage({
                        data: String.fromCharCode(2) + 'k'
                    });
                }
            });

            window.addEventListener('message', function(event) {
                if (event.source !== window)
                    return;
                if (event.data.type !== '_nutty_fromcontentscript')
                    return;
                var msg = event.data;
                if (!msg) {
                    log.console("msg from extension is undefined");
                    return;
                }
                if (msg.nativehost === "connected") {
                    retobj.nativehost = true;
                    safeApply($rootScope);
                    return;
                } else if (msg.nativehost === "disconnected") {
                    retobj.nativehost = false;
                    safeApply($rootScope);
                    return;
                }
                if (inputcbk)
                    inputcbk(msg);
            });

            window.Termdevice = retobj;
            if (Compatibility.browser.incompatible) {
                return retobj;
            }
            $rootScope.$watch(function() {
                return NuttySession.sessionid;
            }, function(newval) {
                if (newval) {
                    postMessage({
                        setsessionid: newval
                    });
                    if (Session.get("onreload")) {
                        postMessage({
                            data: String.fromCharCode(2) + 'r'
                        });
                    } else {
                        $timeout (function() {
                            if (!retobj.nativehost) {
                                alertBox.alert('danger', 'Nutty not installed properly');
                                $timeout (function() {
                                    window.location.assign('/install');
                                }, 4000);
                            }
                        }, 4000);
                        Session.set("onreload", 1);
                    }
                }
            });
            window.copy = function(text) {
                retobj.write({
                    copy: text
                });
            }
            return retobj;
        }
    ]);
<commit_msg>Do not connect to extension from the webpage directly if it is not nutty.io<commit_after>/*
 * https://nutty.io
 * Copyright (c) 2014 krishna.srinivas@gmail.com All rights reserved.
 * GPLv3 License <http://www.gnu.org/licenses/gpl.txt>
 */

angular.module('nuttyapp')
    .factory('Termdevice', ['$rootScope', 'NuttySession', 'Compatibility', '$timeout', 'alertBox', '$location',
        function($rootScope, NuttySession, Compatibility, $timeout, alertBox, $location) {
            var inputcbk;
            var autoreload = false;
            var port;
            var extid = "ooelecakcjobkpmbdnflfneaalbhejmk";
            // var extid = "jboablmfecefcaedlpaaciooecbgjbhl";

            function postMessage(msg) {
                if (port) {
                    port.postMessage(msg)
                } else {
                    msg.type = '_nutty_fromwebpage';
                    window.postMessage(msg, window.location.origin);
                }
            }

            var retobj = {
                extension: false,
                nativehost: false,
                ondata: function(cbk) {
                    inputcbk = cbk;
                },
                write: function(msg) {
                    if (!msg) {
                        console.log("Termdevice.write(): msg is null")
                        return;
                    }
                    if (msg.newtmuxsession) {
                        retobj.newtmuxsession();
                        return;
                    }
                    postMessage(msg);
                },
                newtmuxsession: function() {
                    if (!NuttySession.sessionid)
                        return;
                    postMessage({
                        unsetsessionid: true
                    });
                    postMessage({
                        setsessionid: NuttySession.sessionid
                    });
                    postMessage({
                        rowcol: 1,
                        row: NuttySession.rowcol.row,
                        col: NuttySession.rowcol.col
                    });
                }
            }
            if ($location.host() === 'nutty.io') {
                if (window.chrome && chrome.runtime && chrome.runtime.connect)
                    port = chrome.runtime.connect(extid);
                if (port) {
                    retobj.extension = true;
                    port.onMessage.addListener(function(msg) {
                        if (!msg) {
                            log.console("msg from extension is undefined");
                            return;
                        }
                        if (msg.nativehost === "connected") {
                            retobj.nativehost = true;
                            safeApply($rootScope);
                            return;
                        }
                        else if (msg.nativehost === "disconnected") {
                            retobj.nativehost = false;
                            safeApply($rootScope);
                            return;
                        }
                        if (inputcbk)
                            inputcbk(msg);
                    });
                    port.onDisconnect.addListener (function() {
                        retobj.extension = false;
                        port = undefined;
                        console.log ("nutty extension disconnected");
                    });
                }
            }
            Meteor._reload.onMigrate("onMigrate", function() {
                autoreload = true;
                return [true];
            });
            window.addEventListener('beforeunload', function(e) {
                if (!autoreload) {
                    postMessage({
                        data: String.fromCharCode(2) + 'k'
                    });
                }
            });

            window.addEventListener('message', function(event) {
                if (event.source !== window)
                    return;
                if (event.data.type !== '_nutty_fromcontentscript')
                    return;
                var msg = event.data;
                if (!msg) {
                    log.console("msg from extension is undefined");
                    return;
                }
                if (msg.nativehost === "connected") {
                    retobj.nativehost = true;
                    safeApply($rootScope);
                    return;
                } else if (msg.nativehost === "disconnected") {
                    retobj.nativehost = false;
                    safeApply($rootScope);
                    return;
                }
                if (inputcbk)
                    inputcbk(msg);
            });

            window.Termdevice = retobj;
            if (Compatibility.browser.incompatible) {
                return retobj;
            }
            $rootScope.$watch(function() {
                return NuttySession.sessionid;
            }, function(newval) {
                if (newval) {
                    postMessage({
                        setsessionid: newval
                    });
                    if (Session.get("onreload")) {
                        postMessage({
                            data: String.fromCharCode(2) + 'r'
                        });
                    } else {
                        $timeout (function() {
                            if (!retobj.nativehost) {
                                alertBox.alert('danger', 'Nutty not installed properly');
                                $timeout (function() {
                                    window.location.assign('/install');
                                }, 4000);
                            }
                        }, 4000);
                        Session.set("onreload", 1);
                    }
                }
            });
            window.copy = function(text) {
                retobj.write({
                    copy: text
                });
            }
            return retobj;
        }
    ]);
<|endoftext|>


<commit_before>angular.module('ngIdle.idle', ['ngIdle.keepalive', 'ngIdle.localStorage'])
  .provider('Idle', function() {
    var options = {
      idle: 20 * 60, // in seconds (default is 20min)
      timeout: 30, // in seconds (default is 30sec)
      autoResume: 'idle', // lets events automatically resume (unsets idle state/resets warning)
      interrupt: 'mousemove keydown DOMMouseScroll mousewheel mousedown touchstart touchmove scroll',
      windowInterrupt: null,
      keepalive: true
    };

    /**
     *  Sets the number of seconds a user can be idle before they are considered timed out.
     *  @param {Number|Boolean} seconds A positive number representing seconds OR 0 or false to disable this feature.
     */
    var setTimeout = this.timeout = function(seconds) {
      if (seconds === false) options.timeout = 0;
      else if (angular.isNumber(seconds) && seconds >= 0) options.timeout = seconds;
      else throw new Error('Timeout must be zero or false to disable the feature, or a positive integer (in seconds) to enable it.');
    };

    this.interrupt = function(events) {
      options.interrupt = events;
    };

    this.windowInterrupt = function(events) {
      options.windowInterrupt = events;
    };

    var setIdle = this.idle = function(seconds) {
      if (seconds <= 0) throw new Error('Idle must be a value in seconds, greater than 0.');

      options.idle = seconds;
    };

    this.autoResume = function(value) {
      if (value === true) options.autoResume = 'idle';
      else if (value === false) options.autoResume = 'off';
      else options.autoResume = value;
    };

    this.keepalive = function(enabled) {
      options.keepalive = enabled === true;
    };

    this.$get = ['$interval', '$log', '$rootScope', '$document', 'Keepalive', 'IdleLocalStorage', '$window',
      function($interval, $log, $rootScope, $document, Keepalive, LocalStorage, $window) {
        var state = {
          idle: null,
          timeout: null,
          idling: false,
          running: false,
          countdown: null
        };

        var id = new Date().getTime();

        function startKeepalive() {
          if (!options.keepalive) return;

          if (state.running) Keepalive.ping();

          Keepalive.start();
        }

        function stopKeepalive() {
          if (!options.keepalive) return;

          Keepalive.stop();
        }

        function toggleState() {
          state.idling = !state.idling;
          var name = state.idling ? 'Start' : 'End';

          $rootScope.$broadcast('Idle' + name);

          if (state.idling) {
            stopKeepalive();
            if (options.timeout) {
              state.countdown = options.timeout;
              countdown();
              state.timeout = $interval(countdown, 1000, options.timeout, false);
            }
          } else {
            startKeepalive();
          }

          $interval.cancel(state.idle);
        }

        function countdown() {

          // check not called when no longer idling
          // possible with multiple tabs
          if(!state.idling){
            return;
          }

          // countdown has expired, so signal timeout
          if (state.countdown <= 0) {
            timeout();
            return;
          }

          // countdown hasn't reached zero, so warn and decrement
          $rootScope.$broadcast('IdleWarn', state.countdown);
          state.countdown--;
        }

        function timeout() {
          stopKeepalive();
          $interval.cancel(state.idle);
          $interval.cancel(state.timeout);

          state.idling = true;
          state.running = false;
          state.countdown = 0;

          $rootScope.$broadcast('IdleTimeout');
        }

        function changeOption(self, fn, value) {
          var reset = self.running();

          self.unwatch();
          fn(value);
          if (reset) self.watch();
        }

        function getExpiry() {
          var obj = LocalStorage.get('expiry');

          return obj && obj.time ? new Date(obj.time) : null;
        }

        function setExpiry(date) {
          if (!date) LocalStorage.remove('expiry');
          else LocalStorage.set('expiry', {id: id, time: date});
        }

        var svc = {
          _options: function() {
            return options;
          },
          _getNow: function() {
            return new Date();
          },
          getIdle: function(){
            return options.idle;
          },
          getTimeout: function(){
            return options.timeout;
          },
          setIdle: function(seconds) {
            changeOption(this, setIdle, seconds);
          },
          setTimeout: function(seconds) {
            changeOption(this, setTimeout, seconds);
          },
          isExpired: function() {
            var expiry = getExpiry();
            return expiry !== null && expiry <= this._getNow();
          },
          running: function() {
            return state.running;
          },
          idling: function() {
            return state.idling;
          },
          watch: function(noExpiryUpdate) {
            $interval.cancel(state.idle);
            $interval.cancel(state.timeout);

            // calculate the absolute expiry date, as added insurance against a browser sleeping or paused in the background
            var timeout = !options.timeout ? 0 : options.timeout;
            if (!noExpiryUpdate) setExpiry(new Date(new Date().getTime() + ((options.idle + timeout) * 1000)));

            if (state.idling) toggleState(); // clears the idle state if currently idling
            else if (!state.running) startKeepalive(); // if about to run, start keep alive

            state.running = true;

            state.idle = $interval(toggleState, options.idle * 1000, 0, false);
          },
          unwatch: function() {
            $interval.cancel(state.idle);
            $interval.cancel(state.timeout);

            state.idling = false;
            state.running = false;
            setExpiry(null);

            stopKeepalive();
          },
          interrupt: function(anotherTab) {
            if (!state.running) return;

            if (options.timeout && this.isExpired()) {
              timeout();
              return;
            }

            // note: you can no longer auto resume once we exceed the expiry; you will reset state by calling watch() manually
            if (anotherTab || options.autoResume === 'idle' || (options.autoResume === 'notIdle' && !state.idling)) this.watch(anotherTab);
          }
        };

        var lastMove = {
          clientX: null,
          clientY: null,
          swap: function(event) {
            var last = {clientX: this.clientX, clientY: this.clientY};
            this.clientX = event.clientX;
            this.clientY = event.clientY;
            return last;
          },
          hasMoved: function(event) {
            var last = this.swap(event);
            if (this.clientX === null || event.movementX || event.movementY) return true;
            else if (last.clientX != event.clientX || last.clientY != event.clientY) return true;
            else return false;
          }
        };

        $document.find('html').on(options.interrupt, function(event) {
          if (event.type === 'mousemove' && event.originalEvent && event.originalEvent.movementX === 0 && event.originalEvent.movementY === 0) {
            return; // Fix for Chrome desktop notifications, triggering mousemove event.
          }

          if (event.type !== 'mousemove' || lastMove.hasMoved(event)) {
            svc.interrupt();
          }
        });

        if(options.windowInterrupt) {
          var eventList = options.windowInterrupt.split(' ');
          var fn = function() {
            svc.interrupt();
          };

          for(var i=0; i<eventList.length; i++) {
            if ($window.addEventListener) $window.addEventListener(eventList[i], fn, false);
            else $window.attachEvent(eventList[i], fn)
          }
        }

        var wrap = function(event) {
          if (event.key === 'ngIdle.expiry' && event.newValue && event.newValue !== event.oldValue) {
            var val = angular.fromJson(event.newValue);
            if (val.id === id) return;
            svc.interrupt(true);
          }
        };

        if ($window.addEventListener) $window.addEventListener('storage', wrap, false);
        else $window.attachEvent('onstorage', wrap);

        return svc;
      }
    ];
  });
<commit_msg>Fixes #131 broadcast idle events last broadcast events after meat of toggleState is executed, so it doesn't bowl over watch calls by subscribers<commit_after>angular.module('ngIdle.idle', ['ngIdle.keepalive', 'ngIdle.localStorage'])
  .provider('Idle', function() {
    var options = {
      idle: 20 * 60, // in seconds (default is 20min)
      timeout: 30, // in seconds (default is 30sec)
      autoResume: 'idle', // lets events automatically resume (unsets idle state/resets warning)
      interrupt: 'mousemove keydown DOMMouseScroll mousewheel mousedown touchstart touchmove scroll',
      windowInterrupt: null,
      keepalive: true
    };

    /**
     *  Sets the number of seconds a user can be idle before they are considered timed out.
     *  @param {Number|Boolean} seconds A positive number representing seconds OR 0 or false to disable this feature.
     */
    var setTimeout = this.timeout = function(seconds) {
      if (seconds === false) options.timeout = 0;
      else if (angular.isNumber(seconds) && seconds >= 0) options.timeout = seconds;
      else throw new Error('Timeout must be zero or false to disable the feature, or a positive integer (in seconds) to enable it.');
    };

    this.interrupt = function(events) {
      options.interrupt = events;
    };

    this.windowInterrupt = function(events) {
      options.windowInterrupt = events;
    };

    var setIdle = this.idle = function(seconds) {
      if (seconds <= 0) throw new Error('Idle must be a value in seconds, greater than 0.');

      options.idle = seconds;
    };

    this.autoResume = function(value) {
      if (value === true) options.autoResume = 'idle';
      else if (value === false) options.autoResume = 'off';
      else options.autoResume = value;
    };

    this.keepalive = function(enabled) {
      options.keepalive = enabled === true;
    };

    this.$get = ['$interval', '$log', '$rootScope', '$document', 'Keepalive', 'IdleLocalStorage', '$window',
      function($interval, $log, $rootScope, $document, Keepalive, LocalStorage, $window) {
        var state = {
          idle: null,
          timeout: null,
          idling: false,
          running: false,
          countdown: null
        };

        var id = new Date().getTime();

        function startKeepalive() {
          if (!options.keepalive) return;

          if (state.running) Keepalive.ping();

          Keepalive.start();
        }

        function stopKeepalive() {
          if (!options.keepalive) return;

          Keepalive.stop();
        }

        function toggleState() {
          state.idling = !state.idling;
          var name = state.idling ? 'Start' : 'End';

          if (state.idling) {
            stopKeepalive();
            if (options.timeout) {
              state.countdown = options.timeout;
              countdown();
              state.timeout = $interval(countdown, 1000, options.timeout, false);
            }
          } else {
            startKeepalive();
          }

          $rootScope.$broadcast('Idle' + name);

          $interval.cancel(state.idle);
        }

        function countdown() {

          // check not called when no longer idling
          // possible with multiple tabs
          if(!state.idling){
            return;
          }

          // countdown has expired, so signal timeout
          if (state.countdown <= 0) {
            timeout();
            return;
          }

          // countdown hasn't reached zero, so warn and decrement
          $rootScope.$broadcast('IdleWarn', state.countdown);
          state.countdown--;
        }

        function timeout() {
          stopKeepalive();
          $interval.cancel(state.idle);
          $interval.cancel(state.timeout);

          state.idling = true;
          state.running = false;
          state.countdown = 0;

          $rootScope.$broadcast('IdleTimeout');
        }

        function changeOption(self, fn, value) {
          var reset = self.running();

          self.unwatch();
          fn(value);
          if (reset) self.watch();
        }

        function getExpiry() {
          var obj = LocalStorage.get('expiry');

          return obj && obj.time ? new Date(obj.time) : null;
        }

        function setExpiry(date) {
          if (!date) LocalStorage.remove('expiry');
          else LocalStorage.set('expiry', {id: id, time: date});
        }

        var svc = {
          _options: function() {
            return options;
          },
          _getNow: function() {
            return new Date();
          },
          getIdle: function(){
            return options.idle;
          },
          getTimeout: function(){
            return options.timeout;
          },
          setIdle: function(seconds) {
            changeOption(this, setIdle, seconds);
          },
          setTimeout: function(seconds) {
            changeOption(this, setTimeout, seconds);
          },
          isExpired: function() {
            var expiry = getExpiry();
            return expiry !== null && expiry <= this._getNow();
          },
          running: function() {
            return state.running;
          },
          idling: function() {
            return state.idling;
          },
          watch: function(noExpiryUpdate) {
            $interval.cancel(state.idle);
            $interval.cancel(state.timeout);

            // calculate the absolute expiry date, as added insurance against a browser sleeping or paused in the background
            var timeout = !options.timeout ? 0 : options.timeout;
            if (!noExpiryUpdate) setExpiry(new Date(new Date().getTime() + ((options.idle + timeout) * 1000)));

            if (state.idling) toggleState(); // clears the idle state if currently idling
            else if (!state.running) startKeepalive(); // if about to run, start keep alive

            state.running = true;

            state.idle = $interval(toggleState, options.idle * 1000, 0, false);
          },
          unwatch: function() {
            $interval.cancel(state.idle);
            $interval.cancel(state.timeout);

            state.idling = false;
            state.running = false;
            setExpiry(null);

            stopKeepalive();
          },
          interrupt: function(anotherTab) {
            if (!state.running) return;

            if (options.timeout && this.isExpired()) {
              timeout();
              return;
            }

            // note: you can no longer auto resume once we exceed the expiry; you will reset state by calling watch() manually
            if (anotherTab || options.autoResume === 'idle' || (options.autoResume === 'notIdle' && !state.idling)) this.watch(anotherTab);
          }
        };

        var lastMove = {
          clientX: null,
          clientY: null,
          swap: function(event) {
            var last = {clientX: this.clientX, clientY: this.clientY};
            this.clientX = event.clientX;
            this.clientY = event.clientY;
            return last;
          },
          hasMoved: function(event) {
            var last = this.swap(event);
            if (this.clientX === null || event.movementX || event.movementY) return true;
            else if (last.clientX != event.clientX || last.clientY != event.clientY) return true;
            else return false;
          }
        };

        $document.find('html').on(options.interrupt, function(event) {
          if (event.type === 'mousemove' && event.originalEvent && event.originalEvent.movementX === 0 && event.originalEvent.movementY === 0) {
            return; // Fix for Chrome desktop notifications, triggering mousemove event.
          }

          if (event.type !== 'mousemove' || lastMove.hasMoved(event)) {
            svc.interrupt();
          }
        });

        if(options.windowInterrupt) {
          var eventList = options.windowInterrupt.split(' ');
          var fn = function() {
            svc.interrupt();
          };

          for(var i=0; i<eventList.length; i++) {
            if ($window.addEventListener) $window.addEventListener(eventList[i], fn, false);
            else $window.attachEvent(eventList[i], fn)
          }
        }

        var wrap = function(event) {
          if (event.key === 'ngIdle.expiry' && event.newValue && event.newValue !== event.oldValue) {
            var val = angular.fromJson(event.newValue);
            if (val.id === id) return;
            svc.interrupt(true);
          }
        };

        if ($window.addEventListener) $window.addEventListener('storage', wrap, false);
        else $window.attachEvent('onstorage', wrap);

        return svc;
      }
    ];
  });
<|endoftext|>


<commit_before>
pm.turbineListturbulence = ko.observableArray([]);
pm.turbineturbulence = ko.observableArray([]);
pm.ChartSeriesturbulence = ko.observableArray([]);
pm.DtTurbulence = ko.observableArray([]);

var ti = {
	// RefreshchartTI: function(){
	// 	setTimeout(function() {
	// 		$("#chartTI").data("kendoChart").refresh();
	// 	}, 100);
	// },
	RefreshData: function() {
	    var isValid = fa.LoadData();
	    if(isValid) {
	    	pm.showFilter();
		    if(pm.isFirstTurbulence() === true){
		    	app.loading(true);
		        ti.RefreshchartTI();
		        var metDate = 'Data Available (MET) from: ' + availDateList.availabledatestartmet + ' until: ' + availDateList.availabledateendmet + ''
		        var scadaDate = ' | (SCADA HFD) from: ' + availDateList.startScadaHFD + ' until: ' + availDateList.endScadaHFD + ''
		        $('#availabledatestart').html(metDate);
		        $('#availabledateend').html(scadaDate);

		    }else{
		        var metDate = 'Data Available (MET) from: ' + availDateList.availabledatestartmet + ' until: ' + availDateList.availabledateendmet + ''
		        var scadaDate = ' | (SCADA HFD) from: ' + availDateList.startScadaHFD + ' until: ' + availDateList.endScadaHFD + ''
		        $('#availabledatestart').html(metDate);
		        $('#availabledateend').html(scadaDate);
		        setTimeout(function(){
		            $("#chartTI").data("kendoChart").refresh();
		            app.loading(false);
		        }, 300);
		    }
	    }
	},
	RefreshchartTI: function() {
		var param = {
            period: fa.period,
            Turbine: fa.turbine(),
            DateStart: fa.dateStart,
            DateEnd: fa.dateEnd,
            Project: fa.project
        };
		toolkit.ajaxPost(viewModel.appName + "analyticmeteorology/getturbulenceintensity", param, function (data) {
            pm.isFirstTurbulence(false);

            if(data.ChartSeries == null){
            	app.loading(false);
            }

			var width = $(".main-header").width()
	        // var cfg = ti.ChartConfig(data.Data, data.ChartSeries);
	        pm.ChartSeriesturbulence(data.ChartSeries)
	        pm.DtTurbulence(data)

			$('#chartTI').html('');

			$("#chartTI").kendoChart({
			    // pdf: {
			    //   fileName: "DetailPowerCurve.pdf",
			    // },
			    theme: "flat",
			    chartArea: {
			        background: "transparent"
			    },
			    title: {
			        visible: false
			    },
			    legend: {
			        visible: false,
			        position: "bottom"
			    },
			    seriesDefaults: {
			        type: "scatterLine",
			        style: "smooth",
			    },
			    series: data.ChartSeries,
			    valueAxis: [{
                    labels: {
                        format: "N2",
                    }
                }],
                xAxis: {
                    // majorUnit: 1,
                    title: {
                        // text: "Wind Speed (m/s)",
                        font: '14px Source Sans Pro, Lato , Open Sans , Helvetica Neue, Arial, sans-serif',
                        color: "#585555",
                        visible: true,
                    },
                    crosshair: {
                        visible: true,
                        tooltip: {
                            visible: true,
                            format: "N2",
                            background: "rgb(255,255,255, 0.9)",
                            color: "#58666e",
                            font: 'Source Sans Pro, Lato , Open Sans , Helvetica Neue, Arial, sans-serif',
                            border: {
                                color: "#eee",
                                width: "2px",
                            },
                        }
                    },
                    majorGridLines: {
                        visible: true,
                        color: "#eee",
                        width: 0.8,
                    },
                    // max: 25
                },
                yAxis: {
                    title: {
                        // text: "Generation (KW)",
                        font: '14px Source Sans Pro, Lato , Open Sans , Helvetica Neue, Arial, sans-serif',
                        color: "#585555"
                    },
                    labels: {
                        format: "N2",
                    },
                    axisCrossingValue: -5,
                    majorGridLines: {
                        visible: true,
                        color: "#eee",
                        width: 0.8,
                    },
                    crosshair: {
                        visible: true,
                        tooltip: {
                            visible: true,
                            format: "N2",
                            background: "rgb(255,255,255, 0.9)",
                            color: "#58666e",
                            font: 'Source Sans Pro, Lato , Open Sans , Helvetica Neue, Arial, sans-serif',
                            border: {
                                color: "#eee",
                                width: "2px",
                            },
                        }
                    },
                },
                tooltip: {
                    visible: true,
                    // format: "{1}in {0} minutes",
                    template: "#= series.name #",
                    shared: true,
                    background: "rgb(255,255,255, 0.9)",
                    color: "#58666e",
                    font: 'Source Sans Pro, Lato , Open Sans , Helvetica Neue, Arial, sans-serif',
                    border: {
                        color: "#eee",
                        width: "2px",
                    },
                },
			});
			setTimeout(function() {
				ti.InitRightList();
				app.loading(false);
 				$("#chartTI").data("kendoChart").refresh();
			}, 100);

			// $('#chartTI').width($('#chartTI').parent().parent().width());
			// $('#chartTI').width(width * 0.8);
			// $('#chartTI').height(width * 0.3);
			// $('#chartTI').kendoChart(cfg);
            // $("#chartTI").data("kendoChart").refresh();
		});
	},
	showHideAllLegend: function(e){
	    if (e.checked == true) {
	        $('.fa-check').css("visibility", 'visible');
	        $.each(pm.ChartSeriesturbulence(), function (i, val) {
	            if($("#chartTI").data("kendoChart").options.series[val.idxseries] != undefined){
	                $("#chartTI").data("kendoChart").options.series[val.idxseries].visible = true;
	            }
	        });
	        /*$('#labelShowHide b').text('Untick All Turbines');*/
	        $('#labelShowHide b').text('Select All');
	    } else {
	        $.each(pm.ChartSeriesturbulence(), function (i, val) {
	            if($("#chartTI").data("kendoChart").options.series[val.idxseries] != undefined){
	                $("#chartTI").data("kendoChart").options.series[val.idxseries].visible = false;
	            }
	        });
	        $('.fa-check').css("visibility", 'hidden');
	        /*$('#labelShowHide b').text('Tick All Turbines');*/
	        $('#labelShowHide b').text('Select All');
	    }
	    $('.chk-option').not(e).prop('checked', e.checked);

	    $("#chartTI").data("kendoChart").redraw();
	},
	showHideLegend: function(idx){
	    $('#chk-' + idx).trigger('click');
	    var chart = $("#chartTI").data("kendoChart");
	    var leTur = $('input[id*=chk-][type=checkbox]').length;

	    if ($('input[id*=chk-][type=checkbox]:checked').length == $('input[id*=chk-][type=checkbox]').length) {
	        $('#showHideAllturbulence').prop('checked', true);
	    } else {
	        $('#showHideAllturbulence').prop('checked', false);
	    }

	    if ($('#chk-' + idx).is(':checked')) {
	        $('#icon-' + idx).css("visibility", "visible");
	    } else {
	        $('#icon-' + idx).css("visibility", "hidden");
	    }

	    if ($('#chk-' + idx).is(':checked')) {
	        $("#chartTI").data("kendoChart").options.series[idx].visible = true
	    } else {
	        $("#chartTI").data("kendoChart").options.series[idx].visible = false
	    }
	    $("#chartTI").data("kendoChart").redraw();
	},
	InitRightList: function(){
		$("#right-turbine-turbulence").html("");

		if (pm.ChartSeriesturbulence()!=null){
			if (pm.ChartSeriesturbulence().length > 1) {
				$("#showHideChkturbulence").html('' +
					'<input type="checkbox" id="showHideAllturbulence" checked onclick="ti.showHideAllLegend(this)" >' +
					'' +
					'Select All' +
					'');
			} else {
				$("#showHideChk").html("");
			}

			$.each(pm.ChartSeriesturbulence(), function (idx, val) {
	        $("#right-turbine-turbulence").append('
' +
				'<button class="btn btn-default btn-sm turbine-chk" type="button" onclick="ti.showHideLegend(' + (idx) + ')" style="border-color:' + val.color + ';background-color:' + val.color + '"></button>' +
				'<input class="chk-option" type="checkbox" name="' + val.name + '" checked id="chk-' + (idx) + '" hidden>' +
				'<button class="btn btn-default btn-sm turbine-btn wbtn" onclick="ti.showHideLegend(' + (idx) + ')" type="button">' + val.name + '</button>' +
				'
');
			});
		} else {
			$("#showHideChk").html("");
		}
	},
	ChartConfig: function(data, chartSeries) {
		var colors = [];
		$.each(chartSeries, function(idx,val){
			colors.push(val);
		});
		return {
			dataSource: data,
	        chartArea: {
			    background: "transparent"
			},
			title: {
		        visible: false
		    },
		    legend: {
		        // visible: false,
		        position: "bottom"
		    },
		    seriesDefaults: {
	            type: "scatterLine",
	            style: "smooth",
	        },
		    series: chartSeries,
		    categoryAxis: {
		        // field: "turbine",
	            labels: {
	                visible: false,
	            },
	            crosshair: {
	                visible: false,
	            },
		        majorGridLines: {
		            visible: false,
		        },
		        majorTicks: {
		            visible: false,
		        },
		    },
		    valueAxis: {
		        crosshair: {
	                visible: false
	            },
		        majorGridLines: {
		            visible: false,
		        },
		        majorTicks: {
		            visible: false,
		        },
		    },
	        tooltip: {
	            visible: true,
	            template: "#: category # = #= kendo.format('{0:N2}',value) #"
	        },
	        dataBound: function(e) {
	        	var series = e.sender.options.series;
	        	$.each(series, function(idx, s){
	        		if(s.name=='Average') {
	        			s.dashType = 'dash';
	        		}
	        	});
	        },
		};
	},
};

$(document).ready(function() {
	// ti.LoadData();
});
<commit_msg>add label for turbulence intensity<commit_after>
pm.turbineListturbulence = ko.observableArray([]);
pm.turbineturbulence = ko.observableArray([]);
pm.ChartSeriesturbulence = ko.observableArray([]);
pm.DtTurbulence = ko.observableArray([]);

var ti = {
	// RefreshchartTI: function(){
	// 	setTimeout(function() {
	// 		$("#chartTI").data("kendoChart").refresh();
	// 	}, 100);
	// },
	RefreshData: function() {
	    var isValid = fa.LoadData();
	    if(isValid) {
	    	pm.showFilter();
		    if(pm.isFirstTurbulence() === true){
		    	app.loading(true);
		        ti.RefreshchartTI();
		        var metDate = 'Data Available (MET) from: ' + availDateList.availabledatestartmet + ' until: ' + availDateList.availabledateendmet + ''
		        var scadaDate = ' | (SCADA HFD) from: ' + availDateList.startScadaHFD + ' until: ' + availDateList.endScadaHFD + ''
		        $('#availabledatestart').html(metDate);
		        $('#availabledateend').html(scadaDate);

		    }else{
		        var metDate = 'Data Available (MET) from: ' + availDateList.availabledatestartmet + ' until: ' + availDateList.availabledateendmet + ''
		        var scadaDate = ' | (SCADA HFD) from: ' + availDateList.startScadaHFD + ' until: ' + availDateList.endScadaHFD + ''
		        $('#availabledatestart').html(metDate);
		        $('#availabledateend').html(scadaDate);
		        setTimeout(function(){
		            $("#chartTI").data("kendoChart").refresh();
		            app.loading(false);
		        }, 300);
		    }
	    }
	},
	RefreshchartTI: function() {
		var param = {
            period: fa.period,
            Turbine: fa.turbine(),
            DateStart: fa.dateStart,
            DateEnd: fa.dateEnd,
            Project: fa.project
        };
		toolkit.ajaxPost(viewModel.appName + "analyticmeteorology/getturbulenceintensity", param, function (data) {
            pm.isFirstTurbulence(false);

            if(data.ChartSeries == null){
            	app.loading(false);
            }

			var width = $(".main-header").width()
	        // var cfg = ti.ChartConfig(data.Data, data.ChartSeries);
	        pm.ChartSeriesturbulence(data.ChartSeries)
	        pm.DtTurbulence(data)

			$('#chartTI').html('');

			$("#chartTI").kendoChart({
			    // pdf: {
			    //   fileName: "DetailPowerCurve.pdf",
			    // },
			    theme: "flat",
			    chartArea: {
			        background: "transparent"
			    },
			    title: {
			        visible: false
			    },
			    legend: {
			        visible: false,
			        position: "bottom"
			    },
			    seriesDefaults: {
			        type: "scatterLine",
			        style: "smooth",
			    },
			    series: data.ChartSeries,
			    valueAxis: [{
                    labels: {
                        format: "N2",
                    },
                }],
                xAxis: {
                    // majorUnit: 1,
                    title: {
                        text: "Wind Speed (m/s)",
                        font: '14px Source Sans Pro, Lato , Open Sans , Helvetica Neue, Arial, sans-serif',
                        color: "#585555",
                        visible: true,
                    },
                    crosshair: {
                        visible: true,
                        tooltip: {
                            visible: true,
                            format: "N2",
                            background: "rgb(255,255,255, 0.9)",
                            color: "#58666e",
                            font: 'Source Sans Pro, Lato , Open Sans , Helvetica Neue, Arial, sans-serif',
                            border: {
                                color: "#eee",
                                width: "2px",
                            },
                        }
                    },
                    majorGridLines: {
                        visible: true,
                        color: "#eee",
                        width: 0.8,
                    },
                    // max: 25
                },
                yAxis: {
                    title: {
                        text: "Turbulence Intensity",
                        font: '14px Source Sans Pro, Lato , Open Sans , Helvetica Neue, Arial, sans-serif',
                        color: "#585555"
                    },
                    labels: {
                        format: "N2",
                    },
                    axisCrossingValue: -5,
                    majorGridLines: {
                        visible: true,
                        color: "#eee",
                        width: 0.8,
                    },
                    crosshair: {
                        visible: true,
                        tooltip: {
                            visible: true,
                            format: "N2",
                            background: "rgb(255,255,255, 0.9)",
                            color: "#58666e",
                            font: 'Source Sans Pro, Lato , Open Sans , Helvetica Neue, Arial, sans-serif',
                            border: {
                                color: "#eee",
                                width: "2px",
                            },
                        }
                    },
                },
                tooltip: {
                    visible: true,
                    // format: "{1}in {0} minutes",
                    template: "#= series.name #",
                    shared: true,
                    background: "rgb(255,255,255, 0.9)",
                    color: "#58666e",
                    font: 'Source Sans Pro, Lato , Open Sans , Helvetica Neue, Arial, sans-serif',
                    border: {
                        color: "#eee",
                        width: "2px",
                    },
                },
			});
			setTimeout(function() {
				ti.InitRightList();
				app.loading(false);
 				$("#chartTI").data("kendoChart").refresh();
			}, 100);

			// $('#chartTI').width($('#chartTI').parent().parent().width());
			// $('#chartTI').width(width * 0.8);
			// $('#chartTI').height(width * 0.3);
			// $('#chartTI').kendoChart(cfg);
            // $("#chartTI").data("kendoChart").refresh();
		});
	},
	showHideAllLegend: function(e){
	    if (e.checked == true) {
	        $('.fa-check').css("visibility", 'visible');
	        $.each(pm.ChartSeriesturbulence(), function (i, val) {
	            if($("#chartTI").data("kendoChart").options.series[val.idxseries] != undefined){
	                $("#chartTI").data("kendoChart").options.series[val.idxseries].visible = true;
	            }
	        });
	        /*$('#labelShowHide b').text('Untick All Turbines');*/
	        $('#labelShowHide b').text('Select All');
	    } else {
	        $.each(pm.ChartSeriesturbulence(), function (i, val) {
	            if($("#chartTI").data("kendoChart").options.series[val.idxseries] != undefined){
	                $("#chartTI").data("kendoChart").options.series[val.idxseries].visible = false;
	            }
	        });
	        $('.fa-check').css("visibility", 'hidden');
	        /*$('#labelShowHide b').text('Tick All Turbines');*/
	        $('#labelShowHide b').text('Select All');
	    }
	    $('.chk-option').not(e).prop('checked', e.checked);

	    $("#chartTI").data("kendoChart").redraw();
	},
	showHideLegend: function(idx){
	    $('#chk-' + idx).trigger('click');
	    var chart = $("#chartTI").data("kendoChart");
	    var leTur = $('input[id*=chk-][type=checkbox]').length;

	    if ($('input[id*=chk-][type=checkbox]:checked').length == $('input[id*=chk-][type=checkbox]').length) {
	        $('#showHideAllturbulence').prop('checked', true);
	    } else {
	        $('#showHideAllturbulence').prop('checked', false);
	    }

	    if ($('#chk-' + idx).is(':checked')) {
	        $('#icon-' + idx).css("visibility", "visible");
	    } else {
	        $('#icon-' + idx).css("visibility", "hidden");
	    }

	    if ($('#chk-' + idx).is(':checked')) {
	        $("#chartTI").data("kendoChart").options.series[idx].visible = true
	    } else {
	        $("#chartTI").data("kendoChart").options.series[idx].visible = false
	    }
	    $("#chartTI").data("kendoChart").redraw();
	},
	InitRightList: function(){
		$("#right-turbine-turbulence").html("");

		if (pm.ChartSeriesturbulence()!=null){
			if (pm.ChartSeriesturbulence().length > 1) {
				$("#showHideChkturbulence").html('' +
					'<input type="checkbox" id="showHideAllturbulence" checked onclick="ti.showHideAllLegend(this)" >' +
					'' +
					'Select All' +
					'');
			} else {
				$("#showHideChk").html("");
			}

			$.each(pm.ChartSeriesturbulence(), function (idx, val) {
	        $("#right-turbine-turbulence").append('
' +
				'<button class="btn btn-default btn-sm turbine-chk" type="button" onclick="ti.showHideLegend(' + (idx) + ')" style="border-color:' + val.color + ';background-color:' + val.color + '"></button>' +
				'<input class="chk-option" type="checkbox" name="' + val.name + '" checked id="chk-' + (idx) + '" hidden>' +
				'<button class="btn btn-default btn-sm turbine-btn wbtn" onclick="ti.showHideLegend(' + (idx) + ')" type="button">' + val.name + '</button>' +
				'
');
			});
		} else {
			$("#showHideChk").html("");
		}
	},
	ChartConfig: function(data, chartSeries) {
		var colors = [];
		$.each(chartSeries, function(idx,val){
			colors.push(val);
		});
		return {
			dataSource: data,
	        chartArea: {
			    background: "transparent"
			},
			title: {
		        visible: false
		    },
		    legend: {
		        // visible: false,
		        position: "bottom"
		    },
		    seriesDefaults: {
	            type: "scatterLine",
	            style: "smooth",
	        },
		    series: chartSeries,
		    categoryAxis: {
		        // field: "turbine",
	            labels: {
	                visible: false,
	            },
	            crosshair: {
	                visible: false,
	            },
		        majorGridLines: {
		            visible: false,
		        },
		        majorTicks: {
		            visible: false,
		        },
		    },
		    valueAxis: {
		        crosshair: {
	                visible: false
	            },
		        majorGridLines: {
		            visible: false,
		        },
		        majorTicks: {
		            visible: false,
		        },
		    },
	        tooltip: {
	            visible: true,
	            template: "#: category # = #= kendo.format('{0:N2}',value) #"
	        },
	        dataBound: function(e) {
	        	var series = e.sender.options.series;
	        	$.each(series, function(idx, s){
	        		if(s.name=='Average') {
	        			s.dashType = 'dash';
	        		}
	        	});
	        },
		};
	},
};

$(document).ready(function() {
	// ti.LoadData();
});
<|endoftext|>


<commit_before>const fs = require('fs'); // 文件模块
const matter = require('gray-matter'); // FrontMatter解析器 https://github.com/jonschlinkert/gray-matter
const jsonToYaml = require('json2yaml')
const chalk = require('chalk') // 命令行打印美化
// const arg = process.argv.splice(2)[0]; // 获取命令行传入的参数
const readFileList = require('./modules/readFileList');
const { type, repairDate, dateFormat} = require('./modules/fn');
const log = console.log

const PREFIX = '/pages/'

/**
 * 给.md文件设置frontmatter(标题、日期、永久链接)
 */
function setFrontmatter(sourceDir, themeConfig) {

  const isCategory = themeConfig.category
  const isTag = themeConfig.tag
  const categoryText = themeConfig.categoryText || '随笔'

  const files = readFileList(sourceDir); // 读取所有md文件数据

  files.forEach(file => {
    let dataStr = fs.readFileSync(file.filePath, 'utf8');// 读取每个md文件内容

    // fileMatterObj => {content:'剔除frontmatter后的文件内容字符串', data:{<frontmatter对象>}, ...}
    const fileMatterObj = matter(dataStr);

    if (Object.keys(fileMatterObj.data).length === 0) { // 未定义FrontMatter数据
      const stat = fs.statSync(file.filePath);
      const dateStr = dateFormat(stat.birthtime);// 文件的创建时间

      const categories = getCategories(file, categoryText)

// 注意下面这些反引号字符串的格式会映射到文件
const cateStr = isCategory === false ? '' : `
categories:
  - ${categories[0]}${categories[1] ? '\r\n  - '+ categories[1] : ''}`;

const tagsStr = isTag === false ? '' : `
tags:
  - `;

const fmData = `---
title: ${file.name}
date: ${dateStr}
permalink: ${getPermalink()}${file.filePath.indexOf('_posts') > -1 ? '\r\nsidebar: auto' : ''}${cateStr}${tagsStr}
---`;

      fs.writeFileSync(file.filePath, `${fmData}\r\n${fileMatterObj.content}`); // 写入
      log(chalk.blue('tip ') + chalk.green(`write frontmatter(写入frontmatter)：${file.filePath} `))

    } else { // 已有FrontMatter
      const matterData = fileMatterObj.data;
      let mark = false;

      // 已有FrontMatter，但是没有title、date、permalink、categories、tags数据的
      if (!matterData.hasOwnProperty('title')) { // 标题
        matterData.title = file.name;
        mark = true;
      }

      if (!matterData.hasOwnProperty('date')) { // 日期
        const stat = fs.statSync(file.filePath);
        matterData.date = dateFormat(stat.birthtime);
        mark = true;
      }

      if (!matterData.hasOwnProperty('permalink')) { // 永久链接
        matterData.permalink = getPermalink();
        mark = true;
      }

      if (file.filePath.indexOf('_posts') > -1 && !matterData.hasOwnProperty('sidebar')) { // auto侧边栏，_posts文件夹特有
        matterData.sidebar = "auto";
        mark = true;
      }

      if ( !matterData.hasOwnProperty('pageComponent') && matterData.article !== false ) { // 是文章页才添加分类和标签
        if (isCategory !== false && !matterData.hasOwnProperty('categories')) { // 分类
          matterData.categories = getCategories(file, categoryText)
          mark = true;
        }

        if (isTag !== false && !matterData.hasOwnProperty('tags')) { // 标签
          matterData.tags = [''];
          mark = true;
        }
      }

      if (mark) {
        if(matterData.date && type(matterData.date) === 'date') {
          matterData.date = repairDate(matterData.date) // 修复时间格式
        }
        const newData = jsonToYaml.stringify(matterData).replace(/\n\s{2}/g,"\n").replace(/"/g,"") + '---\r\n' + fileMatterObj.content;
        fs.writeFileSync(file.filePath, newData); // 写入
        log(chalk.blue('tip ') + chalk.green(`write frontmatter(写入frontmatter)：${file.filePath} `))
      }

    }
  })
}

// 获取分类数据
function getCategories(file, categoryText) {
  let categories = []

  if (file.filePath.indexOf('_posts') === -1) { // 不在_posts文件夹
    const filePathArr = file.filePath.split('\\')
    const c = filePathArr[filePathArr.length - 3].split('.').pop() // 获取分类1
    if (c !== 'docs') {
      categories.push(c)
    }
    categories.push(filePathArr[filePathArr.length - 2].split('.').pop()) // 获取分类2
  } else {
    categories.push(categoryText)
  }
  return categories
}

// 定义永久链接数据
function getPermalink() {
  return `${PREFIX + (Math.random() + Math.random()).toString(16).slice(2, 8)}`
}

module.exports = setFrontmatter;
<commit_msg>修复新文档在没有写任何Front matter的情况下，在类linux系统下报错。<commit_after>const fs = require('fs'); // 文件模块
const matter = require('gray-matter'); // FrontMatter解析器 https://github.com/jonschlinkert/gray-matter
const jsonToYaml = require('json2yaml')
const chalk = require('chalk') // 命令行打印美化
// const arg = process.argv.splice(2)[0]; // 获取命令行传入的参数
const readFileList = require('./modules/readFileList');
const { type, repairDate, dateFormat} = require('./modules/fn');
const log = console.log
const path = require('path');

const PREFIX = '/pages/'

/**
 * 给.md文件设置frontmatter(标题、日期、永久链接)
 */
function setFrontmatter(sourceDir, themeConfig) {

  const isCategory = themeConfig.category
  const isTag = themeConfig.tag
  const categoryText = themeConfig.categoryText || '随笔'

  const files = readFileList(sourceDir); // 读取所有md文件数据

  files.forEach(file => {
    let dataStr = fs.readFileSync(file.filePath, 'utf8');// 读取每个md文件内容

    // fileMatterObj => {content:'剔除frontmatter后的文件内容字符串', data:{<frontmatter对象>}, ...}
    const fileMatterObj = matter(dataStr);

    if (Object.keys(fileMatterObj.data).length === 0) { // 未定义FrontMatter数据
      const stat = fs.statSync(file.filePath);
      const dateStr = dateFormat(stat.birthtime);// 文件的创建时间

      const categories = getCategories(file, categoryText)

// 注意下面这些反引号字符串的格式会映射到文件
const cateStr = isCategory === false ? '' : `
categories:
  - ${categories[0]}${categories[1] ? '\r\n  - '+ categories[1] : ''}`;

const tagsStr = isTag === false ? '' : `
tags:
  - `;

const fmData = `---
title: ${file.name}
date: ${dateStr}
permalink: ${getPermalink()}${file.filePath.indexOf('_posts') > -1 ? '\r\nsidebar: auto' : ''}${cateStr}${tagsStr}
---`;

      fs.writeFileSync(file.filePath, `${fmData}\r\n${fileMatterObj.content}`); // 写入
      log(chalk.blue('tip ') + chalk.green(`write frontmatter(写入frontmatter)：${file.filePath} `))

    } else { // 已有FrontMatter
      const matterData = fileMatterObj.data;
      let mark = false;

      // 已有FrontMatter，但是没有title、date、permalink、categories、tags数据的
      if (!matterData.hasOwnProperty('title')) { // 标题
        matterData.title = file.name;
        mark = true;
      }

      if (!matterData.hasOwnProperty('date')) { // 日期
        const stat = fs.statSync(file.filePath);
        matterData.date = dateFormat(stat.birthtime);
        mark = true;
      }

      if (!matterData.hasOwnProperty('permalink')) { // 永久链接
        matterData.permalink = getPermalink();
        mark = true;
      }

      if (file.filePath.indexOf('_posts') > -1 && !matterData.hasOwnProperty('sidebar')) { // auto侧边栏，_posts文件夹特有
        matterData.sidebar = "auto";
        mark = true;
      }

      if ( !matterData.hasOwnProperty('pageComponent') && matterData.article !== false ) { // 是文章页才添加分类和标签
        if (isCategory !== false && !matterData.hasOwnProperty('categories')) { // 分类
          matterData.categories = getCategories(file, categoryText)
          mark = true;
        }

        if (isTag !== false && !matterData.hasOwnProperty('tags')) { // 标签
          matterData.tags = [''];
          mark = true;
        }
      }

      if (mark) {
        if(matterData.date && type(matterData.date) === 'date') {
          matterData.date = repairDate(matterData.date) // 修复时间格式
        }
        const newData = jsonToYaml.stringify(matterData).replace(/\n\s{2}/g,"\n").replace(/"/g,"") + '---\r\n' + fileMatterObj.content;
        fs.writeFileSync(file.filePath, newData); // 写入
        log(chalk.blue('tip ') + chalk.green(`write frontmatter(写入frontmatter)：${file.filePath} `))
      }

    }
  })
}

// 获取分类数据
function getCategories(file, categoryText) {
  let categories = []

  if (file.filePath.indexOf('_posts') === -1) { // 不在_posts文件夹
    const filePathArr = file.filePath.split(path.sep)
    const c = filePathArr[filePathArr.length - 3].split('.').pop() // 获取分类1
    if (c !== 'docs') {
      categories.push(c)
    }
    categories.push(filePathArr[filePathArr.length - 2].split('.').pop()) // 获取分类2
  } else {
    categories.push(categoryText)
  }
  return categories
}

// 定义永久链接数据
function getPermalink() {
  return `${PREFIX + (Math.random() + Math.random()).toString(16).slice(2, 8)}`
}

module.exports = setFrontmatter;
<|endoftext|>