text.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. define(function(require, exports, module) {
  2. var data = require('../core/data');
  3. var Browser = require('../core/kity').Browser;
  4. /**
  5. * @Desc: 增加对不容浏览器下节点中文本\t匹配的处理,不同浏览器下\t无法正确匹配,导致无法使用TAB来批量导入节点
  6. * @Editor: Naixor
  7. * @Date: 2015.9.17
  8. */
  9. var LINE_ENDING = '\r',
  10. LINE_ENDING_SPLITER = /\r\n|\r|\n/,
  11. TAB_CHAR = (function(Browser) {
  12. if (Browser.gecko) {
  13. return {
  14. REGEXP: new RegExp('^(\t|'+ String.fromCharCode(160,160,32,160) +')'),
  15. DELETE: new RegExp('^(\t|'+ String.fromCharCode(160,160,32,160) +')+')
  16. }
  17. } else if (Browser.ie || Browser.edge) {
  18. // ie系列和edge比较特别,\t在div中会被直接转义成SPACE故只好使用SPACE来做处理
  19. return {
  20. REGEXP: new RegExp('^('+ String.fromCharCode(32) +'|'+ String.fromCharCode(160) +')'),
  21. DELETE: new RegExp('^('+ String.fromCharCode(32) +'|'+ String.fromCharCode(160) +')+')
  22. }
  23. } else {
  24. return {
  25. REGEXP: /^(\t|\x20{4})/,
  26. DELETE: /^(\t|\x20{4})+/
  27. }
  28. }
  29. })(Browser);
  30. function repeat(s, n) {
  31. var result = '';
  32. while (n--) result += s;
  33. return result;
  34. }
  35. /**
  36. * 对节点text中的换行符进行处理
  37. * @method encodeWrap
  38. * @param {String} nodeText MinderNode.data.text
  39. * @return {String} \n -> '\n'; \\n -> '\\n'
  40. */
  41. function encodeWrap(nodeText) {
  42. if (!nodeText) {
  43. return '';
  44. }
  45. var textArr = [],
  46. WRAP_TEXT = ['\\', 'n'];
  47. for (var i = 0, j = 0, l = nodeText.length; i < l; i++) {
  48. if (nodeText[i] === '\n' || nodeText[i] === '\r') {
  49. textArr.push('\\n');
  50. j = 0;
  51. continue;
  52. }
  53. if (nodeText[i] === WRAP_TEXT[j]) {
  54. j++;
  55. if (j === 2) {
  56. j = 0;
  57. textArr.push('\\\\n');
  58. }
  59. continue;
  60. }
  61. switch (j) {
  62. case 0: {
  63. textArr.push(nodeText[i]);
  64. break;
  65. }
  66. case 1: {
  67. textArr.push(nodeText[i-1], nodeText[i]);
  68. }
  69. }
  70. j = 0;
  71. }
  72. return textArr.join('');
  73. }
  74. /**
  75. * 将文本内容中的'\n'和'\\n'分别转换成\n和\\n
  76. * @method decodeWrap
  77. * @param {[type]} text [description]
  78. * @return {[type]} [description]
  79. */
  80. function decodeWrap(text) {
  81. if (!text) {
  82. return '';
  83. }
  84. var textArr = [],
  85. WRAP_TEXT = ['\\', '\\', 'n'];
  86. for (var i = 0, j = 0, l = text.length; i < l; i++) {
  87. if (text[i] === WRAP_TEXT[j]) {
  88. j++;
  89. if (j === 3) {
  90. j = 0;
  91. textArr.push('\\n');
  92. }
  93. continue;
  94. }
  95. switch (j) {
  96. case 0: {
  97. textArr.push(text[i]);
  98. j = 0;
  99. break;
  100. }
  101. case 1: {
  102. if (text[i] === 'n') {
  103. textArr.push('\n');
  104. } else {
  105. textArr.push(text[i-1], text[i]);
  106. }
  107. j = 0;
  108. break;
  109. }
  110. case 2: {
  111. textArr.push(text[i-2]);
  112. if (text[i] !== '\\') {
  113. j = 0;
  114. textArr.push(text[i-1], text[i]);
  115. }
  116. break;
  117. }
  118. }
  119. }
  120. return textArr.join('');
  121. }
  122. function encode(json, level) {
  123. var local = '';
  124. level = level || 0;
  125. local += repeat('\t', level);
  126. local += encodeWrap(json.data.text) + LINE_ENDING;
  127. if (json.children) {
  128. json.children.forEach(function(child) {
  129. local += encode(child, level + 1);
  130. });
  131. }
  132. return local;
  133. }
  134. function isEmpty(line) {
  135. return !/\S/.test(line);
  136. }
  137. function getLevel(line) {
  138. var level = 0;
  139. while (TAB_CHAR.REGEXP.test(line)) {
  140. line = line.replace(TAB_CHAR.REGEXP, '');
  141. level++;
  142. }
  143. return level;
  144. }
  145. function getNode(line) {
  146. return {
  147. data: {
  148. text: decodeWrap(line.replace(TAB_CHAR.DELETE, ""))
  149. }
  150. };
  151. }
  152. function decode(local) {
  153. var json,
  154. parentMap = {},
  155. lines = local.split(LINE_ENDING_SPLITER),
  156. line, level, node;
  157. function addChild(parent, child) {
  158. var children = parent.children || (parent.children = []);
  159. children.push(child);
  160. }
  161. for (var i = 0; i < lines.length; i++) {
  162. line = lines[i];
  163. if (isEmpty(line)) continue;
  164. level = getLevel(line);
  165. node = getNode(line);
  166. if (level === 0) {
  167. if (json) {
  168. throw new Error('Invalid local format');
  169. }
  170. json = node;
  171. } else {
  172. if (!parentMap[level - 1]) {
  173. throw new Error('Invalid local format');
  174. }
  175. addChild(parentMap[level - 1], node);
  176. }
  177. parentMap[level] = node;
  178. }
  179. return json;
  180. }
  181. /**
  182. * @Desc: 增加一个将当前选中节点转换成text的方法
  183. * @Editor: Naixor
  184. * @Date: 2015.9.21
  185. */
  186. function Node2Text(node) {
  187. function exportNode(node) {
  188. var exported = {};
  189. exported.data = node.getData();
  190. var childNodes = node.getChildren();
  191. exported.children = [];
  192. for (var i = 0; i < childNodes.length; i++) {
  193. exported.children.push(exportNode(childNodes[i]));
  194. }
  195. return exported;
  196. }
  197. if (!node) return;
  198. if (/^\s*$/.test(node.data.text)) {
  199. node.data.text = "分支主题";
  200. }
  201. return encode(exportNode(node));
  202. }
  203. data.registerProtocol('text', module.exports = {
  204. fileDescription: '大纲文本',
  205. fileExtension: '.txt',
  206. dataType: 'text',
  207. mineType: 'text/plain',
  208. encode: function(json) {
  209. return encode(json.root, 0);
  210. },
  211. decode: function(local) {
  212. return decode(local);
  213. },
  214. Node2Text: function(node) {
  215. return Node2Text(node);
  216. }
  217. });
  218. });