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.
- data/MIT-LICENSE +20 -0
 - data/README.md +34 -0
 - data/Rakefile +39 -0
 - data/lib/kalei.rb +3 -0
 - data/lib/kalei/app.rb +9 -0
 - data/lib/kalei/engine.rb +7 -0
 - data/lib/kalei/public/css/buttons.css +251 -0
 - data/lib/kalei/public/css/demo-styleDoccos.css +360 -0
 - data/lib/kalei/public/css/fixie-demo.css +39 -0
 - data/lib/kalei/public/css/highlight/LICENSE +24 -0
 - data/lib/kalei/public/css/highlight/README.md +120 -0
 - data/lib/kalei/public/css/highlight/README.ru.md +125 -0
 - data/lib/kalei/public/css/highlight/classref.txt +544 -0
 - data/lib/kalei/public/css/highlight/default.min.css +1 -0
 - data/lib/kalei/public/css/highlight/highlight.pack.js +1 -0
 - data/lib/kalei/public/css/highlight/styles/arta.css +153 -0
 - data/lib/kalei/public/css/highlight/styles/ascetic.css +49 -0
 - data/lib/kalei/public/css/highlight/styles/brown_paper.css +104 -0
 - data/lib/kalei/public/css/highlight/styles/brown_papersq.png +0 -0
 - data/lib/kalei/public/css/highlight/styles/dark.css +103 -0
 - data/lib/kalei/public/css/highlight/styles/default.css +133 -0
 - data/lib/kalei/public/css/highlight/styles/far.css +110 -0
 - data/lib/kalei/public/css/highlight/styles/github.css +133 -0
 - data/lib/kalei/public/css/highlight/styles/googlecode.css +143 -0
 - data/lib/kalei/public/css/highlight/styles/idea.css +122 -0
 - data/lib/kalei/public/css/highlight/styles/ir_black.css +99 -0
 - data/lib/kalei/public/css/highlight/styles/magula.css +120 -0
 - data/lib/kalei/public/css/highlight/styles/monokai.css +116 -0
 - data/lib/kalei/public/css/highlight/styles/pojoaque.css +106 -0
 - data/lib/kalei/public/css/highlight/styles/pojoaque.jpg +0 -0
 - data/lib/kalei/public/css/highlight/styles/school_book.css +111 -0
 - data/lib/kalei/public/css/highlight/styles/school_book.png +0 -0
 - data/lib/kalei/public/css/highlight/styles/solarized_dark.css +90 -0
 - data/lib/kalei/public/css/highlight/styles/solarized_light.css +90 -0
 - data/lib/kalei/public/css/highlight/styles/sunburst.css +149 -0
 - data/lib/kalei/public/css/highlight/styles/vs.css +85 -0
 - data/lib/kalei/public/css/highlight/styles/xcode.css +153 -0
 - data/lib/kalei/public/css/highlight/styles/zenburn.css +115 -0
 - data/lib/kalei/public/css/styles.css +95 -0
 - data/lib/kalei/public/css/theme.css +259 -0
 - data/lib/kalei/public/css/theme2.css +51 -0
 - data/lib/kalei/public/js/boilerplate.js +9 -0
 - data/lib/kalei/public/js/config.js +8 -0
 - data/lib/kalei/public/js/events.js +8 -0
 - data/lib/kalei/public/js/libs/backbone/backbone-min.js +37 -0
 - data/lib/kalei/public/js/libs/backbone/backbone-optamd3-min.js +37 -0
 - data/lib/kalei/public/js/libs/cssbeautify/cssbeautify.js +198 -0
 - data/lib/kalei/public/js/libs/fixie/fixie.js +1 -0
 - data/lib/kalei/public/js/libs/highlight/highlight.js +1 -0
 - data/lib/kalei/public/js/libs/highlight/highlight.pack.js +1 -0
 - data/lib/kalei/public/js/libs/highlighter/shBrushCss.js +90 -0
 - data/lib/kalei/public/js/libs/highlighter/shCore.js +2371 -0
 - data/lib/kalei/public/js/libs/jquery/jquery-min.js +4 -0
 - data/lib/kalei/public/js/libs/jscssp/jscssp.js +5431 -0
 - data/lib/kalei/public/js/libs/marked/marked.js +793 -0
 - data/lib/kalei/public/js/libs/pagedown/converter.js +1335 -0
 - data/lib/kalei/public/js/libs/pagedown/pagedown +1332 -0
 - data/lib/kalei/public/js/libs/pagedown/sanitizer.js +108 -0
 - data/lib/kalei/public/js/libs/parseuri/parseuri.js +32 -0
 - data/lib/kalei/public/js/libs/require/order.js +1 -0
 - data/lib/kalei/public/js/libs/require/require.js +31 -0
 - data/lib/kalei/public/js/libs/require/text.js +11 -0
 - data/lib/kalei/public/js/libs/showdown/showdown.js +1344 -0
 - data/lib/kalei/public/js/libs/underscore/underscore-min.js +31 -0
 - data/lib/kalei/public/js/main.js +39 -0
 - data/lib/kalei/public/js/router.js +39 -0
 - data/lib/kalei/public/js/views/app.js +24 -0
 - data/lib/kalei/public/js/views/style/menu.js +77 -0
 - data/lib/kalei/public/js/views/style/page.js +100 -0
 - data/lib/kalei/public/js/vm.js +33 -0
 - data/lib/kalei/public/templates/layout.html +4 -0
 - data/lib/kalei/public/templates/style/menu.html +22 -0
 - data/lib/kalei/public/templates/style/page.html +15 -0
 - data/lib/kalei/views/index.erb +18 -0
 - data/test/dummy/README.rdoc +261 -0
 - data/test/dummy/Rakefile +7 -0
 - data/test/dummy/app/assets/javascripts/application.js +15 -0
 - data/test/dummy/app/assets/stylesheets/application.css +13 -0
 - data/test/dummy/app/assets/stylesheets/example.css +251 -0
 - data/test/dummy/app/controllers/application_controller.rb +3 -0
 - data/test/dummy/app/helpers/application_helper.rb +2 -0
 - data/test/dummy/app/views/layouts/application.html.erb +14 -0
 - data/test/dummy/config.ru +4 -0
 - data/test/dummy/config/application.rb +65 -0
 - data/test/dummy/config/boot.rb +10 -0
 - data/test/dummy/config/environment.rb +5 -0
 - data/test/dummy/config/environments/development.rb +31 -0
 - data/test/dummy/config/environments/production.rb +64 -0
 - data/test/dummy/config/environments/test.rb +35 -0
 - data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
 - data/test/dummy/config/initializers/inflections.rb +15 -0
 - data/test/dummy/config/initializers/mime_types.rb +5 -0
 - data/test/dummy/config/initializers/secret_token.rb +7 -0
 - data/test/dummy/config/initializers/session_store.rb +8 -0
 - data/test/dummy/config/initializers/wrap_parameters.rb +10 -0
 - data/test/dummy/config/locales/en.yml +5 -0
 - data/test/dummy/config/routes.rb +4 -0
 - data/test/dummy/log/development (MacBook Air's conflicted copy 2012-11-07).log +12900 -0
 - data/test/dummy/log/development (Work iMac's conflicted copy 2012-11-06).log +12539 -0
 - data/test/dummy/log/development.log +16426 -0
 - data/test/dummy/public/404.html +26 -0
 - data/test/dummy/public/422.html +26 -0
 - data/test/dummy/public/500.html +25 -0
 - data/test/dummy/public/favicon.ico +0 -0
 - data/test/dummy/script/rails +6 -0
 - data/test/dummy/tmp/cache/assets/BBF/D60/sprockets%2Fc81500801e644b9c5335793957200428 +0 -0
 - data/test/dummy/tmp/cache/assets/BE2/9B0/sprockets%2F4097e8869406a33602004190d03272ad +0 -0
 - data/test/dummy/tmp/cache/assets/C59/B10/sprockets%2Fc6a54e0f5352e41a92c1451976584894 +0 -0
 - data/test/dummy/tmp/cache/assets/C5F/F60/sprockets%2F661d2795e99d0034ce6873925e0256c4 +0 -0
 - data/test/dummy/tmp/cache/assets/C64/8C0/sprockets%2F8996c378630075350fb258019546feef +0 -0
 - data/test/dummy/tmp/cache/assets/C94/F80/sprockets%2F5169b582f529b8d582a59c77c247405f +0 -0
 - data/test/dummy/tmp/cache/assets/CA2/420/sprockets%2Fd6a388375c983c17d367a676398f8c19 +0 -0
 - data/test/dummy/tmp/cache/assets/CB0/0B0/sprockets%2F79332476368821ab45ad05e0ae798ad1 +0 -0
 - data/test/dummy/tmp/cache/assets/CB1/C70/sprockets%2F7022bb23d88717cc1625b47988f0af61 +0 -0
 - data/test/dummy/tmp/cache/assets/CB5/DB0/sprockets%2F3c20130f1945e66bbc9726cb8925f647 +0 -0
 - data/test/dummy/tmp/cache/assets/CB6/DF0/sprockets%2F3d4ce8bf5883f171628c030851a5a669 +0 -0
 - data/test/dummy/tmp/cache/assets/CC1/B70/sprockets%2F2451c355722fdc5979cd365f9f9705a3 +0 -0
 - data/test/dummy/tmp/cache/assets/CC2/550/sprockets%2F07be9de6d83634f4e056ba2982578725 +0 -0
 - data/test/dummy/tmp/cache/assets/CC5/8D0/sprockets%2F31f92d93c1650884a626e941c949bff8 +0 -0
 - data/test/dummy/tmp/cache/assets/CC5/D90/sprockets%2F1b9f99d72878209259dce90e419a04d5 +0 -0
 - data/test/dummy/tmp/cache/assets/CC8/780/sprockets%2F8578d679f76df60299b502a4c762a62f +0 -0
 - data/test/dummy/tmp/cache/assets/CC8/C10/sprockets%2F69e29270f13a4c8cd925ac79608878d6 +0 -0
 - data/test/dummy/tmp/cache/assets/CD1/700/sprockets%2F4a8e02ffcb8924669105305f0b107c1b +0 -0
 - data/test/dummy/tmp/cache/assets/CD5/DC0/sprockets%2F92fa0519b445f0f1027d42bd9a4165e4 +0 -0
 - data/test/dummy/tmp/cache/assets/CD8/370/sprockets%2F357970feca3ac29060c1e3861e2c0953 +0 -0
 - data/test/dummy/tmp/cache/assets/CDB/DC0/sprockets%2F58518572a25128ada56ed9156aac53c4 +0 -0
 - data/test/dummy/tmp/cache/assets/CDE/C90/sprockets%2F2b20d9775c811fdb6a466e86711d15c3 +0 -0
 - data/test/dummy/tmp/cache/assets/CE3/2A0/sprockets%2F334b4fc16f7e765755c1be56c9010e28 +0 -0
 - data/test/dummy/tmp/cache/assets/CE5/FF0/sprockets%2F6113d3e443309efb13b899b3a94b578e +0 -0
 - data/test/dummy/tmp/cache/assets/CF2/7D0/sprockets%2F7c50d8877e9a4ee1553dc6626c373d38 +0 -0
 - data/test/dummy/tmp/cache/assets/CF3/C60/sprockets%2Fdfc0395a5019a0a24b34c170a36424de +0 -0
 - data/test/dummy/tmp/cache/assets/CFC/480/sprockets%2F9d5ab28532957b83f7f9fcbd78021699 +0 -0
 - data/test/dummy/tmp/cache/assets/CFF/C60/sprockets%2F4ed7a36bde489e10f97698475493ae57 +0 -0
 - data/test/dummy/tmp/cache/assets/D00/B00/sprockets%2Fd670c548ea2643bd95a65504c11cc13b +0 -0
 - data/test/dummy/tmp/cache/assets/D0A/CB0/sprockets%2Fed8ba102e7d5015265f1e51a89b8d355 +0 -0
 - data/test/dummy/tmp/cache/assets/D10/2B0/sprockets%2F1941a534f48d6fa7b22e23b4ca397b69 +0 -0
 - data/test/dummy/tmp/cache/assets/D17/2A0/sprockets%2Fc094a0ad0b3abb1b92850a86f2000b61 +0 -0
 - data/test/dummy/tmp/cache/assets/D17/920/sprockets%2Fa6ea2beb942f969acce6231944871652 +0 -0
 - data/test/dummy/tmp/cache/assets/D19/7C0/sprockets%2F6bd121745f94b781ed36dd0ffa473856 +0 -0
 - data/test/dummy/tmp/cache/assets/D1A/6F0/sprockets%2F41dd836dc3f691e237833bc1b6f76d93 +0 -0
 - data/test/dummy/tmp/cache/assets/D1A/770/sprockets%2Fcfad959e3f5eb529a1310d85483b9419 +0 -0
 - data/test/dummy/tmp/cache/assets/D1F/000/sprockets%2Fdecbf7d6343c0d9638d301c9982298c6 +0 -0
 - data/test/dummy/tmp/cache/assets/D1F/4D0/sprockets%2F860075c377f26472f83ef56a7bb89aad +0 -0
 - data/test/dummy/tmp/cache/assets/D20/7D0/sprockets%2F1f7e984b4c793c57d666af84ab414d53 +0 -0
 - data/test/dummy/tmp/cache/assets/D23/D20/sprockets%2F746c5fb7c744dd87e61f34c8644183fb +0 -0
 - data/test/dummy/tmp/cache/assets/D29/080/sprockets%2F6b81d746679c6151bc66da896aa97de9 +0 -0
 - data/test/dummy/tmp/cache/assets/D29/890/sprockets%2Fb5d9c167884139e0f6b8d53816de6e9d +0 -0
 - data/test/dummy/tmp/cache/assets/D2B/2D0/sprockets%2Fbaf7beb2c3603cfa100b276923a86543 +0 -0
 - data/test/dummy/tmp/cache/assets/D2B/3F0/sprockets%2Fd6c1fabe78df17a601309081130ca90d +0 -0
 - data/test/dummy/tmp/cache/assets/D2E/700/sprockets%2F9d6beb99735c03f375e19c5857ccf955 +0 -0
 - data/test/dummy/tmp/cache/assets/D31/DF0/sprockets%2Fb9ca3ac15e18a4d032f61278565b7bd0 +0 -0
 - data/test/dummy/tmp/cache/assets/D32/980/sprockets%2F65a361c15a5ff036ce119cb1d2296e4c +0 -0
 - data/test/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
 - data/test/dummy/tmp/cache/assets/D32/CA0/sprockets%2F05becf082d0b555622d944ac6e7202cf +0 -0
 - data/test/dummy/tmp/cache/assets/D36/570/sprockets%2Fadfccb7c2436e006496eae16d6901523 +0 -0
 - data/test/dummy/tmp/cache/assets/D3F/080/sprockets%2Fb5d1e36ac49d4c9e11728239ecf104e6 +0 -0
 - data/test/dummy/tmp/cache/assets/D3F/630/sprockets%2F9093e471e526d13234feda4a9cc80fc5 +0 -0
 - data/test/dummy/tmp/cache/assets/D41/3D0/sprockets%2Fd570b46455f776a30cbb729b442fbbf8 +0 -0
 - data/test/dummy/tmp/cache/assets/D43/500/sprockets%2F91261e8d0df721df2c19e7c8cc6872b0 +0 -0
 - data/test/dummy/tmp/cache/assets/D44/2F0/sprockets%2F8abebce08d92187dd84464b40264fc73 +0 -0
 - data/test/dummy/tmp/cache/assets/D46/350/sprockets%2Fd8bcb0686002ee32c4bf49887f09be36 +0 -0
 - data/test/dummy/tmp/cache/assets/D4A/F50/sprockets%2F99df6af7ff98150e1255d6d9110b80ea +0 -0
 - data/test/dummy/tmp/cache/assets/D50/480/sprockets%2F6e151e3dec739c7a338a877ef65fc174 +0 -0
 - data/test/dummy/tmp/cache/assets/D56/AE0/sprockets%2F68f98777bb22b8e8a78097ba0c86be0f +0 -0
 - data/test/dummy/tmp/cache/assets/D5A/EA0/sprockets%2Fd771ace226fc8215a3572e0aa35bb0d6 +0 -0
 - data/test/dummy/tmp/cache/assets/D5B/E00/sprockets%2Ffea8965ad9d35e43675fc5b948e0e934 +0 -0
 - data/test/dummy/tmp/cache/assets/D68/860/sprockets%2Fafacb887390255dae680441eaf00ff52 +0 -0
 - data/test/dummy/tmp/cache/assets/D6A/BD0/sprockets%2Fada1b7fa3ff025849aec28559a500c76 +0 -0
 - data/test/dummy/tmp/cache/assets/D6D/F20/sprockets%2F3c1e635c4ba90a4512849be74fcfee07 +0 -0
 - data/test/dummy/tmp/cache/assets/D6E/540/sprockets%2F4ea3314d23fc25fc9beec6262272f7f5 +0 -0
 - data/test/dummy/tmp/cache/assets/D73/690/sprockets%2F356bd79cadb47fd8d6836c17d21318ab +0 -0
 - data/test/dummy/tmp/cache/assets/D73/7D0/sprockets%2Ff89249a45e22e86c35f227bd340adedd +0 -0
 - data/test/dummy/tmp/cache/assets/D75/000/sprockets%2Fdfae73207596c9fcc854a2aa1e4f7661 +0 -0
 - data/test/dummy/tmp/cache/assets/D7A/340/sprockets%2Fc880ec2dd9f7c964cf13a12b9674c63d +0 -0
 - data/test/dummy/tmp/cache/assets/D7B/6F0/sprockets%2Fc16bfd961e80bb761c67cd760179df8c +0 -0
 - data/test/dummy/tmp/cache/assets/D7F/D20/sprockets%2Fe4293aa867945ef5c6eb5b26e69c6aa5 +0 -0
 - data/test/dummy/tmp/cache/assets/D81/180/sprockets%2Fd666d9ef622f0e8cb708f5d8a6b2077f +0 -0
 - data/test/dummy/tmp/cache/assets/D81/240/sprockets%2F1d0f3cd232c07902529b25abd0bd4ccd +0 -0
 - data/test/dummy/tmp/cache/assets/D83/560/sprockets%2F9d807a49bc60df8ffb65e99292f3c0a6 +0 -0
 - data/test/dummy/tmp/cache/assets/D85/D50/sprockets%2Feb82054976bcf4d46c573eafed819f58 +0 -0
 - data/test/dummy/tmp/cache/assets/D8F/870/sprockets%2F696f6648b2fcbceb8e2686875e6cd6b6 +0 -0
 - data/test/dummy/tmp/cache/assets/D94/9D0/sprockets%2Ff1c6747b2a961ab3ef92a5a1abe635c4 +0 -0
 - data/test/dummy/tmp/cache/assets/D96/E00/sprockets%2F7f345bc6ada58cac0203458fc076f1ed +0 -0
 - data/test/dummy/tmp/cache/assets/D98/DE0/sprockets%2Fbeac47000d16b66f5757aa626f5e8bda +0 -0
 - data/test/dummy/tmp/cache/assets/D9D/BD0/sprockets%2F1f338b9df8d5a3ffe0b85591db253ab0 +0 -0
 - data/test/dummy/tmp/cache/assets/DA0/0A0/sprockets%2F61e5c9d0b209a8ce5c8a9aa719ad564d +0 -0
 - data/test/dummy/tmp/cache/assets/DB1/A10/sprockets%2Fde67190aff966baf9a57f6641fda292e +0 -0
 - data/test/dummy/tmp/cache/assets/DBE/950/sprockets%2Fa3fbb592cacd368796899f89b95cde1d +0 -0
 - data/test/dummy/tmp/cache/assets/DC3/950/sprockets%2F12be1e5b8e749be4b42e4ccbb24e1a84 +0 -0
 - data/test/dummy/tmp/cache/assets/DC5/E10/sprockets%2Fd10332dee1b2ee73913f7f01e6bffc2f +0 -0
 - data/test/dummy/tmp/cache/assets/DC7/FF0/sprockets%2F4d3d0db28baaafb745e1b4c5f564d891 +0 -0
 - data/test/dummy/tmp/cache/assets/DCC/810/sprockets%2F8d18398a60db7e9e61ae42bea18b2aeb +0 -0
 - data/test/dummy/tmp/cache/assets/DE5/A10/sprockets%2F1aa8db45a4cf7ab09d460c22ed063adb +0 -0
 - data/test/dummy/tmp/cache/assets/DEB/9E0/sprockets%2F1afb4b1d001bc3c1b7cf8cc548bd73e7 +0 -0
 - data/test/dummy/tmp/cache/assets/DF3/AB0/sprockets%2Fa2fbea7b8e275e2e4b610cd1d8fed006 +0 -0
 - data/test/dummy/tmp/cache/assets/DF4/A90/sprockets%2Fc6d9482adadab4569aacdf12a224af49 +0 -0
 - data/test/dummy/tmp/cache/assets/DF5/520/sprockets%2F0cb7052285cefb59b10efc3ed1c6f5cd +0 -0
 - data/test/dummy/tmp/cache/assets/DF8/000/sprockets%2Fb2bc6fbabfb2c270896a8a44da66fa47 +0 -0
 - data/test/dummy/tmp/cache/assets/DFB/2D0/sprockets%2F0e88b08c47faeae40d7682dc28b1fbad +0 -0
 - data/test/dummy/tmp/cache/assets/DFB/9A0/sprockets%2Fb9a29f57d1ebf045452ed6cbd62eae1d +0 -0
 - data/test/dummy/tmp/cache/assets/E02/D20/sprockets%2Fbd7f5fd245b9c9fc534cad60ef038d4a +0 -0
 - data/test/dummy/tmp/cache/assets/E35/0A0/sprockets%2F9e0f5c61a97a72fc952a7dbbcefb7cb6 +0 -0
 - data/test/dummy/tmp/cache/assets/E38/BA0/sprockets%2Fbee7ee5afe77332bcc53bc4e29c77a7f +0 -0
 - data/test/dummy/tmp/cache/assets/E55/740/sprockets%2Fd51ee7ad0adc4b323ce1a9b88ed4a9af +0 -0
 - data/test/dummy/tmp/cache/assets/E5C/410/sprockets%2F1bec976eb7fc54612519dcaccae6ccbe +0 -0
 - data/test/dummy/tmp/cache/assets/EC5/D20/sprockets%2Fc1cf4676f1d3ab9dc9fcbaae59fbe9da +0 -0
 - data/test/functional/kalei/index_controller_test.rb +11 -0
 - data/test/integration/navigation_test.rb +9 -0
 - data/test/kalei_test.rb +7 -0
 - data/test/test_helper.rb +15 -0
 - 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, """));
         
     | 
| 
      
 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:  
         
     | 
| 
      
 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, ">").replace(/</g, "<").replace(/"/g, """);
         
     | 
| 
      
 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, "&");
         
     | 
| 
      
 1031 
     | 
    
         
            +
             
     | 
| 
      
 1032 
     | 
    
         
            +
                        // Do the angle bracket song and dance:
         
     | 
| 
      
 1033 
     | 
    
         
            +
                        text = text.replace(/</g, "<");
         
     | 
| 
      
 1034 
     | 
    
         
            +
                        text = text.replace(/>/g, ">");
         
     | 
| 
      
 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, "&");
         
     | 
| 
      
 1171 
     | 
    
         
            +
             
     | 
| 
      
 1172 
     | 
    
         
            +
                        // Encode naked <'s
         
     | 
| 
      
 1173 
     | 
    
         
            +
                        text = text.replace(/<(?![a-z\/?\$!])/gi, "<");
         
     | 
| 
      
 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 
     | 
    
         
            +
            });
         
     |