/plugins/svn/tracwysiwyg/tests/testcase.js

https://bitbucket.org/iwata0303/traclightning · JavaScript · 1781 lines · 1721 code · 60 blank · 0 comment · 20 complexity · 5ccf14e2f89dd232717cf41fc80e2514 MD5 · raw file

  1. addEvent(window, "load", function() {
  2. TracWysiwyg.tracPaths = { base: ".", search: "./search", stylesheets: [] };
  3. var options = TracWysiwyg.getOptions();
  4. var instance = new TracWysiwyg(document.getElementById("textarea"), options);
  5. var contentDocument = instance.contentDocument;
  6. var d = document;
  7. var wysiwygHtml = d.getElementById("wysiwyg-html");
  8. var showWysiwygHtml = d.getElementById("show-wysiwyg-html");
  9. setTimeout(function() {
  10. if (showWysiwygHtml.checked) {
  11. var body = contentDocument.body;
  12. var browserIE = body.attachEvent ? true : false;
  13. var elements = body.getElementsByTagName("br");
  14. var count = 0;
  15. var html = body.innerHTML.replace(/<[Bb][Rr] *[^>\/]*/g, function(value) {
  16. var element = elements[count++];
  17. var attributes = element.attributes;
  18. var length = attributes.length;
  19. if (length == 0)
  20. return value;
  21. var texts = [ value ];
  22. for (var i = 0; i < length; i++) {
  23. var attr = attributes[i];
  24. if (!browserIE || !!element[attr.name]) {
  25. texts.push(' ', attr.name, '="', attr.value, '"');
  26. }
  27. }
  28. return texts.join("");
  29. });
  30. if (wysiwygHtml.value != html) {
  31. wysiwygHtml.value = html;
  32. }
  33. }
  34. setTimeout(arguments.callee, 500);
  35. }, 500);
  36. function generate(dom, wikitext, options, withoutDomToWikitext, withoutWikitextToFragment) {
  37. dom = dom.cloneNode(true);
  38. var anonymous = dom.ownerDocument.createElement("div");
  39. anonymous.appendChild(dom);
  40. if (!withoutWikitextToFragment) {
  41. var fragment = instance.wikitextToFragment(wikitext, contentDocument, options);
  42. var generated = contentDocument.createElement("div");
  43. generated.appendChild(fragment);
  44. var generatedHtml = generated.innerHTML;
  45. if (!generated.addEventListener || window.opera) {
  46. generatedHtml = generatedHtml.replace(/\n\r/g, "\uffff").replace(/\uffff\n?/g, "\n");
  47. }
  48. this.assertEqual(anonymous.innerHTML, generatedHtml, "wikitextToFragment");
  49. }
  50. if (!withoutDomToWikitext) {
  51. this.assertEqual(wikitext, instance.domToWikitext(anonymous, options), "domToWikitext");
  52. }
  53. }
  54. function generateFragment(dom, wikitext, options) {
  55. generate.call(this, dom, wikitext, options, true, false);
  56. }
  57. function generateWikitext(dom, wikitext, options) {
  58. generate.call(this, dom, wikitext, options, false, true);
  59. }
  60. function run() {
  61. var unit = new TracWysiwyg.TestUnit();
  62. var fragment = unit.fragment;
  63. var element = unit.element;
  64. var br = function() { return element("br") };
  65. var a = function(link, label) {
  66. var attrs = {
  67. href: "./search?q=" + encodeURIComponent(link),
  68. title: link, "tracwysiwyg-link": link, onclick: "return false;" };
  69. return element("a", attrs, label);
  70. };
  71. unit.add("treeWalk", function() {
  72. var list;
  73. function iterator(node) {
  74. var value;
  75. if (node) {
  76. switch (node.nodeType) {
  77. case 1: value = node.tagName.toLowerCase(); break;
  78. case 3: value = "#text"; break;
  79. }
  80. }
  81. else {
  82. value = "(null)";
  83. }
  84. list.push(value);
  85. }
  86. function doTreeWalk(expected, dom) {
  87. list = [];
  88. instance.treeWalk(dom, iterator);
  89. this.assertEqual(expected, list.join(" "));
  90. list = [];
  91. instance._treeWalkEmulation(dom, iterator);
  92. this.assertEqual(expected, list.join(" "));
  93. }
  94. doTreeWalk.call(this, "p #text (null)", element("div", element("p", "paragraph")));
  95. doTreeWalk.call(this, "#text (null)", element("div", element("p", "paragraph")).firstChild);
  96. doTreeWalk.call(this, "(null)", element("div", element("p")).firstChild);
  97. var dom = element("div");
  98. dom.innerHTML = [
  99. '<h2 id="Tables">Tables</h2>',
  100. '<p>',
  101. 'Simple tables can be created like this:',
  102. '</p>',
  103. '<pre class="wiki">||Cell 1||Cell 2||Cell 3||',
  104. '||Cell 4||Cell 5||Cell 6||',
  105. '</pre><p>',
  106. 'Display:',
  107. '</p>',
  108. '<table class="wiki">',
  109. '<tbody><tr><td>Cell 1</td><td>Cell 2</td><td>Cell 3',
  110. '</td></tr><tr><td>Cell 4</td><td>Cell 5</td><td>Cell 6',
  111. '</td></tr></tbody></table>',
  112. '<p>',
  113. 'Note that more complex tables can be created using',
  114. '<a class="wiki" href="/practice/wiki/WikiRestructuredText#BiggerReSTExample">reStructuredText</a>.',
  115. '</p>' ].join("");
  116. var expected = [
  117. 'h2', '#text', 'p', '#text', 'pre', '#text', 'p', '#text',
  118. 'table', 'tbody',
  119. 'tr', 'td', '#text', 'td', '#text', 'td', '#text',
  120. 'tr', 'td', '#text', 'td', '#text', 'td', '#text',
  121. 'p', '#text', 'a', '#text', '#text',
  122. '(null)'].join(" ");
  123. doTreeWalk.call(this, expected, dom);
  124. });
  125. unit.add("isLastChildInBlockNode", function() {
  126. var dom = fragment(
  127. element("p", element("br")),
  128. element("p", "foobar", element("br"), "foobar"),
  129. element("p", element("b", "foobar", element("br"))),
  130. element("p", element("b", "foobar"), element("br")),
  131. element("br"));
  132. var count = 0;
  133. function assert(expected, node) {
  134. this.assertEqual(expected, instance.isLastChildInBlockNode(node), "#" + (count++));
  135. }
  136. assert.call(this, true, dom.childNodes[0].childNodes[0]);
  137. assert.call(this, false, dom.childNodes[1].childNodes[0]);
  138. assert.call(this, false, dom.childNodes[1].childNodes[1]);
  139. assert.call(this, true, dom.childNodes[1].childNodes[2]);
  140. assert.call(this, false, dom.childNodes[2].childNodes[0].childNodes[0]);
  141. assert.call(this, true, dom.childNodes[2].childNodes[0].childNodes[1]);
  142. assert.call(this, false, dom.childNodes[3].childNodes[0].childNodes[0]);
  143. assert.call(this, true, dom.childNodes[3].childNodes[1]);
  144. assert.call(this, true, dom.childNodes[4]);
  145. });
  146. unit.add("code block", function() {
  147. var dom = fragment(
  148. element("p", element("tt", "abc")),
  149. element("pre", { "class": "wiki" }, "{{{code-block"));
  150. var wikitext = [
  151. "`abc`",
  152. "",
  153. "{{{",
  154. "{{{code-block",
  155. "}}}" ].join("\n");
  156. generate.call(this, dom, wikitext);
  157. });
  158. unit.add("code block nest", function() {
  159. var dom = fragment(
  160. element("pre", { "class": "wiki" }, "#!python\n= level 1\n{{{\n= level 2\n}}}\n= level 1"));
  161. var wikitext = [
  162. "{{{",
  163. "#!python",
  164. "= level 1",
  165. "{{{",
  166. "= level 2",
  167. "}}}",
  168. "= level 1",
  169. "}}}" ].join("\n");
  170. generate.call(this, dom, wikitext);
  171. });
  172. unit.add("paragraph", function() {
  173. var dom = fragment(
  174. element("p", "Paragraph continued..."),
  175. element("p", "Second paragraph continued..."));
  176. generateFragment.call(this, dom, [
  177. "Paragraph",
  178. "continued...",
  179. "",
  180. "Second paragraph",
  181. "continued...",
  182. "" ].join("\n"));
  183. generate.call(this, dom, [
  184. "Paragraph continued...",
  185. "",
  186. "Second paragraph continued..." ].join("\n"));
  187. });
  188. unit.add("hr", function() {
  189. var dom = fragment(
  190. element("p", "Paragraph"),
  191. element("hr"),
  192. element("ul",
  193. element("li", "item 1"),
  194. element("ol", element("li", "item 1.1"))),
  195. element("hr"));
  196. generateFragment.call(this, dom, [
  197. "Paragraph",
  198. "----",
  199. " * item 1",
  200. " 1. item 1.1",
  201. "----" ].join("\n"));
  202. generate.call(this, dom, [
  203. "Paragraph",
  204. "",
  205. "----",
  206. " * item 1",
  207. " 1. item 1.1",
  208. "",
  209. "----" ].join("\n"));
  210. });
  211. unit.add("bold italic", function() {
  212. var dom = element("p", element("b", element("i", "bold italic")));
  213. var wikitext = "'''''bold italic'''''";
  214. generate.call(this, dom, wikitext);
  215. });
  216. unit.add("bold", function() {
  217. var wikitext = [
  218. "The quick '''brown''' fox.",
  219. "",
  220. "The quick '''brown''' fox." ].join("\n");
  221. generateWikitext.call(this,
  222. fragment(
  223. element("p", "The quick ", element("b", "brown"), " fox."),
  224. element("p", "The quick ", element("strong", "brown"), " fox.")),
  225. wikitext);
  226. generateFragment.call(this,
  227. fragment(
  228. element("p", "The quick ", element("b", "brown"), " fox."),
  229. element("p", "The quick ", element("b", "brown"), " fox.")),
  230. wikitext);
  231. });
  232. unit.add("italic", function() {
  233. var wikitext = [
  234. "The quick ''brown'' fox.",
  235. "",
  236. "The quick ''brown'' fox." ].join("\n");
  237. generateWikitext.call(this,
  238. fragment(
  239. element("p", "The quick ", element("i", "brown"), " fox."),
  240. element("p", "The quick ", element("em", "brown"), " fox.")),
  241. wikitext);
  242. generateFragment.call(this,
  243. fragment(
  244. element("p", "The quick ", element("i", "brown"), " fox."),
  245. element("p", "The quick ", element("i", "brown"), " fox.")),
  246. wikitext);
  247. });
  248. unit.add("underline", function() {
  249. var dom = element("p", element("u", "underline"));
  250. var wikitext = "__underline__";
  251. generate.call(this, dom, wikitext);
  252. });
  253. unit.add("strike-through", function() {
  254. var dom = element("p", element("del", "strike-through"));
  255. var wikitext = "~~strike-through~~";
  256. generate.call(this, dom, wikitext);
  257. });
  258. unit.add("superscript", function() {
  259. var dom = element("p", element("sup", "superscript"));
  260. var wikitext = "^superscript^";
  261. generate.call(this, dom, wikitext);
  262. });
  263. unit.add("subscript", function() {
  264. var dom = element("p", element("sub", "subscript"));
  265. var wikitext = ",,subscript,,";
  266. generate.call(this, dom, wikitext);
  267. });
  268. unit.add("monospace", function() {
  269. var dom = element("p", element("tt", "monospace"),
  270. ", ", element("tt", "mono`s`pace"),
  271. ", ", element("tt", "mono{{{s}}}pace"));
  272. var wikitext = "`monospace`, {{{mono`s`pace}}}, `mono{{{s}}}pace`";
  273. generate.call(this, dom, wikitext);
  274. });
  275. unit.add("italic -> bold", function() {
  276. var dom = element("p",
  277. "normal",
  278. element("i", "italic"),
  279. element("b", "bold"),
  280. "normal");
  281. var wikitext = "normal''italic'''''bold'''normal";
  282. generate.call(this, dom, wikitext);
  283. });
  284. unit.add("bold -> italic", function() {
  285. var dom = element("p",
  286. "normal",
  287. element("b", "bold"),
  288. element("i", "italic"),
  289. "normal");
  290. var wikitext = "normal'''bold'''''italic''normal";
  291. generate.call(this, dom, wikitext);
  292. });
  293. unit.add("[ italic [ xyz ] bold ]", function() {
  294. var dom = element("p",
  295. "normal",
  296. element("i", "italic", element("b", "xyz")),
  297. element("b", "bold"),
  298. "normal");
  299. var wikitext = "normal''italic'''xyz''bold'''normal";
  300. generate.call(this, dom, wikitext);
  301. });
  302. unit.add("overlapped markups", function() {
  303. var dom = element("p",
  304. "normal",
  305. element("b", "bold",
  306. element("i", "italic",
  307. element("u", "underline",
  308. element("del", "strike-through",
  309. element("sup", "superscript",
  310. element("sub", "subscript"))))),
  311. element("u", element("del", element("sup", element("sub", "i")))),
  312. element("del", element("sup", element("sub", "u"))),
  313. element("sup", element("sub", "strike")),
  314. element("sub", "sup"),
  315. "sub"),
  316. ".");
  317. var wikitext = "normal'''bold''italic__underline~~strike-through^superscript,,subscript''i__u~~strike^sup,,sub'''.";
  318. generateFragment.call(this, dom, wikitext);
  319. });
  320. unit.add("! bold italic", function() {
  321. var dom = element("p", element("b", element("i", "bold''''' italic")), ".");
  322. var wikitext = "'''''bold!''''' italic'''''.";
  323. generate.call(this, dom, wikitext);
  324. });
  325. unit.add("! bold", function() {
  326. var dom = element("p", element("b", "bold''' bold"), ".");
  327. var wikitext = "'''bold!''' bold'''.";
  328. generate.call(this, dom, wikitext);
  329. });
  330. unit.add("! italic", function() {
  331. var dom = element("p", element("i", "italic'' italic"), ".");
  332. var wikitext = "''italic!'' italic''.";
  333. generate.call(this, dom, wikitext);
  334. });
  335. unit.add("! underline", function() {
  336. var dom = element("p", element("u", "underline__ underline"), ".");
  337. var wikitext = "__underline!__ underline__.";
  338. generate.call(this, dom, wikitext);
  339. });
  340. unit.add("! strike-through", function() {
  341. var dom = element("p", element("del", "strike~~through"), ".");
  342. var wikitext = "~~strike!~~through~~.";
  343. generate.call(this, dom, wikitext);
  344. });
  345. unit.add("! superscript", function() {
  346. var dom = element("p", element("sup", "superscript^ superscript"), ".");
  347. var wikitext = "^superscript!^ superscript^.";
  348. generate.call(this, dom, wikitext);
  349. });
  350. unit.add("! subscript", function() {
  351. var dom = element("p", element("sub", "subscript,, subscript"), ".");
  352. var wikitext = ",,subscript!,, subscript,,.";
  353. generate.call(this, dom, wikitext);
  354. });
  355. unit.add("! monospace", function() {
  356. var dom = element("p", "{{{monospace}}} or `monospace`");
  357. var wikitext = "!{{{monospace}}} or !`monospace`";
  358. generate.call(this, dom, wikitext);
  359. });
  360. unit.add("!||, !=||", function() {
  361. var dom = fragment(
  362. element("p", "Paragraph"),
  363. element("table", { "class": "wiki" },
  364. element("tbody",
  365. element("tr", element("td", "foo||bar!||||==||foobar")))),
  366. element("p", "||||cell=||= =||||=cell|| Paragraph"));
  367. generateFragment.call(this, dom, [
  368. "Paragraph",
  369. "||foo!||bar!!||||=!=||foobar",
  370. "!||||cell!=||=",
  371. "!=||||=cell!||",
  372. "Paragraph" ].join("\n"));
  373. generate.call(this, dom, [
  374. "Paragraph",
  375. "",
  376. "|| foo!||bar!!||||=!=||foobar ||",
  377. "",
  378. "!||||cell!=||= !=||||=cell!|| Paragraph" ].join("\n"));
  379. });
  380. unit.add("#ticket", function() {
  381. var dom = element("p",
  382. element("a", "#1234", {
  383. href: "./search?q=ticket%3A1234", title: "ticket:1234",
  384. "tracwysiwyg-link": "ticket:1234", onclick: "return false;" }),
  385. " #2345 &#3456");
  386. var wikitext = "#1234 !#2345 &#3456";
  387. generate.call(this, dom, wikitext);
  388. });
  389. unit.add("{report}", function() {
  390. var dom = element("p",
  391. "{987}",
  392. element("a", "{123}", {
  393. href: "./search?q=report%3A123", title: "report:123",
  394. "tracwysiwyg-link": "report:123", onclick: "return false;" }));
  395. var wikitext = "!{987}{123}";
  396. generate.call(this, dom, wikitext);
  397. });
  398. unit.add("[changeset]", function() {
  399. var dom = element("p",
  400. element("a", "[123]", {
  401. href: "./search?q=changeset%3A123", title: "changeset:123",
  402. "tracwysiwyg-link": "changeset:123", onclick: "return false;" }),
  403. ", ",
  404. element("a", "r234", {
  405. href: "./search?q=changeset%3A234", title: "changeset:234",
  406. "tracwysiwyg-link": "changeset:234", onclick: "return false;" }),
  407. ", ",
  408. element("a", "[345/trunk]", {
  409. href: "./search?q=changeset%3A345%2Ftrunk", title: "changeset:345/trunk",
  410. "tracwysiwyg-link": "changeset:345/trunk", onclick: "return false;" }),
  411. ", [123], r234, [345/trunk], ar123");
  412. generate.call(this, dom, "[123], r234, [345/trunk], ![123], !r234, ![345/trunk], ar123");
  413. });
  414. unit.add("[log]", function() {
  415. var dom = element("p",
  416. "log - ",
  417. element("a", "r1:3", {
  418. href: "./search?q=log%3A%401%3A3", title: "log:@1:3",
  419. "tracwysiwyg-link": "log:@1:3", onclick: "return false;" }),
  420. ", r1:3, ",
  421. element("a", "[1:3]", {
  422. href: "./search?q=log%3A%401%3A3", title: "log:@1:3",
  423. "tracwysiwyg-link": "log:@1:3", onclick: "return false;" }),
  424. ", [1:3], ",
  425. element("a", "log:@1:3", {
  426. href: "./search?q=log%3A%401%3A3", title: "log:@1:3",
  427. "tracwysiwyg-link": "log:@1:3", onclick: "return false;" }),
  428. ", log:@1:3, ",
  429. element("a", "log:trunk@1:3", {
  430. href: "./search?q=log%3Atrunk%401%3A3", title: "log:trunk@1:3",
  431. "tracwysiwyg-link": "log:trunk@1:3", onclick: "return false;" }),
  432. ", log:trunk@1:3");
  433. generate.call(this, dom, "log - r1:3, !r1:3, [1:3], ![1:3], log:@1:3, !log:@1:3, log:trunk@1:3, !log:trunk@1:3");
  434. });
  435. unit.add("wiki:TracLinks", function() {
  436. var dom = element("p",
  437. element("a", "link:WikiName", {
  438. href: "./search?q=link%3AWikiName", title: "link:WikiName",
  439. "tracwysiwyg-link": "link:WikiName", onclick: "return false;" }),
  440. " ",
  441. element("a", 'link:"Foo Bar"', {
  442. href: "./search?q=link%3A%22Foo%20Bar%22", title: 'link:"Foo Bar"',
  443. "tracwysiwyg-link": 'link:"Foo Bar"', onclick: "return false;" }),
  444. " ",
  445. element("a", 'link:"Foo Bar#baz"', {
  446. href: "./search?q=link%3A%22Foo%20Bar%23baz%22", title: 'link:"Foo Bar#baz"',
  447. "tracwysiwyg-link": 'link:"Foo Bar#baz"', onclick: "return false;" }),
  448. " ",
  449. element("a", "link:'Foo Bar'", {
  450. href: "./search?q=" + encodeURIComponent("link:'Foo Bar'"),
  451. title: "link:'Foo Bar'", "tracwysiwyg-link": "link:'Foo Bar'",
  452. onclick: "return false;" }),
  453. " ",
  454. element("a", "link:'Foo Bar#baz'", {
  455. href: "./search?q=" + encodeURIComponent("link:'Foo Bar#baz'"),
  456. title: "link:'Foo Bar#baz'", "tracwysiwyg-link": "link:'Foo Bar#baz'",
  457. onclick: "return false;" }),
  458. " ",
  459. element("a", "svn+ssh://example.com/trunk", {
  460. href: "./search?q=" + encodeURIComponent("svn+ssh://example.com/trunk"),
  461. title: "svn+ssh://example.com/trunk", "tracwysiwyg-link": "svn+ssh://example.com/trunk",
  462. onclick: "return false;" }),
  463. " ",
  464. element("a", "repository", {
  465. href: "./search?q=" + encodeURIComponent("svn+ssh://example.com/trunk"),
  466. title: "svn+ssh://example.com/trunk", "tracwysiwyg-link": "svn+ssh://example.com/trunk",
  467. onclick: "return false;" }),
  468. " ",
  469. element("a", "rfc-2396.compatible://link", {
  470. href: "./search?q=" + encodeURIComponent("rfc-2396.compatible://link"),
  471. title: "rfc-2396.compatible://link", "tracwysiwyg-link": "rfc-2396.compatible://link",
  472. onclick: "return false;" }),
  473. " ",
  474. element("a", "RFC 2396", {
  475. href: "./search?q=" + encodeURIComponent("rfc-2396.compatible://link"),
  476. title: "rfc-2396.compatible://link", "tracwysiwyg-link": "rfc-2396.compatible://link",
  477. onclick: "return false;" }),
  478. " ",
  479. "21:09,",
  480. element("u", "underline"),
  481. ",abc123 !21:09,",
  482. element("u", "underline"),
  483. ",abc123",
  484. " ",
  485. element("a", "foo:bar", {
  486. href: "./search?q=" + encodeURIComponent("foo:bar"),
  487. title: "foo:bar", "tracwysiwyg-link": "foo:bar",
  488. onclick: "return false;" }),
  489. " begin",
  490. element("a", "foo:bar", {
  491. href: "./search?q=" + encodeURIComponent("foo:bar"),
  492. title: "foo:bar", "tracwysiwyg-link": "foo:bar",
  493. onclick: "return false;" }),
  494. " ",
  495. element("a", "foo:bar", {
  496. href: "./search?q=" + encodeURIComponent("foo:bar"),
  497. title: "foo:bar", "tracwysiwyg-link": "foo:bar",
  498. onclick: "return false;" }),
  499. "end begin",
  500. element("a", "WikiStart", {
  501. href: "./search?q=" + encodeURIComponent("wiki:WikiStart"),
  502. title: "wiki:WikiStart", "tracwysiwyg-link": "wiki:WikiStart",
  503. onclick: "return false;" }),
  504. "end link:'Foo Bar#baz'");
  505. generateFragment.call(this, dom, [
  506. "link:WikiName",
  507. 'link:"Foo Bar" link:"Foo Bar#baz"',
  508. "link:'Foo Bar' link:'Foo Bar#baz'",
  509. "svn+ssh://example.com/trunk [svn+ssh://example.com/trunk repository]",
  510. "rfc-2396.compatible://link [rfc-2396.compatible://link RFC 2396]",
  511. "21:09,__underline__,abc123 !21:09,__underline__,abc123",
  512. "foo:bar begin[foo:bar foo:bar] [foo:bar foo:bar]end begin[wiki:WikiStart]end",
  513. "!link:'Foo Bar#baz'" ].join(" "));
  514. generate.call(this, dom, [
  515. "link:WikiName",
  516. 'link:"Foo Bar" link:"Foo Bar#baz"',
  517. "link:'Foo Bar' link:'Foo Bar#baz'",
  518. "svn+ssh://example.com/trunk [svn+ssh://example.com/trunk repository]",
  519. "rfc-2396.compatible://link [rfc-2396.compatible://link RFC 2396]",
  520. "21:09,__underline__,abc123 !21:09,__underline__,abc123",
  521. "foo:bar begin[foo:bar foo:bar] [foo:bar foo:bar]end begin[wiki:WikiStart]end",
  522. "!link:'Foo Bar#baz'" ].join(" "));
  523. });
  524. unit.add("[wiki:TracLinks label]", function() {
  525. var dom = element("p",
  526. element("a", "WikiName", {
  527. href: "./search?q=link%3AWikiName", title: "link:WikiName",
  528. "tracwysiwyg-link": "link:WikiName", onclick: "return false;" }),
  529. " ",
  530. element("a", "wiki name", {
  531. href: "./search?q=link%3AWikiName", title: "link:WikiName",
  532. "tracwysiwyg-link": "link:WikiName", onclick: "return false;" }),
  533. " ",
  534. element("a", "wiki]name", {
  535. href: "./search?q=wiki%3AWikiName", title: "wiki:WikiName",
  536. "tracwysiwyg-link": "wiki:WikiName", onclick: "return false;" }),
  537. " ",
  538. element("a", "wiki name", {
  539. href: "./search?q=wiki%3AWikiName", title: "wiki:WikiName",
  540. "tracwysiwyg-link": "wiki:WikiName", onclick: "return false;" }),
  541. " ",
  542. element("a", "Foo Bar", {
  543. href: "./search?q=link%3A%22Foo%20Bar%22", title: 'link:"Foo Bar"',
  544. "tracwysiwyg-link": 'link:"Foo Bar"', onclick: "return false;" }),
  545. " ",
  546. element("a", "Foo Bar#baz", {
  547. href: "./search?q=link%3A%22Foo%20Bar%23baz%22", title: 'link:"Foo Bar#baz"',
  548. "tracwysiwyg-link": 'link:"Foo Bar#baz"', onclick: "return false;" }),
  549. " ",
  550. element("a", "bar foo", {
  551. href: "./search?q=link%3A%22Foo%20Bar%22", title: 'link:"Foo Bar"',
  552. "tracwysiwyg-link": 'link:"Foo Bar"', onclick: "return false;" }),
  553. " ",
  554. element("a", 'foo "foobar" bar', {
  555. href: "./search?q=link%3A%22Foo%20Bar%23baz%22", title: 'link:"Foo Bar#baz"',
  556. "tracwysiwyg-link": 'link:"Foo Bar#baz"', onclick: "return false;" }),
  557. " ",
  558. element("a", "Foo Bar", {
  559. href: "./search?q=" + encodeURIComponent("link:'Foo Bar'"),
  560. title: "link:'Foo Bar'", "tracwysiwyg-link": "link:'Foo Bar'",
  561. onclick: "return false;" }),
  562. " ",
  563. element("a", "Foo Bar#baz", {
  564. href: "./search?q=" + encodeURIComponent("link:'Foo Bar#baz'"),
  565. title: "link:'Foo Bar#baz'", "tracwysiwyg-link": "link:'Foo Bar#baz'",
  566. onclick: "return false;" }),
  567. " ",
  568. element("a", "foo bar", {
  569. href: "./search?q=" + encodeURIComponent("link:'Foo Bar'"),
  570. title: "link:'Foo Bar'", "tracwysiwyg-link": "link:'Foo Bar'",
  571. onclick: "return false;" }),
  572. " ",
  573. element("a", "foo 'foobar' bar", {
  574. href: "./search?q=" + encodeURIComponent("link:'Foo Bar#baz'"),
  575. title: "link:'Foo Bar#baz'",
  576. "tracwysiwyg-link": "link:'Foo Bar#baz'",
  577. onclick: "return false;" }),
  578. " [link:'Foo Bar#baz'] [link:'Foo Bar#baz' label]");
  579. generateFragment.call(this, dom, [
  580. "[link:WikiName]",
  581. "[link:WikiName 'wiki name']",
  582. '[wiki:WikiName "wiki]name"]',
  583. "[WikiName 'wiki name']",
  584. '[link:"Foo Bar"] [link:"Foo Bar#baz"]',
  585. '[link:"Foo Bar" "bar foo"] [link:"Foo Bar#baz" foo "foobar" bar]',
  586. "[link:'Foo Bar'] [link:'Foo Bar#baz']",
  587. "[link:'Foo Bar' 'foo bar'] [link:'Foo Bar#baz' foo 'foobar' bar]",
  588. "![link:'Foo Bar#baz'] ![link:'Foo Bar#baz' label]" ].join(" "));
  589. generate.call(this, dom, [
  590. "[link:WikiName]",
  591. "[link:WikiName wiki name]",
  592. '[wiki:WikiName "wiki]name"]',
  593. "[wiki:WikiName wiki name]",
  594. '[link:"Foo Bar" Foo Bar] [link:"Foo Bar#baz" Foo Bar#baz]',
  595. '[link:"Foo Bar" bar foo] [link:"Foo Bar#baz" foo "foobar" bar]',
  596. "[link:'Foo Bar' Foo Bar] [link:'Foo Bar#baz' Foo Bar#baz]",
  597. "[link:'Foo Bar' foo bar] [link:'Foo Bar#baz' foo 'foobar' bar]",
  598. "![link:'Foo Bar#baz'] ![link:'Foo Bar#baz' label]" ].join(" "));
  599. });
  600. unit.add("[/relative label]", function() {
  601. var dom = element("p",
  602. element("a", "Trac", {
  603. href: "../trac", title: "../trac", "tracwysiwyg-link": "../trac",
  604. onclick: "return false;" }),
  605. " ",
  606. element("a", "here", {
  607. href: "/newticket?component=tracwysiwygplugin",
  608. title: "/newticket?component=tracwysiwygplugin",
  609. "tracwysiwyg-link": "/newticket?component=tracwysiwygplugin",
  610. onclick: "return false;" }),
  611. " ",
  612. element("a", "host", {
  613. href: "//hostname", title: "//hostname", "tracwysiwyg-link": "//hostname",
  614. onclick: "return false;" }),
  615. " ",
  616. element("a", "images", {
  617. href: "//hostname/images", title: "//hostname/images",
  618. "tracwysiwyg-link": "//hostname/images", onclick: "return false;" }),
  619. " ",
  620. element("a", "anchor", {
  621. href: "#anchor", title: "#anchor", "tracwysiwyg-link": "#anchor",
  622. onclick: "return false;" }));
  623. var wikitext = [
  624. "[../trac Trac]",
  625. "[/newticket?component=tracwysiwygplugin here]",
  626. "[//hostname host]",
  627. "[//hostname/images images]",
  628. "[#anchor anchor]" ].join(" ");
  629. generate.call(this, dom, wikitext);
  630. });
  631. unit.add("<wiki:bracket links>", function() {
  632. function a(link) {
  633. return element("a", link, {
  634. href: "./search?q=" + encodeURIComponent(link),
  635. title: link, "tracwysiwyg-link": link, onclick: "return false;" });
  636. }
  637. var dom = fragment(
  638. element("p", "<", a("link:1"), ">"),
  639. element("p", "Thing<", a("link:2 and (3)"), ">"),
  640. element("p", "<link:1>"),
  641. element("p", "Thing<link:2 and (3)>"));
  642. var wikitext = [
  643. "<link:1>",
  644. "",
  645. "Thing<link:2 and (3)>",
  646. "",
  647. "!<link:1>",
  648. "",
  649. "Thing!<link:2 and (3)>" ].join("\n");
  650. generate.call(this, dom, wikitext);
  651. });
  652. unit.add("[=#anchor]", function() {
  653. function a(link) {
  654. return element("a", link, {
  655. href: "./search?q=" + encodeURIComponent(link),
  656. title: link, "tracwysiwyg-link": link, onclick: "return false;" });
  657. }
  658. var dom = fragment(
  659. element("p",
  660. "This is the ",
  661. element("span", { "class": "wikianchor", id: "init" }),
  662. " initialization routine: ..."),
  663. element("p",
  664. "Look for ",
  665. element("span", { "class": "wikianchor", id : "extra" },
  666. element("i", "additional explanations")),
  667. " here."),
  668. element("p",
  669. "???",
  670. element("span", { "class": "wikianchor", id: "???" }),
  671. "???????: ..."),
  672. element("p",
  673. element("span", { "class": "wikianchor", id : "??" }, element("i", "????")),
  674. "???????????"));
  675. var wikitext = [
  676. "This is the [=#init] initialization routine: ...",
  677. "",
  678. "Look for [=#extra ''additional explanations''] here.",
  679. "",
  680. "???[=#???]???????: ...",
  681. "",
  682. "[=#?? ''????'']???????????" ].join("\n");
  683. generate.call(this, dom, wikitext);
  684. });
  685. unit.add("[[macro]]", function() {
  686. var dom = element("p",
  687. "Line break ", element("br"), " another line", element("br"),
  688. "last line [[bR]] ![[Br]] [[Macro]] ![[Macro]] [[Image?]] ![[Image?]] [[?]] ![[?]]");
  689. generateFragment.call(this, dom, "Line break [[BR]] another line[[br]]last line ![[bR]] !![[Br]] [[Macro]] ![[Macro]] [[Image?]] ![[Image?]] [[?]] ![[?]]");
  690. generate.call(this, dom, "Line break [[BR]] another line[[BR]]last line ![[bR]] !![[Br]] [[Macro]] ![[Macro]] [[Image?]] ![[Image?]] [[?]] ![[?]]");
  691. });
  692. unit.add("WikiPageName", function() {
  693. var dom = fragment(
  694. element("p",
  695. a("wiki:CamelCase", "CamelCase"),
  696. " CamelCase FooBarA FOo FoobarA OneÅngström Oneångström setTextColor"),
  697. element("p",
  698. a("wiki:WikiStart", "WikiStart"),
  699. " Wiki",
  700. a("wiki:Start", "Start"),
  701. " ",
  702. a("wiki:Wiki", "Wiki"),
  703. "Start Wiki",
  704. a("wiki:Start", "Start"),
  705. "Wiki"));
  706. generate.call(this, dom, [
  707. "CamelCase !CamelCase FooBarA FOo FoobarA OneÅngström Oneångström setTextColor",
  708. "",
  709. "WikiStart Wiki[wiki:Start] [wiki:Wiki]Start Wiki[wiki:Start]Wiki" ].join("\n"));
  710. });
  711. unit.add('["internal free link"]', function() {
  712. var dom = element("p",
  713. "link - ",
  714. element("a", "internal free link", {
  715. href: "./search?q=" + encodeURIComponent('wiki:"internal free link"'),
  716. title: 'wiki:"internal free link"', "tracwysiwyg-link": 'wiki:"internal free link"',
  717. onclick: "return false;" }),
  718. ' - ["free link"]');
  719. generate.call(this, dom, 'link - [wiki:"internal free link" internal free link] - !["free link"]');
  720. });
  721. unit.add("traclink + underline", function() {
  722. var dom = element("p",
  723. element("u", a("ticket:123", "#123")), " ",
  724. a("ticket:123", element("u", "#123")), " ",
  725. element("u", a("report:123", "{123}")), " ",
  726. a("report:123", element("u", "{123}")), " ",
  727. element("u", a("changeset:123", "[123]")), " ",
  728. a("changeset:123", element("u", "[123]")), " ",
  729. element("u", a("changeset:123", "r123")), " ",
  730. a("changeset:123", element("u", "r123")), " ",
  731. element("u", a("log:@123:234", "[123:234]")), " ",
  732. a("log:@123:234", element("u", "[123:234]")), " ",
  733. element("u", a("wiki:WikiStart", "wiki:WikiStart")), " ",
  734. a("wiki:WikiStart", element("u", "wiki:WikiStart")), " ",
  735. element("u", a("wiki:WikiStart", "WikiStart")), " ",
  736. a("wiki:WikiStart", element("u", "WikiStart")));
  737. generateWikitext.call(this, dom, [
  738. '__#123__',
  739. '__#123__',
  740. '__{123}__',
  741. '__{123}__',
  742. '__[123]__',
  743. '__[123]__',
  744. '__[changeset:123 r123]__',
  745. '__[changeset:123 r123]__',
  746. '__[123:234]__',
  747. '__[123:234]__',
  748. '__[wiki:WikiStart wiki:WikiStart]__',
  749. '__[wiki:WikiStart wiki:WikiStart]__',
  750. '__[wiki:WikiStart]__',
  751. '__[wiki:WikiStart]__' ].join(" "));
  752. });
  753. unit.add("token + br", function() {
  754. var dom = fragment(
  755. element("p", "head ", a("http://localhost/", "http://localhost/"), element("br"), "tail"),
  756. element("p", "head http://localhost/", element("br"), "tail"),
  757. element("p", "head ", element("tt", "teletype"), element("br"), "tail"),
  758. element("p", "head ", a("wiki:TracLinks", "TracLinks"), element("br"), "tail"),
  759. element("p",
  760. "head ", a("http://localhost/", "http://localhost/"), " ",
  761. a("wiki:TracLinks", "wiki:TracLinks"),
  762. element("br"),
  763. "tail"),
  764. element("p", "head http://localhost/ wiki:TracLinks", element("br"), "tail"));
  765. generateWikitext.call(this, dom, [
  766. "head http://localhost/ [[BR]]tail",
  767. "",
  768. "head !http://localhost/ [[BR]]tail",
  769. "",
  770. "head `teletype`[[BR]]tail",
  771. "",
  772. "head TracLinks[[BR]]tail",
  773. "",
  774. "head http://localhost/ wiki:TracLinks [[BR]]tail",
  775. "",
  776. "head !http://localhost/ !wiki:TracLinks [[BR]]tail" ].join("\n"));
  777. });
  778. if (window.getSelection) {
  779. unit.add("block + br", function() {
  780. function br() { return element("br"); }
  781. var wikitext = [
  782. "text, br",
  783. "",
  784. "text'', br[[BR]]''",
  785. "",
  786. "|| 1,1[[BR]] || || 1,3 ||",
  787. "|| || 2,2[[BR]][[BR]] ||",
  788. "",
  789. " * list, br[[BR]]",
  790. " * list, br",
  791. " * ",
  792. "",
  793. "text, br[[BR]]" ].join("\n")
  794. generateWikitext.call(this,
  795. fragment(
  796. element("p", "text, br", br()),
  797. element("p", "text", element("i", ", br", br()), br()),
  798. element("table", { "class": "wiki" },
  799. element("tbody",
  800. element("tr",
  801. element("td", "1,1", br(), br()),
  802. element("td", br()),
  803. element("td", "1,3", br())),
  804. element("tr",
  805. element("td", br()),
  806. element("td", "2,2", br(), br(), br())))),
  807. element("ul",
  808. element("li", "list, br", br(), br()),
  809. element("li", "list, br", br()),
  810. element("li")),
  811. element("p", "text, br", br(), br())),
  812. wikitext);
  813. generateFragment.call(this,
  814. fragment(
  815. element("p", "text, br"),
  816. element("p", "text", element("i", ", br", br()), br()),
  817. element("table", { "class": "wiki" },
  818. element("tbody",
  819. element("tr",
  820. element("td", "1,1", br(), br()),
  821. element("td", br()),
  822. element("td", "1,3")),
  823. element("tr",
  824. element("td", br()),
  825. element("td", "2,2", br(), br(), br())))),
  826. element("ul",
  827. element("li", "list, br", br(), br()),
  828. element("li", "list, br"),
  829. element("li", br())),
  830. element("p", "text, br", br(), br())),
  831. wikitext);
  832. });
  833. }
  834. else {
  835. unit.add("block + br", function() {
  836. function br() { return element("br"); }
  837. var wikitext = [
  838. "text, br",
  839. "",
  840. "text'', br[[BR]]''",
  841. "",
  842. "|| 1,1[[BR]] || || 1,3 ||",
  843. "|| || 2,2[[BR]][[BR]] ||",
  844. "",
  845. " * list, br[[BR]]",
  846. " * list, br",
  847. " * ",
  848. "",
  849. "text, br[[BR]]" ].join("\n")
  850. generate.call(this,
  851. fragment(
  852. element("p", "text, br"),
  853. element("p", "text", element("i", ", br", br())),
  854. element("table", { "class": "wiki" },
  855. element("tbody",
  856. element("tr",
  857. element("td", "1,1", br()),
  858. element("td"),
  859. element("td", "1,3")),
  860. element("tr",
  861. element("td"),
  862. element("td", "2,2", br(), br())))),
  863. element("ul",
  864. element("li", "list, br", br()),
  865. element("li", "list, br"),
  866. element("li")),
  867. element("p", "text, br", br())),
  868. wikitext);
  869. });
  870. }
  871. unit.add("citation", function() {
  872. var dom = fragment(
  873. element("blockquote", { "class": "citation" },
  874. element("p", "This is the quoted text continued"),
  875. element("blockquote", { "class": "citation" },
  876. element("p", "a nested quote"),
  877. element("blockquote", { "class": "citation" },
  878. element("p", "a nested-nested quote")))),
  879. element("p", "A comment on the above"),
  880. element("blockquote", { "class": "citation" },
  881. element("blockquote", { "class": "citation" },
  882. element("p", "start 2nd level")),
  883. element("p", "first level")));
  884. generateFragment.call(this, dom, [
  885. "> This is the quoted text",
  886. "> continued",
  887. "> > a nested quote",
  888. "> > > a nested-nested quote",
  889. "A comment on the above",
  890. "> > start 2nd level",
  891. ">first level" ].join("\n"));
  892. generate.call(this, dom, [
  893. "> This is the quoted text continued",
  894. "> > a nested quote",
  895. "> > > a nested-nested quote",
  896. "",
  897. "A comment on the above",
  898. "",
  899. "> > start 2nd level",
  900. "> first level" ].join("\n"));
  901. });
  902. unit.add("header", function() {
  903. var dom = fragment(
  904. element("h1", "Heading 1"),
  905. element("h2", { id: "anchor-2" }, "Heading 2"),
  906. element("h3", element("u", "Heading"), " ", element("i", "3")),
  907. element("h4", { id: "????-4" },
  908. "Heading 4 with ",
  909. element("a", "link", {
  910. href: "./search?q=" + encodeURIComponent('wiki:WikiStart'),
  911. title: 'wiki:WikiStart', "tracwysiwyg-link": 'wiki:WikiStart',
  912. onclick: "return false;" })),
  913. element("h5", "Heading 5"),
  914. element("h6", { id: "anchor-6" }, "Heading 6"));
  915. generate.call(this, dom, [
  916. "= Heading 1 =",
  917. "== Heading 2 == #anchor-2",
  918. "=== __Heading__ ''3'' ===",
  919. "==== Heading 4 with [wiki:WikiStart link] ==== #????-4",
  920. "===== Heading 5 =====",
  921. "====== Heading 6 ====== #anchor-6" ].join("\n"));
  922. });
  923. unit.add("header 2", function() {
  924. var dom = fragment(
  925. element("h1", "Heading 1"),
  926. element("h2", { id: "anchor-2" }, "Heading 2"),
  927. element("h3", element("u", "Heading"), " ", element("i", "3")),
  928. element("h4", { id: "????-4" },
  929. "Heading 4 with ",
  930. element("a", "link", {
  931. href: "./search?q=" + encodeURIComponent('wiki:WikiStart'),
  932. title: 'wiki:WikiStart', "tracwysiwyg-link": 'wiki:WikiStart',
  933. onclick: "return false;" })),
  934. element("h5", "Heading 5"),
  935. element("h6", { id: "anchor-6" }, "Heading 6"));
  936. generateFragment.call(this, dom, [
  937. "= Heading 1 ",
  938. "== Heading 2 #anchor-2",
  939. "=== __Heading__ ''3'' ",
  940. "==== Heading 4 with [wiki:WikiStart link] #????-4",
  941. "===== Heading 5 ",
  942. "====== Heading 6 #anchor-6" ].join("\n"));
  943. });
  944. unit.add("list", function() {
  945. var dom = fragment(
  946. element("p", "Paragraph"),
  947. element("ul",
  948. element("li", "foo bar boo baz"),
  949. element("ul", element("li", "Subitem Subitem line 2")),
  950. element("li", "item 2 item 2 line 2")),
  951. element("p", "Paragraph"));
  952. generateFragment.call(this, dom, [
  953. "Paragraph",
  954. " * foo bar",
  955. " boo baz",
  956. " * Subitem",
  957. " Subitem line 2",
  958. " * item 2",
  959. " item 2 line 2",
  960. "Paragraph" ].join("\n"));
  961. generate.call(this, dom, [
  962. "Paragraph",
  963. "",
  964. " * foo bar boo baz",
  965. " * Subitem Subitem line 2",
  966. " * item 2 item 2 line 2",
  967. "",
  968. "Paragraph" ].join("\n"));
  969. });
  970. unit.add("list 2", function() {
  971. var dom = fragment(
  972. element("ul",
  973. element("li", "foo bar boo baz"),
  974. element("ul",
  975. element("li", "Subitem 1"),
  976. element("ul",
  977. element("li", "nested item 1"),
  978. element("li", "nested item 2 nested item 2 continued")),
  979. element("li", "Subitem 2 subitem 2 continued"),
  980. element("li", "Subitem 3 subitem 3 continued")),
  981. element("li", "item 2 item 2 line 2")),
  982. element("p", "Paragraph"));
  983. generateFragment.call(this, dom, [
  984. " * foo bar",
  985. " boo baz",
  986. " * Subitem 1",
  987. " - nested item 1",
  988. " - nested item 2",
  989. " nested item 2 continued",
  990. " * Subitem 2",
  991. " subitem 2 continued",
  992. " * Subitem 3",
  993. " subitem 3 continued",
  994. " * item 2",
  995. " item 2 line 2",
  996. "Paragraph" ].join("\n"));
  997. generate.call(this, dom, [
  998. " * foo bar boo baz",
  999. " * Subitem 1",
  1000. " * nested item 1",
  1001. " * nested item 2 nested item 2 continued",
  1002. " * Subitem 2 subitem 2 continued",
  1003. " * Subitem 3 subitem 3 continued",
  1004. " * item 2 item 2 line 2",
  1005. "",
  1006. "Paragraph" ].join("\n"));
  1007. });
  1008. unit.add("ordered list", function() {
  1009. var dom = fragment(
  1010. element("p", "Paragraph"),
  1011. element("ol",
  1012. element("li", "item 1"),
  1013. element("ol", { "class": "arabiczero" },
  1014. element("li", "item 1.1"),
  1015. element("li", "item 1.2"),
  1016. element("ol", { "class": "loweralpha" },
  1017. element("li", "item 1.2.a"),
  1018. element("li", "item 1.2.b")),
  1019. element("li", "item 1.3"),
  1020. element("ol", { "class": "loweralpha" },
  1021. element("li", "item 1.3.a"),
  1022. element("li", "item 1.3.b")),
  1023. element("li", "item 1.4"),
  1024. element("ol", { "class": "upperalpha" },
  1025. element("li", "item 1.4.A"),
  1026. element("li", "item 1.4.B"),
  1027. element("li", "item 1.4.C")),
  1028. element("li", "item 1.5"),
  1029. element("ol", { "class": "upperalpha" },
  1030. element("li", "item 1.5.A")),
  1031. element("li", "item 1.6"),
  1032. element("ol", { "class": "lowerroman" },
  1033. element("li", "item 1.6.i"),
  1034. element("li", "item 1.6.ii")),
  1035. element("li", "item 1.7"),
  1036. element("ol", { "class": "upperroman" },
  1037. element("li", "item 1.7.I"),
  1038. element("li", "item 1.7.II")))),
  1039. element("p", "Paragraph"));
  1040. generateFragment.call(this, dom, [
  1041. "Paragraph",
  1042. " 1. item 1",
  1043. " 0. item 1.1",
  1044. " 2. item 1.2",
  1045. " a. item 1.2.a",
  1046. " z. item 1.2.b",
  1047. " a. item 1.3",
  1048. " b. item 1.3.a",
  1049. " y. item 1.3.b",
  1050. " Z. item 1.4",
  1051. " A. item 1.4.A",
  1052. " z. item 1.4.B",
  1053. " z. item 1.4.C",
  1054. " ii. item 1.5",
  1055. " C. item 1.5.A",
  1056. " XVI. item 1.6",
  1057. " i. item 1.6.i",
  1058. " x. item 1.6.ii",
  1059. " 0. item 1.7",
  1060. " I. item 1.7.I",
  1061. " III. item 1.7.II",
  1062. "Paragraph" ].join("\n"));
  1063. generate.call(this, dom, [
  1064. "Paragraph",
  1065. "",
  1066. " 1. item 1",
  1067. " 0. item 1.1",
  1068. " 0. item 1.2",
  1069. " a. item 1.2.a",
  1070. " a. item 1.2.b",
  1071. " 0. item 1.3",
  1072. " a. item 1.3.a",
  1073. " a. item 1.3.b",
  1074. " 0. item 1.4",
  1075. " A. item 1.4.A",
  1076. " A. item 1.4.B",
  1077. " A. item 1.4.C",
  1078. " 0. item 1.5",
  1079. " A. item 1.5.A",
  1080. " 0. item 1.6",
  1081. " i. item 1.6.i",
  1082. " i. item 1.6.ii",
  1083. " 0. item 1.7",
  1084. " I. item 1.7.I",
  1085. " I. item 1.7.II",
  1086. "",
  1087. "Paragraph" ].join("\n"));
  1088. });
  1089. unit.add("list + ordered list", function() {
  1090. var dom = fragment(
  1091. element("ul",
  1092. element("li", "Item 1"),
  1093. element("ul", element("li", "Item 1.1")),
  1094. element("li", "Item 2")),
  1095. element("ol",
  1096. element("li", "Item 1"),
  1097. element("ol", { "class": "loweralpha" },
  1098. element("li", "Item 1.a"),
  1099. element("li", "Item 1.b"),
  1100. element("ol", { "class": "lowerroman" },
  1101. element("li", "Item 1.b.i"),
  1102. element("li", "Item 1.b.ii"))),
  1103. element("li", "Item 2")),
  1104. element("p", "And numbered lists can also be given an explicit number:"),
  1105. element("ol", { start: 3 }, element("li", "Item 3")));
  1106. generateFragment.call(this, dom, [
  1107. " * Item 1",
  1108. " * Item 1.1",
  1109. " * Item 2",
  1110. " 1. Item 1",
  1111. " a. Item 1.a",
  1112. " a. Item 1.b",
  1113. " i. Item 1.b.i",
  1114. " i. Item 1.b.ii",
  1115. " 1. Item 2",
  1116. "And numbered lists can also be given an explicit number:",
  1117. " 3. Item 3" ].join("\n"));
  1118. generate.call(this, dom, [
  1119. " * Item 1",
  1120. " * Item 1.1",
  1121. " * Item 2",
  1122. "",
  1123. " 1. Item 1",
  1124. " a. Item 1.a",
  1125. " a. Item 1.b",
  1126. " i. Item 1.b.i",
  1127. " i. Item 1.b.ii",
  1128. " 1. Item 2",
  1129. "",
  1130. "And numbered lists can also be given an explicit number:",
  1131. "",
  1132. " 3. Item 3" ].join("\n"));
  1133. });
  1134. unit.add("list at beginning of line", function() {
  1135. var dom = fragment(
  1136. element("ul",
  1137. element("li", "item 1"),
  1138. element("li", "item 2"),
  1139. element("ul", element("li", "sub 2.1"), element("li", "sub 2.2"))),
  1140. element("ol", { "class": "loweralpha" },
  1141. element("li", "item A"), element("li", "item B")),
  1142. element("p", "Paragraph"));
  1143. generateFragment.call(this, dom, [
  1144. "- item 1",
  1145. "- item 2",
  1146. " - sub 2.1",
  1147. " - sub 2.2",
  1148. "a. item A",
  1149. "b. item B",
  1150. "Paragraph" ].join("\n"));
  1151. generate.call(this, dom, [
  1152. " * item 1",
  1153. " * item 2",
  1154. " * sub 2.1",
  1155. " * sub 2.2",
  1156. "",
  1157. " a. item A",
  1158. " a. item B",
  1159. "",
  1160. "Paragraph" ].join("\n"));
  1161. });
  1162. unit.add("list + code block", function() {
  1163. var dom = fragment(
  1164. element("p", "Paragraph"),
  1165. element("ul",
  1166. element("li",
  1167. "item 1",
  1168. element("pre", { "class": "wiki" }, "code")),
  1169. element("ul",
  1170. element("li",
  1171. "item 1.1",
  1172. element("pre", { "class": "wiki" }, "code"),
  1173. "cont.",
  1174. element("pre", { "class": "wiki" }, "code"))),
  1175. element("li",
  1176. "item 2",
  1177. element("pre", { "class": "wiki" }, "code"))),
  1178. element("ol", element("li", "item 1")));
  1179. generateFragment.call(this, dom, [
  1180. "Paragraph",
  1181. " * item 1",
  1182. "{{{",
  1183. "code",
  1184. "}}}",
  1185. " * item 1.1",
  1186. "{{{",
  1187. "code",
  1188. "}}}",
  1189. " cont.",
  1190. "{{{",
  1191. "code",
  1192. "}}}",
  1193. " * item 2",
  1194. "{{{",
  1195. "code",
  1196. "}}}",
  1197. " 1. item 1" ].join("\n"));
  1198. generate.call(this, dom, [
  1199. "Paragraph",
  1200. "",
  1201. " * item 1",
  1202. "{{{",
  1203. "code",
  1204. "}}}",
  1205. " * item 1.1",
  1206. "{{{",
  1207. "code",
  1208. "}}}",
  1209. " cont.",
  1210. "{{{",
  1211. "code",
  1212. "}}}",
  1213. " * item 2",
  1214. "{{{",
  1215. "code",
  1216. "}}}",
  1217. "",
  1218. " 1. item 1" ].join("\n"));
  1219. });
  1220. unit.add("list + citation", function() {
  1221. var dom = fragment(
  1222. element('ol', element('li', 'item 1')),
  1223. element('blockquote', { 'class': 'citation' }, element("p", "citation 1")),
  1224. element('ul',
  1225. element('li', 'item 2'),
  1226. element("ol",
  1227. element('li', 'item 2.1'),
  1228. element('li', 'item 2.2'))),
  1229. element('blockquote', { 'class': 'citation' }, element("p", "citation 2 citation 3")),
  1230. element('ol', element('li', 'item 3')));
  1231. generateFragment.call(this, dom, [
  1232. ' 1. item 1',
  1233. '> citation 1',
  1234. ' * item 2',
  1235. ' 1. item 2.1',
  1236. ' 1. item 2.2',
  1237. '> citation 2',
  1238. '> citation 3',
  1239. ' 1. item 3' ].join("\n"));
  1240. generateWikitext.call(this, dom, [
  1241. ' 1. item 1',
  1242. '',
  1243. '> citation 1',
  1244. '',
  1245. ' * item 2',
  1246. ' 1. item 2.1',
  1247. ' 1. item 2.2',
  1248. '',
  1249. '> citation 2 citation 3',
  1250. '',
  1251. ' 1. item 3' ].join("\n"));
  1252. });
  1253. unit.add("definition", function() {
  1254. var dom = element("dl",
  1255. element("dt", "python"),
  1256. element("dd", "www.python.org :: cont."),
  1257. element("dt", element("b", "trac")),
  1258. element("dd",
  1259. element("b", "trac"), ".edgewall.org cont.",
  1260. " ", element("tt", "trac-hacks::"), " trac-hacks.org"));
  1261. generateFragment.call(this, dom, [
  1262. " python:: www.python.org :: cont.",
  1263. " '''trac''':: '''trac'''.edgewall.org",
  1264. " cont.",
  1265. " `trac-hacks::` trac-hacks.org" ].join("\n"));
  1266. generate.call(this, dom, [
  1267. " python:: www.python.org :: cont.",
  1268. " '''trac''':: '''trac'''.edgewall.org cont. `trac-hacks::` trac-hacks.org" ].join("\n"));
  1269. });
  1270. unit.add("blockquote", function() {
  1271. var dom = fragment(
  1272. element("p", "Paragraph"),
  1273. element("blockquote",
  1274. element("p", "blockquote 1 cont. 1"),
  1275. element("blockquote",
  1276. element("p", "blockquote 1.1"),
  1277. element("blockquote", element("p", "blockquote 1.1.1 cont. 1.1.1")),
  1278. element("p", "blockquote 1.2")),
  1279. element("p", "blockquote 2")),
  1280. element("p", "Paragraph"));
  1281. generateFragment.call(this, dom, [
  1282. "Paragraph",
  1283. " blockquote 1",
  1284. " cont. 1",
  1285. " blockquote 1.1",
  1286. " blockquote 1.1.1",
  1287. " cont. 1.1.1",
  1288. " blockquote 1.2",
  1289. " blockquote 2",
  1290. "Paragraph" ].join("\n"));
  1291. generate.call(this, dom, [
  1292. "Paragraph",
  1293. "",
  1294. " blockquote 1 cont. 1",
  1295. " blockquote 1.1",
  1296. " blockquote 1.1.1 cont. 1.1.1",
  1297. " blockquote 1.2",
  1298. " blockquote 2",
  1299. "",
  1300. "Paragraph" ].join("\n"));
  1301. });
  1302. unit.add("table", function() {
  1303. var dom = fragment(
  1304. element("p", "Paragraph"),
  1305. element("table", { "class": "wiki" },
  1306. element("tbody",
  1307. element("tr", element("td", "1.1"), element("td", "1.2")),
  1308. element("tr", element("td", "2.1")),
  1309. element("tr",
  1310. element("td", "3.1"),
  1311. element("td", element("u", "3.2")),
  1312. element("td", element("tt", "3"), " ", element("tt", "-"))))),
  1313. element("p", "Paragraph"));
  1314. generateFragment.call(this, dom, [
  1315. "Paragraph",
  1316. "||1.1||1.2||",
  1317. "||2.1",
  1318. "||3.1||__3.2__||`3` `-`",
  1319. "Paragraph" ].join("\n"));
  1320. generate.call(this, dom, [
  1321. "Paragraph",
  1322. "",
  1323. "|| 1.1 || 1.2 ||",
  1324. "|| 2.1 ||",
  1325. "|| 3.1 || __3.2__ || `3` `-` ||",
  1326. "",
  1327. "Paragraph" ].join("\n"));
  1328. });
  1329. unit.add("colspan", function() {
  1330. var dom = fragment(
  1331. element("p", "Paragraph"),
  1332. element("table", { "class": "wiki" },
  1333. element("tbody",
  1334. element("tr", element("td", "1.1"), element("td", "1.2", { colSpan: 2 })),
  1335. element("tr", element("td", "2.1", { colSpan: 3 })),
  1336. element("tr",
  1337. element("td", "3.1"),
  1338. element("td", element("u", "3.2")),
  1339. element("td", element("tt", "3.3"))))),
  1340. element("p", "Paragraph"));
  1341. generateFragment.call(this, dom, [
  1342. "Paragraph",
  1343. "||1.1||||1.2",
  1344. "||||||2.1",
  1345. "||3.1||__3.2__||`3.3`",
  1346. "Paragraph" ].join("\n"));
  1347. generate.call(this, dom, [
  1348. "Paragraph",
  1349. "",
  1350. "|| 1.1 |||| 1.2 ||",
  1351. "|||||| 2.1 ||",
  1352. "|| 3.1 || __3.2__ || `3.3` ||",
  1353. "",
  1354. "Paragraph" ].join("\n"));
  1355. });
  1356. unit.add("table header", function() {
  1357. var dom = fragment(
  1358. element("p", "Paragraph"),
  1359. element("table", { "class": "wiki" },
  1360. element("tbody",
  1361. element("tr", element("th", "1.1"), element("td", "1.2", { colSpan: 2 })),
  1362. element("tr", element("th", "2.1", { colSpan: 3 })),
  1363. element("tr",
  1364. element("td", "3.1"),
  1365. element("th", element("u", "3.2")),
  1366. element("td", element("tt", "3.3"))))),
  1367. element("p", "Paragraph"));
  1368. generateFragment.call(this, dom, [
  1369. "Paragraph",
  1370. "||=1.1=||||1.2",
  1371. "||||||=2.1=||",
  1372. "||3.1||=__3.2__=||`3.3`",
  1373. "Paragraph" ].join("\n"));
  1374. generate.call(this, dom, [
  1375. "Paragraph",
  1376. "",
  1377. "||= 1.1 =|||| 1.2 ||",
  1378. "||||||= 2.1 =||",
  1379. "|| 3.1 ||= __3.2__ =|| `3.3` ||",
  1380. "",
  1381. "Paragraph" ].join("\n"));
  1382. });
  1383. unit.add("table with alignment", function() {
  1384. var dom = fragment(
  1385. element("p", "Paragraph"),
  1386. element("table", { "class": "wiki" },
  1387. element("tbody",
  1388. element("tr", element("th", "1.1"),
  1389. element("td", "1.2", { colSpan: 2, align: "right" })),
  1390. element("tr", element("th", "2.1", { colSpan: 3, align: "left" })),
  1391. element("tr",
  1392. element("td", "3||1", { align: "right" }),
  1393. element("th", element("u", "3.2")),
  1394. element("td", element("tt", "3.3"), { align: "left" })),
  1395. element("tr",
  1396. element("th", "4.1", { align: "center" }),
  1397. element("td", "4.2"),
  1398. element("td", "4.3", { align: "center" })))),
  1399. element("p", "Paragraph"));
  1400. generateFragment.call(this, dom, [
  1401. "Paragraph",
  1402. "||=1.1=|||| 1.2",
  1403. "||||||=2.1 =||",
  1404. "|| 3!||1||= __3.2__ =||`3.3` ||",
  1405. "||= 4.1 =|| 4.2 || 4.3 ||",
  1406. "Paragraph" ].join("\n"));
  1407. generate.call(this, dom, [
  1408. "Paragraph",
  1409. "",
  1410. "||= 1.1 =|||| 1.2||",
  1411. "||||||=2.1 =||",
  1412. "|| 3!||1||= __3.2__ =||`3.3` ||",
  1413. "||= 4.1 =|| 4.2 || 4.3 ||",
  1414. "",
  1415. "Paragraph" ].join("\n"));
  1416. });
  1417. unit.add("table with row continuation", function() {
  1418. var dom = fragment(
  1419. element("p", "Paragraph"),
  1420. element("table", { "class": "wiki" },
  1421. element("tbody",
  1422. element("tr", element("td", "1.1"), element("td", "1.2"), element("td", "1.3")),
  1423. element("tr", element("td", "2.1")),
  1424. element("tr",
  1425. element("td", "3.1"),
  1426. element("td", element("u", "3.2")),
  1427. element("td", element("tt", "3.3"))))),
  1428. element("p", "Paragraph"));
  1429. generateFragment.call(this, dom, [
  1430. "Paragraph",
  1431. "||1.1||1.2|| \\",
  1432. "||1.3",
  1433. "||2.1",
  1434. "||3.1||__3.2__||`3.3`||\\",
  1435. "Paragraph" ].join("\n"));
  1436. });
  1437. unit.add("table + rule", function() {
  1438. var dom = fragment(
  1439. element("table", { "class": "wiki" },
  1440. element("tbody", element("tr", element("td", "1st")))),
  1441. element("p", element("b", "bold")),
  1442. element("table", { "class": "wiki" },
  1443. element("tbody", element("tr", element("td", "2nd")))),
  1444. element("p", "'''normal"));
  1445. generateFragment.call(this, dom, [
  1446. "||1st||",
  1447. "'''bold'''",
  1448. "||2nd||",
  1449. "!'''normal" ].join("\n"));
  1450. generate.call(this, dom, [
  1451. "|| 1st ||",
  1452. "",
  1453. "'''bold'''",
  1454. "",
  1455. "|| 2nd ||",
  1456. "",
  1457. "!'''normal" ].join("\n"));
  1458. });
  1459. unit.add("blockquote + table", function() {
  1460. var dom = fragment(
  1461. element("p", "Paragraph"),
  1462. element("table", { "class": "wiki" },
  1463. element("tbody",
  1464. element("tr", element("td", "pre.1"), element("td", "pre.2")))),
  1465. element("blockquote",
  1466. element("table", { "class": "wiki" },
  1467. element("tbody",
  1468. element("tr", element("td", "1.1"), element("td", "1.2")),
  1469. element("tr", element("td", "2.1")))),
  1470. element("blockquote",
  1471. element("table", { "class": "wiki" },
  1472. element("tbody",
  1473. element("tr", element("td", "deep"))))),
  1474. element("table", { "class": "wiki" },
  1475. element("tbody",
  1476. element("tr",
  1477. element("td", "3.1"),
  1478. element("td", element("u", "3.2")),
  1479. element("td", element("tt", "3.3")))))),
  1480. element("table", { "class": "wiki" },
  1481. element("tbody",
  1482. element("tr", element("td", "post.1"), element("td", "post.2")))),
  1483. element("p", "Paragraph"));
  1484. generateFragment.call(this, dom, [
  1485. "Paragraph",
  1486. "||pre.1||pre.2||",
  1487. " ||1.1||1.2||",
  1488. " ||2.1",
  1489. " ||deep||",
  1490. " ||3.1||__3.2__||`3.3`",
  1491. "||post.1||post.2||",
  1492. "Paragraph" ].join("\n"));
  1493. generate.call(this, dom, [
  1494. "Paragraph",
  1495. "",
  1496. "|| pre.1 || pre.2 ||",
  1497. "",
  1498. " || 1.1 || 1.2 ||",
  1499. " || 2.1 ||",
  1500. " || deep ||",
  1501. " || 3.1 || __3.2__ || `3.3` ||",
  1502. "",
  1503. "|| post.1 || post.2 ||",
  1504. "",
  1505. "Paragraph" ].join("\n"));
  1506. });
  1507. unit.add("table [ paragraph, ul ]", function() {
  1508. var dom = fragment(
  1509. element("table", { "class": "wiki" },
  1510. element("tbody",
  1511. element("tr",
  1512. element("td", element("p", "1.1")),
  1513. element("td",
  1514. element("ul",
  1515. element("li", "item 1"),
  1516. element("li", "item 2")))),
  1517. element("tr",
  1518. element("td",
  1519. element("p", "2.1"),
  1520. element("ul",
  1521. element("li", "item 3"),
  1522. element("li", "item 4")))))));
  1523. generateWikitext.call(this, dom, [
  1524. "|| 1.1 || * item 1[[BR]] * item 2 ||",
  1525. "|| 2.1[[BR]][[BR]] * item 3[[BR]] * item 4 ||" ].join("\n"));
  1526. });
  1527. unit.add("table from word", function() {
  1528. var dom = element("div");
  1529. dom.innerHTML = [
  1530. '',
  1531. '<table class="MsoTableGrid" style="border: medium none ; border-collapse: collapse;" border="1" cellpadding="0" cellspacing="0">',
  1532. ' <tbody><tr style="">',
  1533. ' <td style="border: 1pt solid windowtext; padding: 0mm 5.4pt; width: 217.55pt;" valign="top" width="290">',
  1534. ' <p class="MsoNormal"><span lang="EN-US">a<o:p></o:p></span></p>',
  1535. ' <p class="MsoNormal"><span lang="EN-US">b<o:p></o:p></span></p>',
  1536. ' </td>',
  1537. ' <td style="border-style: solid solid solid none; border-color: windowtext windowtext windowtext -moz-use-text-color; border-width: 1pt 1pt 1pt medium; padding: 0mm 5.4pt; width: 217.55pt;" valign="top" width="290">',
  1538. '',
  1539. ' <p class="MsoNormal"><span lang="EN-US">b<o:p></o:p></span></p>',
  1540. ' </td>',
  1541. ' </tr>',
  1542. ' <tr style="">',
  1543. ' <td style="border-style: none solid solid; border-color: -moz-use-text-color windowtext windowtext; border-width: medium 1pt 1pt; padding: 0mm 5.4pt; width: 217.55pt;" valign="top" width="290">',
  1544. ' <p class="MsoNormal"><span lang="EN-US">c<o:p></o:p></span></p>',
  1545. ' </td>',
  1546. ' <td style="border-style: none solid solid none; border-color: -moz-use-text-color windowtext windowtext -moz-use-text-color; border-width: medium 1pt 1pt medium; padding: 0mm 5.4pt; width: 217.55pt;" valign="top" width="290">',
  1547. '',
  1548. ' <p class="MsoNormal"><span lang="EN-US">d<o:p></o:p></span></p>',
  1549. ' </td>',
  1550. ' </tr>',
  1551. '</tbody></table>',
  1552. '' ].join("\n");
  1553. generateWikitext.call(this, dom, [
  1554. "|| a[[BR]][[BR]]b || b ||",
  1555. "|| c || d ||" ].join("\n"));
  1556. });
  1557. unit.add("domToWikitext for code block", function() {
  1558. var br = function() { return element("br") };
  1559. var dom = fragment(
  1560. element("h1", "Heading", br(), "1"),
  1561. element("h2", "Heading", br(), "2"),
  1562. element("h3", "Heading", br(), "3"),
  1563. element("h4", "Heading", br(), "4"),
  1564. element("h5", "Heading", br(), "5"),
  1565. element("h6", "Heading", br(), "6"),
  1566. element("p",
  1567. "var TracWysiwyg = function(textarea) {", br(),
  1568. "...", br(),
  1569. "}"),
  1570. element("blockquote", { "class": "citation" }, element("p", "citation", br(), "continued")),
  1571. element("blockquote", element("p", "quote", br(), "continued")),
  1572. element("ul",
  1573. element("li", "item 1", br(), "continued"),
  1574. element("ol", element("li", "item", br(), "1.1"))),
  1575. element("dl",
  1576. element("dt", "def to_s(", br(), ")"),
  1577. element("dd", "dt", br(), "dd")),
  1578. element("table",
  1579. element("tbody",
  1580. element("tr",
  1581. element("td", "cell", br(), "1"),
  1582. element("th", "cell", br(), "2")))));
  1583. var wikitext = instance.domToWikitext(dom, { formatCodeBlock: true });
  1584. this.assertEqual([
  1585. "= Heading 1 =",
  1586. "== Heading 2 ==",
  1587. "=== Heading 3 ===",
  1588. "==== Heading 4 ====",
  1589. "===== Heading 5 =====",
  1590. "====== Heading 6 ======",
  1591. "var TracWysiwyg = function(textarea) {",
  1592. "...",
  1593. "}",
  1594. "",
  1595. "> citation",
  1596. "> continued",
  1597. "",
  1598. " quote",
  1599. " continued",
  1600. "",
  1601. " * item 1",
  1602. " continued",
  1603. " 1. item",
  1604. " 1.1",
  1605. "",
  1606. " def to_s( ):: dt",
  1607. " dd",
  1608. "",
  1609. "|| cell[[BR]]1 ||= cell[[BR]]2 =||" ].join("\n"), wikitext);
  1610. });
  1611. unit.add("escape newlines", function() {
  1612. var dom = fragment(
  1613. element("h1", "header"),
  1614. element("blockquote", { "class": "citation" },
  1615. element("p",
  1616. br(),
  1617. "preserve", br(),
  1618. "newlines", br(),
  1619. br(),
  1620. element("i", "(since 0.11)"), br(),
  1621. br(),
  1622. br())),
  1623. element("p",
  1624. "Whether Wiki formatter should respect the new lines present", br(),
  1625. "in the Wiki text. If set to ", element("b", "default"), ", this is equivalent to", br(),
  1626. element("i", "yes"), " for new environments but keeps the old behavior for", br(),
  1627. "upgraded environments (i.e. 'no')."),
  1628. element("p", "must_preserve_newlines"),
  1629. element("ul",
  1630. element("li", "first", br(), "word"),
  1631. element("li", "second", br(), "word")),
  1632. element("dl",
  1633. element("dt", "trac"),
  1634. element("dd", "trac.edgewall.org", br(), "trac-hacks.org")),
  1635. element("table", { "class": "wiki" },
  1636. element("tbody",
  1637. element("tr",
  1638. element("td", "cell", br(), "cell")))));
  1639. generate.call(this, dom, [
  1640. "= header =",
  1641. "> ",
  1642. "> preserve",
  1643. "> newlines",
  1644. "> ",
  1645. "> ''(since 0.11)''",
  1646. "> ",
  1647. "> ",
  1648. "",
  1649. "Whether Wiki formatter should respect the new lines present",
  1650. "in the Wiki text. If set to '''default''', this is equivalent to",
  1651. "''yes'' for new environments but keeps the old behavior for",
  1652. "upgraded environments (i.e. 'no').",
  1653. "",
  1654. "must_preserve_newlines",
  1655. "",
  1656. " * first[[BR]]word",
  1657. " * second[[BR]]word",
  1658. "",
  1659. " trac:: trac.edgewall.org[[BR]]trac-hacks.org",
  1660. "",
  1661. "|| cell[[BR]]cell ||" ].join("\n"), { escapeNewlines: true });
  1662. });
  1663. unit.add("selectRange", function() {
  1664. var d = instance.contentDocument;
  1665. function _element() {
  1666. var args = [ d ];
  1667. args.push.apply(args, arguments);
  1668. return element.apply(this, args);
  1669. }
  1670. function _text() {
  1671. var args = [ d ];
  1672. args.push.apply(args, arguments);
  1673. return text.apply(this, args);
  1674. }
  1675. function assertRangeText(expected, start, startOffset, end, endOffset) {
  1676. instance.selectRange(start, startOffset, end, endOffset);
  1677. if (expected instanceof RegExp) {
  1678. unit.assertMatch(expected, instance.getSelectionText());
  1679. }
  1680. else {
  1681. unit.assertEqual(expected, instance.getSelectionText());
  1682. }
  1683. }
  1684. var body = d.body;
  1685. while (body.childNodes.length > 0) {
  1686. body.removeChild(body.lastChild);
  1687. }
  1688. body.appendChild(fragment(d,
  1689. _element("p",
  1690. "The", " quick", " brown",
  1691. _element("b", " fox", " jumps", " over"),
  1692. " the", " lazy", " dog."),
  1693. _element("p", "Brick ", "quiz ", "whangs ", "jumpy ", "veldt ", "fox.")));
  1694. var paragraph1 = body.childNodes[0];
  1695. var paragraph2 = body.childNodes[1];
  1696. var bold = paragraph1.childNodes[3];
  1697. assertRangeText("The", paragraph1.childNodes[0], 0, paragraph1.childNodes[0], 3);
  1698. assertRangeText("he", paragraph1.childNodes[0], 1, paragraph1.childNodes[0], 3);
  1699. assertRangeText("e quick brow", paragraph1.childNodes[0], 2, paragraph1.childNodes[2], 5);
  1700. assertRangeText("ick brown", paragraph1.childNodes[1], 3, paragraph1.childNodes[2], 6);
  1701. assertRangeText("ick brown fox j", paragraph1.childNodes[1], 3, bold.childNodes[1], 2);
  1702. assertRangeText("ver the laz", bold.childNodes[2], 2, paragraph1.childNodes[5], 4);
  1703. assertRangeText(" the lazy", paragraph1.childNodes[4], 0, paragraph1.childNodes[5], 5);
  1704. assertRangeText("lazy dog.", paragraph1.childNodes[5], 1, paragraph1.childNodes[6], 5);
  1705. assertRangeText(/^fox jumps over the lazy dog\.[\r\n]*Brick quiz whangs$/,
  1706. bold.childNodes[0], 1, paragraph2.childNodes[2], 6);
  1707. assertRangeText(" fox jumps over", paragraph1, 3, paragraph1, 4);
  1708. assertRangeText(" dog.", paragraph1, 6, paragraph1, 7);
  1709. assertRangeText("", paragraph1, 7, paragraph1, 7);
  1710. assertRangeText("quick brown fox jumps over", paragraph1.childNodes[1], 1, paragraph1, 4);
  1711. assertRangeText(" fox jumps over t", paragraph1, 3, paragraph1.childNodes[4], 2);
  1712. });
  1713. unit.run();
  1714. }
  1715. var button = document.createElement("button");
  1716. button.innerHTML = "run &#187;";
  1717. button.style.textDecoration = "underline";
  1718. document.body.appendChild(button);
  1719. addEvent(button, "click", run);
  1720. button.focus();
  1721. });