UNPKG

109 kBJavaScriptView Raw
1/*!
2* web Studio Code - 🎉 An Editor Used on the Browser Side.
3* git+https://github.com/yelloxing/Web-Studio-Code.git
4*
5* author 心叶
6*
7* version 1.7.2
8*
9* build Fri May 08 2020
10*
11* Copyright yelloxing
12* Released under the MIT license
13*
14* Date:Sat Jun 06 2020 15:23:42 GMT+0800 (GMT+08:00)
15*/
16
17"use strict";
18
19function _toConsumableArray2(arr) { return _arrayWithoutHoles2(arr) || _iterableToArray2(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread2(); }
20
21function _nonIterableSpread2() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
22
23function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
24
25function _iterableToArray2(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }
26
27function _arrayWithoutHoles2(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
28
29function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
30
31function _defineProperty2(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
32
33function _typeof2(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof2 = function _typeof2(obj) { return typeof obj; }; } else { _typeof2 = function _typeof2(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof2(obj); }
34
35(function () {
36 'use strict';
37
38 var _dictionary2;
39
40 if (!window.Symbol) {
41 // 这里其实没有用到Symbol,只是为了兼容IE浏览器,因此没有提供真正的实现
42 window.Symbol = function () {};
43 }
44
45 var toString = Object.prototype.toString;
46 /**
47 * 获取一个值的类型字符串[object type]
48 *
49 * @private
50 * @param {*} value 需要返回类型的值
51 * @returns {string} 返回类型字符串
52 */
53
54 function getType(value) {
55 if (value == null) {
56 return value === undefined ? '[object Undefined]' : '[object Null]';
57 }
58
59 return toString.call(value);
60 }
61 /**
62 * 判断一个值是不是一个朴素的'对象'
63 *
64 * @private
65 * @param {*} value 需要判断类型的值
66 * @returns {boolean} 如果是朴素的'对象'返回true,否则返回false
67 */
68
69
70 function isPlainObject(value) {
71 if (value === null || _typeof2(value) !== 'object' || getType(value) != '[object Object]') {
72 return false;
73 } // 如果原型为null
74
75
76 if (Object.getPrototypeOf(value) === null) {
77 return true;
78 }
79
80 var proto = value;
81
82 while (Object.getPrototypeOf(proto) !== null) {
83 proto = Object.getPrototypeOf(proto);
84 }
85
86 return Object.getPrototypeOf(value) === proto;
87 }
88 /**
89 * 判断一个值是不是结点元素。
90 *
91 * @since V0.1.2
92 * @public
93 * @param {*} value 需要判断类型的值
94 * @returns {boolean} 如果是结点元素返回true,否则返回false
95 */
96
97
98 function isElement(value) {
99 return value !== null && _typeof2(value) === 'object' && (value.nodeType === 1 || value.nodeType === 9 || value.nodeType === 11) && !isPlainObject(value);
100 }
101 /**
102 * 判断一个值是不是String。
103 *
104 * @since V0.1.2
105 * @public
106 * @param {*} value 需要判断类型的值
107 * @returns {boolean} 如果是String返回true,否则返回false
108 */
109
110
111 function isString(value) {
112 var type = _typeof2(value);
113
114 return type === 'string' || type === 'object' && value != null && !Array.isArray(value) && getType(value) === '[object String]';
115 }
116 /**
117 * 判断一个值是不是Object。
118 *
119 * @since V0.1.2
120 * @public
121 * @param {*} value 需要判断类型的值
122 * @returns {boolean} 如果是Object返回true,否则返回false
123 */
124
125
126 function isObject(value) {
127 var type = _typeof2(value);
128
129 return value != null && (type === 'object' || type === 'function');
130 }
131 /**
132 * 判断一个值是不是Function。
133 *
134 * @since V0.1.2
135 * @public
136 * @param {*} value 需要判断类型的值
137 * @returns {boolean} 如果是Function返回true,否则返回false
138 */
139
140
141 function isFunction(value) {
142 if (!isObject(value)) {
143 return false;
144 }
145
146 var type = getType(value);
147 return type === '[object Function]' || type === '[object AsyncFunction]' || type === '[object GeneratorFunction]' || type === '[object Proxy]';
148 } // 计算文字长度
149
150
151 function textWidth(text) {
152 this.__helpDOM.innerText = text;
153 return this.__helpDOM.offsetWidth;
154 } // 计算最佳光标左边位置
155
156
157 function bestLeftNum(x, lineNum) {
158 if (arguments.length < 2) lineNum = lineNum || this.__lineNum;
159 var text = this._contentArray[lineNum];
160 if (x <= 40) return 0;
161 if (x - 40 >= this.$$textWidth(text)) return text.length;
162 var dist = x - 40,
163 i = 1;
164
165 for (; i < text.length; i++) {
166 var tempDist = Math.abs(x - 40 - this.$$textWidth(text.substr(0, i)));
167 if (tempDist > dist) break;
168 dist = tempDist;
169 }
170
171 return i - 1;
172 } // 计算光标对应的x,y值
173
174
175 function calcCanvasXY(leftNum, lineNum) {
176 return {
177 x: this.$$textWidth(this._contentArray[lineNum].substr(0, leftNum)),
178 y: lineNum * 21
179 };
180 } // 判断选区是否为空
181
182
183 function selectIsNotBlank() {
184 return this.__cursor1.lineNum != this.__cursor2.lineNum || this.__cursor1.leftNum != this.__cursor2.leftNum;
185 }
186
187 var xhtml = {
188 // 阻止冒泡
189 "stopPropagation": function stopPropagation(event) {
190 event = event || window.event;
191
192 if (event.stopPropagation) {
193 //这是其他非IE浏览器
194 event.stopPropagation();
195 } else {
196 event.cancelBubble = true;
197 }
198 },
199 // 阻止默认事件
200 "preventDefault": function preventDefault(event) {
201 event = event || window.event;
202
203 if (event.preventDefault) {
204 event.preventDefault();
205 } else {
206 event.returnValue = false;
207 }
208 },
209 // 绑定事件
210 "bind": function bind(el, eventType, callback) {
211 if (window.attachEvent) {
212 el.attachEvent("on" + eventType, callback); // 后绑定的先执行
213 } else {
214 el.addEventListener(eventType, callback, false); // 捕获
215 }
216 },
217 // 触发事件
218 "trigger": function trigger(dom, eventType) {
219 var event; //创建event的对象实例。
220
221 if (document.createEventObject) {
222 // IE浏览器支持fireEvent方法
223 event = document.createEventObject();
224 dom.fireEvent('on' + eventType, event);
225 } // 其他标准浏览器使用dispatchEvent方法
226 else {
227 event = document.createEvent('HTMLEvents'); // 3个参数:事件类型,是否冒泡,是否阻止浏览器的默认行为
228
229 event.initEvent(eventType, true, false);
230 dom.dispatchEvent(event);
231 }
232 },
233 // 变成结点
234 "toNode": function toNode(template) {
235 var frame = document.createElement("div");
236 frame.innerHTML = template;
237 var childNodes = frame.childNodes;
238
239 for (var i = 0; i < childNodes.length; i++) {
240 if (isElement(childNodes[i])) return childNodes[i];
241 }
242
243 return null;
244 },
245 // 结点
246 "appendTo": function appendTo(el, template) {
247 var node = isElement(template) ? template : this.toNode(template);
248 el.appendChild(node);
249 return node;
250 },
251 // 修改样式
252 "css": function css(el, styles) {
253 for (var key in styles) {
254 el.style[key] = styles[key];
255 }
256 },
257 // 修改属性
258 "attr": function attr(el, attrs) {
259 for (var key in attrs) {
260 el.setAttribute(key, attrs[key]);
261 }
262 },
263 // 获取鼠标相对特定元素左上角位置
264 "position": function position(el, event) {
265 event = event || window.event; // 返回元素的大小及其相对于视口的位置
266
267 var bounding = el.getBoundingClientRect();
268 if (!event || !event.clientX) throw new Error('Event is necessary!');
269 var temp = {
270 // 鼠标相对元素位置 = 鼠标相对窗口坐标 - 元素相对窗口坐标
271 "x": event.clientX - bounding.left + el.scrollLeft,
272 "y": event.clientY - bounding.top + el.scrollTop
273 };
274 return temp;
275 },
276 // 复制到剪切板
277 "copy": function copy(text) {
278 var el = this.appendTo(document.body, '<textarea>' + text + '</textarea>'); // 执行复制
279
280 el.select();
281
282 try {
283 var result = window.document.execCommand("copy", false, null);
284
285 if (result) {// console.log('已经复制到剪切板!');
286 } else {// console.log('复制到剪切板失败!');
287 }
288 } catch (e) {
289 console.error(e); // console.log('复制到剪切板失败!');
290 }
291
292 document.body.removeChild(el);
293 }
294 }; // 初始化结点
295
296 function initDom() {
297 var _this = this;
298
299 this._el.innerHTML = "";
300 xhtml.css(this._el, {
301 "font-size": "12px",
302 position: "relative",
303 cursor: "text",
304 "font-family": this._fontFamily,
305 "background": this._colorBackground,
306 overflow: "auto"
307 });
308 xhtml.bind(this._el, 'click', function () {
309 _this.__focusDOM.focus();
310 }); // 辅助标签
311
312 this.__helpDOM = xhtml.appendTo(this._el, "<span></span>");
313 xhtml.css(this.__helpDOM, {
314 position: "absolute",
315 "z-index": "-1",
316 "white-space": "pre",
317 "top": 0,
318 "left": 0,
319 "font-weight": this._fontWeight
320 }); // 光标
321
322 this.__focusDOM = xhtml.appendTo(this._el, "<textarea></textarea>");
323 xhtml.css(this.__focusDOM, {
324 position: "absolute",
325 width: "6px",
326 "margin-top": "3px",
327 height: "15px",
328 "line-height": "15px",
329 resize: "none",
330 overflow: "hidden",
331 padding: "0",
332 outline: "none",
333 border: "none",
334 background: "rgba(0,0,0,0)",
335 color: this._colorCursor
336 });
337 xhtml.attr(this.__focusDOM, {
338 wrap: "off",
339 autocorrect: "off",
340 autocapitalize: "off",
341 spellcheck: "false"
342 }); // 显示区域
343
344 this.__showDOM = xhtml.appendTo(this._el, "<div></div>");
345 xhtml.css(this.__showDOM, {
346 padding: "10px 0"
347 }); // 选中区域
348
349 this.__selectCanvas = xhtml.appendTo(this._el, "<canvas></canvas>");
350 xhtml.css(this.__selectCanvas, {
351 position: "absolute",
352 left: "40px",
353 top: "10px",
354 opacity: "0.5"
355 });
356 this.$$updateCanvasSize(1, 1);
357 } // 初始化视图
358
359
360 function initView() {
361 // 初始化定位光标位置
362 xhtml.css(this.__focusDOM, {
363 left: 40 + this.$$textWidth(this._contentArray[this.__lineNum]) + "px",
364 top: 10 + this.__lineNum * 21 + "px"
365 });
366
367 this.__focusDOM.focus();
368 } // 更新编辑器内容视图
369
370
371 function updateView() {
372 var _this2 = this;
373
374 var template = "";
375
376 this.__formatData.forEach(function (line, index) {
377 var bgcolor = "";
378
379 if (index == _this2.__lineNum) {
380 bgcolor = "background-color:" + _this2._colorEdit;
381 }
382
383 template += "<div style='min-width: fit-content;white-space: nowrap;line-height:21px;height:21px;" + bgcolor + "'>";
384 template += "<em style='color:" + _this2._colorNumber + ";user-select: none;display:inline-block;font-style:normal;width:35px;text-align:right;margin-right:5px;'>" + (index + 1) + "</em>";
385 line.forEach(function (text) {
386 var contentText = text.content; // 提前对特殊字符进行处理
387
388 contentText = contentText.replace(/\&/g, "&amp;");
389 /*[&]*/
390
391 contentText = contentText.replace(/</g, "&lt;");
392 contentText = contentText.replace(/>/g, "&gt;");
393 /*[<,>]*/
394
395 template += "<span style='user-select: none;font-weight:" + _this2._fontWeight + ";white-space: pre;color:" + text.color + "'>" + contentText + "</span>";
396 });
397 template += "</div>";
398 });
399
400 this.__showDOM.innerHTML = template;
401 } // 更新编辑器选中视图
402
403
404 function updateSelectView() {
405 var _this3 = this;
406
407 var ctx = this.__selectCanvas.getContext('2d');
408
409 ctx.fillStyle = this._colorSelect;
410 ctx.clearRect(0, 0, this.__selectCanvas.scrollWidth, this.__selectCanvas.scrollHeight); // 绘制二个区间
411
412 var drawerSelect = function drawerSelect(beginLeftNum, endLeftNum, lineNum) {
413 var xy1 = _this3.$$calcCanvasXY(beginLeftNum, lineNum);
414
415 var xy2 = _this3.$$calcCanvasXY(endLeftNum, lineNum);
416
417 ctx.fillRect(xy1.x, xy1.y, xy2.x - xy1.x, 21);
418 }; // 如果选中区域为空,不用绘制
419
420
421 if (this.__cursor1.lineNum == this.__cursor2.lineNum && this.__cursor1.leftNum == this.__cursor2.leftNum) return;
422 ctx.beginPath(); // 如果在一行
423
424 if (this.__cursor1.lineNum == this.__cursor2.lineNum) {
425 drawerSelect(this.__cursor1.leftNum, this.__cursor2.leftNum, this.__cursor1.lineNum);
426 } // 如果选中的多于一行
427 else {
428 var beginCursor, endCursor;
429
430 if (this.__cursor1.lineNum < this.__cursor2.lineNum) {
431 beginCursor = this.__cursor1;
432 endCursor = this.__cursor2;
433 } else {
434 beginCursor = this.__cursor2;
435 endCursor = this.__cursor1;
436 } // 绘制开始的结尾
437
438
439 drawerSelect(beginCursor.leftNum, this._contentArray[beginCursor.lineNum].length, beginCursor.lineNum); // 绘制结束的开头
440
441 drawerSelect(0, endCursor.leftNum, endCursor.lineNum); // 绘制两行之间
442
443 for (var lineNum = beginCursor.lineNum + 1; lineNum < endCursor.lineNum; lineNum++) {
444 drawerSelect(0, this._contentArray[lineNum].length, lineNum);
445 }
446 }
447 } // 输入的时候更新光标位置
448
449
450 function updateCursorPosition() {
451 xhtml.css(this.__focusDOM, {
452 top: this.__lineNum * 21 + 10 + "px",
453 left: 40 + this.$$textWidth(this._contentArray[this.__lineNum].substring(0, this.__leftNum)) + "px"
454 });
455 } // 更新画布尺寸
456
457
458 function updateCanvasSize(width, height) {
459 if (arguments.length < 2) {
460 width = this._el.scrollWidth - 40;
461 height = this._el.scrollHeight - 10;
462 }
463
464 xhtml.css(this.__selectCanvas, {
465 width: width + "px",
466 height: height + "px"
467 });
468 xhtml.attr(this.__selectCanvas, {
469 width: width,
470 height: height
471 });
472 } // 取消选区
473
474
475 function cancelSelect() {
476 this.$$updateCanvasSize(1, 1);
477 this.__cursor1 = {
478 leftNum: 0,
479 lineNum: 0
480 };
481 this.__cursor2 = {
482 leftNum: 0,
483 lineNum: 0
484 };
485 } // 删除选区
486
487
488 function deleteSelect() {
489 // 假定cursor2是结束光标
490 var beginCursor = this.__cursor2,
491 endCursor = this.__cursor1; // 根据行号来校对
492
493 if (this.__cursor1.lineNum < this.__cursor2.lineNum) {
494 beginCursor = this.__cursor1;
495 endCursor = this.__cursor2;
496 } else if (this.__cursor1.lineNum == this.__cursor2.lineNum) {
497 // 根据列号来校对
498 if (this.__cursor1.leftNum < this.__cursor2.leftNum) {
499 beginCursor = this.__cursor1;
500 endCursor = this.__cursor2;
501 }
502 }
503
504 var newLineText = this._contentArray[beginCursor.lineNum].substr(0, beginCursor.leftNum) + this._contentArray[endCursor.lineNum].substr(endCursor.leftNum);
505
506 this._contentArray.splice(beginCursor.lineNum, endCursor.lineNum - beginCursor.lineNum + 1, newLineText); // 校对光标和选区
507
508
509 this.__leftNum = this.__cursor1.leftNum = this.__cursor2.leftNum = beginCursor.leftNum;
510 this.__lineNum = this.__cursor1.lineNum = this.__cursor2.lineNum = beginCursor.lineNum;
511 this.$$cancelSelect();
512 } // 字典表
513
514
515 var dictionary = (_dictionary2 = {
516 // 数字
517 48: [0, ')'],
518 49: [1, '!'],
519 50: [2, '@'],
520 51: [3, '#'],
521 52: [4, '$'],
522 53: [5, '%'],
523 54: [6, '^'],
524 55: [7, '&'],
525 56: [8, '*'],
526 57: [9, '('],
527 96: [0, 0],
528 97: 1,
529 98: 2,
530 99: 3,
531 100: 4,
532 101: 5,
533 102: 6,
534 103: 7,
535 104: 8,
536 105: 9,
537 106: "*",
538 107: "+",
539 109: "-",
540 110: ".",
541 111: "/",
542 // 字母
543 65: ["a", "A"],
544 66: ["b", "B"],
545 67: ["c", "C"],
546 68: ["d", "D"],
547 69: ["e", "E"],
548 70: ["f", "F"],
549 71: ["g", "G"],
550 72: ["h", "H"],
551 73: ["i", "I"],
552 74: ["j", "J"],
553 75: ["k", "K"],
554 76: ["l", "L"],
555 77: ["m", "M"],
556 78: ["n", "N"],
557 79: ["o", "O"],
558 80: ["p", "P"],
559 81: ["q", "Q"],
560 82: ["r", "R"],
561 83: ["s", "S"],
562 84: ["t", "T"],
563 85: ["u", "U"],
564 86: ["v", "V"],
565 87: ["w", "W"],
566 88: ["x", "X"],
567 89: ["y", "Y"],
568 90: ["z", "Z"],
569 // 方向
570 37: "left",
571 38: "up",
572 39: "right",
573 40: "down",
574 33: "page up",
575 34: "page down",
576 35: "end",
577 36: "home",
578 // 控制键
579 16: "shift",
580 17: "ctrl",
581 18: "alt",
582 91: "command",
583 92: "command",
584 93: "command",
585 9: "tab",
586 20: "caps lock",
587 32: "spacebar",
588 8: "backspace",
589 13: "enter",
590 27: "esc",
591 46: "delete",
592 45: "insert",
593 144: "number lock",
594 145: "scroll lock",
595 12: "clear"
596 }, _defineProperty2(_dictionary2, "45", "insert"), _defineProperty2(_dictionary2, 19, "pause"), _defineProperty2(_dictionary2, 112, "f1"), _defineProperty2(_dictionary2, 113, "f2"), _defineProperty2(_dictionary2, 114, "f3"), _defineProperty2(_dictionary2, 115, "f4"), _defineProperty2(_dictionary2, 116, "f5"), _defineProperty2(_dictionary2, 117, "f6"), _defineProperty2(_dictionary2, 118, "f7"), _defineProperty2(_dictionary2, 119, "f8"), _defineProperty2(_dictionary2, 120, "f9"), _defineProperty2(_dictionary2, 121, "f10"), _defineProperty2(_dictionary2, 122, "f11"), _defineProperty2(_dictionary2, 123, "f12"), _defineProperty2(_dictionary2, 189, ["-", "_"]), _defineProperty2(_dictionary2, 187, ["=", "+"]), _defineProperty2(_dictionary2, 219, ["[", "{"]), _defineProperty2(_dictionary2, 221, ["]", "}"]), _defineProperty2(_dictionary2, 220, ["\\", "|"]), _defineProperty2(_dictionary2, 186, [";", ":"]), _defineProperty2(_dictionary2, 222, ["'", '"']), _defineProperty2(_dictionary2, 188, [",", "<"]), _defineProperty2(_dictionary2, 190, [".", ">"]), _defineProperty2(_dictionary2, 191, ["/", "?"]), _defineProperty2(_dictionary2, 192, ["`", "~"]), _dictionary2); // 非独立键字典
597
598 var help_key = ["shift", "ctrl", "alt"];
599 /**
600 * 键盘按键
601 * 返回键盘此时按下的键的组合结果
602 * @since V0.2.5
603 * @public
604 */
605
606 function keyString(event) {
607 event = event || window.event;
608 var keycode = event.keyCode || event.which;
609 var key = dictionary[keycode] || keycode;
610 if (!key) return;
611 if (key.constructor !== Array) key = [key, key];
612 var shift = event.shiftKey ? "shift+" : "",
613 alt = event.altKey ? "alt+" : "",
614 ctrl = event.ctrlKey ? "ctrl+" : "";
615 var resultKey = "",
616 preKey = ctrl + shift + alt;
617
618 if (help_key.indexOf(key[0]) >= 0) {
619 key[0] = key[1] = "";
620 } // 判断是否按下了caps lock
621
622
623 var lockPress = event.code == "Key" + event.key && !shift; // 只有字母(且没有按下功能Ctrl、shift或alt)区分大小写
624
625 resultKey = preKey + (preKey == '' && lockPress ? key[1] : key[0]);
626
627 if (key[0] == "") {
628 resultKey = resultKey.replace(/\+$/, '');
629 }
630
631 return resultKey;
632 } // 绑定键盘和鼠标等交互事件处理
633
634
635 function bindEvent() {
636 var _this4 = this;
637
638 var mouseDown = false; // 辅助计算选择光标位置
639
640 var calcCursor = function calcCursor(event) {
641 var position = xhtml.position(_this4._el, event);
642 var topIndex = Math.round((position.y - 20.5) / 21);
643 if (topIndex < 0) topIndex = 0;
644 if (topIndex >= _this4._contentArray.length) topIndex = _this4._contentArray.length - 1;
645 return {
646 leftNum: _this4.$$bestLeftNum(position.x, topIndex),
647 lineNum: topIndex
648 };
649 }; // 获取光标之间的内容
650
651
652 var calcTwoCursor = function calcTwoCursor() {
653 // 假定cursor2是结束光标
654 var beginCursor = _this4.__cursor2,
655 endCursor = _this4.__cursor1; // 根据行号来校对
656
657 if (_this4.__cursor1.lineNum < _this4.__cursor2.lineNum) {
658 beginCursor = _this4.__cursor1;
659 endCursor = _this4.__cursor2;
660 } else if (_this4.__cursor1.lineNum == _this4.__cursor2.lineNum) {
661 // 根据列号来校对
662 if (_this4.__cursor1.leftNum < _this4.__cursor2.leftNum) {
663 beginCursor = _this4.__cursor1;
664 endCursor = _this4.__cursor2;
665 }
666
667 return _this4._contentArray[beginCursor.lineNum].substring(beginCursor.leftNum, endCursor.leftNum);
668 } // 余下的一定是多行
669
670
671 var resultData = "";
672 resultData += _this4._contentArray[beginCursor.lineNum].substr(beginCursor.leftNum) + "\n";
673
674 for (var lineNum = beginCursor.lineNum + 1; lineNum < endCursor.lineNum; lineNum++) {
675 resultData += _this4._contentArray[lineNum] + "\n";
676 }
677
678 resultData += _this4._contentArray[endCursor.lineNum].substr(0, endCursor.leftNum);
679 return resultData;
680 }; // 鼠标按下的时候,记录开始光标位置并标记鼠标按下动作
681
682
683 xhtml.bind(document, 'mousedown', function (event) {
684 mouseDown = true;
685 _this4.__cursor2 = _this4.__cursor1 = calcCursor(event);
686
687 _this4.$$updateCanvasSize(); // 绘制选中效果
688
689
690 _this4.$$updateSelectView();
691 }); // 移动的时候不停的同步结束光标位置
692
693 xhtml.bind(document, 'mousemove', function (event) {
694 if (!mouseDown) return;
695 _this4.__cursor2 = calcCursor(event); // 绘制选中效果
696
697 _this4.$$updateSelectView();
698 }); // 鼠标分开或移出的时候,标记鼠标放开
699
700 xhtml.bind(document, 'mouseup', function () {
701 return mouseDown = false;
702 });
703 xhtml.bind(document, 'mouseout', function () {
704 return mouseDown = false;
705 }); // 点击编辑界面
706
707 xhtml.bind(this._el, 'click', function (event) {
708 var position = xhtml.position(_this4._el, event);
709 var topIndex = Math.round((position.y - 20.5) / 21); // 如果超过了内容区域
710
711 if (topIndex < 0 || topIndex >= _this4._contentArray.length) return;
712 _this4.__lineNum = topIndex;
713 _this4.__leftNum = _this4.$$bestLeftNum(position.x);
714
715 _this4.$$updateCursorPosition();
716
717 _this4.$$updateView();
718 });
719
720 var update = function update(text) {
721 // 获取输入内容
722 text = text || _this4.__focusDOM.value;
723 text = _this4.$$filterText(text);
724 _this4.__focusDOM.value = ""; // 如果有选区,先删除选区
725
726 if (_this4.$$selectIsNotBlank()) _this4.$$deleteSelect(); // 如果输入的是回车,切割文本
727
728 if (/^\n$/.test(text)) {
729 if (_this4.__leftNum >= _this4._contentArray[_this4.__lineNum].length) {
730 _this4._contentArray.splice(_this4.__lineNum + 1, 0, "");
731 } else {
732 _this4._contentArray.splice(_this4.__lineNum + 1, 0, _this4._contentArray[_this4.__lineNum].substring(_this4.__leftNum));
733
734 _this4._contentArray[_this4.__lineNum] = _this4._contentArray[_this4.__lineNum].substring(0, _this4.__leftNum);
735 }
736
737 _this4.__lineNum += 1;
738 _this4.__leftNum = 0;
739 } // 否则就是一堆文本(包括复制来的)
740 else {
741 var textArray = text.split(/\n/); // 如果只有一行文本(分开是为了加速)
742
743 if (textArray.length <= 1) {
744 _this4._contentArray[_this4.__lineNum] = _this4._contentArray[_this4.__lineNum].substring(0, _this4.__leftNum) + text + _this4._contentArray[_this4.__lineNum].substring(_this4.__leftNum);
745 _this4.__leftNum += text.length;
746 } // 如果是复制的多行文本
747 else {
748 var _this4$_contentArray;
749
750 // 需要切割的行两边文本
751 var leftText = _this4._contentArray[_this4.__lineNum].substring(0, _this4.__leftNum);
752
753 var rightText = _this4._contentArray[_this4.__lineNum].substring(_this4.__leftNum); // 旧行文本拼接进来
754
755
756 textArray[0] = leftText + textArray[0];
757 textArray[textArray.length - 1] += rightText; // 新内容记录下来
758
759 (_this4$_contentArray = _this4._contentArray).splice.apply(_this4$_contentArray, [_this4.__lineNum, 1].concat(_toConsumableArray2(textArray)));
760
761 _this4.__lineNum += textArray.length - 1;
762 _this4.__leftNum = textArray[textArray.length - 1].length - rightText.length;
763 }
764 } // 着色并更新视图
765
766
767 _this4.__formatData = _this4.$shader(_this4._contentArray.join('\n'), _this4._langColors);
768
769 _this4.$$updateCursorPosition();
770
771 _this4.$$updateView();
772 }; // 中文输入开始
773
774
775 xhtml.bind(this.__focusDOM, 'compositionstart', function () {
776 _this4.__needUpdate = false;
777 _this4.__focusDOM.style.color = "rgba(0,0,0,0)";
778 _this4.__focusDOM.style.borderLeft = '1px solid ' + _this4._colorCursor;
779 }); // 中文输入结束
780
781 xhtml.bind(this.__focusDOM, 'compositionend', function () {
782 _this4.__needUpdate = true;
783 _this4.__focusDOM.style.color = _this4._colorCursor;
784 _this4.__focusDOM.style.borderLeft = "none";
785 update();
786 }); // 输入
787
788 xhtml.bind(this.__focusDOM, 'input', function () {
789 // 如果是中文输入开始,不应该更新
790 if (_this4.__needUpdate) update();
791 }); // 处理键盘控制
792
793 xhtml.bind(this._el, 'keydown', function (event) {
794 switch (keyString(event)) {
795 // 全选
796 case "ctrl+a":
797 {
798 // 修改选区范围
799 _this4.__cursor1 = {
800 leftNum: 0,
801 lineNum: 0
802 };
803 _this4.__cursor2 = {
804 lineNum: _this4._contentArray.length - 1,
805 leftNum: _this4._contentArray[_this4._contentArray.length - 1].length
806 }; // 绘制选中效果
807
808 _this4.$$updateSelectView();
809
810 break;
811 }
812 // 复制
813
814 case "ctrl+c":
815 {
816 if (_this4.$$selectIsNotBlank()) {
817 xhtml.copy(calcTwoCursor());
818
819 _this4.__focusDOM.focus();
820 }
821
822 break;
823 }
824 // 剪切
825
826 case "ctrl+x":
827 {
828 if (_this4.$$selectIsNotBlank()) {
829 xhtml.copy(calcTwoCursor());
830
831 _this4.__focusDOM.focus();
832
833 _this4.$$deleteSelect(); // 由于内容改变,需要重新调用着色
834
835
836 _this4.__formatData = _this4.$shader(_this4._contentArray.join('\n'), _this4._langColors); // 更新视图
837
838 _this4.$$updateCursorPosition();
839
840 _this4.$$updateView();
841
842 _this4.$$cancelSelect();
843 }
844
845 break;
846 }
847 // 多空格输入或多行移位
848
849 case "tab":
850 {
851 // tab用来控制输入多个空格,默认事件需要禁止
852 xhtml.stopPropagation(event);
853 xhtml.preventDefault(event); // 计算空格
854
855 var blanks = "";
856
857 for (var i = 0; i < _this4._tabSpace; i++) {
858 blanks += " ";
859 } // 如果有选区,特殊处理
860
861
862 if (_this4.$$selectIsNotBlank()) {
863 var beginLineNum = _this4.__cursor1.lineNum,
864 endLineNum = _this4.__cursor2.lineNum;
865
866 if (beginLineNum > endLineNum) {
867 beginLineNum = _this4.__cursor2.lineNum;
868 endLineNum = _this4.__cursor1.lineNum;
869 } // 在开头追究tab
870
871
872 for (var lineNum = beginLineNum; lineNum <= endLineNum; lineNum++) {
873 _this4._contentArray[lineNum] = blanks + _this4._contentArray[lineNum];
874 } // 校对选择区域
875
876
877 _this4.__cursor1.leftNum += _this4._tabSpace;
878 _this4.__cursor2.leftNum += _this4._tabSpace; // 校对光标
879
880 _this4.__leftNum += _this4._tabSpace;
881 _this4.__formatData = _this4.$shader(_this4._contentArray.join('\n'), _this4._langColors);
882
883 _this4.$$updateCursorPosition();
884
885 _this4.$$updateView();
886
887 _this4.$$updateCanvasSize();
888
889 _this4.$$updateSelectView();
890 } else {
891 update(blanks);
892 }
893
894 break;
895 }
896 // 光标向上
897
898 case "up":
899 {
900 // 如果是第一行不需要任何处理
901 if (_this4.__lineNum <= 0) return; // 向上一行
902
903 _this4.__lineNum -= 1;
904 _this4.__leftNum = _this4.$$bestLeftNum(_this4.$$textWidth(_this4._contentArray[_this4.__lineNum + 1].substr(0, _this4.__leftNum)) + 40);
905
906 _this4.$$updateCursorPosition();
907
908 _this4.$$updateView();
909
910 _this4.$$cancelSelect();
911
912 _this4._el.scrollTop -= 21;
913 break;
914 }
915 // 光标向下
916
917 case "down":
918 {
919 if (_this4.__lineNum >= _this4._contentArray.length - 1) return; // 向下一行
920
921 _this4.__lineNum += 1;
922 _this4.__leftNum = _this4.$$bestLeftNum(_this4.$$textWidth(_this4._contentArray[_this4.__lineNum - 1].substr(0, _this4.__leftNum)) + 40);
923
924 _this4.$$updateCursorPosition();
925
926 _this4.$$updateView();
927
928 _this4.$$cancelSelect();
929
930 _this4._el.scrollTop += 21;
931 break;
932 }
933 // 光标向左
934
935 case "left":
936 {
937 if (_this4.__leftNum <= 0) {
938 if (_this4.__lineNum <= 0) return;
939 _this4.__lineNum -= 1;
940 _this4.__leftNum = _this4._contentArray[_this4.__lineNum].length;
941 } else {
942 _this4.__leftNum -= 1;
943 }
944
945 _this4.$$updateCursorPosition();
946
947 _this4.$$cancelSelect();
948
949 break;
950 }
951 // 光标向右
952
953 case "right":
954 {
955 if (_this4.__leftNum >= _this4._contentArray[_this4.__lineNum].length) {
956 if (_this4.__lineNum >= _this4._contentArray.length - 1) return;
957 _this4.__lineNum += 1;
958 _this4.__leftNum = 0;
959 } else {
960 _this4.__leftNum += 1;
961 }
962
963 _this4.$$updateCursorPosition();
964
965 _this4.$$cancelSelect();
966
967 break;
968 }
969 // 删除
970
971 case "backspace":
972 {
973 // 如果有选区
974 if (_this4.$$selectIsNotBlank()) {
975 // 删除选区
976 _this4.$$deleteSelect();
977 } // 无选区的常规操作
978 else {
979 if (_this4.__leftNum <= 0) {
980 if (_this4.__lineNum <= 0) return;
981 _this4.__lineNum -= 1;
982 _this4.__leftNum = _this4._contentArray[_this4.__lineNum].length; // 一行的开头应该删除本行(合并到前一行)
983
984 _this4._contentArray[_this4.__lineNum] += _this4._contentArray[_this4.__lineNum + 1];
985
986 _this4._contentArray.splice(_this4.__lineNum + 1, 1);
987 } else {
988 _this4.__leftNum -= 1;
989 _this4._contentArray[_this4.__lineNum] = _this4._contentArray[_this4.__lineNum].substring(0, _this4.__leftNum) + _this4._contentArray[_this4.__lineNum].substring(_this4.__leftNum + 1);
990 }
991 } // 由于内容改变,需要重新调用着色
992
993
994 _this4.__formatData = _this4.$shader(_this4._contentArray.join('\n'), _this4._langColors); // 更新视图
995
996 _this4.$$updateCursorPosition();
997
998 _this4.$$updateView();
999
1000 _this4.$$cancelSelect();
1001
1002 break;
1003 }
1004 }
1005 });
1006 } // 外来文本统一过滤处理
1007
1008
1009 function filterText(oralStr) {
1010 // 把tab统一变成空格
1011 var tab = "";
1012
1013 for (var i = 0; i < this._tabSpace; i++) {
1014 tab += " ";
1015 }
1016
1017 return oralStr.replace(/\t/g, tab);
1018 } // 合并内容
1019
1020
1021 function toShaderReult(words) {
1022 var resultData = [[]],
1023 lineNum = 0;
1024 words.forEach(function (word) {
1025 var codeArray = word.content.split(/\n/);
1026 resultData[lineNum].push({
1027 color: word.color,
1028 content: codeArray[0]
1029 });
1030
1031 for (var index = 1; index < codeArray.length; index++) {
1032 lineNum += 1;
1033 resultData.push([]);
1034 resultData[lineNum].push({
1035 color: word.color,
1036 content: codeArray[index]
1037 });
1038 }
1039 });
1040 return resultData;
1041 } // 获取前置空格
1042
1043
1044 function getTabStringFactory(tabNumber) {
1045 var singleTab = "";
1046
1047 for (var i = 0; i < tabNumber; i++) {
1048 singleTab += " ";
1049 }
1050
1051 return function getTabString(num) {
1052 var temp = '';
1053
1054 for (var j = 0; j < num; j++) {
1055 temp += singleTab;
1056 }
1057
1058 return temp;
1059 };
1060 }
1061
1062 function css_shader(textString, colors, notToResult) {
1063 var shaderArray = []; // 当前面对的
1064
1065 var i = 0; // 获取往后n个值
1066
1067 var nextNValue = function nextNValue(n) {
1068 return textString.substring(i, n + i > textString.length ? textString.length : n + i);
1069 };
1070
1071 var template = ""; // 1:选择器 tag
1072 // 2:属性名 attr
1073 // 3:属性值 string
1074
1075 var state = "tag"; // 初始化模板,开始文本捕获
1076
1077 var initTemplate = function initTemplate() {
1078 if (template != "") {
1079 shaderArray.push({
1080 color: colors[state],
1081 content: template
1082 });
1083 }
1084
1085 template = "";
1086 };
1087
1088 while (true) {
1089 /* 1.注释 */
1090 if (nextNValue(2) == '/*') {
1091 initTemplate();
1092
1093 while (nextNValue(2) !== '*/' && i < textString.length) {
1094 template += textString[i++];
1095 }
1096
1097 shaderArray.push({
1098 color: colors.annotation,
1099 content: template + nextNValue(2)
1100 });
1101 i += 2;
1102 template = "";
1103 }
1104 /* 2.字符串 */
1105 else if (["'", '"'].indexOf(nextNValue(1)) > -1) {
1106 var strBorder = nextNValue(1);
1107 initTemplate();
1108
1109 do {
1110 template += textString[i++];
1111 } while (nextNValue(1) != strBorder && i < textString.length); // 因为可能是没有字符导致的结束
1112
1113
1114 if (nextNValue(1) != strBorder) {
1115 strBorder = "";
1116 } else {
1117 i += 1;
1118 }
1119
1120 shaderArray.push({
1121 color: colors.string,
1122 content: template + strBorder
1123 });
1124 template = "";
1125 }
1126 /* 3.边界 */
1127 else if ([":", '{', '}', ";"].indexOf(nextNValue(1)) > -1) {
1128 initTemplate();
1129 shaderArray.push({
1130 color: colors.border,
1131 content: nextNValue(1)
1132 });
1133 template = "";
1134
1135 if (nextNValue(1) == '{' || nextNValue(1) == ';') {
1136 state = 'attr';
1137 } else if (nextNValue(1) == '}') {
1138 state = 'tag';
1139 } else {
1140 state = 'string';
1141 }
1142
1143 i += 1;
1144 }
1145 /* 追加字符 */
1146 else {
1147 if (i >= textString.length) {
1148 initTemplate();
1149 break;
1150 } else {
1151 template += textString[i++];
1152 }
1153 }
1154 }
1155
1156 return notToResult ? shaderArray : toShaderReult(shaderArray);
1157 } // 关键字
1158
1159
1160 var keyWords = ["abstract", "arguments", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "debugger", "default", "delete", "do", "double", "else", "enum", "eval", "export", "extends", "false", "final", "finally", "float", "for", "function", "goto", "if", "implements", "import", "in", "instanceof", "int", "interface", "let", "long", "native", "new", "null", "package", "private", "protected", "public", "return", "short", "static", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "typeof", "var", "void", "volatile", "while", "with", "yield"];
1161
1162 function javascript_shader(textString, colors, notToResult) {
1163 var shaderArray = []; // 当前面对的
1164
1165 var i = 0; // 获取往后n个值
1166
1167 var nextNValue = function nextNValue(n) {
1168 return textString.substring(i, n + i > textString.length ? textString.length : n + i);
1169 };
1170
1171 var template = ""; // 初始化模板,开始文本捕获
1172
1173 var initTemplate = function initTemplate() {
1174 if (template != "") {
1175 // 考虑开始的(s
1176 if (template[0] == '(') {
1177 shaderArray.push({
1178 color: colors.border,
1179 content: "("
1180 });
1181 template = template.substr(1);
1182 }
1183
1184 shaderArray.push({
1185 color: colors.text,
1186 content: template
1187 });
1188 }
1189
1190 template = "";
1191 };
1192
1193 while (true) {
1194 /* 1.注释1 */
1195 if (nextNValue(2) == '/*') {
1196 initTemplate();
1197
1198 while (nextNValue(2) !== '*/' && i < textString.length) {
1199 template += textString[i++];
1200 }
1201
1202 shaderArray.push({
1203 color: colors.annotation,
1204 content: template + nextNValue(2)
1205 });
1206 i += 2;
1207 template = "";
1208 }
1209 /* 2.注释2 */
1210 else if (nextNValue(2) == '//') {
1211 initTemplate();
1212
1213 while (nextNValue(1) !== '\n' && i < textString.length) {
1214 template += textString[i++];
1215 }
1216
1217 shaderArray.push({
1218 color: colors.annotation,
1219 content: template
1220 });
1221 template = "";
1222 }
1223 /* 3.字符串 */
1224 else if (["'", '"', '`'].indexOf(nextNValue(1)) > -1) {
1225 var strBorder = nextNValue(1);
1226 initTemplate();
1227
1228 do {
1229 template += textString[i++];
1230 } while (nextNValue(1) != strBorder && i < textString.length); // 因为可能是没有字符导致的结束
1231
1232
1233 if (nextNValue(1) != strBorder) {
1234 strBorder = "";
1235 } else {
1236 i += 1;
1237 }
1238
1239 shaderArray.push({
1240 color: colors.string,
1241 content: template + strBorder
1242 });
1243 template = "";
1244 }
1245 /* 4.函数定义 */
1246 else if (nextNValue(1) == '(' && (template[0] == ' ' || i - template.length - 1 >= 0 && textString[i - template.length - 1] == " ")) {
1247 shaderArray.push({
1248 color: colors.tag,
1249 content: template
1250 });
1251 i += 1;
1252 template = "(";
1253 }
1254 /* 5.方法调用 */
1255 else if (nextNValue(1) == '(') {
1256 shaderArray.push({
1257 color: colors.attr,
1258 content: template
1259 });
1260 i += 1;
1261 template = "(";
1262 }
1263 /* 6.边界 */
1264 else if ([";", '{', '}', '(', ')', '.', '\n', '=', '+', '>', '<', '[', ']', '-', '*', '/', '^', '*', '!'].indexOf(nextNValue(1)) > -1) {
1265 initTemplate();
1266 shaderArray.push({
1267 color: colors.border,
1268 content: nextNValue(1)
1269 });
1270 template = "";
1271 i += 1;
1272 }
1273 /* 7.关键字 */
1274 else if (nextNValue(1) == ' ' && keyWords.indexOf(template.trim()) > -1) {
1275 shaderArray.push({
1276 color: colors.key,
1277 content: template + " "
1278 });
1279 template = "";
1280 i += 1;
1281 }
1282 /* 追加字符 */
1283 else {
1284 if (i >= textString.length) {
1285 initTemplate();
1286 break;
1287 } else {
1288 template += textString[i++];
1289 }
1290 }
1291 }
1292
1293 return notToResult ? shaderArray : toShaderReult(shaderArray);
1294 }
1295
1296 function html_shader(textString, colors) {
1297 var shaderArray = []; // 当前面对的
1298
1299 var i = 0; // 获取往后n个值
1300
1301 var nextNValue = function nextNValue(n) {
1302 return textString.substring(i, n + i > textString.length ? textString.length : n + i);
1303 };
1304
1305 var template = ""; // 初始化模板,开始文本捕获
1306
1307 var initTemplate = function initTemplate() {
1308 if (template != "") {
1309 shaderArray.push({
1310 color: colors.text,
1311 content: template
1312 });
1313 }
1314
1315 template = "";
1316 }; // 匹配属性值模板
1317
1318
1319 var getAttrValueTemplate = function getAttrValueTemplate() {
1320 var endStr = " "; // 寻找属性值边界
1321
1322 if (nextNValue(1) == '"') endStr = '"';
1323 if (nextNValue(1) == "'") endStr = "'"; // 到达边界前一直寻找下一个
1324
1325 do {
1326 template += textString[i++];
1327 } while (nextNValue(1) != endStr && i < textString.length); // 如果是匹配成功而不是匹配到末尾
1328
1329
1330 if (endStr != " " && i < textString.length) {
1331 template += endStr;
1332 i += 1;
1333 }
1334
1335 shaderArray.push({
1336 color: colors.string,
1337 content: template
1338 });
1339 template = "";
1340 };
1341
1342 while (true) {
1343 /* 1.注释 */
1344 if (nextNValue(4) == '<!--') {
1345 initTemplate();
1346
1347 while (nextNValue(3) !== '-->' && i < textString.length) {
1348 template += textString[i++];
1349 }
1350
1351 shaderArray.push({
1352 color: colors.annotation,
1353 content: template + nextNValue(3)
1354 });
1355 i += 3;
1356 template = "";
1357 }
1358 /* 2.</ */
1359 else if (nextNValue(2) == '</') {
1360 initTemplate();
1361 shaderArray.push({
1362 color: colors.border,
1363 content: "</"
1364 });
1365 i += 2;
1366
1367 while (nextNValue(1) !== '>' && i < textString.length) {
1368 template += textString[i++];
1369 }
1370
1371 if (template != "") {
1372 shaderArray.push({
1373 color: colors.tag,
1374 content: template
1375 });
1376 template = "";
1377
1378 if (i < textString.length) {
1379 shaderArray.push({
1380 color: colors.border,
1381 content: ">"
1382 });
1383 i += 1;
1384 }
1385 }
1386 }
1387 /* 3.< */
1388 else if (nextNValue(1) == '<' && nextNValue(2) != '< ') {
1389 var specialTag = "";
1390 initTemplate();
1391 shaderArray.push({
1392 color: colors.border,
1393 content: "<"
1394 });
1395 i += 1; // 寻找标签名称
1396
1397 while (nextNValue(1) != '>' && nextNValue(1) != ' ' && i < textString.length) {
1398 template += textString[i++];
1399 }
1400
1401 if (template != '') {
1402 // 针对style和script这样特殊的标签,内部需要调用对应的着色器着色
1403 if (template == "style" || template == 'script') {
1404 specialTag = "</" + template + ">";
1405 }
1406
1407 shaderArray.push({
1408 color: colors.tag,
1409 content: template
1410 });
1411 template = '';
1412
1413 if (i < textString.length) {
1414 // 寻找标签属性
1415 while (i < textString.length) {
1416 // 遇到这个表示标签结束了
1417 // 也就意味着标签匹配结束
1418 if (nextNValue(1) == ">") {
1419 initTemplate();
1420 shaderArray.push({
1421 color: colors.border,
1422 content: ">"
1423 });
1424 i += 1;
1425 break;
1426 } // 如果是空格,表示是属性之间,接着查看下一个即可
1427 else if (nextNValue(1) != ' ') {
1428 initTemplate(); // 匹配属性名称
1429
1430 if (nextNValue(1) != '"' && nextNValue(1) != "'") {
1431 // 如果不是=或>和空格就继续
1432 while (nextNValue(1) != "=" && nextNValue(1) != '>' && i < textString.length && nextNValue(1) != " ") {
1433 template += textString[i++];
1434 }
1435
1436 if (template != "") {
1437 shaderArray.push({
1438 color: colors.attr,
1439 content: template
1440 });
1441 template = ""; // 如果下一个是=,就接着找属性值
1442
1443 if (nextNValue(1) == '=') {
1444 shaderArray.push({
1445 color: colors.text,
1446 content: "="
1447 });
1448 i += 1;
1449
1450 if (i < textString.length && nextNValue(1) != " " && nextNValue(1) != '>') {
1451 // 寻找属性值
1452 getAttrValueTemplate();
1453 }
1454 }
1455 } else {
1456 template += textString[i++];
1457 }
1458 } else if (nextNValue(1) == '=') {
1459 shaderArray.push({
1460 color: colors.text,
1461 content: "="
1462 });
1463 i += 1;
1464 } else {
1465 if (i < textString.length && nextNValue(1) != " " && nextNValue(1) != '>') {
1466 getAttrValueTemplate();
1467 }
1468 }
1469 } else {
1470 template += textString[i++];
1471 }
1472 }
1473 }
1474 }
1475
1476 if (specialTag != "") {
1477 var oldI = i,
1478 oldTemplate = template;
1479
1480 while (nextNValue(specialTag.length) != specialTag && i < textString.length) {
1481 template += textString[i++];
1482 }
1483
1484 if (i < textString.length) {
1485 var innerShaderArray = {
1486 "</style>": css_shader,
1487 "</script>": javascript_shader
1488 }[specialTag](template, colors, true);
1489 innerShaderArray.forEach(function (innerShader) {
1490 shaderArray.push(innerShader);
1491 });
1492 template = "";
1493 } else {
1494 template = oldTemplate;
1495 i = oldI;
1496 }
1497 }
1498 }
1499 /* 追加字符 */
1500 else {
1501 if (i >= textString.length) {
1502 initTemplate();
1503 break;
1504 } else {
1505 template += textString[i++];
1506 }
1507 }
1508 }
1509
1510 return toShaderReult(shaderArray);
1511 }
1512
1513 var _RegExp = {
1514 // 空白字符:http://www.w3.org/TR/css3-selectors/#whitespace
1515 blankReg: new RegExp("[\\x20\\t\\r\\n\\f]"),
1516 blanksReg: /^[\x20\t\r\n\f]{0,}$/
1517 };
1518
1519 function createCommonjsModule(fn, module) {
1520 return module = {
1521 exports: {}
1522 }, fn(module, module.exports), module.exports;
1523 }
1524
1525 var core_min = createCommonjsModule(function (module) {
1526 function _defineProperty(obj, key, value) {
1527 if (key in obj) {
1528 Object.defineProperty(obj, key, {
1529 value: value,
1530 enumerable: true,
1531 configurable: true,
1532 writable: true
1533 });
1534 } else {
1535 obj[key] = value;
1536 }
1537
1538 return obj;
1539 }
1540
1541 function isNativeReflectConstruct() {
1542 if (typeof Reflect === "undefined" || !Reflect.construct) return false;
1543 if (Reflect.construct.sham) return false;
1544 if (typeof Proxy === "function") return true;
1545
1546 try {
1547 Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
1548 return true;
1549 } catch (e) {
1550 return false;
1551 }
1552 }
1553
1554 function _construct(Parent, args, Class) {
1555 if (isNativeReflectConstruct()) {
1556 _construct = Reflect.construct;
1557 } else {
1558 _construct = function _construct(Parent, args, Class) {
1559 var a = [null];
1560 a.push.apply(a, args);
1561 var Constructor = Function.bind.apply(Parent, a);
1562 var instance = new Constructor();
1563 if (Class) _setPrototypeOf(instance, Class.prototype);
1564 return instance;
1565 };
1566 }
1567
1568 return _construct.apply(null, arguments);
1569 }
1570
1571 function _setPrototypeOf(o, p) {
1572 _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
1573 o.__proto__ = p;
1574 return o;
1575 };
1576
1577 return _setPrototypeOf(o, p);
1578 }
1579
1580 function _toConsumableArray(arr) {
1581 return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread();
1582 }
1583
1584 function _nonIterableSpread() {
1585 throw new TypeError("Invalid attempt to spread non-iterable instance");
1586 }
1587
1588 function _iterableToArray(iter) {
1589 if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter);
1590 }
1591
1592 function _arrayWithoutHoles(arr) {
1593 if (Array.isArray(arr)) {
1594 for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) {
1595 arr2[i] = arr[i];
1596 }
1597
1598 return arr2;
1599 }
1600 }
1601
1602 function _typeof(obj) {
1603 if (typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol") {
1604 _typeof = function _typeof(obj) {
1605 return _typeof2(obj);
1606 };
1607 } else {
1608 _typeof = function _typeof(obj) {
1609 return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : _typeof2(obj);
1610 };
1611 }
1612
1613 return _typeof(obj);
1614 }
1615
1616 (function () {
1617 var _dictionary;
1618
1619 var MAX_SAFE_INTEGER = 9007199254740991;
1620
1621 function isLength(value) {
1622 return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
1623 }
1624
1625 function isArrayLike(value) {
1626 return value != null && typeof value != "function" && isLength(value.length);
1627 }
1628
1629 var toString = Object.prototype.toString;
1630
1631 function getType(value) {
1632 if (value == null) {
1633 return value === undefined ? "[object Undefined]" : "[object Null]";
1634 }
1635
1636 return toString.call(value);
1637 }
1638
1639 function isString(value) {
1640 var type = _typeof(value);
1641
1642 return type === "string" || type === "object" && value != null && !Array.isArray(value) && getType(value) === "[object String]";
1643 }
1644
1645 function isArraySpec(value) {
1646 return isArrayLike(value) && !isString(value);
1647 }
1648
1649 var concat = function concat(newArray, values) {
1650 if (!isArraySpec(values)) {
1651 return newArray.push(values);
1652 }
1653
1654 for (var i = 0; i < values.length; i++) {
1655 if (isArraySpec(values[i])) {
1656 if (values[i].length > 1) {
1657 concat(newArray, values[i]);
1658 } else if (values[i].length === 1) {
1659 concat(newArray, values[i][0]);
1660 }
1661 } else {
1662 newArray.push(values[i]);
1663 }
1664 }
1665 };
1666
1667 function concat$1() {
1668 var values = [];
1669
1670 for (var i = 0; i < arguments.length; i++) {
1671 values.push(arguments[i]);
1672 }
1673
1674 var newArray = [];
1675 concat(newArray, values);
1676 return newArray;
1677 }
1678
1679 function eq(value, other) {
1680 return value === other || value !== value && other !== other;
1681 }
1682
1683 function indexOf(array, value, fromIndex) {
1684 if (!isArrayLike(array)) {
1685 return -1;
1686 }
1687
1688 if (!isLength(fromIndex) || fromIndex < 0) {
1689 fromIndex = 0;
1690 }
1691
1692 for (; fromIndex < array.length; fromIndex++) {
1693 if (eq(array[fromIndex], value)) {
1694 return fromIndex;
1695 }
1696 }
1697
1698 return -1;
1699 }
1700
1701 function lastIndexOf(array, value, fromIndex) {
1702 if (!isArrayLike(array)) {
1703 return -1;
1704 }
1705
1706 if (!isLength(fromIndex) || fromIndex > array.length - 1) {
1707 fromIndex = array.length - 1;
1708 }
1709
1710 for (; fromIndex > -1; fromIndex--) {
1711 if (eq(array[fromIndex], value)) {
1712 return fromIndex;
1713 }
1714 }
1715
1716 return -1;
1717 }
1718
1719 function unique(array) {
1720 if (!isArraySpec(array)) {
1721 return array;
1722 }
1723
1724 if (array.length === 0) {
1725 return [];
1726 }
1727
1728 if (array.length === 1) {
1729 return [array[0]];
1730 }
1731
1732 var newArray = [],
1733 help = _construct(Array, _toConsumableArray(array));
1734
1735 while (help.length > 0) {
1736 newArray.push(help[0]);
1737 var value = help[0],
1738 j = -1;
1739
1740 for (var i = 1; i < help.length; i++) {
1741 if (!eq(value, help[i])) {
1742 help[j + 1] = help[i];
1743 j += 1;
1744 }
1745 }
1746
1747 help.length = j + 1;
1748 }
1749
1750 return newArray;
1751 }
1752
1753 function isSymbol(value) {
1754 var type = _typeof(value);
1755
1756 return type === "symbol" || type === "object" && value !== null && getType(value) === "[object Symbol]";
1757 }
1758
1759 var symbolToString = Symbol.prototype.toString;
1760 var hasOwnProperty = Object.prototype.hasOwnProperty;
1761 var INFINITY = 1 / 0;
1762
1763 function toString$1(value) {
1764 if (value == null) {
1765 return "";
1766 }
1767
1768 if (typeof value === "string") {
1769 return value;
1770 }
1771
1772 if (isString(value)) {
1773 return value + "";
1774 }
1775
1776 if (Array.isArray(value)) {
1777 var _temp = [];
1778
1779 for (var i = 0; i < value.length; i++) {
1780 _temp[i] = toString$1(value[i]);
1781 }
1782
1783 return "[".concat(_temp, "]");
1784 }
1785
1786 if (isSymbol(value)) {
1787 return symbolToString ? symbolToString.call(value) : "";
1788 }
1789
1790 var temp = "";
1791
1792 for (var key in value) {
1793 if (hasOwnProperty.call(value, key)) temp += ',"' + toString$1(key) + '":' + toString$1(value[key]);
1794 }
1795
1796 if (temp !== "") {
1797 temp = temp.replace(/^,/, "");
1798 return "{" + temp + "}";
1799 }
1800
1801 var result = "".concat(value);
1802 return result === "0" && 1 / value === -INFINITY ? "-0" : result;
1803 }
1804
1805 function isArray(value, notStrict) {
1806 if (notStrict) {
1807 return isArraySpec(value);
1808 }
1809
1810 return Array.isArray(value);
1811 }
1812
1813 function isObject(value) {
1814 var type = _typeof(value);
1815
1816 return value != null && (type === "object" || type === "function");
1817 }
1818
1819 function isBoolean(value) {
1820 return value === true || value === false || value !== null && _typeof(value) === "object" && getType(value) === "[object Boolean]";
1821 }
1822
1823 function isPlainObject(value) {
1824 if (value === null || _typeof(value) !== "object" || getType(value) != "[object Object]") {
1825 return false;
1826 }
1827
1828 if (Object.getPrototypeOf(value) === null) {
1829 return true;
1830 }
1831
1832 var proto = value;
1833
1834 while (Object.getPrototypeOf(proto) !== null) {
1835 proto = Object.getPrototypeOf(proto);
1836 }
1837
1838 return Object.getPrototypeOf(value) === proto;
1839 }
1840
1841 function isElement(value) {
1842 return value !== null && _typeof(value) === "object" && (value.nodeType === 1 || value.nodeType === 9 || value.nodeType === 11) && !isPlainObject(value);
1843 }
1844
1845 function isText(value) {
1846 return value !== null && _typeof(value) === "object" && value.nodeType === 3 && !isPlainObject(value);
1847 }
1848
1849 function isFunction(value) {
1850 if (!isObject(value)) {
1851 return false;
1852 }
1853
1854 var type = getType(value);
1855 return type === "[object Function]" || type === "[object AsyncFunction]" || type === "[object GeneratorFunction]" || type === "[object Proxy]";
1856 }
1857
1858 function isError(value) {
1859 if (value === null || _typeof(value) !== "object") {
1860 return false;
1861 }
1862
1863 var type = getType(value);
1864 return type === "[object Error]" || type === "[object DOMException]" || typeof value.message === "string" && typeof value.name === "string" && !isPlainObject(value);
1865 }
1866
1867 function isNull(value) {
1868 return value === null;
1869 }
1870
1871 function isNumber(value) {
1872 return typeof value === "number" || value !== null && _typeof(value) === "object" && getType(value) === "[object Number]";
1873 }
1874
1875 function isUndefined(value) {
1876 return value === undefined;
1877 }
1878
1879 function max(array, valback) {
1880 if (!isArrayLike(array) || array.length < 1) {
1881 return undefined;
1882 }
1883
1884 if (valback) {
1885 var maxIndex = 0,
1886 maxValue = valback(array[0], 0),
1887 temp;
1888
1889 for (var index = 1; index < array.length; index++) {
1890 temp = valback(array[index], index);
1891
1892 if (temp > maxValue) {
1893 maxValue = temp;
1894 maxIndex = index;
1895 }
1896 }
1897
1898 return array[maxIndex];
1899 } else {
1900 var _maxIndex = 0;
1901
1902 for (var _index = 1; _index < array.length; _index++) {
1903 if (array[_index] > array[_maxIndex]) {
1904 _maxIndex = _index;
1905 }
1906 }
1907
1908 return array[_maxIndex];
1909 }
1910 }
1911
1912 function min(array, valback) {
1913 if (!isArrayLike(array) || array.length < 1) {
1914 return undefined;
1915 }
1916
1917 if (valback) {
1918 var minIndex = 0,
1919 minValue = valback(array[0], 0),
1920 temp;
1921
1922 for (var index = 1; index < array.length; index++) {
1923 temp = valback(array[index], index);
1924
1925 if (temp < minValue) {
1926 minValue = temp;
1927 minIndex = index;
1928 }
1929 }
1930
1931 return array[minIndex];
1932 } else {
1933 var _minIndex = 0;
1934
1935 for (var _index2 = 1; _index2 < array.length; _index2++) {
1936 if (array[_index2] < array[_minIndex]) {
1937 _minIndex = _index2;
1938 }
1939 }
1940
1941 return array[_minIndex];
1942 }
1943 }
1944
1945 function isKey(value, object) {
1946 if (Array.isArray(value)) {
1947 return false;
1948 }
1949
1950 var type = _typeof(value);
1951
1952 if (type == "number" || type == "boolean" || value == null || isSymbol(value)) {
1953 return true;
1954 }
1955
1956 return object !== null && value in Object(object) || /^\w*$/.test(value);
1957 }
1958
1959 function stringToPath(value) {
1960 return value.replace(/\[/g, ".").replace(/\]/g, "").replace(/"/g, "").replace(/'/g, "").split(".");
1961 }
1962
1963 function castPath(value, object) {
1964 if (Array.isArray(value)) {
1965 return value;
1966 }
1967
1968 return isKey(value, object) ? [value] : stringToPath(value);
1969 }
1970
1971 var INFINITY$1 = 1 / 0;
1972
1973 function toKey(value) {
1974 if (typeof value === "string" || isSymbol(value)) {
1975 return value;
1976 }
1977
1978 var result = "".concat(value);
1979 return result === "0" && 1 / value === -INFINITY$1 ? "-0" : result;
1980 }
1981
1982 function baseGet(object, path) {
1983 path = castPath(path, object);
1984 var index = 0;
1985
1986 for (; index < path.length && object !== null; index++) {
1987 object = object[toKey(path[index])];
1988 }
1989
1990 return index && index === path.length ? object : undefined;
1991 }
1992
1993 function get(object, path, defaultValue) {
1994 var result = object == null ? undefined : baseGet(object, path);
1995 return result === undefined ? defaultValue : result;
1996 }
1997
1998 function baseAssignValue(object, key, value) {
1999 if (key == "__proto__") {
2000 Object.defineProperty(object, key, {
2001 configurable: true,
2002 enumerable: true,
2003 value: value,
2004 writable: true
2005 });
2006 } else {
2007 object[key] = value;
2008 }
2009 }
2010
2011 function assignValue(object, key, value) {
2012 baseAssignValue(object, key, value);
2013 }
2014
2015 function baseSet(object, path, value, customizer) {
2016 if (!isObject(object)) {
2017 return object;
2018 }
2019
2020 path = castPath(path, object);
2021 var nested = object;
2022
2023 for (var index = 0; index < path.length; index++) {
2024 var key = toKey(path[index]);
2025 var newValue = value;
2026
2027 if (index + 1 != path.length) {
2028 var objValue = nested[key];
2029
2030 if (!isObject(objValue)) {
2031 newValue = customizer ? customizer(objValue, key, nested) : undefined;
2032
2033 if (newValue === undefined) {
2034 newValue = {};
2035 }
2036 } else {
2037 newValue = objValue;
2038 }
2039 }
2040
2041 assignValue(nested, key, newValue);
2042 nested = nested[key];
2043 }
2044
2045 return object;
2046 }
2047
2048 function set(object, path, value, customizer) {
2049 customizer = typeof customizer === "function" ? customizer : undefined;
2050 return object == null ? object : baseSet(object, path, value, customizer);
2051 }
2052
2053 function split(str, splitStr) {
2054 str = toString$1(str);
2055 var resultArray = [],
2056 temp = str.split(splitStr);
2057
2058 for (var i = 0; i < temp.length; i++) {
2059 temp[i] = temp[i].trim();
2060
2061 if (temp[i] != "") {
2062 resultArray.push(temp[i]);
2063 }
2064 }
2065
2066 return resultArray;
2067 }
2068
2069 var $timers = [];
2070 var $interval = 13;
2071 var $speeds = 400;
2072 var $timerId = null;
2073
2074 function animation(doback, duration, callback) {
2075 var clock = {
2076 timer: function timer(tick, duration, callback) {
2077 if (!tick) {
2078 throw new Error("Tick is required!");
2079 }
2080
2081 duration = duration || $speeds;
2082 var id = new Date().valueOf() + "_" + (Math.random() * 1e3).toFixed(0);
2083 $timers.push({
2084 id: id,
2085 createTime: new Date(),
2086 tick: tick,
2087 duration: duration,
2088 callback: callback
2089 });
2090 clock.start();
2091 return id;
2092 },
2093 start: function start() {
2094 if (!$timerId) {
2095 $timerId = setInterval(clock.tick, $interval);
2096 }
2097 },
2098 tick: function tick() {
2099 var createTime,
2100 flag,
2101 tick,
2102 callback,
2103 timer,
2104 duration,
2105 passTime,
2106 timers = $timers;
2107 $timers = [];
2108 $timers.length = 0;
2109
2110 for (flag = 0; flag < timers.length; flag++) {
2111 timer = timers[flag];
2112 createTime = timer.createTime;
2113 tick = timer.tick;
2114 duration = timer.duration;
2115 callback = timer.callback;
2116 passTime = (+new Date() - createTime) / duration;
2117 passTime = passTime > 1 ? 1 : passTime;
2118 tick(passTime);
2119
2120 if (passTime < 1 && timer.id) {
2121 $timers.push(timer);
2122 } else if (callback) {
2123 callback(passTime);
2124 }
2125 }
2126
2127 if ($timers.length <= 0) {
2128 clock.stop();
2129 }
2130 },
2131 stop: function stop() {
2132 if ($timerId) {
2133 clearInterval($timerId);
2134 $timerId = null;
2135 }
2136 }
2137 };
2138 var id = clock.timer(function (deep) {
2139 doback(deep);
2140 }, duration, callback);
2141 return function () {
2142 var i;
2143
2144 for (i in $timers) {
2145 if ($timers[i].id == id) {
2146 $timers[i].id = undefined;
2147 return;
2148 }
2149 }
2150 };
2151 }
2152
2153 function initConfig(init, data) {
2154 for (var key in data) {
2155 try {
2156 init[key] = data[key];
2157 } catch (e) {
2158 throw new Error("Illegal property value!");
2159 }
2160 }
2161
2162 return init;
2163 }
2164
2165 function Hermite(config) {
2166 config = initConfig({
2167 u: .5
2168 }, config);
2169 var MR, a, b;
2170
2171 var hermite = function hermite(x) {
2172 if (MR) {
2173 var sx = (x - a) / (b - a),
2174 sx2 = sx * sx,
2175 sx3 = sx * sx2;
2176 var sResult = sx3 * MR[0] + sx2 * MR[1] + sx * MR[2] + MR[3];
2177 return sResult * (b - a);
2178 } else throw new Error("You shoud first set the position!");
2179 };
2180
2181 hermite.setP = function (x1, y1, x2, y2, s1, s2) {
2182 if (x1 < x2) {
2183 a = x1;
2184 b = x2;
2185 var p3 = config.u * s1,
2186 p4 = config.u * s2;
2187 y1 /= x2 - x1;
2188 y2 /= x2 - x1;
2189 MR = [2 * y1 - 2 * y2 + p3 + p4, 3 * y2 - 3 * y1 - 2 * p3 - p4, p3, y1];
2190 } else throw new Error("The point x-position should be increamented!");
2191
2192 return hermite;
2193 };
2194
2195 return hermite;
2196 }
2197
2198 var dictionary = (_dictionary = {
2199 48: [0, ")"],
2200 49: [1, "!"],
2201 50: [2, "@"],
2202 51: [3, "#"],
2203 52: [4, "$"],
2204 53: [5, "%"],
2205 54: [6, "^"],
2206 55: [7, "&"],
2207 56: [8, "*"],
2208 57: [9, "("],
2209 96: [0, 0],
2210 97: 1,
2211 98: 2,
2212 99: 3,
2213 100: 4,
2214 101: 5,
2215 102: 6,
2216 103: 7,
2217 104: 8,
2218 105: 9,
2219 106: "*",
2220 107: "+",
2221 109: "-",
2222 110: ".",
2223 111: "/",
2224 65: ["a", "A"],
2225 66: ["b", "B"],
2226 67: ["c", "C"],
2227 68: ["d", "D"],
2228 69: ["e", "E"],
2229 70: ["f", "F"],
2230 71: ["g", "G"],
2231 72: ["h", "H"],
2232 73: ["i", "I"],
2233 74: ["j", "J"],
2234 75: ["k", "K"],
2235 76: ["l", "L"],
2236 77: ["m", "M"],
2237 78: ["n", "N"],
2238 79: ["o", "O"],
2239 80: ["p", "P"],
2240 81: ["q", "Q"],
2241 82: ["r", "R"],
2242 83: ["s", "S"],
2243 84: ["t", "T"],
2244 85: ["u", "U"],
2245 86: ["v", "V"],
2246 87: ["w", "W"],
2247 88: ["x", "X"],
2248 89: ["y", "Y"],
2249 90: ["z", "Z"],
2250 37: "left",
2251 38: "up",
2252 39: "right",
2253 40: "down",
2254 33: "page up",
2255 34: "page down",
2256 35: "end",
2257 36: "home",
2258 16: "shift",
2259 17: "ctrl",
2260 18: "alt",
2261 91: "command",
2262 92: "command",
2263 93: "command",
2264 9: "tab",
2265 20: "caps lock",
2266 32: "spacebar",
2267 8: "backspace",
2268 13: "enter",
2269 27: "esc",
2270 46: "delete",
2271 45: "insert",
2272 144: "number lock",
2273 145: "scroll lock",
2274 12: "clear"
2275 }, _defineProperty(_dictionary, "45", "insert"), _defineProperty(_dictionary, 19, "pause"), _defineProperty(_dictionary, 112, "f1"), _defineProperty(_dictionary, 113, "f2"), _defineProperty(_dictionary, 114, "f3"), _defineProperty(_dictionary, 115, "f4"), _defineProperty(_dictionary, 116, "f5"), _defineProperty(_dictionary, 117, "f6"), _defineProperty(_dictionary, 118, "f7"), _defineProperty(_dictionary, 119, "f8"), _defineProperty(_dictionary, 120, "f9"), _defineProperty(_dictionary, 121, "f10"), _defineProperty(_dictionary, 122, "f11"), _defineProperty(_dictionary, 123, "f12"), _defineProperty(_dictionary, 189, ["-", "_"]), _defineProperty(_dictionary, 187, ["=", "+"]), _defineProperty(_dictionary, 219, ["[", "{"]), _defineProperty(_dictionary, 221, ["]", "}"]), _defineProperty(_dictionary, 220, ["\\", "|"]), _defineProperty(_dictionary, 186, [";", ":"]), _defineProperty(_dictionary, 222, ["'", '"']), _defineProperty(_dictionary, 188, [",", "<"]), _defineProperty(_dictionary, 190, [".", ">"]), _defineProperty(_dictionary, 191, ["/", "?"]), _defineProperty(_dictionary, 192, ["`", "~"]), _dictionary);
2276 var help_key = ["shift", "ctrl", "alt"];
2277
2278 function keyString(event) {
2279 event = event || window.event;
2280 var keycode = event.keyCode || event.which;
2281 var key = dictionary[keycode] || keycode;
2282 if (!key) return;
2283 if (key.constructor !== Array) key = [key, key];
2284 var shift = event.shiftKey ? "shift+" : "",
2285 alt = event.altKey ? "alt+" : "",
2286 ctrl = event.ctrlKey ? "ctrl+" : "";
2287 var resultKey = "",
2288 preKey = ctrl + shift + alt;
2289
2290 if (help_key.indexOf(key[0]) >= 0) {
2291 key[0] = key[1] = "";
2292 }
2293
2294 var lockPress = event.code == "Key" + event.key && !shift;
2295 resultKey = preKey + (preKey == "" && lockPress ? key[1] : key[0]);
2296
2297 if (key[0] == "") {
2298 resultKey = resultKey.replace(/\+$/, "");
2299 }
2300
2301 return resultKey;
2302 }
2303
2304 function _move(d, a, b, c) {
2305 c = c || 0;
2306 var sqrt = Math.sqrt(a * a + b * b + c * c);
2307 return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, a * d / sqrt, b * d / sqrt, c * d / sqrt, 1];
2308 }
2309
2310 function _rotate(deg) {
2311 var sin = Math.sin(deg),
2312 cos = Math.cos(deg);
2313 return [cos, sin, 0, 0, -sin, cos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
2314 }
2315
2316 function _scale(xTimes, yTimes, zTimes, cx, cy, cz) {
2317 cx = cx || 0;
2318 cy = cy || 0;
2319 cz = cz || 0;
2320 return [xTimes, 0, 0, 0, 0, yTimes, 0, 0, 0, 0, zTimes, 0, cx - cx * xTimes, cy - cy * yTimes, cz - cz * zTimes, 1];
2321 }
2322
2323 function _transform(a1, b1, c1, a2, b2, c2) {
2324 if (typeof a1 === "number" && typeof b1 === "number") {
2325 if (typeof c1 !== "number") {
2326 c1 = 0;
2327 a2 = a1;
2328 b2 = b1;
2329 c2 = 1;
2330 } else if (typeof a2 !== "number" || typeof b2 !== "number" || typeof c2 !== "number") {
2331 a2 = a1;
2332 b2 = b1;
2333 c2 = c1;
2334 a1 = 0;
2335 b1 = 0;
2336 c1 = 0;
2337 }
2338
2339 if (a1 == a2 && b1 == b2 && c1 == c2) throw new Error("It's not a legitimate ray!");
2340 var sqrt1 = Math.sqrt((a2 - a1) * (a2 - a1) + (b2 - b1) * (b2 - b1)),
2341 cos1 = sqrt1 != 0 ? (b2 - b1) / sqrt1 : 1,
2342 sin1 = sqrt1 != 0 ? (a2 - a1) / sqrt1 : 0,
2343 b = (a2 - a1) * sin1 + (b2 - b1) * cos1,
2344 c = c2 - c1,
2345 sqrt2 = Math.sqrt(b * b + c * c),
2346 cos2 = sqrt2 != 0 ? c / sqrt2 : 1,
2347 sin2 = sqrt2 != 0 ? b / sqrt2 : 0;
2348 return [[cos1, cos2 * sin1, sin1 * sin2, 0, -sin1, cos1 * cos2, cos1 * sin2, 0, 0, -sin2, cos2, 0, b1 * sin1 - a1 * cos1, c1 * sin2 - a1 * sin1 * cos2 - b1 * cos1 * cos2, -a1 * sin1 * sin2 - b1 * cos1 * sin2 - c1 * cos2, 1], [cos1, -sin1, 0, 0, cos2 * sin1, cos2 * cos1, -sin2, 0, sin1 * sin2, cos1 * sin2, cos2, 0, a1, b1, c1, 1]];
2349 } else {
2350 throw new Error("a1 and b1 is required!");
2351 }
2352 }
2353
2354 var _multiply = function _multiply(matrix4, param) {
2355 var newParam = [];
2356
2357 for (var i = 0; i < 4; i++) {
2358 for (var j = 0; j < param.length / 4; j++) {
2359 newParam[j * 4 + i] = matrix4[i] * param[j * 4] + matrix4[i + 4] * param[j * 4 + 1] + matrix4[i + 8] * param[j * 4 + 2] + matrix4[i + 12] * param[j * 4 + 3];
2360 }
2361 }
2362
2363 return newParam;
2364 };
2365
2366 function Matrix4(initMatrix4) {
2367 var matrix4 = initMatrix4 || [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
2368 var matrix4Obj = {
2369 move: function move(dis, a, b, c) {
2370 matrix4 = _multiply(_move(dis, a, b, c), matrix4);
2371 return matrix4Obj;
2372 },
2373 rotate: function rotate(deg, a1, b1, c1, a2, b2, c2) {
2374 var matrix4s = _transform(a1, b1, c1, a2, b2, c2);
2375
2376 matrix4 = _multiply(_multiply(_multiply(matrix4s[1], _rotate(deg)), matrix4s[0]), matrix4);
2377 return matrix4Obj;
2378 },
2379 scale: function scale(xTimes, yTimes, zTimes, cx, cy, cz) {
2380 matrix4 = _multiply(_scale(xTimes, yTimes, zTimes, cx, cy, cz), matrix4);
2381 return matrix4Obj;
2382 },
2383 multiply: function multiply(newMatrix4, flag) {
2384 matrix4 = flag ? _multiply(matrix4, newMatrix4) : _multiply(newMatrix4, matrix4);
2385 return matrix4Obj;
2386 },
2387 use: function use(x, y, z, w) {
2388 z = z || 0;
2389 w = w || 1;
2390
2391 var temp = _multiply(matrix4, [x, y, z, w]);
2392
2393 temp[0] = +temp[0].toFixed(7);
2394 temp[1] = +temp[1].toFixed(7);
2395 temp[2] = +temp[2].toFixed(7);
2396 temp[3] = +temp[3].toFixed(7);
2397 return temp;
2398 },
2399 value: function value() {
2400 return matrix4;
2401 }
2402 };
2403 return matrix4Obj;
2404 }
2405
2406 function tree(_config) {
2407 var config = _config || {},
2408 alltreedata,
2409 rootid;
2410
2411 var update = function update() {
2412 var beforeDis = [],
2413 size = 0,
2414 maxDeep = 0;
2415
2416 (function positionCalc(pNode, deep) {
2417 if (deep > maxDeep) maxDeep = deep;
2418 var flag;
2419
2420 for (flag = 0; flag < pNode.children.length; flag++) {
2421 positionCalc(alltreedata[pNode.children[flag]], deep + 1);
2422 }
2423
2424 alltreedata[pNode.id].left = deep + .5;
2425
2426 if (flag == 0) {
2427 if (beforeDis[deep] == undefined) beforeDis[deep] = -.5;
2428 if (beforeDis[deep - 1] == undefined) beforeDis[deep - 1] = -.5;
2429 alltreedata[pNode.id].top = beforeDis[deep] + 1;
2430 var pTop = beforeDis[deep] + 1 + (alltreedata[pNode.pid].children.length - 1) * .5;
2431 if (pTop - 1 < beforeDis[deep - 1]) alltreedata[pNode.id].top = beforeDis[deep - 1] + 1 - (alltreedata[pNode.pid].children.length - 1) * .5;
2432 } else {
2433 alltreedata[pNode.id].top = (alltreedata[pNode.children[0]].top + alltreedata[pNode.children[flag - 1]].top) * .5;
2434 }
2435
2436 if (alltreedata[pNode.id].top <= beforeDis[deep]) {
2437 var needUp = beforeDis[deep] + 1 - alltreedata[pNode.id].top;
2438
2439 (function doUp(_pid, _deep) {
2440 alltreedata[_pid].top += needUp;
2441 if (beforeDis[_deep] < alltreedata[_pid].top) beforeDis[_deep] = alltreedata[_pid].top;
2442
2443 var _flag;
2444
2445 for (_flag = 0; _flag < alltreedata[_pid].children.length; _flag++) {
2446 doUp(alltreedata[_pid].children[_flag], _deep + 1);
2447 }
2448 })(pNode.id, deep);
2449 }
2450
2451 beforeDis[deep] = alltreedata[pNode.id].top;
2452 if (alltreedata[pNode.id].top + .5 > size) size = alltreedata[pNode.id].top + .5;
2453 })(alltreedata[rootid], 0);
2454
2455 return {
2456 node: alltreedata,
2457 root: rootid,
2458 size: size,
2459 deep: maxDeep + 1
2460 };
2461 };
2462
2463 var toInnerTree = function toInnerTree(initTree) {
2464 var tempTree = {};
2465 var temp = config.root(initTree),
2466 id,
2467 rid;
2468 id = rid = config.id(temp);
2469 tempTree[id] = {
2470 data: temp,
2471 pid: null,
2472 id: id,
2473 children: []
2474 };
2475
2476 (function createTree(pdata, pid) {
2477 var children = config.child(pdata, initTree),
2478 flag;
2479
2480 for (flag = 0; children && flag < children.length; flag++) {
2481 id = config.id(children[flag]);
2482 tempTree[pid].children.push(id);
2483 tempTree[id] = {
2484 data: children[flag],
2485 pid: pid,
2486 id: id,
2487 children: []
2488 };
2489 createTree(children[flag], id);
2490 }
2491 })(temp, id);
2492
2493 return [rid, tempTree];
2494 };
2495
2496 var tree = function tree(initTree) {
2497 var treeData = toInnerTree(initTree);
2498 alltreedata = treeData[1];
2499 rootid = treeData[0];
2500 return update();
2501 };
2502
2503 tree.root = function (rootback) {
2504 config.root = rootback;
2505 return tree;
2506 };
2507
2508 tree.child = function (childback) {
2509 config.child = childback;
2510 return tree;
2511 };
2512
2513 tree.id = function (idback) {
2514 config.id = idback;
2515 return tree;
2516 };
2517
2518 return tree;
2519 }
2520
2521 var __ = {
2522 concat: concat$1,
2523 indexOf: indexOf,
2524 lastIndexOf: lastIndexOf,
2525 unique: unique,
2526 eq: eq,
2527 toString: toString$1,
2528 isObject: isObject,
2529 isSymbol: isSymbol,
2530 isString: isString,
2531 isBoolean: isBoolean,
2532 isElement: isElement,
2533 isText: isText,
2534 isFunction: isFunction,
2535 isError: isError,
2536 isNull: isNull,
2537 isNumber: isNumber,
2538 isUndefined: isUndefined,
2539 isArray: isArray,
2540 max: max,
2541 min: min,
2542 get: get,
2543 set: set,
2544 split: split,
2545 animation: animation,
2546 Hermite: Hermite,
2547 keyString: keyString,
2548 Matrix4: Matrix4,
2549 tree: tree
2550 };
2551
2552 if (_typeof(module) === "object" && _typeof(module.exports) === "object") {
2553 module.exports = __;
2554 } else {
2555 var $__ = window.__;
2556
2557 __.noConflict = function (deep) {
2558 if (window.__ === __) {
2559 window.__ = $__;
2560 }
2561
2562 return __;
2563 };
2564
2565 window.__ = __;
2566 }
2567 })();
2568 });
2569 var blanksReg = _RegExp.blanksReg; // 分析结点的属性
2570
2571 var analyseTag = function analyseTag(attrString) {
2572 var attr = {},
2573 index = 0;
2574 attrString = attrString.trim();
2575
2576 var getOneAttr = function getOneAttr() {
2577 // 属性名和属性值
2578 var attrName = "",
2579 attrValue = ""; // 先寻找属性名
2580
2581 for (; index < attrString.length; index++) {
2582 // 寻找属性名的时候遇到空白或结尾的时候,肯定没有属性值
2583 if (blanksReg.test(attrString[index]) || index == attrString.length - 1) {
2584 attrName += attrString[index]; // 如果属性名是空白,就不需要记录了
2585
2586 if (!blanksReg.test(attrName)) {
2587 attr[attrName.trim()] = "";
2588 }
2589
2590 index += 1;
2591 break;
2592 } // 如果遇到等号,说明属性名寻找结束了
2593 else if (attrString[index] == '=') {
2594 // 接着寻找属性值
2595 index += 1; // 由于属性可能由引号包裹或直接暴露
2596
2597 var preCode = null,
2598 preLeng = -1; // 如果是由'或者"包裹
2599
2600 if (attrString.substr(index, 1) == '"' || attrString.substr(index, 1) == "'") {
2601 preCode = attrString.substr(index, 1);
2602 preLeng = 1;
2603 index += 1;
2604 } // 如果是由\'或\"包裹
2605 else if (attrString.substr(index, 2) == '\"' || attrString.substr(index, 2) == "\'") {
2606 preCode = attrString.substr(index, 2);
2607 preLeng = 2;
2608 index += 2;
2609 } // 开始正式寻找属性值
2610 // 如果没有包裹,是直接暴露在外面的
2611 // 我们寻找到空格或结尾即可
2612
2613
2614 if (preCode !== null) {
2615 for (; index < attrString.length; index++) {
2616 if (attrString.substr(index, preLeng) == preCode) {
2617 attr[attrName.trim()] = attrValue.trim();
2618 index += 2;
2619 break;
2620 } else {
2621 attrValue += attrString[index];
2622 }
2623 }
2624 } // 如果是包裹的
2625 // 我们确定寻找到对应的包裹闭合即可
2626 else {
2627 for (; index < attrString.length; index++) {
2628 if (blanksReg.test(attrString[index])) {
2629 attr[attrName.trim()] = attrValue.trim();
2630 index += 1;
2631 break;
2632 } else {
2633 attrValue += attrString[index];
2634 }
2635 }
2636 }
2637
2638 break;
2639 } else {
2640 attrName += attrString[index];
2641 }
2642 } // 如果还有字符串,继续解析
2643
2644
2645 if (index < attrString.length) {
2646 getOneAttr();
2647 }
2648 };
2649
2650 getOneAttr();
2651 return attr;
2652 };
2653
2654 var blankReg = _RegExp.blankReg,
2655 blanksReg$1 = _RegExp.blanksReg;
2656
2657 var nextTag = function nextTag(template) {
2658 var i = -1,
2659 // 当前面对的字符
2660 currentChar = null; // 如果前面是获取的js或css,还有pre等开始标签,比较特殊,直接寻址闭合的
2661
2662 var preIsSpecial = false,
2663 specialCode = "";
2664 var specialTag = ['script', 'pre', 'style', 'code']; // 获取下一个字符
2665
2666 var next = function next() {
2667 currentChar = i++ < template.length - 1 ? template[i] : null;
2668 return currentChar;
2669 }; // 获取往后n个值
2670
2671
2672 var nextNValue = function nextNValue(n) {
2673 return template.substring(i, n + i > template.length ? template.length : n + i);
2674 };
2675
2676 next(); // 剔除开头的空白
2677
2678 while (blankReg.test(currentChar) && i < template.length - 1) {
2679 next();
2680 }
2681 /**
2682 * 一个Tag存在哪些类型?如下:
2683 * 1.<tag-name> { tagName:'tag-name', type:'beginTag', attrs:{} } 开始标签
2684 * 2.</tag-name> { tagName:'tag-name', type:'endTag' } 结束标签
2685 * 3.<tag-name /> { tagName:'tag-name', type:'fullTag', attrs:{} } 自闭合标签
2686 * 4.text { tagName:'text', type:'textcode' } 文本结点
2687 * 5.<!-- text --> { tagName:'text', type:'comment' } 注释
2688 * 6.<!DOCTYPE text> { tagName:'text', type:'DOCTYPE' } 声明
2689 *
2690 *
2691 */
2692
2693
2694 return function () {
2695 var tag = currentChar,
2696 tagObj = {};
2697 if (tag == null) return null;
2698 /**
2699 * 特殊标签内容获取
2700 * ========================================
2701 */
2702 // 如果是获取特殊标签里面的内容
2703 // 先不考虑里面包含'</XXX>'
2704
2705 if (preIsSpecial) {
2706 tagObj.type = 'textcode';
2707 tagObj.tagName = tag;
2708
2709 while (nextNValue(specialCode.length + 3) != '</' + specialCode + '>' && i < template.length) {
2710 tagObj.tagName += next();
2711 }
2712
2713 tagObj.tagName = tagObj.tagName.replace(/<$/, '');
2714 preIsSpecial = false;
2715 return tagObj;
2716 }
2717 /**
2718 * 特殊标签获取
2719 * ========================================
2720 */
2721 // 针对特殊的comment
2722
2723
2724 if (nextNValue(4) == '<!--') {
2725 tagObj.type = 'comment';
2726 tagObj.tagName = tag;
2727
2728 while (nextNValue(3) != '-->' && i < template.length) {
2729 tagObj.tagName += next();
2730 }
2731
2732 next();
2733 next();
2734 next();
2735 tagObj.tagName = tagObj.tagName.replace(/^<!--/, '').replace(/-$/, '');
2736 return tagObj;
2737 } // 针对特殊的doctype
2738
2739
2740 if (nextNValue(9) == '<!DOCTYPE') {
2741 tagObj.type = 'DOCTYPE';
2742 tagObj.tagName = tag;
2743
2744 while (nextNValue(1) != '>' && i < template.length) {
2745 tagObj.tagName += next();
2746 }
2747
2748 next();
2749 tagObj.tagName = tagObj.tagName.replace(/^<!DOCTYPE/, '').replace(/>$/, '');
2750 return tagObj;
2751 }
2752 /**
2753 * 普通的
2754 * ========================================
2755 */
2756 // 如果是期望归结非文本结点
2757 else if (tag == '<') {
2758 // 标记是否处于属性值是字符串包裹中
2759 var isAttrString = false,
2760 attrLeftValue = null,
2761 attrLeftLen = null; // 如果在包裹中或者没有遇到‘>’说明没有结束
2762
2763 while (isAttrString || currentChar != '>' && i < template.length) {
2764 tag += next(); // 如果是包裹里面,试探是否即将遇到了结束
2765
2766 if (isAttrString) {
2767 var next23Value = nextNValue(attrLeftLen + 1).substring(1);
2768
2769 if (next23Value == attrLeftValue) {
2770 isAttrString = false;
2771 }
2772 } // 如果在包裹外面,试探是否即将进入包裹
2773 else {
2774 var _next23Value = nextNValue(2);
2775
2776 if (_next23Value == '="' || _next23Value == "='") {
2777 attrLeftValue = _next23Value.replace('=', '');
2778 attrLeftLen = 1;
2779 isAttrString = true;
2780 }
2781
2782 _next23Value = nextNValue(3);
2783
2784 if (_next23Value == '=\"' || _next23Value == "=\'") {
2785 attrLeftValue = _next23Value.replace('=', '');
2786 attrLeftLen = 2;
2787 isAttrString = true;
2788 }
2789 }
2790 } // 针对特殊的结束标签
2791
2792
2793 if (/^<\//.test(tag)) {
2794 tagObj.tagName = tag.replace(/^<\//, '').replace(/>$/, '');
2795 tagObj.type = 'endTag';
2796 } else {
2797 if (/\/>$/.test(tag)) {
2798 tagObj.type = 'fullTag';
2799 tag = tag.replace(/\/>$/, '');
2800 } else {
2801 tagObj.type = 'beginTag';
2802 tag = tag.replace(/>$/, '');
2803 }
2804
2805 tag = tag.replace(/^</, '');
2806 tagObj.tagName = "";
2807 var _i = 0;
2808
2809 for (; _i < tag.length; _i++) {
2810 if (tag[_i] == ' ') break;
2811 tagObj.tagName += tag[_i];
2812 }
2813
2814 var attrString = tag.substring(_i);
2815
2816 if (blanksReg$1.test(attrString)) {
2817 tagObj.attrs = {};
2818 } else {
2819 tagObj.attrs = analyseTag(attrString);
2820 }
2821 }
2822 } // 如果是归结文本结点
2823 // 如果文本中包含<的先忽略考虑
2824 else {
2825 tagObj.type = 'textcode';
2826 tagObj.tagName = currentChar;
2827
2828 while (nextNValue(1) != '<' && i < template.length) {
2829 tagObj.tagName += next();
2830 }
2831
2832 tagObj.tagName = tagObj.tagName.replace(/<$/, '');
2833 i -= 1;
2834 } // 如果遇到开始script或者style、pre等特殊标签,标记开始获取特殊文本
2835
2836
2837 if (tagObj.type == 'beginTag') {
2838 if (specialTag.indexOf(tagObj.tagName.toLowerCase()) > -1) {
2839 preIsSpecial = true;
2840 specialCode = tagObj.tagName;
2841 }
2842 } // 如果遇到结束script或者style、pre等特殊标签,标记结束获取特殊文本
2843 else if (tagObj.type == 'endTag') {
2844 if (specialTag.indexOf(tagObj.tagName.toLowerCase()) > -1) {
2845 preIsSpecial = false;
2846 }
2847 }
2848
2849 next();
2850 return tagObj;
2851 };
2852 }; // 分析deep
2853 // 我们会在这里校对那些没有结束标签的开始标签
2854 // 这步结束以后,每个都是一个单独的标签
2855 // 也就是不用再区分开始或闭合了
2856
2857
2858 var analyseDeep = function analyseDeep(tagArray) {
2859 // 闭合标签
2860 tagArray = closeTag(tagArray);
2861 var deep = 0,
2862 tagDeepArray = [];
2863 tagArray.forEach(function (tag) {
2864 if (tag.type == 'beginTag') {
2865 tagDeepArray.push({
2866 type: "tag",
2867 name: tag.tagName,
2868 attrs: tag.attrs,
2869 __deep__: ++deep,
2870 __tagType__: "double"
2871 });
2872 } else if (tag.type == 'endTag') {
2873 deep -= 1;
2874 } else if (tag.type == 'textcode') {
2875 // 如果是文本
2876 tagDeepArray.push({
2877 type: "text",
2878 content: tag.tagName,
2879 __deep__: deep + 1
2880 });
2881 } else if (tag.type == 'comment') {
2882 // 如果是注释
2883 tagDeepArray.push({
2884 type: "comment",
2885 content: tag.tagName,
2886 __deep__: deep + 1
2887 });
2888 } else {
2889 // 如果是自闭合结点
2890 tagDeepArray.push({
2891 type: "tag",
2892 name: tag.tagName,
2893 attrs: tag.attrs,
2894 __deep__: deep + 1,
2895 __tagType__: "single"
2896 });
2897 }
2898 });
2899 return tagDeepArray;
2900 }; // 标记所有没有闭合结点的直接自闭合
2901
2902
2903 var closeTag = function closeTag(tagArray) {
2904 var needClose = [];
2905 tagArray.forEach(function (tag, i) {
2906 if (tag.type == 'beginTag') {
2907 needClose.push([i, tag.tagName]);
2908 } else if (tag.type == 'endTag') {
2909 while (needClose.length > 0) {
2910 var needCloseTag = needClose.pop();
2911
2912 if (needCloseTag[1] == tag.tagName) {
2913 break;
2914 } else {
2915 tagArray[needCloseTag[0]].type = 'fullTag';
2916 }
2917 }
2918 }
2919 });
2920 return tagArray;
2921 };
2922
2923 var blanksReg$2 = _RegExp.blanksReg; // 获取一棵DOM树
2924 // noIgnore为true表示不忽略任何标签
2925
2926 var DomTree = function DomTree(template, noIgnore) {
2927 if (!core_min.isString(template)) throw new Error("Template must be a String!"); // 获取读取下一个标签对象
2928
2929 var nextTag$1 = nextTag(template);
2930 var tag = nextTag$1(),
2931 DomTree = [];
2932
2933 while (tag != null) {
2934 if (tag.type == 'textcode' && blanksReg$2.test(tag.tagName)) ;else if (tag.type == 'DOCTYPE') ;else if (tag.type == 'comment') {
2935 // 注释目前也默认过滤掉,除非显示声明不忽略
2936 if (noIgnore) {
2937 DomTree.push(tag);
2938 }
2939 } else {
2940 DomTree.push(tag);
2941 }
2942 tag = nextTag$1();
2943 } // 分析层次
2944
2945
2946 DomTree = analyseDeep(DomTree);
2947 /**
2948 * 模仿浏览器构建的一棵树,每个节点有如下属性:
2949 *
2950 * 1.parentNode index 父结点
2951 * 2.childNodes [] 孩子结点
2952 * 3.preNode index 前一个兄弟结点
2953 * 4.nextNode index 后一个兄弟结点
2954 *
2955 * 5.attrs:{} 当前结点的属性
2956 * 6.name 节点名称
2957 * 7.type 节点类型(tag和text)
2958 * 8.content 文本结点内容
2959 *
2960 * 需要注意的是:如果一个文本结点内容只包含回车,tab,空格等空白字符,会直接被忽视
2961 */
2962
2963 var presNode = [null],
2964 preDeep = 0;
2965
2966 for (var i = 0; i < DomTree.length; i++) {
2967 // 当前结点
2968 var currentIndex = i,
2969 currentDeep = DomTree[i].__deep__;
2970 DomTree[i].childNodes = [];
2971 DomTree[i].preNode = null;
2972 DomTree[i].nextNode = null; // 前置三个结点
2973
2974 var lastPre = presNode[presNode.length - 1];
2975 var last2Pre = presNode.length > 1 ? presNode[presNode.length - 2] : null; // 如果遇到的是兄弟结点
2976
2977 if (currentDeep == preDeep) {
2978 // 修改兄弟关系
2979 DomTree[currentIndex].preNode = lastPre;
2980 DomTree[lastPre].nextNode = currentIndex; // 修改父子关系
2981
2982 DomTree[currentIndex].parentNode = last2Pre;
2983 DomTree[last2Pre].childNodes.push(currentIndex); // 校对presNode
2984
2985 presNode[presNode.length - 1] = currentIndex;
2986 } // 如果是遇到了孩子
2987 else if (currentDeep > preDeep) {
2988 // 修改兄弟关系
2989 // todo
2990 // 修改父子关系
2991 DomTree[currentIndex].parentNode = lastPre;
2992 if (lastPre != null) DomTree[lastPre].childNodes.push(currentIndex); // 校对presNode
2993
2994 presNode.push(currentIndex);
2995 } // 如果是遇到了祖先
2996 else {
2997 var preTempIndex = presNode[presNode.length - 1 - (preDeep - currentDeep)];
2998 var preTemp2Index = presNode[presNode.length - 2 - (preDeep - currentDeep)]; // 修改兄弟关系
2999
3000 DomTree[currentIndex].preNode = preTempIndex;
3001 if (preTempIndex != null) DomTree[preTempIndex].nextNode = currentIndex; // 修改父子关系
3002
3003 DomTree[currentIndex].parentNode = preTemp2Index;
3004 if (preTemp2Index != null) DomTree[preTemp2Index].childNodes.push(currentIndex); // 校对presNode
3005
3006 for (var _i2 = 0; _i2 < preDeep - currentDeep; _i2++) {
3007 presNode.pop();
3008 }
3009
3010 presNode[presNode.length - 1] = currentIndex;
3011 }
3012
3013 preDeep = currentDeep;
3014 }
3015
3016 return DomTree;
3017 };
3018
3019 function css_format(textString, tabNumber) {
3020 var preNumber = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
3021 var getTabString = getTabStringFactory(tabNumber);
3022 console.warn("[提醒] CSS格式化方法未提供!");
3023 return textString;
3024 }
3025
3026 function javascript_format(textString, tabNumber) {
3027 var preNumber = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
3028 var getTabString = getTabStringFactory(tabNumber);
3029 console.warn("[提醒] JavaScript格式化方法未提供!");
3030 return textString;
3031 }
3032
3033 function html_format(textString, tabNumber) {
3034 // 借助开源项目获得的模板分析结果:git+https://github.com/yelloxing/xhtml-engine.git
3035 var domTree = DomTree("<help-root>" + textString + "</help-root>", true);
3036
3037 if (domTree[domTree.length - 1].type == 'comment') {
3038 domTree[domTree.length - 1].content = domTree[domTree.length - 1].content.replace(/\<\/help\-root\>null$/, '');
3039 }
3040
3041 var getTabString = getTabStringFactory(tabNumber);
3042 /**
3043 * 为了避免使用递归,我们定义一个计算数组needCalcs来登记已经计算过的结果和待计算的内容
3044 * 虽然需要频繁插入,可是感觉问题不大,并且数组的话,方便最后模板的获取
3045 *
3046 * 算法思想:来自深度优先遍历树图
3047 *
3048 */
3049
3050 var needCalcs = domTree[0].childNodes,
3051 index = 0,
3052 currentNode,
3053 attrsString,
3054 needReplace,
3055 preTag = "";
3056
3057 while (index < needCalcs.length) {
3058 // 寻找第一个没有计算的
3059 do {
3060 currentNode = needCalcs[index++];
3061 } while (isString(currentNode));
3062
3063 currentNode = domTree[currentNode];
3064
3065 if (!currentNode) {
3066 break;
3067 }
3068 /**
3069 * 对当前面对的进行处理(计算当前模板)
3070 */
3071 // 如果是标签
3072
3073
3074 if (currentNode.type == 'tag') {
3075 attrsString = ""; // 只有是标签,属性一定存在
3076
3077 for (var key in currentNode.attrs) {
3078 attrsString += "".concat(key, "=\"").concat(currentNode.attrs[key], "\" ");
3079 } // 这种情况稍微麻烦点,需要登记开头和结尾,而且需要插入孩子
3080
3081
3082 if (currentNode.__tagType__ == 'double') {
3083 preTag = currentNode.name;
3084 needReplace = []; // 登记开头
3085
3086 needReplace.push(getTabString(currentNode.__deep__ - 2) + "<".concat(currentNode.name, " ").concat(attrsString, ">")); // 登记孩子
3087
3088 for (var i = 0; i < currentNode.childNodes.length; i++) {
3089 needReplace.push(currentNode.childNodes[i]);
3090 } // 登记结尾
3091
3092
3093 needReplace.push(getTabString(currentNode.__deep__ - 2) + "</".concat(currentNode.name, ">"));
3094 needCalcs.splice.apply(needCalcs, [index - 1, 1].concat(_toConsumableArray2(needReplace)));
3095 } // 如果不是有开始和结束标签的,一定没有孩子
3096 else {
3097 needCalcs[index - 1] = getTabString(currentNode.__deep__ - 2) + "<".concat(currentNode.name, " ").concat(attrsString, "/>");
3098 }
3099 } // 如果是文本
3100 else if (currentNode.type == 'text') {
3101 switch (preTag) {
3102 case "script":
3103 {
3104 needCalcs[index - 1] = javascript_format(currentNode.content.trim(), tabNumber, currentNode.__deep__ - 2);
3105 break;
3106 }
3107
3108 case "style":
3109 {
3110 needCalcs[index - 1] = css_format(currentNode.content.trim(), tabNumber, currentNode.__deep__ - 2);
3111 break;
3112 }
3113
3114 default:
3115 {
3116 needCalcs[index - 1] = getTabString(currentNode.__deep__ - 2) + currentNode.content.trim();
3117 }
3118 }
3119 } // 如果是注释
3120 else if (currentNode.type == 'comment') {
3121 needCalcs[index - 1] = getTabString(currentNode.__deep__ - 2) + "<!-- " + currentNode.content.trim() + " -->";
3122 }
3123 }
3124
3125 return needCalcs.join("\n");
3126 }
3127
3128 function json_shader(textString, colors, notToResult) {
3129 var shaderArray = []; // 当前面对的
3130
3131 var i = 0; // 获取往后n个值
3132
3133 var nextNValue = function nextNValue(n) {
3134 return textString.substring(i, n + i > textString.length ? textString.length : n + i);
3135 };
3136
3137 var template = ""; // 1:选择器 tag
3138 // 2:属性名 attr
3139 // 3:属性值 string
3140
3141 var state = "tag"; // 初始化模板,开始文本捕获
3142
3143 var initTemplate = function initTemplate() {
3144 if (template != "") {
3145 shaderArray.push({
3146 color: colors[state],
3147 content: template
3148 });
3149 }
3150
3151 template = "";
3152 };
3153
3154 while (true) {
3155 /* 1.注释 */
3156 if (nextNValue(2) == '/*') {
3157 initTemplate();
3158
3159 while (nextNValue(2) !== '*/' && i < textString.length) {
3160 template += textString[i++];
3161 }
3162
3163 shaderArray.push({
3164 color: colors.annotation,
3165 content: template + nextNValue(2)
3166 });
3167 i += 2;
3168 template = "";
3169 }
3170 /* 2.字符串 */
3171 else if (["'", '"'].indexOf(nextNValue(1)) > -1) {
3172 var strBorder = nextNValue(1);
3173 initTemplate();
3174
3175 do {
3176 template += textString[i++];
3177 } while (nextNValue(1) != strBorder && i < textString.length); // 因为可能是没有字符导致的结束
3178
3179
3180 if (nextNValue(1) != strBorder) {
3181 strBorder = "";
3182 } else {
3183 i += 1;
3184 }
3185
3186 shaderArray.push({
3187 color: colors.string,
3188 content: template + strBorder
3189 });
3190 template = "";
3191 }
3192 /* 3.边界 */
3193 else if ([":", '{', '}', ",", "[", "]"].indexOf(nextNValue(1)) > -1) {
3194 initTemplate();
3195 shaderArray.push({
3196 color: colors.border,
3197 content: nextNValue(1)
3198 });
3199 template = "";
3200
3201 if (nextNValue(1) == '{' || nextNValue(1) == ',') {
3202 state = 'attr';
3203 } else if (nextNValue(1) == '}') {
3204 state = 'tag';
3205 } else {
3206 state = 'string';
3207 }
3208
3209 i += 1;
3210 }
3211 /* 追加字符 */
3212 else {
3213 if (i >= textString.length) {
3214 initTemplate();
3215 break;
3216 } else {
3217 template += textString[i++];
3218 }
3219 }
3220 }
3221
3222 return notToResult ? shaderArray : toShaderReult(shaderArray);
3223 } // 温馨提示:只支持标准的JSON格式化
3224
3225
3226 function json_format(textString, tabNumber) {
3227 return JSON.stringify(JSON.parse(textString), null, tabNumber);
3228 }
3229
3230 var wscode = function wscode(options) {
3231 var _this5 = this;
3232
3233 if (!(this instanceof wscode)) {
3234 throw new Error('WSCode is a constructor and should be called with the `new` keyword');
3235 }
3236 /**
3237 *
3238 * [格式化配置]
3239 *
3240 * 所有的配置校验和默认值设置等都应该在这里进行
3241 * 经过这里处理以后,后续不需要再进行校验了
3242 * 因此这里的内容的更改一定要慎重
3243 *
3244 */
3245 // 编辑器挂载点
3246
3247
3248 if (isElement(options.el)) {
3249 // 着色器
3250 var shader = {
3251 html: html_shader,
3252 css: css_shader,
3253 javascript: javascript_shader,
3254 json: json_shader,
3255 normal: function normal() {
3256 var resultData = [];
3257
3258 _this5._contentArray.forEach(function (text) {
3259 resultData.push([{
3260 content: text,
3261 color: _this5._colorText
3262 }]);
3263 });
3264
3265 return resultData;
3266 }
3267 }; // 格式化
3268
3269 var format = {
3270 html: html_format,
3271 css: css_format,
3272 javascript: javascript_format,
3273 json: json_format,
3274 normal: function normal(textString) {
3275 return textString;
3276 }
3277 };
3278 this._el = options.el; // 公共配置
3279
3280 options.color = options.color || {};
3281 this._colorBackground = options.color.background || "#d6d6e4";
3282 /*编辑器背景*/
3283
3284 this._colorText = options.color.text || "#000000";
3285 /*普通文本颜色*/
3286
3287 this._colorNumber = options.color.number || "#888484";
3288 /*行号颜色*/
3289
3290 this._colorEdit = options.color.edit || "#eaeaf1";
3291 /*编辑行颜色*/
3292
3293 this._colorCursor = options.color.cursor || "#ff0000";
3294 /*光标颜色*/
3295
3296 this._colorSelect = options.color.select || "#6c6cf1";
3297 /*选择背景*/
3298
3299 this._fontFamily = options["font-family"] || "新宋体";
3300 /*字体*/
3301
3302 this._fontWeight = options["font-weight"] || 600;
3303 /*字重*/
3304
3305 this._tabSpace = options.tabSpace || 4;
3306 /*设置一个tab表示多少个空格*/
3307 // 语言类型
3308
3309 var lang = options.lang || {};
3310 this._langType = lang.type || "normal";
3311 /*默认普通文本*/
3312
3313 this._langColors = lang.color || {};
3314 this._langColors.text = this._colorText;
3315
3316 var initOptions = function initOptions(defaultOptinos, configOptions) {
3317 configOptions = configOptions || {};
3318
3319 for (var key in configOptions) {
3320 defaultOptinos[key] = configOptions[key];
3321 }
3322
3323 return defaultOptinos;
3324 }; // 着色色彩配置
3325
3326
3327 this._langColors = initOptions({
3328 "annotation": "#6a9955",
3329
3330 /*注释颜色*/
3331 "border": "#ffffff",
3332
3333 /*边界颜色*/
3334 "tag": "#1e50b3",
3335
3336 /*结点颜色*/
3337 "attr": "#1e83b1",
3338
3339 /*属性颜色*/
3340 "string": "#ac4c1e",
3341
3342 /*字符串颜色*/
3343 "key": "#ff0000"
3344 /*关键字颜色*/
3345
3346 }, this._langColors); // 语言类型校对
3347
3348 if (["normal", "html", "css", "javascript", "json"].indexOf(this._langType) < 0) {
3349 console.error("[错误]配置的语言类型‘" + this._langType + "’不支持!"); // 重置默认类型
3350
3351 this._langType = "normal";
3352 } // 文本
3353
3354
3355 this._contentArray = isString(options.content) ? (this.$$filterText(options.content) + "").split("\n") : [""]; // 着色方法
3356
3357 this.$shader = isFunction(options.shader) ? options.shader : shader[this._langType]; // 格式化方法
3358
3359 this.$format = isFunction(options.format) ? options.format : format[this._langType];
3360 } else {
3361 // 挂载点是必须的,一定要有
3362 throw new Error('options.el is not a element!');
3363 } // 先初始化DOM
3364
3365
3366 this.$$initDom(); // 初始化控制变量
3367
3368 this.__needUpdate = true;
3369 this.__lineNum = this._contentArray.length - 1;
3370 this.__leftNum = this._contentArray[this.__lineNum].length;
3371 this.__cursor1 = this.__cursor2 = {
3372 leftNum: 0,
3373 lineNum: 0
3374 };
3375 this.__formatData = this.$shader(this._contentArray.join('\n'), this._langColors); // 初始化视图
3376
3377 this.$$initView(); // 更新视图
3378
3379 this.$$updateView(); // 绑定操作
3380
3381 this.$$bindEvent();
3382
3383 this.valueOf = function () {
3384 return _this5._contentArray.join('\n');
3385 };
3386
3387 this.format = function () {
3388 // 格式化内容
3389 _this5._contentArray = _this5.$format(_this5._contentArray.join('\n'), _this5._tabSpace).split('\n');
3390 _this5.__lineNum = _this5._contentArray.length - 1;
3391 _this5.__leftNum = _this5._contentArray[_this5.__lineNum].length; // 着色
3392
3393 _this5.__formatData = _this5.$shader(_this5._contentArray.join('\n'), _this5._langColors); // 更新视图
3394
3395 _this5.$$updateView(); // 更新光标位置
3396
3397
3398 _this5.$$initView();
3399 };
3400 }; // 挂载辅助方法
3401
3402
3403 wscode.prototype.$$textWidth = textWidth;
3404 wscode.prototype.$$bestLeftNum = bestLeftNum;
3405 wscode.prototype.$$calcCanvasXY = calcCanvasXY;
3406 wscode.prototype.$$selectIsNotBlank = selectIsNotBlank;
3407 wscode.prototype.$$filterText = filterText; // 挂载核心方法
3408
3409 wscode.prototype.$$initDom = initDom;
3410 wscode.prototype.$$initView = initView;
3411 wscode.prototype.$$updateView = updateView;
3412 wscode.prototype.$$updateSelectView = updateSelectView;
3413 wscode.prototype.$$updateCursorPosition = updateCursorPosition;
3414 wscode.prototype.$$updateCanvasSize = updateCanvasSize;
3415 wscode.prototype.$$cancelSelect = cancelSelect;
3416 wscode.prototype.$$deleteSelect = deleteSelect;
3417 wscode.prototype.$$bindEvent = bindEvent;
3418 wscode.author = '心叶(yelloxing@gmail.com)';
3419
3420 if ((typeof module === "undefined" ? "undefined" : _typeof2(module)) === "object" && _typeof2(module.exports) === "object") {
3421 module.exports = wscode;
3422 } else {
3423 window.WSCode = wscode;
3424 }
3425})();
\No newline at end of file