kalei 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (211) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +34 -0
  3. data/Rakefile +39 -0
  4. data/lib/kalei.rb +3 -0
  5. data/lib/kalei/app.rb +9 -0
  6. data/lib/kalei/engine.rb +7 -0
  7. data/lib/kalei/public/css/buttons.css +251 -0
  8. data/lib/kalei/public/css/demo-styleDoccos.css +360 -0
  9. data/lib/kalei/public/css/fixie-demo.css +39 -0
  10. data/lib/kalei/public/css/highlight/LICENSE +24 -0
  11. data/lib/kalei/public/css/highlight/README.md +120 -0
  12. data/lib/kalei/public/css/highlight/README.ru.md +125 -0
  13. data/lib/kalei/public/css/highlight/classref.txt +544 -0
  14. data/lib/kalei/public/css/highlight/default.min.css +1 -0
  15. data/lib/kalei/public/css/highlight/highlight.pack.js +1 -0
  16. data/lib/kalei/public/css/highlight/styles/arta.css +153 -0
  17. data/lib/kalei/public/css/highlight/styles/ascetic.css +49 -0
  18. data/lib/kalei/public/css/highlight/styles/brown_paper.css +104 -0
  19. data/lib/kalei/public/css/highlight/styles/brown_papersq.png +0 -0
  20. data/lib/kalei/public/css/highlight/styles/dark.css +103 -0
  21. data/lib/kalei/public/css/highlight/styles/default.css +133 -0
  22. data/lib/kalei/public/css/highlight/styles/far.css +110 -0
  23. data/lib/kalei/public/css/highlight/styles/github.css +133 -0
  24. data/lib/kalei/public/css/highlight/styles/googlecode.css +143 -0
  25. data/lib/kalei/public/css/highlight/styles/idea.css +122 -0
  26. data/lib/kalei/public/css/highlight/styles/ir_black.css +99 -0
  27. data/lib/kalei/public/css/highlight/styles/magula.css +120 -0
  28. data/lib/kalei/public/css/highlight/styles/monokai.css +116 -0
  29. data/lib/kalei/public/css/highlight/styles/pojoaque.css +106 -0
  30. data/lib/kalei/public/css/highlight/styles/pojoaque.jpg +0 -0
  31. data/lib/kalei/public/css/highlight/styles/school_book.css +111 -0
  32. data/lib/kalei/public/css/highlight/styles/school_book.png +0 -0
  33. data/lib/kalei/public/css/highlight/styles/solarized_dark.css +90 -0
  34. data/lib/kalei/public/css/highlight/styles/solarized_light.css +90 -0
  35. data/lib/kalei/public/css/highlight/styles/sunburst.css +149 -0
  36. data/lib/kalei/public/css/highlight/styles/vs.css +85 -0
  37. data/lib/kalei/public/css/highlight/styles/xcode.css +153 -0
  38. data/lib/kalei/public/css/highlight/styles/zenburn.css +115 -0
  39. data/lib/kalei/public/css/styles.css +95 -0
  40. data/lib/kalei/public/css/theme.css +259 -0
  41. data/lib/kalei/public/css/theme2.css +51 -0
  42. data/lib/kalei/public/js/boilerplate.js +9 -0
  43. data/lib/kalei/public/js/config.js +8 -0
  44. data/lib/kalei/public/js/events.js +8 -0
  45. data/lib/kalei/public/js/libs/backbone/backbone-min.js +37 -0
  46. data/lib/kalei/public/js/libs/backbone/backbone-optamd3-min.js +37 -0
  47. data/lib/kalei/public/js/libs/cssbeautify/cssbeautify.js +198 -0
  48. data/lib/kalei/public/js/libs/fixie/fixie.js +1 -0
  49. data/lib/kalei/public/js/libs/highlight/highlight.js +1 -0
  50. data/lib/kalei/public/js/libs/highlight/highlight.pack.js +1 -0
  51. data/lib/kalei/public/js/libs/highlighter/shBrushCss.js +90 -0
  52. data/lib/kalei/public/js/libs/highlighter/shCore.js +2371 -0
  53. data/lib/kalei/public/js/libs/jquery/jquery-min.js +4 -0
  54. data/lib/kalei/public/js/libs/jscssp/jscssp.js +5431 -0
  55. data/lib/kalei/public/js/libs/marked/marked.js +793 -0
  56. data/lib/kalei/public/js/libs/pagedown/converter.js +1335 -0
  57. data/lib/kalei/public/js/libs/pagedown/pagedown +1332 -0
  58. data/lib/kalei/public/js/libs/pagedown/sanitizer.js +108 -0
  59. data/lib/kalei/public/js/libs/parseuri/parseuri.js +32 -0
  60. data/lib/kalei/public/js/libs/require/order.js +1 -0
  61. data/lib/kalei/public/js/libs/require/require.js +31 -0
  62. data/lib/kalei/public/js/libs/require/text.js +11 -0
  63. data/lib/kalei/public/js/libs/showdown/showdown.js +1344 -0
  64. data/lib/kalei/public/js/libs/underscore/underscore-min.js +31 -0
  65. data/lib/kalei/public/js/main.js +39 -0
  66. data/lib/kalei/public/js/router.js +39 -0
  67. data/lib/kalei/public/js/views/app.js +24 -0
  68. data/lib/kalei/public/js/views/style/menu.js +77 -0
  69. data/lib/kalei/public/js/views/style/page.js +100 -0
  70. data/lib/kalei/public/js/vm.js +33 -0
  71. data/lib/kalei/public/templates/layout.html +4 -0
  72. data/lib/kalei/public/templates/style/menu.html +22 -0
  73. data/lib/kalei/public/templates/style/page.html +15 -0
  74. data/lib/kalei/views/index.erb +18 -0
  75. data/test/dummy/README.rdoc +261 -0
  76. data/test/dummy/Rakefile +7 -0
  77. data/test/dummy/app/assets/javascripts/application.js +15 -0
  78. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  79. data/test/dummy/app/assets/stylesheets/example.css +251 -0
  80. data/test/dummy/app/controllers/application_controller.rb +3 -0
  81. data/test/dummy/app/helpers/application_helper.rb +2 -0
  82. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  83. data/test/dummy/config.ru +4 -0
  84. data/test/dummy/config/application.rb +65 -0
  85. data/test/dummy/config/boot.rb +10 -0
  86. data/test/dummy/config/environment.rb +5 -0
  87. data/test/dummy/config/environments/development.rb +31 -0
  88. data/test/dummy/config/environments/production.rb +64 -0
  89. data/test/dummy/config/environments/test.rb +35 -0
  90. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  91. data/test/dummy/config/initializers/inflections.rb +15 -0
  92. data/test/dummy/config/initializers/mime_types.rb +5 -0
  93. data/test/dummy/config/initializers/secret_token.rb +7 -0
  94. data/test/dummy/config/initializers/session_store.rb +8 -0
  95. data/test/dummy/config/initializers/wrap_parameters.rb +10 -0
  96. data/test/dummy/config/locales/en.yml +5 -0
  97. data/test/dummy/config/routes.rb +4 -0
  98. data/test/dummy/log/development (MacBook Air's conflicted copy 2012-11-07).log +12900 -0
  99. data/test/dummy/log/development (Work iMac's conflicted copy 2012-11-06).log +12539 -0
  100. data/test/dummy/log/development.log +16426 -0
  101. data/test/dummy/public/404.html +26 -0
  102. data/test/dummy/public/422.html +26 -0
  103. data/test/dummy/public/500.html +25 -0
  104. data/test/dummy/public/favicon.ico +0 -0
  105. data/test/dummy/script/rails +6 -0
  106. data/test/dummy/tmp/cache/assets/BBF/D60/sprockets%2Fc81500801e644b9c5335793957200428 +0 -0
  107. data/test/dummy/tmp/cache/assets/BE2/9B0/sprockets%2F4097e8869406a33602004190d03272ad +0 -0
  108. data/test/dummy/tmp/cache/assets/C59/B10/sprockets%2Fc6a54e0f5352e41a92c1451976584894 +0 -0
  109. data/test/dummy/tmp/cache/assets/C5F/F60/sprockets%2F661d2795e99d0034ce6873925e0256c4 +0 -0
  110. data/test/dummy/tmp/cache/assets/C64/8C0/sprockets%2F8996c378630075350fb258019546feef +0 -0
  111. data/test/dummy/tmp/cache/assets/C94/F80/sprockets%2F5169b582f529b8d582a59c77c247405f +0 -0
  112. data/test/dummy/tmp/cache/assets/CA2/420/sprockets%2Fd6a388375c983c17d367a676398f8c19 +0 -0
  113. data/test/dummy/tmp/cache/assets/CB0/0B0/sprockets%2F79332476368821ab45ad05e0ae798ad1 +0 -0
  114. data/test/dummy/tmp/cache/assets/CB1/C70/sprockets%2F7022bb23d88717cc1625b47988f0af61 +0 -0
  115. data/test/dummy/tmp/cache/assets/CB5/DB0/sprockets%2F3c20130f1945e66bbc9726cb8925f647 +0 -0
  116. data/test/dummy/tmp/cache/assets/CB6/DF0/sprockets%2F3d4ce8bf5883f171628c030851a5a669 +0 -0
  117. data/test/dummy/tmp/cache/assets/CC1/B70/sprockets%2F2451c355722fdc5979cd365f9f9705a3 +0 -0
  118. data/test/dummy/tmp/cache/assets/CC2/550/sprockets%2F07be9de6d83634f4e056ba2982578725 +0 -0
  119. data/test/dummy/tmp/cache/assets/CC5/8D0/sprockets%2F31f92d93c1650884a626e941c949bff8 +0 -0
  120. data/test/dummy/tmp/cache/assets/CC5/D90/sprockets%2F1b9f99d72878209259dce90e419a04d5 +0 -0
  121. data/test/dummy/tmp/cache/assets/CC8/780/sprockets%2F8578d679f76df60299b502a4c762a62f +0 -0
  122. data/test/dummy/tmp/cache/assets/CC8/C10/sprockets%2F69e29270f13a4c8cd925ac79608878d6 +0 -0
  123. data/test/dummy/tmp/cache/assets/CD1/700/sprockets%2F4a8e02ffcb8924669105305f0b107c1b +0 -0
  124. data/test/dummy/tmp/cache/assets/CD5/DC0/sprockets%2F92fa0519b445f0f1027d42bd9a4165e4 +0 -0
  125. data/test/dummy/tmp/cache/assets/CD8/370/sprockets%2F357970feca3ac29060c1e3861e2c0953 +0 -0
  126. data/test/dummy/tmp/cache/assets/CDB/DC0/sprockets%2F58518572a25128ada56ed9156aac53c4 +0 -0
  127. data/test/dummy/tmp/cache/assets/CDE/C90/sprockets%2F2b20d9775c811fdb6a466e86711d15c3 +0 -0
  128. data/test/dummy/tmp/cache/assets/CE3/2A0/sprockets%2F334b4fc16f7e765755c1be56c9010e28 +0 -0
  129. data/test/dummy/tmp/cache/assets/CE5/FF0/sprockets%2F6113d3e443309efb13b899b3a94b578e +0 -0
  130. data/test/dummy/tmp/cache/assets/CF2/7D0/sprockets%2F7c50d8877e9a4ee1553dc6626c373d38 +0 -0
  131. data/test/dummy/tmp/cache/assets/CF3/C60/sprockets%2Fdfc0395a5019a0a24b34c170a36424de +0 -0
  132. data/test/dummy/tmp/cache/assets/CFC/480/sprockets%2F9d5ab28532957b83f7f9fcbd78021699 +0 -0
  133. data/test/dummy/tmp/cache/assets/CFF/C60/sprockets%2F4ed7a36bde489e10f97698475493ae57 +0 -0
  134. data/test/dummy/tmp/cache/assets/D00/B00/sprockets%2Fd670c548ea2643bd95a65504c11cc13b +0 -0
  135. data/test/dummy/tmp/cache/assets/D0A/CB0/sprockets%2Fed8ba102e7d5015265f1e51a89b8d355 +0 -0
  136. data/test/dummy/tmp/cache/assets/D10/2B0/sprockets%2F1941a534f48d6fa7b22e23b4ca397b69 +0 -0
  137. data/test/dummy/tmp/cache/assets/D17/2A0/sprockets%2Fc094a0ad0b3abb1b92850a86f2000b61 +0 -0
  138. data/test/dummy/tmp/cache/assets/D17/920/sprockets%2Fa6ea2beb942f969acce6231944871652 +0 -0
  139. data/test/dummy/tmp/cache/assets/D19/7C0/sprockets%2F6bd121745f94b781ed36dd0ffa473856 +0 -0
  140. data/test/dummy/tmp/cache/assets/D1A/6F0/sprockets%2F41dd836dc3f691e237833bc1b6f76d93 +0 -0
  141. data/test/dummy/tmp/cache/assets/D1A/770/sprockets%2Fcfad959e3f5eb529a1310d85483b9419 +0 -0
  142. data/test/dummy/tmp/cache/assets/D1F/000/sprockets%2Fdecbf7d6343c0d9638d301c9982298c6 +0 -0
  143. data/test/dummy/tmp/cache/assets/D1F/4D0/sprockets%2F860075c377f26472f83ef56a7bb89aad +0 -0
  144. data/test/dummy/tmp/cache/assets/D20/7D0/sprockets%2F1f7e984b4c793c57d666af84ab414d53 +0 -0
  145. data/test/dummy/tmp/cache/assets/D23/D20/sprockets%2F746c5fb7c744dd87e61f34c8644183fb +0 -0
  146. data/test/dummy/tmp/cache/assets/D29/080/sprockets%2F6b81d746679c6151bc66da896aa97de9 +0 -0
  147. data/test/dummy/tmp/cache/assets/D29/890/sprockets%2Fb5d9c167884139e0f6b8d53816de6e9d +0 -0
  148. data/test/dummy/tmp/cache/assets/D2B/2D0/sprockets%2Fbaf7beb2c3603cfa100b276923a86543 +0 -0
  149. data/test/dummy/tmp/cache/assets/D2B/3F0/sprockets%2Fd6c1fabe78df17a601309081130ca90d +0 -0
  150. data/test/dummy/tmp/cache/assets/D2E/700/sprockets%2F9d6beb99735c03f375e19c5857ccf955 +0 -0
  151. data/test/dummy/tmp/cache/assets/D31/DF0/sprockets%2Fb9ca3ac15e18a4d032f61278565b7bd0 +0 -0
  152. data/test/dummy/tmp/cache/assets/D32/980/sprockets%2F65a361c15a5ff036ce119cb1d2296e4c +0 -0
  153. data/test/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
  154. data/test/dummy/tmp/cache/assets/D32/CA0/sprockets%2F05becf082d0b555622d944ac6e7202cf +0 -0
  155. data/test/dummy/tmp/cache/assets/D36/570/sprockets%2Fadfccb7c2436e006496eae16d6901523 +0 -0
  156. data/test/dummy/tmp/cache/assets/D3F/080/sprockets%2Fb5d1e36ac49d4c9e11728239ecf104e6 +0 -0
  157. data/test/dummy/tmp/cache/assets/D3F/630/sprockets%2F9093e471e526d13234feda4a9cc80fc5 +0 -0
  158. data/test/dummy/tmp/cache/assets/D41/3D0/sprockets%2Fd570b46455f776a30cbb729b442fbbf8 +0 -0
  159. data/test/dummy/tmp/cache/assets/D43/500/sprockets%2F91261e8d0df721df2c19e7c8cc6872b0 +0 -0
  160. data/test/dummy/tmp/cache/assets/D44/2F0/sprockets%2F8abebce08d92187dd84464b40264fc73 +0 -0
  161. data/test/dummy/tmp/cache/assets/D46/350/sprockets%2Fd8bcb0686002ee32c4bf49887f09be36 +0 -0
  162. data/test/dummy/tmp/cache/assets/D4A/F50/sprockets%2F99df6af7ff98150e1255d6d9110b80ea +0 -0
  163. data/test/dummy/tmp/cache/assets/D50/480/sprockets%2F6e151e3dec739c7a338a877ef65fc174 +0 -0
  164. data/test/dummy/tmp/cache/assets/D56/AE0/sprockets%2F68f98777bb22b8e8a78097ba0c86be0f +0 -0
  165. data/test/dummy/tmp/cache/assets/D5A/EA0/sprockets%2Fd771ace226fc8215a3572e0aa35bb0d6 +0 -0
  166. data/test/dummy/tmp/cache/assets/D5B/E00/sprockets%2Ffea8965ad9d35e43675fc5b948e0e934 +0 -0
  167. data/test/dummy/tmp/cache/assets/D68/860/sprockets%2Fafacb887390255dae680441eaf00ff52 +0 -0
  168. data/test/dummy/tmp/cache/assets/D6A/BD0/sprockets%2Fada1b7fa3ff025849aec28559a500c76 +0 -0
  169. data/test/dummy/tmp/cache/assets/D6D/F20/sprockets%2F3c1e635c4ba90a4512849be74fcfee07 +0 -0
  170. data/test/dummy/tmp/cache/assets/D6E/540/sprockets%2F4ea3314d23fc25fc9beec6262272f7f5 +0 -0
  171. data/test/dummy/tmp/cache/assets/D73/690/sprockets%2F356bd79cadb47fd8d6836c17d21318ab +0 -0
  172. data/test/dummy/tmp/cache/assets/D73/7D0/sprockets%2Ff89249a45e22e86c35f227bd340adedd +0 -0
  173. data/test/dummy/tmp/cache/assets/D75/000/sprockets%2Fdfae73207596c9fcc854a2aa1e4f7661 +0 -0
  174. data/test/dummy/tmp/cache/assets/D7A/340/sprockets%2Fc880ec2dd9f7c964cf13a12b9674c63d +0 -0
  175. data/test/dummy/tmp/cache/assets/D7B/6F0/sprockets%2Fc16bfd961e80bb761c67cd760179df8c +0 -0
  176. data/test/dummy/tmp/cache/assets/D7F/D20/sprockets%2Fe4293aa867945ef5c6eb5b26e69c6aa5 +0 -0
  177. data/test/dummy/tmp/cache/assets/D81/180/sprockets%2Fd666d9ef622f0e8cb708f5d8a6b2077f +0 -0
  178. data/test/dummy/tmp/cache/assets/D81/240/sprockets%2F1d0f3cd232c07902529b25abd0bd4ccd +0 -0
  179. data/test/dummy/tmp/cache/assets/D83/560/sprockets%2F9d807a49bc60df8ffb65e99292f3c0a6 +0 -0
  180. data/test/dummy/tmp/cache/assets/D85/D50/sprockets%2Feb82054976bcf4d46c573eafed819f58 +0 -0
  181. data/test/dummy/tmp/cache/assets/D8F/870/sprockets%2F696f6648b2fcbceb8e2686875e6cd6b6 +0 -0
  182. data/test/dummy/tmp/cache/assets/D94/9D0/sprockets%2Ff1c6747b2a961ab3ef92a5a1abe635c4 +0 -0
  183. data/test/dummy/tmp/cache/assets/D96/E00/sprockets%2F7f345bc6ada58cac0203458fc076f1ed +0 -0
  184. data/test/dummy/tmp/cache/assets/D98/DE0/sprockets%2Fbeac47000d16b66f5757aa626f5e8bda +0 -0
  185. data/test/dummy/tmp/cache/assets/D9D/BD0/sprockets%2F1f338b9df8d5a3ffe0b85591db253ab0 +0 -0
  186. data/test/dummy/tmp/cache/assets/DA0/0A0/sprockets%2F61e5c9d0b209a8ce5c8a9aa719ad564d +0 -0
  187. data/test/dummy/tmp/cache/assets/DB1/A10/sprockets%2Fde67190aff966baf9a57f6641fda292e +0 -0
  188. data/test/dummy/tmp/cache/assets/DBE/950/sprockets%2Fa3fbb592cacd368796899f89b95cde1d +0 -0
  189. data/test/dummy/tmp/cache/assets/DC3/950/sprockets%2F12be1e5b8e749be4b42e4ccbb24e1a84 +0 -0
  190. data/test/dummy/tmp/cache/assets/DC5/E10/sprockets%2Fd10332dee1b2ee73913f7f01e6bffc2f +0 -0
  191. data/test/dummy/tmp/cache/assets/DC7/FF0/sprockets%2F4d3d0db28baaafb745e1b4c5f564d891 +0 -0
  192. data/test/dummy/tmp/cache/assets/DCC/810/sprockets%2F8d18398a60db7e9e61ae42bea18b2aeb +0 -0
  193. data/test/dummy/tmp/cache/assets/DE5/A10/sprockets%2F1aa8db45a4cf7ab09d460c22ed063adb +0 -0
  194. data/test/dummy/tmp/cache/assets/DEB/9E0/sprockets%2F1afb4b1d001bc3c1b7cf8cc548bd73e7 +0 -0
  195. data/test/dummy/tmp/cache/assets/DF3/AB0/sprockets%2Fa2fbea7b8e275e2e4b610cd1d8fed006 +0 -0
  196. data/test/dummy/tmp/cache/assets/DF4/A90/sprockets%2Fc6d9482adadab4569aacdf12a224af49 +0 -0
  197. data/test/dummy/tmp/cache/assets/DF5/520/sprockets%2F0cb7052285cefb59b10efc3ed1c6f5cd +0 -0
  198. data/test/dummy/tmp/cache/assets/DF8/000/sprockets%2Fb2bc6fbabfb2c270896a8a44da66fa47 +0 -0
  199. data/test/dummy/tmp/cache/assets/DFB/2D0/sprockets%2F0e88b08c47faeae40d7682dc28b1fbad +0 -0
  200. data/test/dummy/tmp/cache/assets/DFB/9A0/sprockets%2Fb9a29f57d1ebf045452ed6cbd62eae1d +0 -0
  201. data/test/dummy/tmp/cache/assets/E02/D20/sprockets%2Fbd7f5fd245b9c9fc534cad60ef038d4a +0 -0
  202. data/test/dummy/tmp/cache/assets/E35/0A0/sprockets%2F9e0f5c61a97a72fc952a7dbbcefb7cb6 +0 -0
  203. data/test/dummy/tmp/cache/assets/E38/BA0/sprockets%2Fbee7ee5afe77332bcc53bc4e29c77a7f +0 -0
  204. data/test/dummy/tmp/cache/assets/E55/740/sprockets%2Fd51ee7ad0adc4b323ce1a9b88ed4a9af +0 -0
  205. data/test/dummy/tmp/cache/assets/E5C/410/sprockets%2F1bec976eb7fc54612519dcaccae6ccbe +0 -0
  206. data/test/dummy/tmp/cache/assets/EC5/D20/sprockets%2Fc1cf4676f1d3ab9dc9fcbaae59fbe9da +0 -0
  207. data/test/functional/kalei/index_controller_test.rb +11 -0
  208. data/test/integration/navigation_test.rb +9 -0
  209. data/test/kalei_test.rb +7 -0
  210. data/test/test_helper.rb +15 -0
  211. metadata +414 -0
@@ -0,0 +1,1335 @@
1
+ define([], function () {
2
+ var Markdown;
3
+
4
+ if (typeof exports === "object" && typeof require === "function") // we're in a CommonJS (e.g. Node.js) module
5
+ Markdown = exports;
6
+ else
7
+ Markdown = {};
8
+
9
+ // The following text is included for historical reasons, but should
10
+ // be taken with a pinch of salt; it's not all true anymore.
11
+
12
+ //
13
+ // Wherever possible, Showdown is a straight, line-by-line port
14
+ // of the Perl version of Markdown.
15
+ //
16
+ // This is not a normal parser design; it's basically just a
17
+ // series of string substitutions. It's hard to read and
18
+ // maintain this way, but keeping Showdown close to the original
19
+ // design makes it easier to port new features.
20
+ //
21
+ // More importantly, Showdown behaves like markdown.pl in most
22
+ // edge cases. So web applications can do client-side preview
23
+ // in Javascript, and then build identical HTML on the server.
24
+ //
25
+ // This port needs the new RegExp functionality of ECMA 262,
26
+ // 3rd Edition (i.e. Javascript 1.5). Most modern web browsers
27
+ // should do fine. Even with the new regular expression features,
28
+ // We do a lot of work to emulate Perl's regex functionality.
29
+ // The tricky changes in this file mostly have the "attacklab:"
30
+ // label. Major or self-explanatory changes don't.
31
+ //
32
+ // Smart diff tools like Araxis Merge will be able to match up
33
+ // this file with markdown.pl in a useful way. A little tweaking
34
+ // helps: in a copy of markdown.pl, replace "#" with "//" and
35
+ // replace "$text" with "text". Be sure to ignore whitespace
36
+ // and line endings.
37
+ //
38
+
39
+
40
+ //
41
+ // Usage:
42
+ //
43
+ // var text = "Markdown *rocks*.";
44
+ //
45
+ // var converter = new Markdown.Converter();
46
+ // var html = converter.makeHtml(text);
47
+ //
48
+ // alert(html);
49
+ //
50
+ // Note: move the sample code to the bottom of this
51
+ // file before uncommenting it.
52
+ //
53
+
54
+ (function () {
55
+
56
+ function identity(x) { return x; }
57
+ function returnFalse(x) { return false; }
58
+
59
+ function HookCollection() { }
60
+
61
+ HookCollection.prototype = {
62
+
63
+ chain: function (hookname, func) {
64
+ var original = this[hookname];
65
+ if (!original)
66
+ throw new Error("unknown hook " + hookname);
67
+
68
+ if (original === identity)
69
+ this[hookname] = func;
70
+ else
71
+ this[hookname] = function (x) { return func(original(x)); }
72
+ },
73
+ set: function (hookname, func) {
74
+ if (!this[hookname])
75
+ throw new Error("unknown hook " + hookname);
76
+ this[hookname] = func;
77
+ },
78
+ addNoop: function (hookname) {
79
+ this[hookname] = identity;
80
+ },
81
+ addFalse: function (hookname) {
82
+ this[hookname] = returnFalse;
83
+ }
84
+ };
85
+
86
+ Markdown.HookCollection = HookCollection;
87
+
88
+ // g_urls and g_titles allow arbitrary user-entered strings as keys. This
89
+ // caused an exception (and hence stopped the rendering) when the user entered
90
+ // e.g. [push] or [__proto__]. Adding a prefix to the actual key prevents this
91
+ // (since no builtin property starts with "s_"). See
92
+ // http://meta.stackoverflow.com/questions/64655/strange-wmd-bug
93
+ // (granted, switching from Array() to Object() alone would have left only __proto__
94
+ // to be a problem)
95
+ function SaveHash() { }
96
+ SaveHash.prototype = {
97
+ set: function (key, value) {
98
+ this["s_" + key] = value;
99
+ },
100
+ get: function (key) {
101
+ return this["s_" + key];
102
+ }
103
+ };
104
+
105
+ Markdown.Converter = function () {
106
+ var pluginHooks = this.hooks = new HookCollection();
107
+ pluginHooks.addNoop("plainLinkText"); // given a URL that was encountered by itself (without markup), should return the link text that's to be given to this link
108
+ pluginHooks.addNoop("preConversion"); // called with the orignal text as given to makeHtml. The result of this plugin hook is the actual markdown source that will be cooked
109
+ pluginHooks.addNoop("postConversion"); // called with the final cooked HTML code. The result of this plugin hook is the actual output of makeHtml
110
+
111
+ //
112
+ // Private state of the converter instance:
113
+ //
114
+
115
+ // Global hashes, used by various utility routines
116
+ var g_urls;
117
+ var g_titles;
118
+ var g_html_blocks;
119
+
120
+ // Used to track when we're inside an ordered or unordered list
121
+ // (see _ProcessListItems() for details):
122
+ var g_list_level;
123
+
124
+ this.makeHtml = function (text) {
125
+
126
+ //
127
+ // Main function. The order in which other subs are called here is
128
+ // essential. Link and image substitutions need to happen before
129
+ // _EscapeSpecialCharsWithinTagAttributes(), so that any *'s or _'s in the <a>
130
+ // and <img> tags get encoded.
131
+ //
132
+
133
+ // This will only happen if makeHtml on the same converter instance is called from a plugin hook.
134
+ // Don't do that.
135
+ if (g_urls)
136
+ throw new Error("Recursive call to converter.makeHtml");
137
+
138
+ // Create the private state objects.
139
+ g_urls = new SaveHash();
140
+ g_titles = new SaveHash();
141
+ g_html_blocks = [];
142
+ g_list_level = 0;
143
+
144
+ text = pluginHooks.preConversion(text);
145
+
146
+ // attacklab: Replace ~ with ~T
147
+ // This lets us use tilde as an escape char to avoid md5 hashes
148
+ // The choice of character is arbitray; anything that isn't
149
+ // magic in Markdown will work.
150
+ text = text.replace(/~/g, "~T");
151
+
152
+ // attacklab: Replace $ with ~D
153
+ // RegExp interprets $ as a special character
154
+ // when it's in a replacement string
155
+ text = text.replace(/\$/g, "~D");
156
+
157
+ // Standardize line endings
158
+ text = text.replace(/\r\n/g, "\n"); // DOS to Unix
159
+ text = text.replace(/\r/g, "\n"); // Mac to Unix
160
+
161
+ // Make sure text begins and ends with a couple of newlines:
162
+ text = "\n\n" + text + "\n\n";
163
+
164
+ // Convert all tabs to spaces.
165
+ text = _Detab(text);
166
+
167
+ // Strip any lines consisting only of spaces and tabs.
168
+ // This makes subsequent regexen easier to write, because we can
169
+ // match consecutive blank lines with /\n+/ instead of something
170
+ // contorted like /[ \t]*\n+/ .
171
+ text = text.replace(/^[ \t]+$/mg, "");
172
+
173
+ // Turn block-level HTML blocks into hash entries
174
+ text = _HashHTMLBlocks(text);
175
+
176
+ // Strip link definitions, store in hashes.
177
+ text = _StripLinkDefinitions(text);
178
+
179
+ text = _RunBlockGamut(text);
180
+
181
+ text = _UnescapeSpecialChars(text);
182
+
183
+ // attacklab: Restore dollar signs
184
+ text = text.replace(/~D/g, "$$");
185
+
186
+ // attacklab: Restore tildes
187
+ text = text.replace(/~T/g, "~");
188
+
189
+ text = pluginHooks.postConversion(text);
190
+
191
+ g_html_blocks = g_titles = g_urls = null;
192
+
193
+ return text;
194
+ };
195
+
196
+ function _StripLinkDefinitions(text) {
197
+ //
198
+ // Strips link definitions from text, stores the URLs and titles in
199
+ // hash references.
200
+ //
201
+
202
+ // Link defs are in the form: ^[id]: url "optional title"
203
+
204
+ /*
205
+ text = text.replace(/
206
+ ^[ ]{0,3}\[(.+)\]: // id = $1 attacklab: g_tab_width - 1
207
+ [ \t]*
208
+ \n? // maybe *one* newline
209
+ [ \t]*
210
+ <?(\S+?)>? // url = $2
211
+ (?=\s|$) // lookahead for whitespace instead of the lookbehind removed below
212
+ [ \t]*
213
+ \n? // maybe one newline
214
+ [ \t]*
215
+ ( // (potential) title = $3
216
+ (\n*) // any lines skipped = $4 attacklab: lookbehind removed
217
+ [ \t]+
218
+ ["(]
219
+ (.+?) // title = $5
220
+ [")]
221
+ [ \t]*
222
+ )? // title is optional
223
+ (?:\n+|$)
224
+ /gm, function(){...});
225
+ */
226
+
227
+ text = text.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?(?=\s|$)[ \t]*\n?[ \t]*((\n*)["(](.+?)[")][ \t]*)?(?:\n+)/gm,
228
+ function (wholeMatch, m1, m2, m3, m4, m5) {
229
+ m1 = m1.toLowerCase();
230
+ g_urls.set(m1, _EncodeAmpsAndAngles(m2)); // Link IDs are case-insensitive
231
+ if (m4) {
232
+ // Oops, found blank lines, so it's not a title.
233
+ // Put back the parenthetical statement we stole.
234
+ return m3;
235
+ } else if (m5) {
236
+ g_titles.set(m1, m5.replace(/"/g, "&quot;"));
237
+ }
238
+
239
+ // Completely remove the definition from the text
240
+ return "";
241
+ }
242
+ );
243
+
244
+ return text;
245
+ }
246
+
247
+ function _HashHTMLBlocks(text) {
248
+
249
+ // Hashify HTML blocks:
250
+ // We only want to do this for block-level HTML tags, such as headers,
251
+ // lists, and tables. That's because we still want to wrap <p>s around
252
+ // "paragraphs" that are wrapped in non-block-level tags, such as anchors,
253
+ // phrase emphasis, and spans. The list of tags we're looking for is
254
+ // hard-coded:
255
+ var block_tags_a = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del"
256
+ var block_tags_b = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math"
257
+
258
+ // First, look for nested blocks, e.g.:
259
+ // <div>
260
+ // <div>
261
+ // tags for inner block must be indented.
262
+ // </div>
263
+ // </div>
264
+ //
265
+ // The outermost tags must start at the left margin for this to match, and
266
+ // the inner nested divs must be indented.
267
+ // We need to do this before the next, more liberal match, because the next
268
+ // match will start at the first `<div>` and stop at the first `</div>`.
269
+
270
+ // attacklab: This regex can be expensive when it fails.
271
+
272
+ /*
273
+ text = text.replace(/
274
+ ( // save in $1
275
+ ^ // start of line (with /m)
276
+ <($block_tags_a) // start tag = $2
277
+ \b // word break
278
+ // attacklab: hack around khtml/pcre bug...
279
+ [^\r]*?\n // any number of lines, minimally matching
280
+ </\2> // the matching end tag
281
+ [ \t]* // trailing spaces/tabs
282
+ (?=\n+) // followed by a newline
283
+ ) // attacklab: there are sentinel newlines at end of document
284
+ /gm,function(){...}};
285
+ */
286
+ text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm, hashElement);
287
+
288
+ //
289
+ // Now match more liberally, simply from `\n<tag>` to `</tag>\n`
290
+ //
291
+
292
+ /*
293
+ text = text.replace(/
294
+ ( // save in $1
295
+ ^ // start of line (with /m)
296
+ <($block_tags_b) // start tag = $2
297
+ \b // word break
298
+ // attacklab: hack around khtml/pcre bug...
299
+ [^\r]*? // any number of lines, minimally matching
300
+ .*</\2> // the matching end tag
301
+ [ \t]* // trailing spaces/tabs
302
+ (?=\n+) // followed by a newline
303
+ ) // attacklab: there are sentinel newlines at end of document
304
+ /gm,function(){...}};
305
+ */
306
+ text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math)\b[^\r]*?.*<\/\2>[ \t]*(?=\n+)\n)/gm, hashElement);
307
+
308
+ // Special case just for <hr />. It was easier to make a special case than
309
+ // to make the other regex more complicated.
310
+
311
+ /*
312
+ text = text.replace(/
313
+ \n // Starting after a blank line
314
+ [ ]{0,3}
315
+ ( // save in $1
316
+ (<(hr) // start tag = $2
317
+ \b // word break
318
+ ([^<>])*?
319
+ \/?>) // the matching end tag
320
+ [ \t]*
321
+ (?=\n{2,}) // followed by a blank line
322
+ )
323
+ /g,hashElement);
324
+ */
325
+ text = text.replace(/\n[ ]{0,3}((<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g, hashElement);
326
+
327
+ // Special case for standalone HTML comments:
328
+
329
+ /*
330
+ text = text.replace(/
331
+ \n\n // Starting after a blank line
332
+ [ ]{0,3} // attacklab: g_tab_width - 1
333
+ ( // save in $1
334
+ <!
335
+ (--(?:|(?:[^>-]|-[^>])(?:[^-]|-[^-])*)--) // see http://www.w3.org/TR/html-markup/syntax.html#comments and http://meta.stackoverflow.com/q/95256
336
+ >
337
+ [ \t]*
338
+ (?=\n{2,}) // followed by a blank line
339
+ )
340
+ /g,hashElement);
341
+ */
342
+ text = text.replace(/\n\n[ ]{0,3}(<!(--(?:|(?:[^>-]|-[^>])(?:[^-]|-[^-])*)--)>[ \t]*(?=\n{2,}))/g, hashElement);
343
+
344
+ // PHP and ASP-style processor instructions (<?...?> and <%...%>)
345
+
346
+ /*
347
+ text = text.replace(/
348
+ (?:
349
+ \n\n // Starting after a blank line
350
+ )
351
+ ( // save in $1
352
+ [ ]{0,3} // attacklab: g_tab_width - 1
353
+ (?:
354
+ <([?%]) // $2
355
+ [^\r]*?
356
+ \2>
357
+ )
358
+ [ \t]*
359
+ (?=\n{2,}) // followed by a blank line
360
+ )
361
+ /g,hashElement);
362
+ */
363
+ text = text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g, hashElement);
364
+
365
+ return text;
366
+ }
367
+
368
+ function hashElement(wholeMatch, m1) {
369
+ var blockText = m1;
370
+
371
+ // Undo double lines
372
+ blockText = blockText.replace(/^\n+/, "");
373
+
374
+ // strip trailing blank lines
375
+ blockText = blockText.replace(/\n+$/g, "");
376
+
377
+ // Replace the element text with a marker ("~KxK" where x is its key)
378
+ blockText = "\n\n~K" + (g_html_blocks.push(blockText) - 1) + "K\n\n";
379
+
380
+ return blockText;
381
+ }
382
+
383
+ function _RunBlockGamut(text, doNotUnhash) {
384
+ //
385
+ // These are all the transformations that form block-level
386
+ // tags like paragraphs, headers, and list items.
387
+ //
388
+ text = _DoHeaders(text);
389
+
390
+ // Do Horizontal Rules:
391
+ var replacement = "<hr />\n";
392
+ text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm, replacement);
393
+ text = text.replace(/^[ ]{0,2}([ ]?-[ ]?){3,}[ \t]*$/gm, replacement);
394
+ text = text.replace(/^[ ]{0,2}([ ]?_[ ]?){3,}[ \t]*$/gm, replacement);
395
+
396
+ text = _DoLists(text);
397
+ text = _DoCodeBlocks(text);
398
+ text = _DoBlockQuotes(text);
399
+
400
+ // We already ran _HashHTMLBlocks() before, in Markdown(), but that
401
+ // was to escape raw HTML in the original Markdown source. This time,
402
+ // we're escaping the markup we've just created, so that we don't wrap
403
+ // <p> tags around block-level tags.
404
+ text = _HashHTMLBlocks(text);
405
+ text = _FormParagraphs(text, doNotUnhash);
406
+
407
+ return text;
408
+ }
409
+
410
+ function _RunSpanGamut(text) {
411
+ //
412
+ // These are all the transformations that occur *within* block-level
413
+ // tags like paragraphs, headers, and list items.
414
+ //
415
+
416
+ text = _DoCodeSpans(text);
417
+ text = _EscapeSpecialCharsWithinTagAttributes(text);
418
+ text = _EncodeBackslashEscapes(text);
419
+
420
+ // Process anchor and image tags. Images must come first,
421
+ // because ![foo][f] looks like an anchor.
422
+ text = _DoImages(text);
423
+ text = _DoAnchors(text);
424
+
425
+ // Make links out of things like `<http://example.com/>`
426
+ // Must come after _DoAnchors(), because you can use < and >
427
+ // delimiters in inline links like [this](<url>).
428
+ text = _DoAutoLinks(text);
429
+
430
+ text = text.replace(/~P/g, "://"); // put in place to prevent autolinking; reset now
431
+
432
+ text = _EncodeAmpsAndAngles(text);
433
+ text = _DoItalicsAndBold(text);
434
+
435
+ // Do hard breaks:
436
+ text = text.replace(/ +\n/g, " <br>\n");
437
+
438
+ return text;
439
+ }
440
+
441
+ function _EscapeSpecialCharsWithinTagAttributes(text) {
442
+ //
443
+ // Within tags -- meaning between < and > -- encode [\ ` * _] so they
444
+ // don't conflict with their use in Markdown for code, italics and strong.
445
+ //
446
+
447
+ // Build a regex to find HTML tags and comments. See Friedl's
448
+ // "Mastering Regular Expressions", 2nd Ed., pp. 200-201.
449
+
450
+ // SE: changed the comment part of the regex
451
+
452
+ var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--(?:|(?:[^>-]|-[^>])(?:[^-]|-[^-])*)--)>)/gi;
453
+
454
+ text = text.replace(regex, function (wholeMatch) {
455
+ var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g, "$1`");
456
+ tag = escapeCharacters(tag, wholeMatch.charAt(1) == "!" ? "\\`*_/" : "\\`*_"); // also escape slashes in comments to prevent autolinking there -- http://meta.stackoverflow.com/questions/95987
457
+ return tag;
458
+ });
459
+
460
+ return text;
461
+ }
462
+
463
+ function _DoAnchors(text) {
464
+ //
465
+ // Turn Markdown link shortcuts into XHTML <a> tags.
466
+ //
467
+ //
468
+ // First, handle reference-style links: [link text] [id]
469
+ //
470
+
471
+ /*
472
+ text = text.replace(/
473
+ ( // wrap whole match in $1
474
+ \[
475
+ (
476
+ (?:
477
+ \[[^\]]*\] // allow brackets nested one level
478
+ |
479
+ [^\[] // or anything else
480
+ )*
481
+ )
482
+ \]
483
+
484
+ [ ]? // one optional space
485
+ (?:\n[ ]*)? // one optional newline followed by spaces
486
+
487
+ \[
488
+ (.*?) // id = $3
489
+ \]
490
+ )
491
+ ()()()() // pad remaining backreferences
492
+ /g, writeAnchorTag);
493
+ */
494
+ text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeAnchorTag);
495
+
496
+ //
497
+ // Next, inline-style links: [link text](url "optional title")
498
+ //
499
+
500
+ /*
501
+ text = text.replace(/
502
+ ( // wrap whole match in $1
503
+ \[
504
+ (
505
+ (?:
506
+ \[[^\]]*\] // allow brackets nested one level
507
+ |
508
+ [^\[\]] // or anything else
509
+ )*
510
+ )
511
+ \]
512
+ \( // literal paren
513
+ [ \t]*
514
+ () // no id, so leave $3 empty
515
+ <?( // href = $4
516
+ (?:
517
+ \([^)]*\) // allow one level of (correctly nested) parens (think MSDN)
518
+ |
519
+ [^()\s]
520
+ )*?
521
+ )>?
522
+ [ \t]*
523
+ ( // $5
524
+ (['"]) // quote char = $6
525
+ (.*?) // Title = $7
526
+ \6 // matching quote
527
+ [ \t]* // ignore any spaces/tabs between closing quote and )
528
+ )? // title is optional
529
+ \)
530
+ )
531
+ /g, writeAnchorTag);
532
+ */
533
+
534
+ text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?((?:\([^)]*\)|[^()\s])*?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writeAnchorTag);
535
+
536
+ //
537
+ // Last, handle reference-style shortcuts: [link text]
538
+ // These must come last in case you've also got [link test][1]
539
+ // or [link test](/foo)
540
+ //
541
+
542
+ /*
543
+ text = text.replace(/
544
+ ( // wrap whole match in $1
545
+ \[
546
+ ([^\[\]]+) // link text = $2; can't contain '[' or ']'
547
+ \]
548
+ )
549
+ ()()()()() // pad rest of backreferences
550
+ /g, writeAnchorTag);
551
+ */
552
+ text = text.replace(/(\[([^\[\]]+)\])()()()()()/g, writeAnchorTag);
553
+
554
+ return text;
555
+ }
556
+
557
+ function writeAnchorTag(wholeMatch, m1, m2, m3, m4, m5, m6, m7) {
558
+ if (m7 == undefined) m7 = "";
559
+ var whole_match = m1;
560
+ var link_text = m2.replace(/:\/\//g, "~P"); // to prevent auto-linking withing the link. will be converted back after the auto-linker runs
561
+ var link_id = m3.toLowerCase();
562
+ var url = m4;
563
+ var title = m7;
564
+
565
+ if (url == "") {
566
+ if (link_id == "") {
567
+ // lower-case and turn embedded newlines into spaces
568
+ link_id = link_text.toLowerCase().replace(/ ?\n/g, " ");
569
+ }
570
+ url = "#" + link_id;
571
+
572
+ if (g_urls.get(link_id) != undefined) {
573
+ url = g_urls.get(link_id);
574
+ if (g_titles.get(link_id) != undefined) {
575
+ title = g_titles.get(link_id);
576
+ }
577
+ }
578
+ else {
579
+ if (whole_match.search(/\(\s*\)$/m) > -1) {
580
+ // Special case for explicit empty url
581
+ url = "";
582
+ } else {
583
+ return whole_match;
584
+ }
585
+ }
586
+ }
587
+ url = encodeProblemUrlChars(url);
588
+ url = escapeCharacters(url, "*_");
589
+ var result = "<a href=\"" + url + "\"";
590
+
591
+ if (title != "") {
592
+ title = attributeEncode(title);
593
+ title = escapeCharacters(title, "*_");
594
+ result += " title=\"" + title + "\"";
595
+ }
596
+
597
+ result += ">" + link_text + "</a>";
598
+
599
+ return result;
600
+ }
601
+
602
+ function _DoImages(text) {
603
+ //
604
+ // Turn Markdown image shortcuts into <img> tags.
605
+ //
606
+
607
+ //
608
+ // First, handle reference-style labeled images: ![alt text][id]
609
+ //
610
+
611
+ /*
612
+ text = text.replace(/
613
+ ( // wrap whole match in $1
614
+ !\[
615
+ (.*?) // alt text = $2
616
+ \]
617
+
618
+ [ ]? // one optional space
619
+ (?:\n[ ]*)? // one optional newline followed by spaces
620
+
621
+ \[
622
+ (.*?) // id = $3
623
+ \]
624
+ )
625
+ ()()()() // pad rest of backreferences
626
+ /g, writeImageTag);
627
+ */
628
+ text = text.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeImageTag);
629
+
630
+ //
631
+ // Next, handle inline images: ![alt text](url "optional title")
632
+ // Don't forget: encode * and _
633
+
634
+ /*
635
+ text = text.replace(/
636
+ ( // wrap whole match in $1
637
+ !\[
638
+ (.*?) // alt text = $2
639
+ \]
640
+ \s? // One optional whitespace character
641
+ \( // literal paren
642
+ [ \t]*
643
+ () // no id, so leave $3 empty
644
+ <?(\S+?)>? // src url = $4
645
+ [ \t]*
646
+ ( // $5
647
+ (['"]) // quote char = $6
648
+ (.*?) // title = $7
649
+ \6 // matching quote
650
+ [ \t]*
651
+ )? // title is optional
652
+ \)
653
+ )
654
+ /g, writeImageTag);
655
+ */
656
+ text = text.replace(/(!\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writeImageTag);
657
+
658
+ return text;
659
+ }
660
+
661
+ function attributeEncode(text) {
662
+ // unconditionally replace angle brackets here -- what ends up in an attribute (e.g. alt or title)
663
+ // never makes sense to have verbatim HTML in it (and the sanitizer would totally break it)
664
+ return text.replace(/>/g, "&gt;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
665
+ }
666
+
667
+ function writeImageTag(wholeMatch, m1, m2, m3, m4, m5, m6, m7) {
668
+ var whole_match = m1;
669
+ var alt_text = m2;
670
+ var link_id = m3.toLowerCase();
671
+ var url = m4;
672
+ var title = m7;
673
+
674
+ if (!title) title = "";
675
+
676
+ if (url == "") {
677
+ if (link_id == "") {
678
+ // lower-case and turn embedded newlines into spaces
679
+ link_id = alt_text.toLowerCase().replace(/ ?\n/g, " ");
680
+ }
681
+ url = "#" + link_id;
682
+
683
+ if (g_urls.get(link_id) != undefined) {
684
+ url = g_urls.get(link_id);
685
+ if (g_titles.get(link_id) != undefined) {
686
+ title = g_titles.get(link_id);
687
+ }
688
+ }
689
+ else {
690
+ return whole_match;
691
+ }
692
+ }
693
+
694
+ alt_text = escapeCharacters(attributeEncode(alt_text), "*_[]()");
695
+ url = escapeCharacters(url, "*_");
696
+ var result = "<img src=\"" + url + "\" alt=\"" + alt_text + "\"";
697
+
698
+ // attacklab: Markdown.pl adds empty title attributes to images.
699
+ // Replicate this bug.
700
+
701
+ //if (title != "") {
702
+ title = attributeEncode(title);
703
+ title = escapeCharacters(title, "*_");
704
+ result += " title=\"" + title + "\"";
705
+ //}
706
+
707
+ result += " />";
708
+
709
+ return result;
710
+ }
711
+
712
+ function _DoHeaders(text) {
713
+
714
+ // Setext-style headers:
715
+ // Header 1
716
+ // ========
717
+ //
718
+ // Header 2
719
+ // --------
720
+ //
721
+ text = text.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,
722
+ function (wholeMatch, m1) { return "<h1>" + _RunSpanGamut(m1) + "</h1>\n\n"; }
723
+ );
724
+
725
+ text = text.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,
726
+ function (matchFound, m1) { return "<h2>" + _RunSpanGamut(m1) + "</h2>\n\n"; }
727
+ );
728
+
729
+ // atx-style headers:
730
+ // # Header 1
731
+ // ## Header 2
732
+ // ## Header 2 with closing hashes ##
733
+ // ...
734
+ // ###### Header 6
735
+ //
736
+
737
+ /*
738
+ text = text.replace(/
739
+ ^(\#{1,6}) // $1 = string of #'s
740
+ [ \t]*
741
+ (.+?) // $2 = Header text
742
+ [ \t]*
743
+ \#* // optional closing #'s (not counted)
744
+ \n+
745
+ /gm, function() {...});
746
+ */
747
+
748
+ text = text.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,
749
+ function (wholeMatch, m1, m2) {
750
+ var h_level = m1.length;
751
+ return "<h" + h_level + ">" + _RunSpanGamut(m2) + "</h" + h_level + ">\n\n";
752
+ }
753
+ );
754
+
755
+ return text;
756
+ }
757
+
758
+ function _DoLists(text) {
759
+ //
760
+ // Form HTML ordered (numbered) and unordered (bulleted) lists.
761
+ //
762
+
763
+ // attacklab: add sentinel to hack around khtml/safari bug:
764
+ // http://bugs.webkit.org/show_bug.cgi?id=11231
765
+ text += "~0";
766
+
767
+ // Re-usable pattern to match any entirel ul or ol list:
768
+
769
+ /*
770
+ var whole_list = /
771
+ ( // $1 = whole list
772
+ ( // $2
773
+ [ ]{0,3} // attacklab: g_tab_width - 1
774
+ ([*+-]|\d+[.]) // $3 = first list item marker
775
+ [ \t]+
776
+ )
777
+ [^\r]+?
778
+ ( // $4
779
+ ~0 // sentinel for workaround; should be $
780
+ |
781
+ \n{2,}
782
+ (?=\S)
783
+ (?! // Negative lookahead for another list item marker
784
+ [ \t]*
785
+ (?:[*+-]|\d+[.])[ \t]+
786
+ )
787
+ )
788
+ )
789
+ /g
790
+ */
791
+ var whole_list = /^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;
792
+
793
+ if (g_list_level) {
794
+ text = text.replace(whole_list, function (wholeMatch, m1, m2) {
795
+ var list = m1;
796
+ var list_type = (m2.search(/[*+-]/g) > -1) ? "ul" : "ol";
797
+
798
+ var result = _ProcessListItems(list, list_type);
799
+
800
+ // Trim any trailing whitespace, to put the closing `</$list_type>`
801
+ // up on the preceding line, to get it past the current stupid
802
+ // HTML block parser. This is a hack to work around the terrible
803
+ // hack that is the HTML block parser.
804
+ result = result.replace(/\s+$/, "");
805
+ result = "<" + list_type + ">" + result + "</" + list_type + ">\n";
806
+ return result;
807
+ });
808
+ } else {
809
+ whole_list = /(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g;
810
+ text = text.replace(whole_list, function (wholeMatch, m1, m2, m3) {
811
+ var runup = m1;
812
+ var list = m2;
813
+
814
+ var list_type = (m3.search(/[*+-]/g) > -1) ? "ul" : "ol";
815
+ var result = _ProcessListItems(list, list_type);
816
+ result = runup + "<" + list_type + ">\n" + result + "</" + list_type + ">\n";
817
+ return result;
818
+ });
819
+ }
820
+
821
+ // attacklab: strip sentinel
822
+ text = text.replace(/~0/, "");
823
+
824
+ return text;
825
+ }
826
+
827
+ var _listItemMarkers = { ol: "\\d+[.]", ul: "[*+-]" };
828
+
829
+ function _ProcessListItems(list_str, list_type) {
830
+ //
831
+ // Process the contents of a single ordered or unordered list, splitting it
832
+ // into individual list items.
833
+ //
834
+ // list_type is either "ul" or "ol".
835
+
836
+ // The $g_list_level global keeps track of when we're inside a list.
837
+ // Each time we enter a list, we increment it; when we leave a list,
838
+ // we decrement. If it's zero, we're not in a list anymore.
839
+ //
840
+ // We do this because when we're not inside a list, we want to treat
841
+ // something like this:
842
+ //
843
+ // I recommend upgrading to version
844
+ // 8. Oops, now this line is treated
845
+ // as a sub-list.
846
+ //
847
+ // As a single paragraph, despite the fact that the second line starts
848
+ // with a digit-period-space sequence.
849
+ //
850
+ // Whereas when we're inside a list (or sub-list), that line will be
851
+ // treated as the start of a sub-list. What a kludge, huh? This is
852
+ // an aspect of Markdown's syntax that's hard to parse perfectly
853
+ // without resorting to mind-reading. Perhaps the solution is to
854
+ // change the syntax rules such that sub-lists must start with a
855
+ // starting cardinal number; e.g. "1." or "a.".
856
+
857
+ g_list_level++;
858
+
859
+ // trim trailing blank lines:
860
+ list_str = list_str.replace(/\n{2,}$/, "\n");
861
+
862
+ // attacklab: add sentinel to emulate \z
863
+ list_str += "~0";
864
+
865
+ // In the original attacklab showdown, list_type was not given to this function, and anything
866
+ // that matched /[*+-]|\d+[.]/ would just create the next <li>, causing this mismatch:
867
+ //
868
+ // Markdown rendered by WMD rendered by MarkdownSharp
869
+ // ------------------------------------------------------------------
870
+ // 1. first 1. first 1. first
871
+ // 2. second 2. second 2. second
872
+ // - third 3. third * third
873
+ //
874
+ // We changed this to behave identical to MarkdownSharp. This is the constructed RegEx,
875
+ // with {MARKER} being one of \d+[.] or [*+-], depending on list_type:
876
+
877
+ /*
878
+ list_str = list_str.replace(/
879
+ (^[ \t]*) // leading whitespace = $1
880
+ ({MARKER}) [ \t]+ // list marker = $2
881
+ ([^\r]+? // list item text = $3
882
+ (\n+)
883
+ )
884
+ (?=
885
+ (~0 | \2 ({MARKER}) [ \t]+)
886
+ )
887
+ /gm, function(){...});
888
+ */
889
+
890
+ var marker = _listItemMarkers[list_type];
891
+ var re = new RegExp("(^[ \\t]*)(" + marker + ")[ \\t]+([^\\r]+?(\\n+))(?=(~0|\\1(" + marker + ")[ \\t]+))", "gm");
892
+ var last_item_had_a_double_newline = false;
893
+ list_str = list_str.replace(re,
894
+ function (wholeMatch, m1, m2, m3) {
895
+ var item = m3;
896
+ var leading_space = m1;
897
+ var ends_with_double_newline = /\n\n$/.test(item);
898
+ var contains_double_newline = ends_with_double_newline || item.search(/\n{2,}/) > -1;
899
+
900
+ if (contains_double_newline || last_item_had_a_double_newline) {
901
+ item = _RunBlockGamut(_Outdent(item), /* doNotUnhash = */true);
902
+ }
903
+ else {
904
+ // Recursion for sub-lists:
905
+ item = _DoLists(_Outdent(item));
906
+ item = item.replace(/\n$/, ""); // chomp(item)
907
+ item = _RunSpanGamut(item);
908
+ }
909
+ last_item_had_a_double_newline = ends_with_double_newline;
910
+ return "<li>" + item + "</li>\n";
911
+ }
912
+ );
913
+
914
+ // attacklab: strip sentinel
915
+ list_str = list_str.replace(/~0/g, "");
916
+
917
+ g_list_level--;
918
+ return list_str;
919
+ }
920
+
921
+ function _DoCodeBlocks(text) {
922
+ //
923
+ // Process Markdown `<pre><code>` blocks.
924
+ //
925
+
926
+ /*
927
+ text = text.replace(/
928
+ (?:\n\n|^)
929
+ ( // $1 = the code block -- one or more lines, starting with a space/tab
930
+ (?:
931
+ (?:[ ]{4}|\t) // Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width
932
+ .*\n+
933
+ )+
934
+ )
935
+ (\n*[ ]{0,3}[^ \t\n]|(?=~0)) // attacklab: g_tab_width
936
+ /g ,function(){...});
937
+ */
938
+
939
+ // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
940
+ text += "~0";
941
+
942
+ text = text.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,
943
+ function (wholeMatch, m1, m2) {
944
+ var codeblock = m1;
945
+ var nextChar = m2;
946
+
947
+ codeblock = _EncodeCode(_Outdent(codeblock));
948
+ codeblock = _Detab(codeblock);
949
+ codeblock = codeblock.replace(/^\n+/g, ""); // trim leading newlines
950
+ codeblock = codeblock.replace(/\n+$/g, ""); // trim trailing whitespace
951
+
952
+ codeblock = "<pre><code>" + codeblock + "\n</code></pre>";
953
+
954
+ return "\n\n" + codeblock + "\n\n" + nextChar;
955
+ }
956
+ );
957
+
958
+ // attacklab: strip sentinel
959
+ text = text.replace(/~0/, "");
960
+
961
+ return text;
962
+ }
963
+
964
+ function hashBlock(text) {
965
+ text = text.replace(/(^\n+|\n+$)/g, "");
966
+ return "\n\n~K" + (g_html_blocks.push(text) - 1) + "K\n\n";
967
+ }
968
+
969
+ function _DoCodeSpans(text) {
970
+ //
971
+ // * Backtick quotes are used for <code></code> spans.
972
+ //
973
+ // * You can use multiple backticks as the delimiters if you want to
974
+ // include literal backticks in the code span. So, this input:
975
+ //
976
+ // Just type ``foo `bar` baz`` at the prompt.
977
+ //
978
+ // Will translate to:
979
+ //
980
+ // <p>Just type <code>foo `bar` baz</code> at the prompt.</p>
981
+ //
982
+ // There's no arbitrary limit to the number of backticks you
983
+ // can use as delimters. If you need three consecutive backticks
984
+ // in your code, use four for delimiters, etc.
985
+ //
986
+ // * You can use spaces to get literal backticks at the edges:
987
+ //
988
+ // ... type `` `bar` `` ...
989
+ //
990
+ // Turns to:
991
+ //
992
+ // ... type <code>`bar`</code> ...
993
+ //
994
+
995
+ /*
996
+ text = text.replace(/
997
+ (^|[^\\]) // Character before opening ` can't be a backslash
998
+ (`+) // $2 = Opening run of `
999
+ ( // $3 = The code block
1000
+ [^\r]*?
1001
+ [^`] // attacklab: work around lack of lookbehind
1002
+ )
1003
+ \2 // Matching closer
1004
+ (?!`)
1005
+ /gm, function(){...});
1006
+ */
1007
+
1008
+ text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,
1009
+ function (wholeMatch, m1, m2, m3, m4) {
1010
+ var c = m3;
1011
+ c = c.replace(/^([ \t]*)/g, ""); // leading whitespace
1012
+ c = c.replace(/[ \t]*$/g, ""); // trailing whitespace
1013
+ c = _EncodeCode(c);
1014
+ c = c.replace(/:\/\//g, "~P"); // to prevent auto-linking. Not necessary in code *blocks*, but in code spans. Will be converted back after the auto-linker runs.
1015
+ return m1 + "<code>" + c + "</code>";
1016
+ }
1017
+ );
1018
+
1019
+ return text;
1020
+ }
1021
+
1022
+ function _EncodeCode(text) {
1023
+ //
1024
+ // Encode/escape certain characters inside Markdown code runs.
1025
+ // The point is that in code, these characters are literals,
1026
+ // and lose their special Markdown meanings.
1027
+ //
1028
+ // Encode all ampersands; HTML entities are not
1029
+ // entities within a Markdown code span.
1030
+ text = text.replace(/&/g, "&amp;");
1031
+
1032
+ // Do the angle bracket song and dance:
1033
+ text = text.replace(/</g, "&lt;");
1034
+ text = text.replace(/>/g, "&gt;");
1035
+
1036
+ // Now, escape characters that are magic in Markdown:
1037
+ text = escapeCharacters(text, "\*_{}[]\\", false);
1038
+
1039
+ // jj the line above breaks this:
1040
+ //---
1041
+
1042
+ //* Item
1043
+
1044
+ // 1. Subitem
1045
+
1046
+ // special char: *
1047
+ //---
1048
+
1049
+ return text;
1050
+ }
1051
+
1052
+ function _DoItalicsAndBold(text) {
1053
+
1054
+ // <strong> must go first:
1055
+ text = text.replace(/([\W_]|^)(\*\*|__)(?=\S)([^\r]*?\S[\*_]*)\2([\W_]|$)/g,
1056
+ "$1<strong>$3</strong>$4");
1057
+
1058
+ text = text.replace(/([\W_]|^)(\*|_)(?=\S)([^\r\*_]*?\S)\2([\W_]|$)/g,
1059
+ "$1<em>$3</em>$4");
1060
+
1061
+ return text;
1062
+ }
1063
+
1064
+ function _DoBlockQuotes(text) {
1065
+
1066
+ /*
1067
+ text = text.replace(/
1068
+ ( // Wrap whole match in $1
1069
+ (
1070
+ ^[ \t]*>[ \t]? // '>' at the start of a line
1071
+ .+\n // rest of the first line
1072
+ (.+\n)* // subsequent consecutive lines
1073
+ \n* // blanks
1074
+ )+
1075
+ )
1076
+ /gm, function(){...});
1077
+ */
1078
+
1079
+ text = text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,
1080
+ function (wholeMatch, m1) {
1081
+ var bq = m1;
1082
+
1083
+ // attacklab: hack around Konqueror 3.5.4 bug:
1084
+ // "----------bug".replace(/^-/g,"") == "bug"
1085
+
1086
+ bq = bq.replace(/^[ \t]*>[ \t]?/gm, "~0"); // trim one level of quoting
1087
+
1088
+ // attacklab: clean up hack
1089
+ bq = bq.replace(/~0/g, "");
1090
+
1091
+ bq = bq.replace(/^[ \t]+$/gm, ""); // trim whitespace-only lines
1092
+ bq = _RunBlockGamut(bq); // recurse
1093
+
1094
+ bq = bq.replace(/(^|\n)/g, "$1 ");
1095
+ // These leading spaces screw with <pre> content, so we need to fix that:
1096
+ bq = bq.replace(
1097
+ /(\s*<pre>[^\r]+?<\/pre>)/gm,
1098
+ function (wholeMatch, m1) {
1099
+ var pre = m1;
1100
+ // attacklab: hack around Konqueror 3.5.4 bug:
1101
+ pre = pre.replace(/^ /mg, "~0");
1102
+ pre = pre.replace(/~0/g, "");
1103
+ return pre;
1104
+ });
1105
+
1106
+ return hashBlock("<blockquote>\n" + bq + "\n</blockquote>");
1107
+ }
1108
+ );
1109
+ return text;
1110
+ }
1111
+
1112
+ function _FormParagraphs(text, doNotUnhash) {
1113
+ //
1114
+ // Params:
1115
+ // $text - string to process with html <p> tags
1116
+ //
1117
+
1118
+ // Strip leading and trailing lines:
1119
+ text = text.replace(/^\n+/g, "");
1120
+ text = text.replace(/\n+$/g, "");
1121
+
1122
+ var grafs = text.split(/\n{2,}/g);
1123
+ var grafsOut = [];
1124
+
1125
+ var markerRe = /~K(\d+)K/;
1126
+
1127
+ //
1128
+ // Wrap <p> tags.
1129
+ //
1130
+ var end = grafs.length;
1131
+ for (var i = 0; i < end; i++) {
1132
+ var str = grafs[i];
1133
+
1134
+ // if this is an HTML marker, copy it
1135
+ if (markerRe.test(str)) {
1136
+ grafsOut.push(str);
1137
+ }
1138
+ else if (/\S/.test(str)) {
1139
+ str = _RunSpanGamut(str);
1140
+ str = str.replace(/^([ \t]*)/g, "<p>");
1141
+ str += "</p>"
1142
+ grafsOut.push(str);
1143
+ }
1144
+
1145
+ }
1146
+ //
1147
+ // Unhashify HTML blocks
1148
+ //
1149
+ if (!doNotUnhash) {
1150
+ end = grafsOut.length;
1151
+ for (var i = 0; i < end; i++) {
1152
+ var foundAny = true;
1153
+ while (foundAny) { // we may need several runs, since the data may be nested
1154
+ foundAny = false;
1155
+ grafsOut[i] = grafsOut[i].replace(/~K(\d+)K/g, function (wholeMatch, id) {
1156
+ foundAny = true;
1157
+ return g_html_blocks[id];
1158
+ });
1159
+ }
1160
+ }
1161
+ }
1162
+ return grafsOut.join("\n\n");
1163
+ }
1164
+
1165
+ function _EncodeAmpsAndAngles(text) {
1166
+ // Smart processing for ampersands and angle brackets that need to be encoded.
1167
+
1168
+ // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:
1169
+ // http://bumppo.net/projects/amputator/
1170
+ text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, "&amp;");
1171
+
1172
+ // Encode naked <'s
1173
+ text = text.replace(/<(?![a-z\/?\$!])/gi, "&lt;");
1174
+
1175
+ return text;
1176
+ }
1177
+
1178
+ function _EncodeBackslashEscapes(text) {
1179
+ //
1180
+ // Parameter: String.
1181
+ // Returns: The string, with after processing the following backslash
1182
+ // escape sequences.
1183
+ //
1184
+
1185
+ // attacklab: The polite way to do this is with the new
1186
+ // escapeCharacters() function:
1187
+ //
1188
+ // text = escapeCharacters(text,"\\",true);
1189
+ // text = escapeCharacters(text,"`*_{}[]()>#+-.!",true);
1190
+ //
1191
+ // ...but we're sidestepping its use of the (slow) RegExp constructor
1192
+ // as an optimization for Firefox. This function gets called a LOT.
1193
+
1194
+ text = text.replace(/\\(\\)/g, escapeCharacters_callback);
1195
+ text = text.replace(/\\([`*_{}\[\]()>#+-.!])/g, escapeCharacters_callback);
1196
+ return text;
1197
+ }
1198
+
1199
+ function _DoAutoLinks(text) {
1200
+
1201
+ // note that at this point, all other URL in the text are already hyperlinked as <a href=""></a>
1202
+ // *except* for the <http://www.foo.com> case
1203
+
1204
+ // automatically add < and > around unadorned raw hyperlinks
1205
+ // must be preceded by space/BOF and followed by non-word/EOF character
1206
+ text = text.replace(/(^|\s)(https?|ftp)(:\/\/[-A-Z0-9+&@#\/%?=~_|\[\]\(\)!:,\.;]*[-A-Z0-9+&@#\/%=~_|\[\]])($|\W)/gi, "$1<$2$3>$4");
1207
+
1208
+ // autolink anything like <http://example.com>
1209
+
1210
+ var replacer = function (wholematch, m1) { return "<a href=\"" + m1 + "\">" + pluginHooks.plainLinkText(m1) + "</a>"; }
1211
+ text = text.replace(/<((https?|ftp):[^'">\s]+)>/gi, replacer);
1212
+
1213
+ // Email addresses: <address@domain.foo>
1214
+ /*
1215
+ text = text.replace(/
1216
+ <
1217
+ (?:mailto:)?
1218
+ (
1219
+ [-.\w]+
1220
+ \@
1221
+ [-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+
1222
+ )
1223
+ >
1224
+ /gi, _DoAutoLinks_callback());
1225
+ */
1226
+
1227
+ /* disabling email autolinking, since we don't do that on the server, either
1228
+ text = text.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,
1229
+ function(wholeMatch,m1) {
1230
+ return _EncodeEmailAddress( _UnescapeSpecialChars(m1) );
1231
+ }
1232
+ );
1233
+ */
1234
+ return text;
1235
+ }
1236
+
1237
+ function _UnescapeSpecialChars(text) {
1238
+ //
1239
+ // Swap back in all the special characters we've hidden.
1240
+ //
1241
+ text = text.replace(/~E(\d+)E/g,
1242
+ function (wholeMatch, m1) {
1243
+ var charCodeToReplace = parseInt(m1);
1244
+ return String.fromCharCode(charCodeToReplace);
1245
+ }
1246
+ );
1247
+ return text;
1248
+ }
1249
+
1250
+ function _Outdent(text) {
1251
+ //
1252
+ // Remove one level of line-leading tabs or spaces
1253
+ //
1254
+
1255
+ // attacklab: hack around Konqueror 3.5.4 bug:
1256
+ // "----------bug".replace(/^-/g,"") == "bug"
1257
+
1258
+ text = text.replace(/^(\t|[ ]{1,4})/gm, "~0"); // attacklab: g_tab_width
1259
+
1260
+ // attacklab: clean up hack
1261
+ text = text.replace(/~0/g, "")
1262
+
1263
+ return text;
1264
+ }
1265
+
1266
+ function _Detab(text) {
1267
+ if (!/\t/.test(text))
1268
+ return text;
1269
+
1270
+ var spaces = [" ", " ", " ", " "],
1271
+ skew = 0,
1272
+ v;
1273
+
1274
+ return text.replace(/[\n\t]/g, function (match, offset) {
1275
+ if (match === "\n") {
1276
+ skew = offset + 1;
1277
+ return match;
1278
+ }
1279
+ v = (offset - skew) % 4;
1280
+ skew = offset + 1;
1281
+ return spaces[v];
1282
+ });
1283
+ }
1284
+
1285
+ //
1286
+ // attacklab: Utility functions
1287
+ //
1288
+
1289
+ var _problemUrlChars = /(?:["'*()[\]:]|~D)/g;
1290
+
1291
+ // hex-encodes some unusual "problem" chars in URLs to avoid URL detection problems
1292
+ function encodeProblemUrlChars(url) {
1293
+ if (!url)
1294
+ return "";
1295
+
1296
+ var len = url.length;
1297
+
1298
+ return url.replace(_problemUrlChars, function (match, offset) {
1299
+ if (match == "~D") // escape for dollar
1300
+ return "%24";
1301
+ if (match == ":") {
1302
+ if (offset == len - 1 || /[0-9\/]/.test(url.charAt(offset + 1)))
1303
+ return ":"
1304
+ }
1305
+ return "%" + match.charCodeAt(0).toString(16);
1306
+ });
1307
+ }
1308
+
1309
+
1310
+ function escapeCharacters(text, charsToEscape, afterBackslash) {
1311
+ // First we have to escape the escape characters so that
1312
+ // we can build a character class out of them
1313
+ var regexString = "([" + charsToEscape.replace(/([\[\]\\])/g, "\\$1") + "])";
1314
+
1315
+ if (afterBackslash) {
1316
+ regexString = "\\\\" + regexString;
1317
+ }
1318
+
1319
+ var regex = new RegExp(regexString, "g");
1320
+ text = text.replace(regex, escapeCharacters_callback);
1321
+
1322
+ return text;
1323
+ }
1324
+
1325
+
1326
+ function escapeCharacters_callback(wholeMatch, m1) {
1327
+ var charCodeToEscape = m1.charCodeAt(0);
1328
+ return "~E" + charCodeToEscape + "E";
1329
+ }
1330
+
1331
+ }; // end of the Markdown.Converter constructor
1332
+
1333
+ })();
1334
+ return Markdown;
1335
+ });