@7polo/kityminder-core
Version:
KityMinder Core Implement
238 lines (218 loc) • 6.99 kB
JavaScript
define(function(require, exports, module) {
var data = require('../core/data');
var Browser = require('../core/kity').Browser;
/**
* @Desc: 增加对不容浏览器下节点中文本\t匹配的处理,不同浏览器下\t无法正确匹配,导致无法使用TAB来批量导入节点
* @Editor: Naixor
* @Date: 2015.9.17
*/
var LINE_ENDING = '\r',
LINE_ENDING_SPLITER = /\r\n|\r|\n/,
TAB_CHAR = (function(Browser) {
if (Browser.gecko) {
return {
REGEXP: new RegExp('^(\t|'+ String.fromCharCode(160,160,32,160) +')'),
DELETE: new RegExp('^(\t|'+ String.fromCharCode(160,160,32,160) +')+')
}
} else if (Browser.ie || Browser.edge) {
// ie系列和edge比较特别,\t在div中会被直接转义成SPACE故只好使用SPACE来做处理
return {
REGEXP: new RegExp('^('+ String.fromCharCode(32) +'|'+ String.fromCharCode(160) +')'),
DELETE: new RegExp('^('+ String.fromCharCode(32) +'|'+ String.fromCharCode(160) +')+')
}
} else {
return {
REGEXP: /^(\t|\x20{4})/,
DELETE: /^(\t|\x20{4})+/
}
}
})(Browser);
function repeat(s, n) {
var result = '';
while (n--) result += s;
return result;
}
/**
* 对节点text中的换行符进行处理
* @method encodeWrap
* @param {String} nodeText MinderNode.data.text
* @return {String} \n -> '\n'; \\n -> '\\n'
*/
function encodeWrap(nodeText) {
if (!nodeText) {
return '';
}
var textArr = [],
WRAP_TEXT = ['\\', 'n'];
for (var i = 0, j = 0, l = nodeText.length; i < l; i++) {
if (nodeText[i] === '\n' || nodeText[i] === '\r') {
textArr.push('\\n');
j = 0;
continue;
}
if (nodeText[i] === WRAP_TEXT[j]) {
j++;
if (j === 2) {
j = 0;
textArr.push('\\\\n');
}
continue;
}
switch (j) {
case 0: {
textArr.push(nodeText[i]);
break;
}
case 1: {
textArr.push(nodeText[i-1], nodeText[i]);
}
}
j = 0;
}
return textArr.join('');
}
/**
* 将文本内容中的'\n'和'\\n'分别转换成\n和\\n
* @method decodeWrap
* @param {[type]} text [description]
* @return {[type]} [description]
*/
function decodeWrap(text) {
if (!text) {
return '';
}
var textArr = [],
WRAP_TEXT = ['\\', '\\', 'n'];
for (var i = 0, j = 0, l = text.length; i < l; i++) {
if (text[i] === WRAP_TEXT[j]) {
j++;
if (j === 3) {
j = 0;
textArr.push('\\n');
}
continue;
}
switch (j) {
case 0: {
textArr.push(text[i]);
j = 0;
break;
}
case 1: {
if (text[i] === 'n') {
textArr.push('\n');
} else {
textArr.push(text[i-1], text[i]);
}
j = 0;
break;
}
case 2: {
textArr.push(text[i-2]);
if (text[i] !== '\\') {
j = 0;
textArr.push(text[i-1], text[i]);
}
break;
}
}
}
return textArr.join('');
}
function encode(json, level) {
var local = '';
level = level || 0;
local += repeat('\t', level);
local += encodeWrap(json.data.text) + LINE_ENDING;
if (json.children) {
json.children.forEach(function(child) {
local += encode(child, level + 1);
});
}
return local;
}
function isEmpty(line) {
return !/\S/.test(line);
}
function getLevel(line) {
var level = 0;
while (TAB_CHAR.REGEXP.test(line)) {
line = line.replace(TAB_CHAR.REGEXP, '');
level++;
}
return level;
}
function getNode(line) {
return {
data: {
text: decodeWrap(line.replace(TAB_CHAR.DELETE, ""))
}
};
}
function decode(local) {
var json,
parentMap = {},
lines = local.split(LINE_ENDING_SPLITER),
line, level, node;
function addChild(parent, child) {
var children = parent.children || (parent.children = []);
children.push(child);
}
for (var i = 0; i < lines.length; i++) {
line = lines[i];
if (isEmpty(line)) continue;
level = getLevel(line);
node = getNode(line);
if (level === 0) {
if (json) {
throw new Error('Invalid local format');
}
json = node;
} else {
if (!parentMap[level - 1]) {
throw new Error('Invalid local format');
}
addChild(parentMap[level - 1], node);
}
parentMap[level] = node;
}
return json;
}
/**
* @Desc: 增加一个将当前选中节点转换成text的方法
* @Editor: Naixor
* @Date: 2015.9.21
*/
function Node2Text(node) {
function exportNode(node) {
var exported = {};
exported.data = node.getData();
var childNodes = node.getChildren();
exported.children = [];
for (var i = 0; i < childNodes.length; i++) {
exported.children.push(exportNode(childNodes[i]));
}
return exported;
}
if (!node) return;
if (/^\s*$/.test(node.data.text)) {
node.data.text = "分支主题";
}
return encode(exportNode(node));
}
data.registerProtocol('text', module.exports = {
fileDescription: '大纲文本',
fileExtension: '.txt',
dataType: 'text',
mineType: 'text/plain',
encode: function(json) {
return encode(json.root, 0);
},
decode: function(local) {
return decode(local);
},
Node2Text: function(node) {
return Node2Text(node);
}
});
});