kalei 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,108 @@
1
+ (function () {
2
+ var output, Converter;
3
+ if (typeof exports === "object" && typeof require === "function") { // we're in a CommonJS (e.g. Node.js) module
4
+ output = exports;
5
+ Converter = require("./Markdown.Converter").Converter;
6
+ } else {
7
+ output = window.Markdown;
8
+ Converter = output.Converter;
9
+ }
10
+
11
+ output.getSanitizingConverter = function () {
12
+ var converter = new Converter();
13
+ converter.hooks.chain("postConversion", sanitizeHtml);
14
+ converter.hooks.chain("postConversion", balanceTags);
15
+ return converter;
16
+ }
17
+
18
+ function sanitizeHtml(html) {
19
+ return html.replace(/<[^>]*>?/gi, sanitizeTag);
20
+ }
21
+
22
+ // (tags that can be opened/closed) | (tags that stand alone)
23
+ var basic_tag_whitelist = /^(<\/?(b|blockquote|code|del|dd|dl|dt|em|h1|h2|h3|i|kbd|li|ol|p|pre|s|sup|sub|strong|strike|ul)>|<(br|hr)\s?\/?>)$/i;
24
+ // <a href="url..." optional title>|</a>
25
+ var a_white = /^(<a\shref="((https?|ftp):\/\/|\/)[-A-Za-z0-9+&@#\/%?=~_|!:,.;\(\)]+"(\stitle="[^"<>]+")?\s?>|<\/a>)$/i;
26
+
27
+ // <img src="url..." optional width optional height optional alt optional title
28
+ var img_white = /^(<img\ssrc="(https?:\/\/|\/)[-A-Za-z0-9+&@#\/%?=~_|!:,.;\(\)]+"(\swidth="\d{1,3}")?(\sheight="\d{1,3}")?(\salt="[^"<>]*")?(\stitle="[^"<>]*")?\s?\/?>)$/i;
29
+
30
+ function sanitizeTag(tag) {
31
+ if (tag.match(basic_tag_whitelist) || tag.match(a_white) || tag.match(img_white))
32
+ return tag;
33
+ else
34
+ return "";
35
+ }
36
+
37
+ /// <summary>
38
+ /// attempt to balance HTML tags in the html string
39
+ /// by removing any unmatched opening or closing tags
40
+ /// IMPORTANT: we *assume* HTML has *already* been
41
+ /// sanitized and is safe/sane before balancing!
42
+ ///
43
+ /// adapted from CODESNIPPET: A8591DBA-D1D3-11DE-947C-BA5556D89593
44
+ /// </summary>
45
+ function balanceTags(html) {
46
+
47
+ if (html == "")
48
+ return "";
49
+
50
+ var re = /<\/?\w+[^>]*(\s|$|>)/g;
51
+ // convert everything to lower case; this makes
52
+ // our case insensitive comparisons easier
53
+ var tags = html.toLowerCase().match(re);
54
+
55
+ // no HTML tags present? nothing to do; exit now
56
+ var tagcount = (tags || []).length;
57
+ if (tagcount == 0)
58
+ return html;
59
+
60
+ var tagname, tag;
61
+ var ignoredtags = "<p><img><br><li><hr>";
62
+ var match;
63
+ var tagpaired = [];
64
+ var tagremove = [];
65
+ var needsRemoval = false;
66
+
67
+ // loop through matched tags in forward order
68
+ for (var ctag = 0; ctag < tagcount; ctag++) {
69
+ tagname = tags[ctag].replace(/<\/?(\w+).*/, "$1");
70
+ // skip any already paired tags
71
+ // and skip tags in our ignore list; assume they're self-closed
72
+ if (tagpaired[ctag] || ignoredtags.search("<" + tagname + ">") > -1)
73
+ continue;
74
+
75
+ tag = tags[ctag];
76
+ match = -1;
77
+
78
+ if (!/^<\//.test(tag)) {
79
+ // this is an opening tag
80
+ // search forwards (next tags), look for closing tags
81
+ for (var ntag = ctag + 1; ntag < tagcount; ntag++) {
82
+ if (!tagpaired[ntag] && tags[ntag] == "</" + tagname + ">") {
83
+ match = ntag;
84
+ break;
85
+ }
86
+ }
87
+ }
88
+
89
+ if (match == -1)
90
+ needsRemoval = tagremove[ctag] = true; // mark for removal
91
+ else
92
+ tagpaired[match] = true; // mark paired
93
+ }
94
+
95
+ if (!needsRemoval)
96
+ return html;
97
+
98
+ // delete all orphaned tags from the string
99
+
100
+ var ctag = 0;
101
+ html = html.replace(re, function (match) {
102
+ var res = tagremove[ctag] ? "" : match;
103
+ ctag++;
104
+ return res;
105
+ });
106
+ return html;
107
+ }
108
+ })();
@@ -0,0 +1,32 @@
1
+ define(function () {
2
+
3
+ var parseUri = function (str) {
4
+ var o = parseUri.options,
5
+ m = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
6
+ uri = {},
7
+ i = 14;
8
+
9
+ while (i--) uri[o.key[i]] = m[i] || "";
10
+
11
+ uri[o.q.name] = {};
12
+ uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
13
+ if ($1) uri[o.q.name][$1] = $2;
14
+ });
15
+
16
+ return uri;
17
+ };
18
+
19
+ parseUri.options = {
20
+ strictMode: false,
21
+ key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
22
+ q: {
23
+ name: "queryKey",
24
+ parser: /(?:^|&)([^&=]*)=?([^&]*)/g
25
+ },
26
+ parser: {
27
+ strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
28
+ loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
29
+ }
30
+ };
31
+ return parseUri;
32
+ })
@@ -0,0 +1 @@
1
+ (function(){function k(a){var b=a.currentTarget||a.srcElement,c;if(a.type==="load"||l.test(b.readyState)){a=b.getAttribute("data-requiremodule");j[a]=!0;for(a=0;c=g[a];a++)if(j[c.name])c.req([c.name],c.onLoad);else break;a>0&&g.splice(0,a);setTimeout(function(){b.parentNode.removeChild(b)},15)}}function m(a){var b,c;a.setAttribute("data-orderloaded","loaded");for(a=0;c=h[a];a++)if((b=i[c])&&b.getAttribute("data-orderloaded")==="loaded")delete i[c],require.addScriptToDom(b);else break;a>0&&h.splice(0,a)}var f=typeof document!=="undefined"&&typeof window!=="undefined"&&document.createElement("script"),n=f&&(f.async||window.opera&&Object.prototype.toString.call(window.opera)==="[object Opera]"||"MozAppearance"in document.documentElement.style),o=f&&f.readyState==="uninitialized",l=/^(complete|loaded)$/,g=[],j={},i={},h=[],f=null;define({version:"1.0.5",load:function(a,b,c,e){var d;b.nameToUrl?(d=b.nameToUrl(a,null),require.s.skipAsync[d]=!0,n||e.isBuild?b([a],c):o?(e=require.s.contexts._,!e.urlFetched[d]&&!e.loaded[a]&&(e.urlFetched[d]=!0,require.resourcesReady(!1),e.scriptCount+=1,d=require.attach(d,e,a,null,null,m),i[a]=d,h.push(a)),b([a],c)):b.specified(a)?b([a],c):(g.push({name:a,req:b,onLoad:c}),require.attach(d,null,a,k,"script/cache"))):b([a],c)}})})();
@@ -0,0 +1,31 @@
1
+ /*
2
+ RequireJS 1.0.2 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
3
+ Available via the MIT or new BSD license.
4
+ see: http://github.com/jrburke/requirejs for details
5
+ */
6
+ var requirejs,require,define;
7
+ (function(){function J(a){return M.call(a)==="[object Function]"}function E(a){return M.call(a)==="[object Array]"}function Z(a,c,h){for(var k in c)if(!(k in K)&&(!(k in a)||h))a[k]=c[k];return d}function N(a,c,d){a=Error(c+"\nhttp://requirejs.org/docs/errors.html#"+a);if(d)a.originalError=d;return a}function $(a,c,d){var k,j,q;for(k=0;q=c[k];k++){q=typeof q==="string"?{name:q}:q;j=q.location;if(d&&(!j||j.indexOf("/")!==0&&j.indexOf(":")===-1))j=d+"/"+(j||q.name);a[q.name]={name:q.name,location:j||
8
+ q.name,main:(q.main||"main").replace(ea,"").replace(aa,"")}}}function V(a,c){a.holdReady?a.holdReady(c):c?a.readyWait+=1:a.ready(!0)}function fa(a){function c(b,l){var f,a;if(b&&b.charAt(0)===".")if(l){p.pkgs[l]?l=[l]:(l=l.split("/"),l=l.slice(0,l.length-1));f=b=l.concat(b.split("/"));var c;for(a=0;c=f[a];a++)if(c===".")f.splice(a,1),a-=1;else if(c==="..")if(a===1&&(f[2]===".."||f[0]===".."))break;else a>0&&(f.splice(a-1,2),a-=2);a=p.pkgs[f=b[0]];b=b.join("/");a&&b===f+"/"+a.main&&(b=f)}else b.indexOf("./")===
9
+ 0&&(b=b.substring(2));return b}function h(b,l){var f=b?b.indexOf("!"):-1,a=null,d=l?l.name:null,i=b,e,h;f!==-1&&(a=b.substring(0,f),b=b.substring(f+1,b.length));a&&(a=c(a,d));b&&(a?e=(f=m[a])&&f.normalize?f.normalize(b,function(b){return c(b,d)}):c(b,d):(e=c(b,d),h=E[e],h||(h=g.nameToUrl(e,null,l),E[e]=h)));return{prefix:a,name:e,parentMap:l,url:h,originalName:i,fullName:a?a+"!"+(e||""):e}}function k(){var b=!0,l=p.priorityWait,f,a;if(l){for(a=0;f=l[a];a++)if(!s[f]){b=!1;break}b&&delete p.priorityWait}return b}
10
+ function j(b,l,f){return function(){var a=ga.call(arguments,0),c;if(f&&J(c=a[a.length-1]))c.__requireJsBuild=!0;a.push(l);return b.apply(null,a)}}function q(b,l){var a=j(g.require,b,l);Z(a,{nameToUrl:j(g.nameToUrl,b),toUrl:j(g.toUrl,b),defined:j(g.requireDefined,b),specified:j(g.requireSpecified,b),isBrowser:d.isBrowser});return a}function o(b){var l,a,c,C=b.callback,i=b.map,e=i.fullName,ba=b.deps;c=b.listeners;if(C&&J(C)){if(p.catchError.define)try{a=d.execCb(e,b.callback,ba,m[e])}catch(k){l=k}else a=
11
+ d.execCb(e,b.callback,ba,m[e]);if(e)(C=b.cjsModule)&&C.exports!==void 0&&C.exports!==m[e]?a=m[e]=b.cjsModule.exports:a===void 0&&b.usingExports?a=m[e]:(m[e]=a,F[e]&&(Q[e]=!0))}else e&&(a=m[e]=C,F[e]&&(Q[e]=!0));if(D[b.id])delete D[b.id],b.isDone=!0,g.waitCount-=1,g.waitCount===0&&(I=[]);delete R[e];if(d.onResourceLoad&&!b.placeholder)d.onResourceLoad(g,i,b.depArray);if(l)return a=(e?h(e).url:"")||l.fileName||l.sourceURL,c=l.moduleTree,l=N("defineerror",'Error evaluating module "'+e+'" at location "'+
12
+ a+'":\n'+l+"\nfileName:"+a+"\nlineNumber: "+(l.lineNumber||l.line),l),l.moduleName=e,l.moduleTree=c,d.onError(l);for(l=0;C=c[l];l++)C(a)}function r(b,a){return function(f){b.depDone[a]||(b.depDone[a]=!0,b.deps[a]=f,b.depCount-=1,b.depCount||o(b))}}function u(b,a){var f=a.map,c=f.fullName,h=f.name,i=L[b]||(L[b]=m[b]),e;if(!a.loading)a.loading=!0,e=function(b){a.callback=function(){return b};o(a);s[a.id]=!0;w()},e.fromText=function(b,a){var l=O;s[b]=!1;g.scriptCount+=1;g.fake[b]=!0;l&&(O=!1);d.exec(a);
13
+ l&&(O=!0);g.completeLoad(b)},c in m?e(m[c]):i.load(h,q(f.parentMap,!0),e,p)}function v(b){D[b.id]||(D[b.id]=b,I.push(b),g.waitCount+=1)}function B(b){this.listeners.push(b)}function t(b,a){var f=b.fullName,c=b.prefix,d=c?L[c]||(L[c]=m[c]):null,i,e;f&&(i=R[f]);if(!i&&(e=!0,i={id:(c&&!d?M++ +"__p@:":"")+(f||"__r@"+M++),map:b,depCount:0,depDone:[],depCallbacks:[],deps:[],listeners:[],add:B},y[i.id]=!0,f&&(!c||L[c])))R[f]=i;c&&!d?(f=t(h(c),!0),f.add(function(){var a=h(b.originalName,b.parentMap),a=t(a,
14
+ !0);i.placeholder=!0;a.add(function(b){i.callback=function(){return b};o(i)})})):e&&a&&(s[i.id]=!1,g.paused.push(i),v(i));return i}function x(b,a,f,c){var b=h(b,c),d=b.name,i=b.fullName,e=t(b),k=e.id,j=e.deps,n;if(i){if(i in m||s[k]===!0||i==="jquery"&&p.jQuery&&p.jQuery!==f().fn.jquery)return;y[k]=!0;s[k]=!0;i==="jquery"&&f&&S(f())}e.depArray=a;e.callback=f;for(f=0;f<a.length;f++)if(k=a[f])k=h(k,d?b:c),n=k.fullName,a[f]=n,n==="require"?j[f]=q(b):n==="exports"?(j[f]=m[i]={},e.usingExports=!0):n===
15
+ "module"?e.cjsModule=j[f]={id:d,uri:d?g.nameToUrl(d,null,c):void 0,exports:m[i]}:n in m&&!(n in D)&&(!(i in F)||i in F&&Q[n])?j[f]=m[n]:(i in F&&(F[n]=!0,delete m[n],T[k.url]=!1),e.depCount+=1,e.depCallbacks[f]=r(e,f),t(k,!0).add(e.depCallbacks[f]));e.depCount?v(e):o(e)}function n(b){x.apply(null,b)}function z(b,a){if(!b.isDone){var c=b.map.fullName,d=b.depArray,g,i,e,k;if(c){if(a[c])return m[c];a[c]=!0}if(d)for(g=0;g<d.length;g++)if(i=d[g])if((e=h(i).prefix)&&(k=D[e])&&z(k,a),(e=D[i])&&!e.isDone&&
16
+ s[i])i=z(e,a),b.depCallbacks[g](i);return c?m[c]:void 0}}function A(){var b=p.waitSeconds*1E3,a=b&&g.startTime+b<(new Date).getTime(),b="",c=!1,h=!1,j;if(!(g.pausedCount>0)){if(p.priorityWait)if(k())w();else return;for(j in s)if(!(j in K)&&(c=!0,!s[j]))if(a)b+=j+" ";else{h=!0;break}if(c||g.waitCount){if(a&&b)return j=N("timeout","Load timeout for modules: "+b),j.requireType="timeout",j.requireModules=b,d.onError(j);if(h||g.scriptCount){if((G||ca)&&!W)W=setTimeout(function(){W=0;A()},50)}else{if(g.waitCount){for(H=
17
+ 0;b=I[H];H++)z(b,{});g.paused.length&&w();X<5&&(X+=1,A())}X=0;d.checkReadyState()}}}}var g,w,p={waitSeconds:7,baseUrl:"./",paths:{},pkgs:{},catchError:{}},P=[],y={require:!0,exports:!0,module:!0},E={},m={},s={},D={},I=[],T={},M=0,R={},L={},F={},Q={},Y=0;S=function(b){if(!g.jQuery&&(b=b||(typeof jQuery!=="undefined"?jQuery:null))&&!(p.jQuery&&b.fn.jquery!==p.jQuery)&&("holdReady"in b||"readyWait"in b))if(g.jQuery=b,n(["jquery",[],function(){return jQuery}]),g.scriptCount)V(b,!0),g.jQueryIncremented=
18
+ !0};w=function(){var b,a,c,h,j,i;Y+=1;if(g.scriptCount<=0)g.scriptCount=0;for(;P.length;)if(b=P.shift(),b[0]===null)return d.onError(N("mismatch","Mismatched anonymous define() module: "+b[b.length-1]));else n(b);if(!p.priorityWait||k())for(;g.paused.length;){j=g.paused;g.pausedCount+=j.length;g.paused=[];for(h=0;b=j[h];h++)a=b.map,c=a.url,i=a.fullName,a.prefix?u(a.prefix,b):!T[c]&&!s[i]&&(d.load(g,i,c),c.indexOf("empty:")!==0&&(T[c]=!0));g.startTime=(new Date).getTime();g.pausedCount-=j.length}Y===
19
+ 1&&A();Y-=1};g={contextName:a,config:p,defQueue:P,waiting:D,waitCount:0,specified:y,loaded:s,urlMap:E,urlFetched:T,scriptCount:0,defined:m,paused:[],pausedCount:0,plugins:L,needFullExec:F,fake:{},fullExec:Q,managerCallbacks:R,makeModuleMap:h,normalize:c,configure:function(b){var a,c,d;b.baseUrl&&b.baseUrl.charAt(b.baseUrl.length-1)!=="/"&&(b.baseUrl+="/");a=p.paths;d=p.pkgs;Z(p,b,!0);if(b.paths){for(c in b.paths)c in K||(a[c]=b.paths[c]);p.paths=a}if((a=b.packagePaths)||b.packages){if(a)for(c in a)c in
20
+ K||$(d,a[c],c);b.packages&&$(d,b.packages);p.pkgs=d}if(b.priority)c=g.requireWait,g.requireWait=!1,g.takeGlobalQueue(),w(),g.require(b.priority),w(),g.requireWait=c,p.priorityWait=b.priority;if(b.deps||b.callback)g.require(b.deps||[],b.callback)},requireDefined:function(b,a){return h(b,a).fullName in m},requireSpecified:function(b,a){return h(b,a).fullName in y},require:function(b,c,f){if(typeof b==="string"){if(J(c))return d.onError(N("requireargs","Invalid require call"));if(d.get)return d.get(g,
21
+ b,c);c=h(b,c);b=c.fullName;return!(b in m)?d.onError(N("notloaded","Module name '"+c.fullName+"' has not been loaded yet for context: "+a)):m[b]}(b&&b.length||c)&&x(null,b,c,f);if(!g.requireWait)for(;!g.scriptCount&&g.paused.length;)g.takeGlobalQueue(),w();return g.require},takeGlobalQueue:function(){U.length&&(ha.apply(g.defQueue,[g.defQueue.length-1,0].concat(U)),U=[])},completeLoad:function(b){var a;for(g.takeGlobalQueue();P.length;)if(a=P.shift(),a[0]===null){a[0]=b;break}else if(a[0]===b)break;
22
+ else n(a),a=null;a?n(a):n([b,[],b==="jquery"&&typeof jQuery!=="undefined"?function(){return jQuery}:null]);S();d.isAsync&&(g.scriptCount-=1);w();d.isAsync||(g.scriptCount-=1)},toUrl:function(a,c){var d=a.lastIndexOf("."),h=null;d!==-1&&(h=a.substring(d,a.length),a=a.substring(0,d));return g.nameToUrl(a,h,c)},nameToUrl:function(a,h,f){var j,k,i,e,m=g.config,a=c(a,f&&f.fullName);if(d.jsExtRegExp.test(a))h=a+(h?h:"");else{j=m.paths;k=m.pkgs;f=a.split("/");for(e=f.length;e>0;e--)if(i=f.slice(0,e).join("/"),
23
+ j[i]){f.splice(0,e,j[i]);break}else if(i=k[i]){a=a===i.name?i.location+"/"+i.main:i.location;f.splice(0,e,a);break}h=f.join("/")+(h||".js");h=(h.charAt(0)==="/"||h.match(/^\w+:/)?"":m.baseUrl)+h}return m.urlArgs?h+((h.indexOf("?")===-1?"?":"&")+m.urlArgs):h}};g.jQueryCheck=S;g.resume=w;return g}function ia(){var a,c,d;if(n&&n.readyState==="interactive")return n;a=document.getElementsByTagName("script");for(c=a.length-1;c>-1&&(d=a[c]);c--)if(d.readyState==="interactive")return n=d;return null}var ja=
24
+ /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,ka=/require\(\s*["']([^'"\s]+)["']\s*\)/g,ea=/^\.\//,aa=/\.js$/,M=Object.prototype.toString,r=Array.prototype,ga=r.slice,ha=r.splice,G=!!(typeof window!=="undefined"&&navigator&&document),ca=!G&&typeof importScripts!=="undefined",la=G&&navigator.platform==="PLAYSTATION 3"?/^complete$/:/^(complete|loaded)$/,da=typeof opera!=="undefined"&&opera.toString()==="[object Opera]",K={},t={},U=[],n=null,X=0,O=!1,d,r={},I,v,x,y,u,z,A,H,B,S,W;if(typeof define==="undefined"){if(typeof requirejs!==
25
+ "undefined")if(J(requirejs))return;else r=requirejs,requirejs=void 0;typeof require!=="undefined"&&!J(require)&&(r=require,require=void 0);d=requirejs=function(a,c,d){var k="_",j;!E(a)&&typeof a!=="string"&&(j=a,E(c)?(a=c,c=d):a=[]);if(j&&j.context)k=j.context;d=t[k]||(t[k]=fa(k));j&&d.configure(j);return d.require(a,c)};d.config=function(a){return d(a)};require||(require=d);d.toUrl=function(a){return t._.toUrl(a)};d.version="1.0.2";d.jsExtRegExp=/^\/|:|\?|\.js$/;v=d.s={contexts:t,skipAsync:{}};if(d.isAsync=
26
+ d.isBrowser=G)if(x=v.head=document.getElementsByTagName("head")[0],y=document.getElementsByTagName("base")[0])x=v.head=y.parentNode;d.onError=function(a){throw a;};d.load=function(a,c,h){d.resourcesReady(!1);a.scriptCount+=1;d.attach(h,a,c);if(a.jQuery&&!a.jQueryIncremented)V(a.jQuery,!0),a.jQueryIncremented=!0};define=function(a,c,d){var k,j;typeof a!=="string"&&(d=c,c=a,a=null);E(c)||(d=c,c=[]);!c.length&&J(d)&&d.length&&(d.toString().replace(ja,"").replace(ka,function(a,d){c.push(d)}),c=(d.length===
27
+ 1?["require"]:["require","exports","module"]).concat(c));if(O&&(k=I||ia()))a||(a=k.getAttribute("data-requiremodule")),j=t[k.getAttribute("data-requirecontext")];(j?j.defQueue:U).push([a,c,d])};define.amd={multiversion:!0,plugins:!0,jQuery:!0};d.exec=function(a){return eval(a)};d.execCb=function(a,c,d,k){return c.apply(k,d)};d.addScriptToDom=function(a){I=a;y?x.insertBefore(a,y):x.appendChild(a);I=null};d.onScriptLoad=function(a){var c=a.currentTarget||a.srcElement,h;if(a.type==="load"||c&&la.test(c.readyState))n=
28
+ null,a=c.getAttribute("data-requirecontext"),h=c.getAttribute("data-requiremodule"),t[a].completeLoad(h),c.detachEvent&&!da?c.detachEvent("onreadystatechange",d.onScriptLoad):c.removeEventListener("load",d.onScriptLoad,!1)};d.attach=function(a,c,h,k,j,n){var o;if(G)return k=k||d.onScriptLoad,o=c&&c.config&&c.config.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script"),o.type=j||"text/javascript",o.charset="utf-8",o.async=!v.skipAsync[a],c&&o.setAttribute("data-requirecontext",
29
+ c.contextName),o.setAttribute("data-requiremodule",h),o.attachEvent&&!da?(O=!0,n?o.onreadystatechange=function(){if(o.readyState==="loaded")o.onreadystatechange=null,o.attachEvent("onreadystatechange",k),n(o)}:o.attachEvent("onreadystatechange",k)):o.addEventListener("load",k,!1),o.src=a,n||d.addScriptToDom(o),o;else ca&&(importScripts(a),c.completeLoad(h));return null};if(G){u=document.getElementsByTagName("script");for(H=u.length-1;H>-1&&(z=u[H]);H--){if(!x)x=z.parentNode;if(A=z.getAttribute("data-main")){if(!r.baseUrl)u=
30
+ A.split("/"),z=u.pop(),u=u.length?u.join("/")+"/":"./",r.baseUrl=u,A=z.replace(aa,"");r.deps=r.deps?r.deps.concat(A):[A];break}}}d.checkReadyState=function(){var a=v.contexts,c;for(c in a)if(!(c in K)&&a[c].waitCount)return;d.resourcesReady(!0)};d.resourcesReady=function(a){var c,h;d.resourcesDone=a;if(d.resourcesDone)for(h in a=v.contexts,a)if(!(h in K)&&(c=a[h],c.jQueryIncremented))V(c.jQuery,!1),c.jQueryIncremented=!1};d.pageLoaded=function(){if(document.readyState!=="complete")document.readyState=
31
+ "complete"};if(G&&document.addEventListener&&!document.readyState)document.readyState="loading",window.addEventListener("load",d.pageLoaded,!1);d(r);if(d.isAsync&&typeof setTimeout!=="undefined")B=v.contexts[r.context||"_"],B.requireWait=!0,setTimeout(function(){B.requireWait=!1;B.takeGlobalQueue();B.jQueryCheck();B.scriptCount||B.resume();d.checkReadyState()},0)}})();
@@ -0,0 +1,11 @@
1
+ /*
2
+ RequireJS text 0.27.0 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
3
+ Available via the MIT or new BSD license.
4
+ see: http://github.com/jrburke/requirejs for details
5
+ */
6
+ (function(){var k=["Msxml2.XMLHTTP","Microsoft.XMLHTTP","Msxml2.XMLHTTP.4.0"],n=/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im,o=/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im,i=typeof location!=="undefined"&&location.href,p=i&&location.protocol&&location.protocol.replace(/\:/,""),q=i&&location.hostname,r=i&&(location.port||void 0),j=[];define(function(){var g,h,l;typeof window!=="undefined"&&window.navigator&&window.document?h=function(a,b){var c=g.createXhr();c.open("GET",a,!0);c.onreadystatechange=
7
+ function(){c.readyState===4&&b(c.responseText)};c.send(null)}:typeof process!=="undefined"&&process.versions&&process.versions.node?(l=require.nodeRequire("fs"),h=function(a,b){b(l.readFileSync(a,"utf8"))}):typeof Packages!=="undefined"&&(h=function(a,b){var c=new java.io.File(a),e=java.lang.System.getProperty("line.separator"),c=new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(c),"utf-8")),d,f,g="";try{d=new java.lang.StringBuffer;(f=c.readLine())&&f.length()&&
8
+ f.charAt(0)===65279&&(f=f.substring(1));for(d.append(f);(f=c.readLine())!==null;)d.append(e),d.append(f);g=String(d.toString())}finally{c.close()}b(g)});return g={version:"0.27.0",strip:function(a){if(a){var a=a.replace(n,""),b=a.match(o);b&&(a=b[1])}else a="";return a},jsEscape:function(a){return a.replace(/(['\\])/g,"\\$1").replace(/[\f]/g,"\\f").replace(/[\b]/g,"\\b").replace(/[\n]/g,"\\n").replace(/[\t]/g,"\\t").replace(/[\r]/g,"\\r")},createXhr:function(){var a,b,c;if(typeof XMLHttpRequest!==
9
+ "undefined")return new XMLHttpRequest;else for(b=0;b<3;b++){c=k[b];try{a=new ActiveXObject(c)}catch(e){}if(a){k=[c];break}}if(!a)throw Error("createXhr(): XMLHttpRequest not available");return a},get:h,parseName:function(a){var b=!1,c=a.indexOf("."),e=a.substring(0,c),a=a.substring(c+1,a.length),c=a.indexOf("!");c!==-1&&(b=a.substring(c+1,a.length),b=b==="strip",a=a.substring(0,c));return{moduleName:e,ext:a,strip:b}},xdRegExp:/^((\w+)\:)?\/\/([^\/\\]+)/,useXhr:function(a,b,c,e){var d=g.xdRegExp.exec(a),
10
+ f;if(!d)return!0;a=d[2];d=d[3];d=d.split(":");f=d[1];d=d[0];return(!a||a===b)&&(!d||d===c)&&(!f&&!d||f===e)},finishLoad:function(a,b,c,e,d){c=b?g.strip(c):c;d.isBuild&&d.inlineText&&(j[a]=c);e(c)},load:function(a,b,c,e){var d=g.parseName(a),f=d.moduleName+"."+d.ext,m=b.toUrl(f),h=e&&e.text&&e.text.useXhr||g.useXhr;!i||h(m,p,q,r)?g.get(m,function(b){g.finishLoad(a,d.strip,b,c,e)}):b([f],function(a){g.finishLoad(d.moduleName+"."+d.ext,d.strip,a,c,e)})},write:function(a,b,c){if(b in j){var e=g.jsEscape(j[b]);
11
+ c.asModule(a+"!"+b,"define(function () { return '"+e+"';});\n")}},writeFile:function(a,b,c,e,d){var b=g.parseName(b),f=b.moduleName+"."+b.ext,h=c.toUrl(b.moduleName+"."+b.ext)+".js";g.load(f,c,function(){var b=function(a){return e(h,a)};b.asModule=function(a,b){return e.asModule(a,h,b)};g.write(a,f,b,d)},d)}}})})();
@@ -0,0 +1,1344 @@
1
+ //
2
+ // showdown.js -- A javascript port of Markdown.
3
+ //
4
+ // Copyright (c) 2007 John Fraser.
5
+ //
6
+ // Original Markdown Copyright (c) 2004-2005 John Gruber
7
+ // <http://daringfireball.net/projects/markdown/>
8
+ //
9
+ // Redistributable under a BSD-style open source license.
10
+ // See license.txt for more information.
11
+ //
12
+ // The full source distribution is at:
13
+ //
14
+ // A A L
15
+ // T C A
16
+ // T K B
17
+ //
18
+ // <http://www.attacklab.net/>
19
+ //
20
+
21
+ //
22
+ // Wherever possible, Showdown is a straight, line-by-line port
23
+ // of the Perl version of Markdown.
24
+ //
25
+ // This is not a normal parser design; it's basically just a
26
+ // series of string substitutions. It's hard to read and
27
+ // maintain this way, but keeping Showdown close to the original
28
+ // design makes it easier to port new features.
29
+ //
30
+ // More importantly, Showdown behaves like markdown.pl in most
31
+ // edge cases. So web applications can do client-side preview
32
+ // in Javascript, and then build identical HTML on the server.
33
+ //
34
+ // This port needs the new RegExp functionality of ECMA 262,
35
+ // 3rd Edition (i.e. Javascript 1.5). Most modern web browsers
36
+ // should do fine. Even with the new regular expression features,
37
+ // We do a lot of work to emulate Perl's regex functionality.
38
+ // The tricky changes in this file mostly have the "attacklab:"
39
+ // label. Major or self-explanatory changes don't.
40
+ //
41
+ // Smart diff tools like Araxis Merge will be able to match up
42
+ // this file with markdown.pl in a useful way. A little tweaking
43
+ // helps: in a copy of markdown.pl, replace "#" with "//" and
44
+ // replace "$text" with "text". Be sure to ignore whitespace
45
+ // and line endings.
46
+ //
47
+
48
+
49
+ //
50
+ // Showdown usage:
51
+ //
52
+ // var text = "Markdown *rocks*.";
53
+ //
54
+ // var converter = new Showdown.converter();
55
+ // var html = converter.makeHtml(text);
56
+ //
57
+ // alert(html);
58
+ //
59
+ // Note: move the sample code to the bottom of this
60
+ // file before uncommenting it.
61
+ //
62
+
63
+ define(function () {
64
+
65
+
66
+
67
+ //
68
+ // Showdown namespace
69
+ //
70
+ var Showdown = {};
71
+
72
+ //
73
+ // converter
74
+ //
75
+ // Wraps all "globals" so that the only thing
76
+ // exposed is makeHtml().
77
+ //
78
+ Showdown.converter = function() {
79
+
80
+ //
81
+ // Globals:
82
+ //
83
+
84
+ // Global hashes, used by various utility routines
85
+ var g_urls;
86
+ var g_titles;
87
+ var g_html_blocks;
88
+
89
+ // Used to track when we're inside an ordered or unordered list
90
+ // (see _ProcessListItems() for details):
91
+ var g_list_level = 0;
92
+
93
+
94
+ this.makeHtml = function(text) {
95
+ //
96
+ // Main function. The order in which other subs are called here is
97
+ // essential. Link and image substitutions need to happen before
98
+ // _EscapeSpecialCharsWithinTagAttributes(), so that any *'s or _'s in the <a>
99
+ // and <img> tags get encoded.
100
+ //
101
+
102
+ // Clear the global hashes. If we don't clear these, you get conflicts
103
+ // from other articles when generating a page which contains more than
104
+ // one article (e.g. an index page that shows the N most recent
105
+ // articles):
106
+ g_urls = new Array();
107
+ g_titles = new Array();
108
+ g_html_blocks = new Array();
109
+
110
+ // attacklab: Replace ~ with ~T
111
+ // This lets us use tilde as an escape char to avoid md5 hashes
112
+ // The choice of character is arbitray; anything that isn't
113
+ // magic in Markdown will work.
114
+ text = text.replace(/~/g,"~T");
115
+
116
+ // attacklab: Replace $ with ~D
117
+ // RegExp interprets $ as a special character
118
+ // when it's in a replacement string
119
+ text = text.replace(/\$/g,"~D");
120
+
121
+ // Standardize line endings
122
+ text = text.replace(/\r\n/g,"\n"); // DOS to Unix
123
+ text = text.replace(/\r/g,"\n"); // Mac to Unix
124
+
125
+ // Make sure text begins and ends with a couple of newlines:
126
+ text = "\n\n" + text + "\n\n";
127
+
128
+ // Convert all tabs to spaces.
129
+ text = _Detab(text);
130
+
131
+ // Strip any lines consisting only of spaces and tabs.
132
+ // This makes subsequent regexen easier to write, because we can
133
+ // match consecutive blank lines with /\n+/ instead of something
134
+ // contorted like /[ \t]*\n+/ .
135
+ text = text.replace(/^[ \t]+$/mg,"");
136
+
137
+ // Turn block-level HTML blocks into hash entries
138
+ text = _HashHTMLBlocks(text);
139
+
140
+ // Strip link definitions, store in hashes.
141
+ text = _StripLinkDefinitions(text);
142
+
143
+ text = _RunBlockGamut(text);
144
+
145
+ text = _UnescapeSpecialChars(text);
146
+
147
+ // attacklab: Restore dollar signs
148
+ text = text.replace(/~D/g,"$$");
149
+
150
+ // attacklab: Restore tildes
151
+ text = text.replace(/~T/g,"~");
152
+
153
+ return text;
154
+ }
155
+
156
+
157
+ var _StripLinkDefinitions = function(text) {
158
+ //
159
+ // Strips link definitions from text, stores the URLs and titles in
160
+ // hash references.
161
+ //
162
+
163
+ // Link defs are in the form: ^[id]: url "optional title"
164
+
165
+ /*
166
+ var text = text.replace(/
167
+ ^[ ]{0,3}\[(.+)\]: // id = $1 attacklab: g_tab_width - 1
168
+ [ \t]*
169
+ \n? // maybe *one* newline
170
+ [ \t]*
171
+ <?(\S+?)>? // url = $2
172
+ [ \t]*
173
+ \n? // maybe one newline
174
+ [ \t]*
175
+ (?:
176
+ (\n*) // any lines skipped = $3 attacklab: lookbehind removed
177
+ ["(]
178
+ (.+?) // title = $4
179
+ [")]
180
+ [ \t]*
181
+ )? // title is optional
182
+ (?:\n+|$)
183
+ /gm,
184
+ function(){...});
185
+ */
186
+ var text = text.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|\Z)/gm,
187
+ function (wholeMatch,m1,m2,m3,m4) {
188
+ m1 = m1.toLowerCase();
189
+ g_urls[m1] = _EncodeAmpsAndAngles(m2); // Link IDs are case-insensitive
190
+ if (m3) {
191
+ // Oops, found blank lines, so it's not a title.
192
+ // Put back the parenthetical statement we stole.
193
+ return m3+m4;
194
+ } else if (m4) {
195
+ g_titles[m1] = m4.replace(/"/g,"&quot;");
196
+ }
197
+
198
+ // Completely remove the definition from the text
199
+ return "";
200
+ }
201
+ );
202
+
203
+ return text;
204
+ }
205
+
206
+
207
+ var _HashHTMLBlocks = function(text) {
208
+ // attacklab: Double up blank lines to reduce lookaround
209
+ text = text.replace(/\n/g,"\n\n");
210
+
211
+ // Hashify HTML blocks:
212
+ // We only want to do this for block-level HTML tags, such as headers,
213
+ // lists, and tables. That's because we still want to wrap <p>s around
214
+ // "paragraphs" that are wrapped in non-block-level tags, such as anchors,
215
+ // phrase emphasis, and spans. The list of tags we're looking for is
216
+ // hard-coded:
217
+ var block_tags_a = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del"
218
+ var block_tags_b = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math"
219
+
220
+ // First, look for nested blocks, e.g.:
221
+ // <div>
222
+ // <div>
223
+ // tags for inner block must be indented.
224
+ // </div>
225
+ // </div>
226
+ //
227
+ // The outermost tags must start at the left margin for this to match, and
228
+ // the inner nested divs must be indented.
229
+ // We need to do this before the next, more liberal match, because the next
230
+ // match will start at the first `<div>` and stop at the first `</div>`.
231
+
232
+ // attacklab: This regex can be expensive when it fails.
233
+ /*
234
+ var text = text.replace(/
235
+ ( // save in $1
236
+ ^ // start of line (with /m)
237
+ <($block_tags_a) // start tag = $2
238
+ \b // word break
239
+ // attacklab: hack around khtml/pcre bug...
240
+ [^\r]*?\n // any number of lines, minimally matching
241
+ </\2> // the matching end tag
242
+ [ \t]* // trailing spaces/tabs
243
+ (?=\n+) // followed by a newline
244
+ ) // attacklab: there are sentinel newlines at end of document
245
+ /gm,function(){...}};
246
+ */
247
+ 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);
248
+
249
+ //
250
+ // Now match more liberally, simply from `\n<tag>` to `</tag>\n`
251
+ //
252
+
253
+ /*
254
+ var text = text.replace(/
255
+ ( // save in $1
256
+ ^ // start of line (with /m)
257
+ <($block_tags_b) // start tag = $2
258
+ \b // word break
259
+ // attacklab: hack around khtml/pcre bug...
260
+ [^\r]*? // any number of lines, minimally matching
261
+ .*</\2> // the matching end tag
262
+ [ \t]* // trailing spaces/tabs
263
+ (?=\n+) // followed by a newline
264
+ ) // attacklab: there are sentinel newlines at end of document
265
+ /gm,function(){...}};
266
+ */
267
+ 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);
268
+
269
+ // Special case just for <hr />. It was easier to make a special case than
270
+ // to make the other regex more complicated.
271
+
272
+ /*
273
+ text = text.replace(/
274
+ ( // save in $1
275
+ \n\n // Starting after a blank line
276
+ [ ]{0,3}
277
+ (<(hr) // start tag = $2
278
+ \b // word break
279
+ ([^<>])*? //
280
+ \/?>) // the matching end tag
281
+ [ \t]*
282
+ (?=\n{2,}) // followed by a blank line
283
+ )
284
+ /g,hashElement);
285
+ */
286
+ text = text.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,hashElement);
287
+
288
+ // Special case for standalone HTML comments:
289
+
290
+ /*
291
+ text = text.replace(/
292
+ ( // save in $1
293
+ \n\n // Starting after a blank line
294
+ [ ]{0,3} // attacklab: g_tab_width - 1
295
+ <!
296
+ (--[^\r]*?--\s*)+
297
+ >
298
+ [ \t]*
299
+ (?=\n{2,}) // followed by a blank line
300
+ )
301
+ /g,hashElement);
302
+ */
303
+ text = text.replace(/(\n\n[ ]{0,3}<!(--[^\r]*?--\s*)+>[ \t]*(?=\n{2,}))/g,hashElement);
304
+
305
+ // PHP and ASP-style processor instructions (<?...?> and <%...%>)
306
+
307
+ /*
308
+ text = text.replace(/
309
+ (?:
310
+ \n\n // Starting after a blank line
311
+ )
312
+ ( // save in $1
313
+ [ ]{0,3} // attacklab: g_tab_width - 1
314
+ (?:
315
+ <([?%]) // $2
316
+ [^\r]*?
317
+ \2>
318
+ )
319
+ [ \t]*
320
+ (?=\n{2,}) // followed by a blank line
321
+ )
322
+ /g,hashElement);
323
+ */
324
+ text = text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,hashElement);
325
+
326
+ // attacklab: Undo double lines (see comment at top of this function)
327
+ text = text.replace(/\n\n/g,"\n");
328
+ return text;
329
+ }
330
+
331
+ var hashElement = function(wholeMatch,m1) {
332
+ var blockText = m1;
333
+
334
+ // Undo double lines
335
+ blockText = blockText.replace(/\n\n/g,"\n");
336
+ blockText = blockText.replace(/^\n/,"");
337
+
338
+ // strip trailing blank lines
339
+ blockText = blockText.replace(/\n+$/g,"");
340
+
341
+ // Replace the element text with a marker ("~KxK" where x is its key)
342
+ blockText = "\n\n~K" + (g_html_blocks.push(blockText)-1) + "K\n\n";
343
+
344
+ return blockText;
345
+ };
346
+
347
+ var _RunBlockGamut = function(text) {
348
+ //
349
+ // These are all the transformations that form block-level
350
+ // tags like paragraphs, headers, and list items.
351
+ //
352
+ text = _DoHeaders(text);
353
+
354
+ // Do Horizontal Rules:
355
+ var key = hashBlock("<hr />");
356
+ text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm,key);
357
+ text = text.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm,key);
358
+ text = text.replace(/^[ ]{0,2}([ ]?\_[ ]?){3,}[ \t]*$/gm,key);
359
+
360
+ text = _DoLists(text);
361
+ text = _DoGithubCodeBlocks(text);
362
+ text = _DoCodeBlocks(text);
363
+ text = _DoBlockQuotes(text);
364
+
365
+ // We already ran _HashHTMLBlocks() before, in Markdown(), but that
366
+ // was to escape raw HTML in the original Markdown source. This time,
367
+ // we're escaping the markup we've just created, so that we don't wrap
368
+ // <p> tags around block-level tags.
369
+ text = _HashHTMLBlocks(text);
370
+ text = _FormParagraphs(text);
371
+
372
+ return text;
373
+ }
374
+
375
+
376
+ var _RunSpanGamut = function(text) {
377
+ //
378
+ // These are all the transformations that occur *within* block-level
379
+ // tags like paragraphs, headers, and list items.
380
+ //
381
+
382
+ text = _DoCodeSpans(text);
383
+ text = _EscapeSpecialCharsWithinTagAttributes(text);
384
+ text = _EncodeBackslashEscapes(text);
385
+
386
+ // Process anchor and image tags. Images must come first,
387
+ // because ![foo][f] looks like an anchor.
388
+ text = _DoImages(text);
389
+ text = _DoAnchors(text);
390
+
391
+ // Make links out of things like `<http://example.com/>`
392
+ // Must come after _DoAnchors(), because you can use < and >
393
+ // delimiters in inline links like [this](<url>).
394
+ text = _DoAutoLinks(text);
395
+ text = _EncodeAmpsAndAngles(text);
396
+ text = _DoItalicsAndBold(text);
397
+
398
+ // Do hard breaks:
399
+ text = text.replace(/ +\n/g," <br />\n");
400
+
401
+ return text;
402
+ }
403
+
404
+ var _EscapeSpecialCharsWithinTagAttributes = function(text) {
405
+ //
406
+ // Within tags -- meaning between < and > -- encode [\ ` * _] so they
407
+ // don't conflict with their use in Markdown for code, italics and strong.
408
+ //
409
+
410
+ // Build a regex to find HTML tags and comments. See Friedl's
411
+ // "Mastering Regular Expressions", 2nd Ed., pp. 200-201.
412
+ var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi;
413
+
414
+ text = text.replace(regex, function(wholeMatch) {
415
+ var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g,"$1`");
416
+ tag = escapeCharacters(tag,"\\`*_");
417
+ return tag;
418
+ });
419
+
420
+ return text;
421
+ }
422
+
423
+ var _DoAnchors = function(text) {
424
+ //
425
+ // Turn Markdown link shortcuts into XHTML <a> tags.
426
+ //
427
+ //
428
+ // First, handle reference-style links: [link text] [id]
429
+ //
430
+
431
+ /*
432
+ text = text.replace(/
433
+ ( // wrap whole match in $1
434
+ \[
435
+ (
436
+ (?:
437
+ \[[^\]]*\] // allow brackets nested one level
438
+ |
439
+ [^\[] // or anything else
440
+ )*
441
+ )
442
+ \]
443
+
444
+ [ ]? // one optional space
445
+ (?:\n[ ]*)? // one optional newline followed by spaces
446
+
447
+ \[
448
+ (.*?) // id = $3
449
+ \]
450
+ )()()()() // pad remaining backreferences
451
+ /g,_DoAnchors_callback);
452
+ */
453
+ text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,writeAnchorTag);
454
+
455
+ //
456
+ // Next, inline-style links: [link text](url "optional title")
457
+ //
458
+
459
+ /*
460
+ text = text.replace(/
461
+ ( // wrap whole match in $1
462
+ \[
463
+ (
464
+ (?:
465
+ \[[^\]]*\] // allow brackets nested one level
466
+ |
467
+ [^\[\]] // or anything else
468
+ )
469
+ )
470
+ \]
471
+ \( // literal paren
472
+ [ \t]*
473
+ () // no id, so leave $3 empty
474
+ <?(.*?)>? // href = $4
475
+ [ \t]*
476
+ ( // $5
477
+ (['"]) // quote char = $6
478
+ (.*?) // Title = $7
479
+ \6 // matching quote
480
+ [ \t]* // ignore any spaces/tabs between closing quote and )
481
+ )? // title is optional
482
+ \)
483
+ )
484
+ /g,writeAnchorTag);
485
+ */
486
+ text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?(.*?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,writeAnchorTag);
487
+
488
+ //
489
+ // Last, handle reference-style shortcuts: [link text]
490
+ // These must come last in case you've also got [link test][1]
491
+ // or [link test](/foo)
492
+ //
493
+
494
+ /*
495
+ text = text.replace(/
496
+ ( // wrap whole match in $1
497
+ \[
498
+ ([^\[\]]+) // link text = $2; can't contain '[' or ']'
499
+ \]
500
+ )()()()()() // pad rest of backreferences
501
+ /g, writeAnchorTag);
502
+ */
503
+ text = text.replace(/(\[([^\[\]]+)\])()()()()()/g, writeAnchorTag);
504
+
505
+ return text;
506
+ }
507
+
508
+ var writeAnchorTag = function(wholeMatch,m1,m2,m3,m4,m5,m6,m7) {
509
+ if (m7 == undefined) m7 = "";
510
+ var whole_match = m1;
511
+ var link_text = m2;
512
+ var link_id = m3.toLowerCase();
513
+ var url = m4;
514
+ var title = m7;
515
+
516
+ if (url == "") {
517
+ if (link_id == "") {
518
+ // lower-case and turn embedded newlines into spaces
519
+ link_id = link_text.toLowerCase().replace(/ ?\n/g," ");
520
+ }
521
+ url = "#"+link_id;
522
+
523
+ if (g_urls[link_id] != undefined) {
524
+ url = g_urls[link_id];
525
+ if (g_titles[link_id] != undefined) {
526
+ title = g_titles[link_id];
527
+ }
528
+ }
529
+ else {
530
+ if (whole_match.search(/\(\s*\)$/m)>-1) {
531
+ // Special case for explicit empty url
532
+ url = "";
533
+ } else {
534
+ return whole_match;
535
+ }
536
+ }
537
+ }
538
+
539
+ url = escapeCharacters(url,"*_");
540
+ var result = "<a href=\"" + url + "\"";
541
+
542
+ if (title != "") {
543
+ title = title.replace(/"/g,"&quot;");
544
+ title = escapeCharacters(title,"*_");
545
+ result += " title=\"" + title + "\"";
546
+ }
547
+
548
+ result += ">" + link_text + "</a>";
549
+
550
+ return result;
551
+ }
552
+
553
+
554
+ var _DoImages = function(text) {
555
+ //
556
+ // Turn Markdown image shortcuts into <img> tags.
557
+ //
558
+
559
+ //
560
+ // First, handle reference-style labeled images: ![alt text][id]
561
+ //
562
+
563
+ /*
564
+ text = text.replace(/
565
+ ( // wrap whole match in $1
566
+ !\[
567
+ (.*?) // alt text = $2
568
+ \]
569
+
570
+ [ ]? // one optional space
571
+ (?:\n[ ]*)? // one optional newline followed by spaces
572
+
573
+ \[
574
+ (.*?) // id = $3
575
+ \]
576
+ )()()()() // pad rest of backreferences
577
+ /g,writeImageTag);
578
+ */
579
+ text = text.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,writeImageTag);
580
+
581
+ //
582
+ // Next, handle inline images: ![alt text](url "optional title")
583
+ // Don't forget: encode * and _
584
+
585
+ /*
586
+ text = text.replace(/
587
+ ( // wrap whole match in $1
588
+ !\[
589
+ (.*?) // alt text = $2
590
+ \]
591
+ \s? // One optional whitespace character
592
+ \( // literal paren
593
+ [ \t]*
594
+ () // no id, so leave $3 empty
595
+ <?(\S+?)>? // src url = $4
596
+ [ \t]*
597
+ ( // $5
598
+ (['"]) // quote char = $6
599
+ (.*?) // title = $7
600
+ \6 // matching quote
601
+ [ \t]*
602
+ )? // title is optional
603
+ \)
604
+ )
605
+ /g,writeImageTag);
606
+ */
607
+ text = text.replace(/(!\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,writeImageTag);
608
+
609
+ return text;
610
+ }
611
+
612
+ var writeImageTag = function(wholeMatch,m1,m2,m3,m4,m5,m6,m7) {
613
+ var whole_match = m1;
614
+ var alt_text = m2;
615
+ var link_id = m3.toLowerCase();
616
+ var url = m4;
617
+ var title = m7;
618
+
619
+ if (!title) title = "";
620
+
621
+ if (url == "") {
622
+ if (link_id == "") {
623
+ // lower-case and turn embedded newlines into spaces
624
+ link_id = alt_text.toLowerCase().replace(/ ?\n/g," ");
625
+ }
626
+ url = "#"+link_id;
627
+
628
+ if (g_urls[link_id] != undefined) {
629
+ url = g_urls[link_id];
630
+ if (g_titles[link_id] != undefined) {
631
+ title = g_titles[link_id];
632
+ }
633
+ }
634
+ else {
635
+ return whole_match;
636
+ }
637
+ }
638
+
639
+ alt_text = alt_text.replace(/"/g,"&quot;");
640
+ url = escapeCharacters(url,"*_");
641
+ var result = "<img src=\"" + url + "\" alt=\"" + alt_text + "\"";
642
+
643
+ // attacklab: Markdown.pl adds empty title attributes to images.
644
+ // Replicate this bug.
645
+
646
+ //if (title != "") {
647
+ title = title.replace(/"/g,"&quot;");
648
+ title = escapeCharacters(title,"*_");
649
+ result += " title=\"" + title + "\"";
650
+ //}
651
+
652
+ result += " />";
653
+
654
+ return result;
655
+ }
656
+
657
+
658
+ var _DoHeaders = function(text) {
659
+
660
+ // Setext-style headers:
661
+ // Header 1
662
+ // ========
663
+ //
664
+ // Header 2
665
+ // --------
666
+ //
667
+ text = text.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,
668
+ function(wholeMatch,m1){return hashBlock('<h1 id="' + headerId(m1) + '">' + _RunSpanGamut(m1) + "</h1>");});
669
+
670
+ text = text.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,
671
+ function(matchFound,m1){return hashBlock('<h2 id="' + headerId(m1) + '">' + _RunSpanGamut(m1) + "</h2>");});
672
+
673
+ // atx-style headers:
674
+ // # Header 1
675
+ // ## Header 2
676
+ // ## Header 2 with closing hashes ##
677
+ // ...
678
+ // ###### Header 6
679
+ //
680
+
681
+ /*
682
+ text = text.replace(/
683
+ ^(\#{1,6}) // $1 = string of #'s
684
+ [ \t]*
685
+ (.+?) // $2 = Header text
686
+ [ \t]*
687
+ \#* // optional closing #'s (not counted)
688
+ \n+
689
+ /gm, function() {...});
690
+ */
691
+
692
+ text = text.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,
693
+ function(wholeMatch,m1,m2) {
694
+ var h_level = m1.length;
695
+ return hashBlock("<h" + h_level + ' id="' + headerId(m2) + '">' + _RunSpanGamut(m2) + "</h" + h_level + ">");
696
+ });
697
+
698
+ function headerId(m) {
699
+ return m.replace(/[^\w]/g, '').toLowerCase();
700
+ }
701
+ return text;
702
+ }
703
+
704
+ // This declaration keeps Dojo compressor from outputting garbage:
705
+ var _ProcessListItems;
706
+
707
+ var _DoLists = function(text) {
708
+ //
709
+ // Form HTML ordered (numbered) and unordered (bulleted) lists.
710
+ //
711
+
712
+ // attacklab: add sentinel to hack around khtml/safari bug:
713
+ // http://bugs.webkit.org/show_bug.cgi?id=11231
714
+ text += "~0";
715
+
716
+ // Re-usable pattern to match any entirel ul or ol list:
717
+
718
+ /*
719
+ var whole_list = /
720
+ ( // $1 = whole list
721
+ ( // $2
722
+ [ ]{0,3} // attacklab: g_tab_width - 1
723
+ ([*+-]|\d+[.]) // $3 = first list item marker
724
+ [ \t]+
725
+ )
726
+ [^\r]+?
727
+ ( // $4
728
+ ~0 // sentinel for workaround; should be $
729
+ |
730
+ \n{2,}
731
+ (?=\S)
732
+ (?! // Negative lookahead for another list item marker
733
+ [ \t]*
734
+ (?:[*+-]|\d+[.])[ \t]+
735
+ )
736
+ )
737
+ )/g
738
+ */
739
+ var whole_list = /^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;
740
+
741
+ if (g_list_level) {
742
+ text = text.replace(whole_list,function(wholeMatch,m1,m2) {
743
+ var list = m1;
744
+ var list_type = (m2.search(/[*+-]/g)>-1) ? "ul" : "ol";
745
+
746
+ // Turn double returns into triple returns, so that we can make a
747
+ // paragraph for the last item in a list, if necessary:
748
+ list = list.replace(/\n{2,}/g,"\n\n\n");;
749
+ var result = _ProcessListItems(list);
750
+
751
+ // Trim any trailing whitespace, to put the closing `</$list_type>`
752
+ // up on the preceding line, to get it past the current stupid
753
+ // HTML block parser. This is a hack to work around the terrible
754
+ // hack that is the HTML block parser.
755
+ result = result.replace(/\s+$/,"");
756
+ result = "<"+list_type+">" + result + "</"+list_type+">\n";
757
+ return result;
758
+ });
759
+ } else {
760
+ whole_list = /(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g;
761
+ text = text.replace(whole_list,function(wholeMatch,m1,m2,m3) {
762
+ var runup = m1;
763
+ var list = m2;
764
+
765
+ var list_type = (m3.search(/[*+-]/g)>-1) ? "ul" : "ol";
766
+ // Turn double returns into triple returns, so that we can make a
767
+ // paragraph for the last item in a list, if necessary:
768
+ var list = list.replace(/\n{2,}/g,"\n\n\n");;
769
+ var result = _ProcessListItems(list);
770
+ result = runup + "<"+list_type+">\n" + result + "</"+list_type+">\n";
771
+ return result;
772
+ });
773
+ }
774
+
775
+ // attacklab: strip sentinel
776
+ text = text.replace(/~0/,"");
777
+
778
+ return text;
779
+ }
780
+
781
+ _ProcessListItems = function(list_str) {
782
+ //
783
+ // Process the contents of a single ordered or unordered list, splitting it
784
+ // into individual list items.
785
+ //
786
+ // The $g_list_level global keeps track of when we're inside a list.
787
+ // Each time we enter a list, we increment it; when we leave a list,
788
+ // we decrement. If it's zero, we're not in a list anymore.
789
+ //
790
+ // We do this because when we're not inside a list, we want to treat
791
+ // something like this:
792
+ //
793
+ // I recommend upgrading to version
794
+ // 8. Oops, now this line is treated
795
+ // as a sub-list.
796
+ //
797
+ // As a single paragraph, despite the fact that the second line starts
798
+ // with a digit-period-space sequence.
799
+ //
800
+ // Whereas when we're inside a list (or sub-list), that line will be
801
+ // treated as the start of a sub-list. What a kludge, huh? This is
802
+ // an aspect of Markdown's syntax that's hard to parse perfectly
803
+ // without resorting to mind-reading. Perhaps the solution is to
804
+ // change the syntax rules such that sub-lists must start with a
805
+ // starting cardinal number; e.g. "1." or "a.".
806
+
807
+ g_list_level++;
808
+
809
+ // trim trailing blank lines:
810
+ list_str = list_str.replace(/\n{2,}$/,"\n");
811
+
812
+ // attacklab: add sentinel to emulate \z
813
+ list_str += "~0";
814
+
815
+ /*
816
+ list_str = list_str.replace(/
817
+ (\n)? // leading line = $1
818
+ (^[ \t]*) // leading whitespace = $2
819
+ ([*+-]|\d+[.]) [ \t]+ // list marker = $3
820
+ ([^\r]+? // list item text = $4
821
+ (\n{1,2}))
822
+ (?= \n* (~0 | \2 ([*+-]|\d+[.]) [ \t]+))
823
+ /gm, function(){...});
824
+ */
825
+ list_str = list_str.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,
826
+ function(wholeMatch,m1,m2,m3,m4){
827
+ var item = m4;
828
+ var leading_line = m1;
829
+ var leading_space = m2;
830
+
831
+ if (leading_line || (item.search(/\n{2,}/)>-1)) {
832
+ item = _RunBlockGamut(_Outdent(item));
833
+ }
834
+ else {
835
+ // Recursion for sub-lists:
836
+ item = _DoLists(_Outdent(item));
837
+ item = item.replace(/\n$/,""); // chomp(item)
838
+ item = _RunSpanGamut(item);
839
+ }
840
+
841
+ return "<li>" + item + "</li>\n";
842
+ }
843
+ );
844
+
845
+ // attacklab: strip sentinel
846
+ list_str = list_str.replace(/~0/g,"");
847
+
848
+ g_list_level--;
849
+ return list_str;
850
+ }
851
+
852
+
853
+ var _DoCodeBlocks = function(text) {
854
+ //
855
+ // Process Markdown `<pre><code>` blocks.
856
+ //
857
+
858
+ /*
859
+ text = text.replace(text,
860
+ /(?:\n\n|^)
861
+ ( // $1 = the code block -- one or more lines, starting with a space/tab
862
+ (?:
863
+ (?:[ ]{4}|\t) // Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width
864
+ .*\n+
865
+ )+
866
+ )
867
+ (\n*[ ]{0,3}[^ \t\n]|(?=~0)) // attacklab: g_tab_width
868
+ /g,function(){...});
869
+ */
870
+
871
+ // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
872
+ text += "~0";
873
+
874
+ text = text.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,
875
+ function(wholeMatch,m1,m2) {
876
+ var codeblock = m1;
877
+ var nextChar = m2;
878
+
879
+ codeblock = _EncodeCode( _Outdent(codeblock));
880
+ codeblock = _Detab(codeblock);
881
+ codeblock = codeblock.replace(/^\n+/g,""); // trim leading newlines
882
+ codeblock = codeblock.replace(/\n+$/g,""); // trim trailing whitespace
883
+
884
+ codeblock = "<pre><code>" + codeblock + "\n</code></pre>";
885
+
886
+ return hashBlock(codeblock) + nextChar;
887
+ }
888
+ );
889
+
890
+ // attacklab: strip sentinel
891
+ text = text.replace(/~0/,"");
892
+
893
+ return text;
894
+ }
895
+
896
+ var _DoGithubCodeBlocks = function(text) {
897
+ //
898
+ // Process Github-style code blocks
899
+ // Example:
900
+ // ```ruby
901
+ // def hello_world(x)
902
+ // puts "Hello, #{x}"
903
+ // end
904
+ // ```
905
+ //
906
+
907
+
908
+ // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
909
+ text += "~0";
910
+
911
+ text = text.replace(/\n```(.*)\n([^`]+)\n```/g,
912
+ function(wholeMatch,m1,m2) {
913
+ var language = m1;
914
+ var codeblock = m2;
915
+
916
+ codeblock = _EncodeCode(codeblock);
917
+ codeblock = _Detab(codeblock);
918
+ codeblock = codeblock.replace(/^\n+/g,""); // trim leading newlines
919
+ codeblock = codeblock.replace(/\n+$/g,""); // trim trailing whitespace
920
+
921
+ codeblock = "<pre><code class=" + language + ">" + codeblock + "\n</code></pre>";
922
+
923
+ return hashBlock(codeblock);
924
+ }
925
+ );
926
+
927
+ // attacklab: strip sentinel
928
+ text = text.replace(/~0/,"");
929
+
930
+ return text;
931
+ }
932
+
933
+ var hashBlock = function(text) {
934
+ text = text.replace(/(^\n+|\n+$)/g,"");
935
+ return "\n\n~K" + (g_html_blocks.push(text)-1) + "K\n\n";
936
+ }
937
+
938
+ var _DoCodeSpans = function(text) {
939
+ //
940
+ // * Backtick quotes are used for <code></code> spans.
941
+ //
942
+ // * You can use multiple backticks as the delimiters if you want to
943
+ // include literal backticks in the code span. So, this input:
944
+ //
945
+ // Just type ``foo `bar` baz`` at the prompt.
946
+ //
947
+ // Will translate to:
948
+ //
949
+ // <p>Just type <code>foo `bar` baz</code> at the prompt.</p>
950
+ //
951
+ // There's no arbitrary limit to the number of backticks you
952
+ // can use as delimters. If you need three consecutive backticks
953
+ // in your code, use four for delimiters, etc.
954
+ //
955
+ // * You can use spaces to get literal backticks at the edges:
956
+ //
957
+ // ... type `` `bar` `` ...
958
+ //
959
+ // Turns to:
960
+ //
961
+ // ... type <code>`bar`</code> ...
962
+ //
963
+
964
+ /*
965
+ text = text.replace(/
966
+ (^|[^\\]) // Character before opening ` can't be a backslash
967
+ (`+) // $2 = Opening run of `
968
+ ( // $3 = The code block
969
+ [^\r]*?
970
+ [^`] // attacklab: work around lack of lookbehind
971
+ )
972
+ \2 // Matching closer
973
+ (?!`)
974
+ /gm, function(){...});
975
+ */
976
+
977
+ text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,
978
+ function(wholeMatch,m1,m2,m3,m4) {
979
+ var c = m3;
980
+ c = c.replace(/^([ \t]*)/g,""); // leading whitespace
981
+ c = c.replace(/[ \t]*$/g,""); // trailing whitespace
982
+ c = _EncodeCode(c);
983
+ return m1+"<code>"+c+"</code>";
984
+ });
985
+
986
+ return text;
987
+ }
988
+
989
+ var _EncodeCode = function(text) {
990
+ //
991
+ // Encode/escape certain characters inside Markdown code runs.
992
+ // The point is that in code, these characters are literals,
993
+ // and lose their special Markdown meanings.
994
+ //
995
+ // Encode all ampersands; HTML entities are not
996
+ // entities within a Markdown code span.
997
+ text = text.replace(/&/g,"&amp;");
998
+
999
+ // Do the angle bracket song and dance:
1000
+ text = text.replace(/</g,"&lt;");
1001
+ text = text.replace(/>/g,"&gt;");
1002
+
1003
+ // Now, escape characters that are magic in Markdown:
1004
+ text = escapeCharacters(text,"\*_{}[]\\",false);
1005
+
1006
+ // jj the line above breaks this:
1007
+ //---
1008
+
1009
+ //* Item
1010
+
1011
+ // 1. Subitem
1012
+
1013
+ // special char: *
1014
+ //---
1015
+
1016
+ return text;
1017
+ }
1018
+
1019
+
1020
+ var _DoItalicsAndBold = function(text) {
1021
+
1022
+ // <strong> must go first:
1023
+ text = text.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g,
1024
+ "<strong>$2</strong>");
1025
+
1026
+ text = text.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g,
1027
+ "<em>$2</em>");
1028
+
1029
+ return text;
1030
+ }
1031
+
1032
+
1033
+ var _DoBlockQuotes = function(text) {
1034
+
1035
+ /*
1036
+ text = text.replace(/
1037
+ ( // Wrap whole match in $1
1038
+ (
1039
+ ^[ \t]*>[ \t]? // '>' at the start of a line
1040
+ .+\n // rest of the first line
1041
+ (.+\n)* // subsequent consecutive lines
1042
+ \n* // blanks
1043
+ )+
1044
+ )
1045
+ /gm, function(){...});
1046
+ */
1047
+
1048
+ text = text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,
1049
+ function(wholeMatch,m1) {
1050
+ var bq = m1;
1051
+
1052
+ // attacklab: hack around Konqueror 3.5.4 bug:
1053
+ // "----------bug".replace(/^-/g,"") == "bug"
1054
+
1055
+ bq = bq.replace(/^[ \t]*>[ \t]?/gm,"~0"); // trim one level of quoting
1056
+
1057
+ // attacklab: clean up hack
1058
+ bq = bq.replace(/~0/g,"");
1059
+
1060
+ bq = bq.replace(/^[ \t]+$/gm,""); // trim whitespace-only lines
1061
+ bq = _RunBlockGamut(bq); // recurse
1062
+
1063
+ bq = bq.replace(/(^|\n)/g,"$1 ");
1064
+ // These leading spaces screw with <pre> content, so we need to fix that:
1065
+ bq = bq.replace(
1066
+ /(\s*<pre>[^\r]+?<\/pre>)/gm,
1067
+ function(wholeMatch,m1) {
1068
+ var pre = m1;
1069
+ // attacklab: hack around Konqueror 3.5.4 bug:
1070
+ pre = pre.replace(/^ /mg,"~0");
1071
+ pre = pre.replace(/~0/g,"");
1072
+ return pre;
1073
+ });
1074
+
1075
+ return hashBlock("<blockquote>\n" + bq + "\n</blockquote>");
1076
+ });
1077
+ return text;
1078
+ }
1079
+
1080
+
1081
+ var _FormParagraphs = function(text) {
1082
+ //
1083
+ // Params:
1084
+ // $text - string to process with html <p> tags
1085
+ //
1086
+
1087
+ // Strip leading and trailing lines:
1088
+ text = text.replace(/^\n+/g,"");
1089
+ text = text.replace(/\n+$/g,"");
1090
+
1091
+ var grafs = text.split(/\n{2,}/g);
1092
+ var grafsOut = new Array();
1093
+
1094
+ //
1095
+ // Wrap <p> tags.
1096
+ //
1097
+ var end = grafs.length;
1098
+ for (var i=0; i<end; i++) {
1099
+ var str = grafs[i];
1100
+
1101
+ // if this is an HTML marker, copy it
1102
+ if (str.search(/~K(\d+)K/g) >= 0) {
1103
+ grafsOut.push(str);
1104
+ }
1105
+ else if (str.search(/\S/) >= 0) {
1106
+ str = _RunSpanGamut(str);
1107
+ str = str.replace(/^([ \t]*)/g,"<p>");
1108
+ str += "</p>"
1109
+ grafsOut.push(str);
1110
+ }
1111
+
1112
+ }
1113
+
1114
+ //
1115
+ // Unhashify HTML blocks
1116
+ //
1117
+ end = grafsOut.length;
1118
+ for (var i=0; i<end; i++) {
1119
+ // if this is a marker for an html block...
1120
+ while (grafsOut[i].search(/~K(\d+)K/) >= 0) {
1121
+ var blockText = g_html_blocks[RegExp.$1];
1122
+ blockText = blockText.replace(/\$/g,"$$$$"); // Escape any dollar signs
1123
+ grafsOut[i] = grafsOut[i].replace(/~K\d+K/,blockText);
1124
+ }
1125
+ }
1126
+
1127
+ return grafsOut.join("\n\n");
1128
+ }
1129
+
1130
+
1131
+ var _EncodeAmpsAndAngles = function(text) {
1132
+ // Smart processing for ampersands and angle brackets that need to be encoded.
1133
+
1134
+ // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:
1135
+ // http://bumppo.net/projects/amputator/
1136
+ text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g,"&amp;");
1137
+
1138
+ // Encode naked <'s
1139
+ text = text.replace(/<(?![a-z\/?\$!])/gi,"&lt;");
1140
+
1141
+ return text;
1142
+ }
1143
+
1144
+
1145
+ var _EncodeBackslashEscapes = function(text) {
1146
+ //
1147
+ // Parameter: String.
1148
+ // Returns: The string, with after processing the following backslash
1149
+ // escape sequences.
1150
+ //
1151
+
1152
+ // attacklab: The polite way to do this is with the new
1153
+ // escapeCharacters() function:
1154
+ //
1155
+ // text = escapeCharacters(text,"\\",true);
1156
+ // text = escapeCharacters(text,"`*_{}[]()>#+-.!",true);
1157
+ //
1158
+ // ...but we're sidestepping its use of the (slow) RegExp constructor
1159
+ // as an optimization for Firefox. This function gets called a LOT.
1160
+
1161
+ text = text.replace(/\\(\\)/g,escapeCharacters_callback);
1162
+ text = text.replace(/\\([`*_{}\[\]()>#+-.!])/g,escapeCharacters_callback);
1163
+ return text;
1164
+ }
1165
+
1166
+
1167
+ var _DoAutoLinks = function(text) {
1168
+
1169
+ text = text.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi,"<a href=\"$1\">$1</a>");
1170
+
1171
+ // Email addresses: <address@domain.foo>
1172
+
1173
+ /*
1174
+ text = text.replace(/
1175
+ <
1176
+ (?:mailto:)?
1177
+ (
1178
+ [-.\w]+
1179
+ \@
1180
+ [-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+
1181
+ )
1182
+ >
1183
+ /gi, _DoAutoLinks_callback());
1184
+ */
1185
+ text = text.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,
1186
+ function(wholeMatch,m1) {
1187
+ return _EncodeEmailAddress( _UnescapeSpecialChars(m1) );
1188
+ }
1189
+ );
1190
+
1191
+ return text;
1192
+ }
1193
+
1194
+
1195
+ var _EncodeEmailAddress = function(addr) {
1196
+ //
1197
+ // Input: an email address, e.g. "foo@example.com"
1198
+ //
1199
+ // Output: the email address as a mailto link, with each character
1200
+ // of the address encoded as either a decimal or hex entity, in
1201
+ // the hopes of foiling most address harvesting spam bots. E.g.:
1202
+ //
1203
+ // <a href="&#x6D;&#97;&#105;&#108;&#x74;&#111;:&#102;&#111;&#111;&#64;&#101;
1204
+ // x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;">&#102;&#111;&#111;
1205
+ // &#64;&#101;x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;</a>
1206
+ //
1207
+ // Based on a filter by Matthew Wickline, posted to the BBEdit-Talk
1208
+ // mailing list: <http://tinyurl.com/yu7ue>
1209
+ //
1210
+
1211
+ // attacklab: why can't javascript speak hex?
1212
+ function char2hex(ch) {
1213
+ var hexDigits = '0123456789ABCDEF';
1214
+ var dec = ch.charCodeAt(0);
1215
+ return(hexDigits.charAt(dec>>4) + hexDigits.charAt(dec&15));
1216
+ }
1217
+
1218
+ var encode = [
1219
+ function(ch){return "&#"+ch.charCodeAt(0)+";";},
1220
+ function(ch){return "&#x"+char2hex(ch)+";";},
1221
+ function(ch){return ch;}
1222
+ ];
1223
+
1224
+ addr = "mailto:" + addr;
1225
+
1226
+ addr = addr.replace(/./g, function(ch) {
1227
+ if (ch == "@") {
1228
+ // this *must* be encoded. I insist.
1229
+ ch = encode[Math.floor(Math.random()*2)](ch);
1230
+ } else if (ch !=":") {
1231
+ // leave ':' alone (to spot mailto: later)
1232
+ var r = Math.random();
1233
+ // roughly 10% raw, 45% hex, 45% dec
1234
+ ch = (
1235
+ r > .9 ? encode[2](ch) :
1236
+ r > .45 ? encode[1](ch) :
1237
+ encode[0](ch)
1238
+ );
1239
+ }
1240
+ return ch;
1241
+ });
1242
+
1243
+ addr = "<a href=\"" + addr + "\">" + addr + "</a>";
1244
+ addr = addr.replace(/">.+:/g,"\">"); // strip the mailto: from the visible part
1245
+
1246
+ return addr;
1247
+ }
1248
+
1249
+
1250
+ var _UnescapeSpecialChars = function(text) {
1251
+ //
1252
+ // Swap back in all the special characters we've hidden.
1253
+ //
1254
+ text = text.replace(/~E(\d+)E/g,
1255
+ function(wholeMatch,m1) {
1256
+ var charCodeToReplace = parseInt(m1);
1257
+ return String.fromCharCode(charCodeToReplace);
1258
+ }
1259
+ );
1260
+ return text;
1261
+ }
1262
+
1263
+
1264
+ var _Outdent = function(text) {
1265
+ //
1266
+ // Remove one level of line-leading tabs or spaces
1267
+ //
1268
+
1269
+ // attacklab: hack around Konqueror 3.5.4 bug:
1270
+ // "----------bug".replace(/^-/g,"") == "bug"
1271
+
1272
+ text = text.replace(/^(\t|[ ]{1,4})/gm,"~0"); // attacklab: g_tab_width
1273
+
1274
+ // attacklab: clean up hack
1275
+ text = text.replace(/~0/g,"")
1276
+
1277
+ return text;
1278
+ }
1279
+
1280
+ var _Detab = function(text) {
1281
+ // attacklab: Detab's completely rewritten for speed.
1282
+ // In perl we could fix it by anchoring the regexp with \G.
1283
+ // In javascript we're less fortunate.
1284
+
1285
+ // expand first n-1 tabs
1286
+ text = text.replace(/\t(?=\t)/g," "); // attacklab: g_tab_width
1287
+
1288
+ // replace the nth with two sentinels
1289
+ text = text.replace(/\t/g,"~A~B");
1290
+
1291
+ // use the sentinel to anchor our regex so it doesn't explode
1292
+ text = text.replace(/~B(.+?)~A/g,
1293
+ function(wholeMatch,m1,m2) {
1294
+ var leadingText = m1;
1295
+ var numSpaces = 4 - leadingText.length % 4; // attacklab: g_tab_width
1296
+
1297
+ // there *must* be a better way to do this:
1298
+ for (var i=0; i<numSpaces; i++) leadingText+=" ";
1299
+
1300
+ return leadingText;
1301
+ }
1302
+ );
1303
+
1304
+ // clean up sentinels
1305
+ text = text.replace(/~A/g," "); // attacklab: g_tab_width
1306
+ text = text.replace(/~B/g,"");
1307
+
1308
+ return text;
1309
+ }
1310
+
1311
+
1312
+ //
1313
+ // attacklab: Utility functions
1314
+ //
1315
+
1316
+
1317
+ var escapeCharacters = function(text, charsToEscape, afterBackslash) {
1318
+ // First we have to escape the escape characters so that
1319
+ // we can build a character class out of them
1320
+ var regexString = "([" + charsToEscape.replace(/([\[\]\\])/g,"\\$1") + "])";
1321
+
1322
+ if (afterBackslash) {
1323
+ regexString = "\\\\" + regexString;
1324
+ }
1325
+
1326
+ var regex = new RegExp(regexString,"g");
1327
+ text = text.replace(regex,escapeCharacters_callback);
1328
+
1329
+ return text;
1330
+ }
1331
+
1332
+
1333
+ var escapeCharacters_callback = function(wholeMatch,m1) {
1334
+ var charCodeToEscape = m1.charCodeAt(0);
1335
+ return "~E"+charCodeToEscape+"E";
1336
+ }
1337
+
1338
+ } // end of Showdown.converter
1339
+
1340
+ // export
1341
+ if (typeof exports != 'undefined') exports = Showdown;
1342
+
1343
+ return Showdown;
1344
+ });