insertcode.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. /**
  2. * 插入代码插件
  3. * @file
  4. * @since 1.2.6.1
  5. */
  6. UE.plugins["insertcode"] = function() {
  7. var me = this;
  8. me.ready(function() {
  9. utils.cssRule(
  10. "pre",
  11. "pre{margin:.5em 0;padding:.4em .6em;border-radius:8px;background:#f8f8f8;}",
  12. me.document
  13. );
  14. });
  15. me.setOpt("insertcode", {
  16. as3: "ActionScript3",
  17. bash: "Bash/Shell",
  18. cpp: "C/C++",
  19. css: "Css",
  20. cf: "CodeFunction",
  21. "c#": "C#",
  22. delphi: "Delphi",
  23. diff: "Diff",
  24. erlang: "Erlang",
  25. groovy: "Groovy",
  26. html: "Html",
  27. java: "Java",
  28. jfx: "JavaFx",
  29. js: "Javascript",
  30. pl: "Perl",
  31. php: "Php",
  32. plain: "Plain Text",
  33. ps: "PowerShell",
  34. python: "Python",
  35. ruby: "Ruby",
  36. scala: "Scala",
  37. sql: "Sql",
  38. vb: "Vb",
  39. xml: "Xml"
  40. });
  41. /**
  42. * 插入代码
  43. * @command insertcode
  44. * @method execCommand
  45. * @param { String } cmd 命令字符串
  46. * @param { String } lang 插入代码的语言
  47. * @example
  48. * ```javascript
  49. * editor.execCommand( 'insertcode', 'javascript' );
  50. * ```
  51. */
  52. /**
  53. * 如果选区所在位置是插入插入代码区域,返回代码的语言
  54. * @command insertcode
  55. * @method queryCommandValue
  56. * @param { String } cmd 命令字符串
  57. * @return { String } 返回代码的语言
  58. * @example
  59. * ```javascript
  60. * editor.queryCommandValue( 'insertcode' );
  61. * ```
  62. */
  63. me.commands["insertcode"] = {
  64. execCommand: function(cmd, lang) {
  65. var me = this,
  66. rng = me.selection.getRange(),
  67. pre = domUtils.findParentByTagName(rng.startContainer, "pre", true);
  68. if (pre) {
  69. pre.className = "brush:" + lang + ";toolbar:false;";
  70. } else {
  71. var code = "";
  72. if (rng.collapsed) {
  73. code = browser.ie && browser.ie11below
  74. ? browser.version <= 8 ? "&nbsp;" : ""
  75. : "<br/>";
  76. } else {
  77. var frag = rng.extractContents();
  78. var div = me.document.createElement("div");
  79. div.appendChild(frag);
  80. utils.each(
  81. UE.filterNode(
  82. UE.htmlparser(div.innerHTML.replace(/[\r\t]/g, "")),
  83. me.options.filterTxtRules
  84. ).children,
  85. function(node) {
  86. if (browser.ie && browser.ie11below && browser.version > 8) {
  87. if (node.type == "element") {
  88. if (node.tagName == "br") {
  89. code += "\n";
  90. } else if (!dtd.$empty[node.tagName]) {
  91. utils.each(node.children, function(cn) {
  92. if (cn.type == "element") {
  93. if (cn.tagName == "br") {
  94. code += "\n";
  95. } else if (!dtd.$empty[node.tagName]) {
  96. code += cn.innerText();
  97. }
  98. } else {
  99. code += cn.data;
  100. }
  101. });
  102. if (!/\n$/.test(code)) {
  103. code += "\n";
  104. }
  105. }
  106. } else {
  107. code += node.data + "\n";
  108. }
  109. if (!node.nextSibling() && /\n$/.test(code)) {
  110. code = code.replace(/\n$/, "");
  111. }
  112. } else {
  113. if (browser.ie && browser.ie11below) {
  114. if (node.type == "element") {
  115. if (node.tagName == "br") {
  116. code += "<br>";
  117. } else if (!dtd.$empty[node.tagName]) {
  118. utils.each(node.children, function(cn) {
  119. if (cn.type == "element") {
  120. if (cn.tagName == "br") {
  121. code += "<br>";
  122. } else if (!dtd.$empty[node.tagName]) {
  123. code += cn.innerText();
  124. }
  125. } else {
  126. code += cn.data;
  127. }
  128. });
  129. if (!/br>$/.test(code)) {
  130. code += "<br>";
  131. }
  132. }
  133. } else {
  134. code += node.data + "<br>";
  135. }
  136. if (!node.nextSibling() && /<br>$/.test(code)) {
  137. code = code.replace(/<br>$/, "");
  138. }
  139. } else {
  140. code += node.type == "element"
  141. ? dtd.$empty[node.tagName] ? "" : node.innerText()
  142. : node.data;
  143. if (!/br\/?\s*>$/.test(code)) {
  144. if (!node.nextSibling()) return;
  145. code += "<br>";
  146. }
  147. }
  148. }
  149. }
  150. );
  151. }
  152. me.execCommand(
  153. "inserthtml",
  154. '<pre id="coder"class="brush:' +
  155. lang +
  156. ';toolbar:false">' +
  157. code +
  158. "</pre>",
  159. true
  160. );
  161. pre = me.document.getElementById("coder");
  162. domUtils.removeAttributes(pre, "id");
  163. var tmpNode = pre.previousSibling;
  164. if (
  165. tmpNode &&
  166. ((tmpNode.nodeType == 3 &&
  167. tmpNode.nodeValue.length == 1 &&
  168. browser.ie &&
  169. browser.version == 6) ||
  170. domUtils.isEmptyBlock(tmpNode))
  171. ) {
  172. domUtils.remove(tmpNode);
  173. }
  174. var rng = me.selection.getRange();
  175. if (domUtils.isEmptyBlock(pre)) {
  176. rng.setStart(pre, 0).setCursor(false, true);
  177. } else {
  178. rng.selectNodeContents(pre).select();
  179. }
  180. }
  181. },
  182. queryCommandValue: function() {
  183. var path = this.selection.getStartElementPath();
  184. var lang = "";
  185. utils.each(path, function(node) {
  186. if (node.nodeName == "PRE") {
  187. var match = node.className.match(/brush:([^;]+)/);
  188. lang = match && match[1] ? match[1] : "";
  189. return false;
  190. }
  191. });
  192. return lang;
  193. }
  194. };
  195. me.addInputRule(function(root) {
  196. utils.each(root.getNodesByTagName("pre"), function(pre) {
  197. var brs = pre.getNodesByTagName("br");
  198. if (brs.length) {
  199. browser.ie &&
  200. browser.ie11below &&
  201. browser.version > 8 &&
  202. utils.each(brs, function(br) {
  203. var txt = UE.uNode.createText("\n");
  204. br.parentNode.insertBefore(txt, br);
  205. br.parentNode.removeChild(br);
  206. });
  207. return;
  208. }
  209. if (browser.ie && browser.ie11below && browser.version > 8) return;
  210. var code = pre.innerText().split(/\n/);
  211. pre.innerHTML("");
  212. utils.each(code, function(c) {
  213. if (c.length) {
  214. pre.appendChild(UE.uNode.createText(c));
  215. }
  216. pre.appendChild(UE.uNode.createElement("br"));
  217. });
  218. });
  219. });
  220. me.addOutputRule(function(root) {
  221. utils.each(root.getNodesByTagName("pre"), function(pre) {
  222. var code = "";
  223. utils.each(pre.children, function(n) {
  224. if (n.type == "text") {
  225. //在ie下文本内容有可能末尾带有\n要去掉
  226. //trace:3396
  227. code += n.data.replace(/[ ]/g, "&nbsp;").replace(/\n$/, "");
  228. } else {
  229. if (n.tagName == "br") {
  230. code += "\n";
  231. } else {
  232. code += !dtd.$empty[n.tagName] ? "" : n.innerText();
  233. }
  234. }
  235. });
  236. pre.innerText(code.replace(/(&nbsp;|\n)+$/, ""));
  237. });
  238. });
  239. //不需要判断highlight的command列表
  240. me.notNeedCodeQuery = {
  241. help: 1,
  242. undo: 1,
  243. redo: 1,
  244. source: 1,
  245. print: 1,
  246. searchreplace: 1,
  247. fullscreen: 1,
  248. preview: 1,
  249. insertparagraph: 1,
  250. elementpath: 1,
  251. insertcode: 1,
  252. inserthtml: 1,
  253. selectall: 1
  254. };
  255. //将queyCommamndState重置
  256. var orgQuery = me.queryCommandState;
  257. me.queryCommandState = function(cmd) {
  258. var me = this;
  259. if (
  260. !me.notNeedCodeQuery[cmd.toLowerCase()] &&
  261. me.selection &&
  262. me.queryCommandValue("insertcode")
  263. ) {
  264. return -1;
  265. }
  266. return UE.Editor.prototype.queryCommandState.apply(this, arguments);
  267. };
  268. me.addListener("beforeenterkeydown", function() {
  269. var rng = me.selection.getRange();
  270. var pre = domUtils.findParentByTagName(rng.startContainer, "pre", true);
  271. if (pre) {
  272. me.fireEvent("saveScene");
  273. if (!rng.collapsed) {
  274. rng.deleteContents();
  275. }
  276. if (!browser.ie || browser.ie9above) {
  277. var tmpNode = me.document.createElement("br"),
  278. pre;
  279. rng.insertNode(tmpNode).setStartAfter(tmpNode).collapse(true);
  280. var next = tmpNode.nextSibling;
  281. if (!next && (!browser.ie || browser.version > 10)) {
  282. rng.insertNode(tmpNode.cloneNode(false));
  283. } else {
  284. rng.setStartAfter(tmpNode);
  285. }
  286. pre = tmpNode.previousSibling;
  287. var tmp;
  288. while (pre) {
  289. tmp = pre;
  290. pre = pre.previousSibling;
  291. if (!pre || pre.nodeName == "BR") {
  292. pre = tmp;
  293. break;
  294. }
  295. }
  296. if (pre) {
  297. var str = "";
  298. while (
  299. pre &&
  300. pre.nodeName != "BR" &&
  301. new RegExp("^[\\s" + domUtils.fillChar + "]*$").test(pre.nodeValue)
  302. ) {
  303. str += pre.nodeValue;
  304. pre = pre.nextSibling;
  305. }
  306. if (pre.nodeName != "BR") {
  307. var match = pre.nodeValue.match(
  308. new RegExp("^([\\s" + domUtils.fillChar + "]+)")
  309. );
  310. if (match && match[1]) {
  311. str += match[1];
  312. }
  313. }
  314. if (str) {
  315. str = me.document.createTextNode(str);
  316. rng.insertNode(str).setStartAfter(str);
  317. }
  318. }
  319. rng.collapse(true).select(true);
  320. } else {
  321. if (browser.version > 8) {
  322. var txt = me.document.createTextNode("\n");
  323. var start = rng.startContainer;
  324. if (rng.startOffset == 0) {
  325. var preNode = start.previousSibling;
  326. if (preNode) {
  327. rng.insertNode(txt);
  328. var fillchar = me.document.createTextNode(" ");
  329. rng
  330. .setStartAfter(txt)
  331. .insertNode(fillchar)
  332. .setStart(fillchar, 0)
  333. .collapse(true)
  334. .select(true);
  335. }
  336. } else {
  337. rng.insertNode(txt).setStartAfter(txt);
  338. var fillchar = me.document.createTextNode(" ");
  339. start = rng.startContainer.childNodes[rng.startOffset];
  340. if (start && !/^\n/.test(start.nodeValue)) {
  341. rng.setStartBefore(txt);
  342. }
  343. rng
  344. .insertNode(fillchar)
  345. .setStart(fillchar, 0)
  346. .collapse(true)
  347. .select(true);
  348. }
  349. } else {
  350. var tmpNode = me.document.createElement("br");
  351. rng.insertNode(tmpNode);
  352. rng.insertNode(me.document.createTextNode(domUtils.fillChar));
  353. rng.setStartAfter(tmpNode);
  354. pre = tmpNode.previousSibling;
  355. var tmp;
  356. while (pre) {
  357. tmp = pre;
  358. pre = pre.previousSibling;
  359. if (!pre || pre.nodeName == "BR") {
  360. pre = tmp;
  361. break;
  362. }
  363. }
  364. if (pre) {
  365. var str = "";
  366. while (
  367. pre &&
  368. pre.nodeName != "BR" &&
  369. new RegExp("^[ " + domUtils.fillChar + "]*$").test(pre.nodeValue)
  370. ) {
  371. str += pre.nodeValue;
  372. pre = pre.nextSibling;
  373. }
  374. if (pre.nodeName != "BR") {
  375. var match = pre.nodeValue.match(
  376. new RegExp("^([ " + domUtils.fillChar + "]+)")
  377. );
  378. if (match && match[1]) {
  379. str += match[1];
  380. }
  381. }
  382. str = me.document.createTextNode(str);
  383. rng.insertNode(str).setStartAfter(str);
  384. }
  385. rng.collapse(true).select();
  386. }
  387. }
  388. me.fireEvent("saveScene");
  389. return true;
  390. }
  391. });
  392. me.addListener("tabkeydown", function(cmd, evt) {
  393. var rng = me.selection.getRange();
  394. var pre = domUtils.findParentByTagName(rng.startContainer, "pre", true);
  395. if (pre) {
  396. me.fireEvent("saveScene");
  397. if (evt.shiftKey) {
  398. } else {
  399. if (!rng.collapsed) {
  400. var bk = rng.createBookmark();
  401. var start = bk.start.previousSibling;
  402. while (start) {
  403. if (pre.firstChild === start && !domUtils.isBr(start)) {
  404. pre.insertBefore(me.document.createTextNode(" "), start);
  405. break;
  406. }
  407. if (domUtils.isBr(start)) {
  408. pre.insertBefore(
  409. me.document.createTextNode(" "),
  410. start.nextSibling
  411. );
  412. break;
  413. }
  414. start = start.previousSibling;
  415. }
  416. var end = bk.end;
  417. start = bk.start.nextSibling;
  418. if (pre.firstChild === bk.start) {
  419. pre.insertBefore(
  420. me.document.createTextNode(" "),
  421. start.nextSibling
  422. );
  423. }
  424. while (start && start !== end) {
  425. if (domUtils.isBr(start) && start.nextSibling) {
  426. if (start.nextSibling === end) {
  427. break;
  428. }
  429. pre.insertBefore(
  430. me.document.createTextNode(" "),
  431. start.nextSibling
  432. );
  433. }
  434. start = start.nextSibling;
  435. }
  436. rng.moveToBookmark(bk).select();
  437. } else {
  438. var tmpNode = me.document.createTextNode(" ");
  439. rng
  440. .insertNode(tmpNode)
  441. .setStartAfter(tmpNode)
  442. .collapse(true)
  443. .select(true);
  444. }
  445. }
  446. me.fireEvent("saveScene");
  447. return true;
  448. }
  449. });
  450. me.addListener("beforeinserthtml", function(evtName, html) {
  451. var me = this,
  452. rng = me.selection.getRange(),
  453. pre = domUtils.findParentByTagName(rng.startContainer, "pre", true);
  454. if (pre) {
  455. if (!rng.collapsed) {
  456. rng.deleteContents();
  457. }
  458. var htmlstr = "";
  459. if (browser.ie && browser.version > 8) {
  460. utils.each(
  461. UE.filterNode(UE.htmlparser(html), me.options.filterTxtRules)
  462. .children,
  463. function(node) {
  464. if (node.type == "element") {
  465. if (node.tagName == "br") {
  466. htmlstr += "\n";
  467. } else if (!dtd.$empty[node.tagName]) {
  468. utils.each(node.children, function(cn) {
  469. if (cn.type == "element") {
  470. if (cn.tagName == "br") {
  471. htmlstr += "\n";
  472. } else if (!dtd.$empty[node.tagName]) {
  473. htmlstr += cn.innerText();
  474. }
  475. } else {
  476. htmlstr += cn.data;
  477. }
  478. });
  479. if (!/\n$/.test(htmlstr)) {
  480. htmlstr += "\n";
  481. }
  482. }
  483. } else {
  484. htmlstr += node.data + "\n";
  485. }
  486. if (!node.nextSibling() && /\n$/.test(htmlstr)) {
  487. htmlstr = htmlstr.replace(/\n$/, "");
  488. }
  489. }
  490. );
  491. var tmpNode = me.document.createTextNode(
  492. utils.html(htmlstr.replace(/&nbsp;/g, " "))
  493. );
  494. rng.insertNode(tmpNode).selectNode(tmpNode).select();
  495. } else {
  496. var frag = me.document.createDocumentFragment();
  497. utils.each(
  498. UE.filterNode(UE.htmlparser(html), me.options.filterTxtRules)
  499. .children,
  500. function(node) {
  501. if (node.type == "element") {
  502. if (node.tagName == "br") {
  503. frag.appendChild(me.document.createElement("br"));
  504. } else if (!dtd.$empty[node.tagName]) {
  505. utils.each(node.children, function(cn) {
  506. if (cn.type == "element") {
  507. if (cn.tagName == "br") {
  508. frag.appendChild(me.document.createElement("br"));
  509. } else if (!dtd.$empty[node.tagName]) {
  510. frag.appendChild(
  511. me.document.createTextNode(
  512. utils.html(cn.innerText().replace(/&nbsp;/g, " "))
  513. )
  514. );
  515. }
  516. } else {
  517. frag.appendChild(
  518. me.document.createTextNode(
  519. utils.html(cn.data.replace(/&nbsp;/g, " "))
  520. )
  521. );
  522. }
  523. });
  524. if (frag.lastChild.nodeName != "BR") {
  525. frag.appendChild(me.document.createElement("br"));
  526. }
  527. }
  528. } else {
  529. frag.appendChild(
  530. me.document.createTextNode(
  531. utils.html(node.data.replace(/&nbsp;/g, " "))
  532. )
  533. );
  534. }
  535. if (!node.nextSibling() && frag.lastChild.nodeName == "BR") {
  536. frag.removeChild(frag.lastChild);
  537. }
  538. }
  539. );
  540. rng.insertNode(frag).select();
  541. }
  542. return true;
  543. }
  544. });
  545. //方向键的处理
  546. me.addListener("keydown", function(cmd, evt) {
  547. var me = this,
  548. keyCode = evt.keyCode || evt.which;
  549. if (keyCode == 40) {
  550. var rng = me.selection.getRange(),
  551. pre,
  552. start = rng.startContainer;
  553. if (
  554. rng.collapsed &&
  555. (pre = domUtils.findParentByTagName(rng.startContainer, "pre", true)) &&
  556. !pre.nextSibling
  557. ) {
  558. var last = pre.lastChild;
  559. while (last && last.nodeName == "BR") {
  560. last = last.previousSibling;
  561. }
  562. if (
  563. last === start ||
  564. (rng.startContainer === pre &&
  565. rng.startOffset == pre.childNodes.length)
  566. ) {
  567. me.execCommand("insertparagraph");
  568. domUtils.preventDefault(evt);
  569. }
  570. }
  571. }
  572. });
  573. //trace:3395
  574. me.addListener("delkeydown", function(type, evt) {
  575. var rng = this.selection.getRange();
  576. rng.txtToElmBoundary(true);
  577. var start = rng.startContainer;
  578. if (
  579. domUtils.isTagNode(start, "pre") &&
  580. rng.collapsed &&
  581. domUtils.isStartInblock(rng)
  582. ) {
  583. var p = me.document.createElement("p");
  584. domUtils.fillNode(me.document, p);
  585. start.parentNode.insertBefore(p, start);
  586. domUtils.remove(start);
  587. rng.setStart(p, 0).setCursor(false, true);
  588. domUtils.preventDefault(evt);
  589. return true;
  590. }
  591. });
  592. };