spree_awesome_blog 3.0.2
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/README.md +13 -0
 - data/app/controllers/admin/comments_controller.rb +32 -0
 - data/app/controllers/admin/post_images_controller.rb +55 -0
 - data/app/controllers/admin/posts_controller.rb +19 -0
 - data/app/controllers/comments_controller.rb +23 -0
 - data/app/controllers/posts_controller.rb +32 -0
 - data/app/helpers/posts_helper.rb +19 -0
 - data/app/models/comment.rb +31 -0
 - data/app/models/comment.rb~ +31 -0
 - data/app/models/post.rb +47 -0
 - data/app/stylesheets/blog.less +234 -0
 - data/app/views/admin/comments/_form.html.erb +28 -0
 - data/app/views/admin/comments/edit.html.erb +8 -0
 - data/app/views/admin/comments/index.html.erb +45 -0
 - data/app/views/admin/post_images/_form.html.erb +8 -0
 - data/app/views/admin/post_images/edit.html.erb +18 -0
 - data/app/views/admin/post_images/index.html.erb +44 -0
 - data/app/views/admin/post_images/new.html.erb +22 -0
 - data/app/views/admin/posts/_form.html.erb +39 -0
 - data/app/views/admin/posts/edit.html.erb +8 -0
 - data/app/views/admin/posts/index.html.erb +53 -0
 - data/app/views/admin/posts/new.html.erb +6 -0
 - data/app/views/comments/_form.html.erb +30 -0
 - data/app/views/comments/new.html.erb +3 -0
 - data/app/views/posts/_sidebar.html.erb +34 -0
 - data/app/views/posts/_tag_cloud.html.erb +5 -0
 - data/app/views/posts/_tags.html.erb +3 -0
 - data/app/views/posts/index.html.erb +32 -0
 - data/app/views/posts/index.rss.builder +18 -0
 - data/app/views/posts/show.html.erb +43 -0
 - data/app/views/shared/_blog_sub_menu.html.erb +9 -0
 - data/app/views/shared/_blog_tabs.html.erb +25 -0
 - data/config/locales/en-US.yml +35 -0
 - data/config/routes.rb +20 -0
 - data/lib/generators/spree_awesome_blog/install_generator.rb +14 -0
 - data/lib/generators/templates/db/migrate/20110110042721_create_posts.rb +21 -0
 - data/lib/generators/templates/db/migrate/20110110042722_create_comments.rb +20 -0
 - data/lib/generators/templates/db/migrate/20110110053623_acts_as_taggable_on_migration.rb +28 -0
 - data/lib/generators/templates/public/images/markitup/bold.png +0 -0
 - data/lib/generators/templates/public/images/markitup/clean.png +0 -0
 - data/lib/generators/templates/public/images/markitup/h1.png +0 -0
 - data/lib/generators/templates/public/images/markitup/h2.png +0 -0
 - data/lib/generators/templates/public/images/markitup/h3.png +0 -0
 - data/lib/generators/templates/public/images/markitup/h4.png +0 -0
 - data/lib/generators/templates/public/images/markitup/h5.png +0 -0
 - data/lib/generators/templates/public/images/markitup/h6.png +0 -0
 - data/lib/generators/templates/public/images/markitup/image.png +0 -0
 - data/lib/generators/templates/public/images/markitup/italic.png +0 -0
 - data/lib/generators/templates/public/images/markitup/link.png +0 -0
 - data/lib/generators/templates/public/images/markitup/list-bullet.png +0 -0
 - data/lib/generators/templates/public/images/markitup/list-numeric.png +0 -0
 - data/lib/generators/templates/public/images/markitup/paragraph.png +0 -0
 - data/lib/generators/templates/public/images/markitup/picture.png +0 -0
 - data/lib/generators/templates/public/images/markitup/preview.png +0 -0
 - data/lib/generators/templates/public/images/markitup/quotes.png +0 -0
 - data/lib/generators/templates/public/images/markitup/stroke.png +0 -0
 - data/lib/generators/templates/public/javascripts/admin/blog.js +15 -0
 - data/lib/generators/templates/public/javascripts/jquery.markitup.showdown.js +1904 -0
 - data/lib/generators/templates/public/stylesheets/admin/blog.css +163 -0
 - data/lib/generators/templates/public/stylesheets/blog.css +34 -0
 - data/lib/spree_awesome_blog.rb +5 -0
 - data/lib/spree_awesome_blog/engine.rb +29 -0
 - data/lib/spree_awesome_blog_hooks.rb +10 -0
 - metadata +179 -0
 
| 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            <h1><%= raw(t("editing_post") + " “#{@post.title}”") %></h1>
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            <% content_for :sidebar do %>
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              <h3><%= @post.title %></h3>
         
     | 
| 
      
 6 
     | 
    
         
            +
              <br class="clear" />
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              <ul class="sidebar post-menu">
         
     | 
| 
      
 9 
     | 
    
         
            +
                <%= hook :admin_post_tabs, {:current => current} do %>
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  <li<%= raw(' class="active"') if current == "Post" %>>
         
     | 
| 
      
 12 
     | 
    
         
            +
                  <%= link_to t("post"), edit_admin_post_path(@post) %>
         
     | 
| 
      
 13 
     | 
    
         
            +
                  </li>
         
     | 
| 
      
 14 
     | 
    
         
            +
                  <li<%= raw(' class="active"') if current == "Images" %>>
         
     | 
| 
      
 15 
     | 
    
         
            +
                  <%= link_to "#{t("images")} (#{@post.images.count})", admin_post_images_path(@post) %>
         
     | 
| 
      
 16 
     | 
    
         
            +
                  </li>
         
     | 
| 
      
 17 
     | 
    
         
            +
                  <li<%= raw(' class="active"') if current == "Comments" %>>
         
     | 
| 
      
 18 
     | 
    
         
            +
                  <%= link_to "#{t("comments")} (#{@post.comments.count})",  admin_post_comments_path(@post)  %>
         
     | 
| 
      
 19 
     | 
    
         
            +
                  </li>
         
     | 
| 
      
 20 
     | 
    
         
            +
                <% end %>
         
     | 
| 
      
 21 
     | 
    
         
            +
              </ul>
         
     | 
| 
      
 22 
     | 
    
         
            +
              <br class="clear" />
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            <% end %>
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,35 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- 
         
     | 
| 
      
 2 
     | 
    
         
            +
            en:  
         
     | 
| 
      
 3 
     | 
    
         
            +
              blog: Blog
         
     | 
| 
      
 4 
     | 
    
         
            +
              posts: Posts
         
     | 
| 
      
 5 
     | 
    
         
            +
              title: Title
         
     | 
| 
      
 6 
     | 
    
         
            +
              new_post: New Post
         
     | 
| 
      
 7 
     | 
    
         
            +
              unpublished: Unpublished
         
     | 
| 
      
 8 
     | 
    
         
            +
              published: Published
         
     | 
| 
      
 9 
     | 
    
         
            +
              publish: Publish
         
     | 
| 
      
 10 
     | 
    
         
            +
              body: Body
         
     | 
| 
      
 11 
     | 
    
         
            +
              comments: Comments
         
     | 
| 
      
 12 
     | 
    
         
            +
              comment: Comment
         
     | 
| 
      
 13 
     | 
    
         
            +
              post: Post
         
     | 
| 
      
 14 
     | 
    
         
            +
              approved: Approved
         
     | 
| 
      
 15 
     | 
    
         
            +
              not approved: Not Approved
         
     | 
| 
      
 16 
     | 
    
         
            +
              editing_post: Editing post
         
     | 
| 
      
 17 
     | 
    
         
            +
              comments_for: Comments for
         
     | 
| 
      
 18 
     | 
    
         
            +
              posts_tagged: Posts tagged %s
         
     | 
| 
      
 19 
     | 
    
         
            +
              posts_year: Posts for year %s
         
     | 
| 
      
 20 
     | 
    
         
            +
              posts_month: Posts for %s
         
     | 
| 
      
 21 
     | 
    
         
            +
              posts_day: Posts for %s
         
     | 
| 
      
 22 
     | 
    
         
            +
              read_more: Read more
         
     | 
| 
      
 23 
     | 
    
         
            +
              tags: Tags
         
     | 
| 
      
 24 
     | 
    
         
            +
              comma_seperated: Comma seperated
         
     | 
| 
      
 25 
     | 
    
         
            +
              your_name: Your name
         
     | 
| 
      
 26 
     | 
    
         
            +
              your_email: Your email
         
     | 
| 
      
 27 
     | 
    
         
            +
              your_website: Your website
         
     | 
| 
      
 28 
     | 
    
         
            +
              post_comment: Post Comment
         
     | 
| 
      
 29 
     | 
    
         
            +
              commenting_on: Commenting on "%s"
         
     | 
| 
      
 30 
     | 
    
         
            +
              not_shared: Your email is never shared with anyone
         
     | 
| 
      
 31 
     | 
    
         
            +
              created_successfully_pending_approval: Comment was successfully created. It will displayed once it is approved
         
     | 
| 
      
 32 
     | 
    
         
            +
              comment_on_post: Comment on this post
         
     | 
| 
      
 33 
     | 
    
         
            +
              blog_archive: Blog Archive
         
     | 
| 
      
 34 
     | 
    
         
            +
              url: URL
         
     | 
| 
      
 35 
     | 
    
         
            +
              editing_comment: Edit Comment
         
     | 
    
        data/config/routes.rb
    ADDED
    
    | 
         @@ -0,0 +1,20 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Rails.application.routes.draw do
         
     | 
| 
      
 2 
     | 
    
         
            +
              scope "/#{(Spree::Config[:blog_title] || 'blog').to_url}" do
         
     | 
| 
      
 3 
     | 
    
         
            +
                match '/tagged/:tag',           :to => 'posts#index', :as => 'posts_by_tag'
         
     | 
| 
      
 4 
     | 
    
         
            +
                match '/:year(/:month(/:day))', :to => 'posts#index', :as => 'posts_by_date', 
         
     | 
| 
      
 5 
     | 
    
         
            +
                                                                        :year  => /\d{4}/,
         
     | 
| 
      
 6 
     | 
    
         
            +
                                                                        :month => /\d{1,2}/,
         
     | 
| 
      
 7 
     | 
    
         
            +
                                                                        :day   => /\d{1,2}/
         
     | 
| 
      
 8 
     | 
    
         
            +
                resources :posts, :path => '/' do
         
     | 
| 
      
 9 
     | 
    
         
            +
                  resources :comments
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              namespace :admin do 
         
     | 
| 
      
 14 
     | 
    
         
            +
                resources :posts do
         
     | 
| 
      
 15 
     | 
    
         
            +
                  resources :comments
         
     | 
| 
      
 16 
     | 
    
         
            +
                  resources :images, :controller => 'post_images'
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
                resources :comments
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SpreeAwesomeBlog
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Generators
         
     | 
| 
      
 3 
     | 
    
         
            +
                class InstallGenerator < Rails::Generators::Base
         
     | 
| 
      
 4 
     | 
    
         
            +
                  source_root File.expand_path("../../templates", __FILE__)
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  desc "Configures your Rails application for use with spree_awesome_blog"
         
     | 
| 
      
 7 
     | 
    
         
            +
                  def copy_files
         
     | 
| 
      
 8 
     | 
    
         
            +
                    directory "db"
         
     | 
| 
      
 9 
     | 
    
         
            +
                    directory "public"
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class CreatePosts < ActiveRecord::Migration
         
     | 
| 
      
 2 
     | 
    
         
            +
              def self.up
         
     | 
| 
      
 3 
     | 
    
         
            +
                create_table :posts do |t|
         
     | 
| 
      
 4 
     | 
    
         
            +
                  t.string :title
         
     | 
| 
      
 5 
     | 
    
         
            +
                  t.string :permalink
         
     | 
| 
      
 6 
     | 
    
         
            +
                  t.text :summary
         
     | 
| 
      
 7 
     | 
    
         
            +
                  t.text :body
         
     | 
| 
      
 8 
     | 
    
         
            +
                  t.text :tags
         
     | 
| 
      
 9 
     | 
    
         
            +
                  t.boolean :publish
         
     | 
| 
      
 10 
     | 
    
         
            +
                  t.datetime :published_on
         
     | 
| 
      
 11 
     | 
    
         
            +
                  t.string :meta_keywords
         
     | 
| 
      
 12 
     | 
    
         
            +
                  t.string :meta_description
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  t.timestamps
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              def self.down
         
     | 
| 
      
 19 
     | 
    
         
            +
                drop_table :posts
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,20 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class CreateComments < ActiveRecord::Migration
         
     | 
| 
      
 2 
     | 
    
         
            +
              def self.up
         
     | 
| 
      
 3 
     | 
    
         
            +
                create_table :comments do |t|
         
     | 
| 
      
 4 
     | 
    
         
            +
                  t.integer :post_id
         
     | 
| 
      
 5 
     | 
    
         
            +
                  t.integer :user_id
         
     | 
| 
      
 6 
     | 
    
         
            +
                  t.string  :name
         
     | 
| 
      
 7 
     | 
    
         
            +
                  t.string  :email
         
     | 
| 
      
 8 
     | 
    
         
            +
                  t.string  :url
         
     | 
| 
      
 9 
     | 
    
         
            +
                  t.text    :message
         
     | 
| 
      
 10 
     | 
    
         
            +
                  t.boolean :approved, :default => false
         
     | 
| 
      
 11 
     | 
    
         
            +
                  t.datetime :approved_on
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  t.timestamps
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              def self.down
         
     | 
| 
      
 18 
     | 
    
         
            +
                drop_table :comments
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,28 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class ActsAsTaggableOnMigration < ActiveRecord::Migration
         
     | 
| 
      
 2 
     | 
    
         
            +
              def self.up
         
     | 
| 
      
 3 
     | 
    
         
            +
                create_table :tags do |t|
         
     | 
| 
      
 4 
     | 
    
         
            +
                  t.string :name
         
     | 
| 
      
 5 
     | 
    
         
            +
                end
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                create_table :taggings do |t|
         
     | 
| 
      
 8 
     | 
    
         
            +
                  t.references :tag
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  # You should make sure that the column created is
         
     | 
| 
      
 11 
     | 
    
         
            +
                  # long enough to store the required class names.
         
     | 
| 
      
 12 
     | 
    
         
            +
                  t.references :taggable, :polymorphic => true
         
     | 
| 
      
 13 
     | 
    
         
            +
                  t.references :tagger, :polymorphic => true
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  t.string :context
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  t.datetime :created_at
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                add_index :taggings, :tag_id
         
     | 
| 
      
 21 
     | 
    
         
            +
                add_index :taggings, [:taggable_id, :taggable_type, :context]
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              def self.down
         
     | 
| 
      
 25 
     | 
    
         
            +
                drop_table :taggings
         
     | 
| 
      
 26 
     | 
    
         
            +
                drop_table :tags
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
            end
         
     | 
| 
         Binary file 
     | 
| 
         Binary file 
     | 
| 
         Binary file 
     | 
| 
         Binary file 
     | 
| 
         Binary file 
     | 
| 
         Binary file 
     | 
| 
         Binary file 
     | 
| 
         Binary file 
     | 
| 
         Binary file 
     | 
| 
         Binary file 
     | 
| 
         Binary file 
     | 
| 
         Binary file 
     | 
| 
         Binary file 
     | 
| 
         Binary file 
     | 
| 
         Binary file 
     | 
| 
         Binary file 
     | 
| 
         Binary file 
     | 
| 
         Binary file 
     | 
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            $(function() {
         
     | 
| 
      
 2 
     | 
    
         
            +
                var pictures = [];
         
     | 
| 
      
 3 
     | 
    
         
            +
                var allowPictures = false;
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                if ($('#images').size() > 0) {
         
     | 
| 
      
 6 
     | 
    
         
            +
                  allowPictures = true;
         
     | 
| 
      
 7 
     | 
    
         
            +
                  //load images
         
     | 
| 
      
 8 
     | 
    
         
            +
                  $('#images img').each(function() {
         
     | 
| 
      
 9 
     | 
    
         
            +
                    pictures.push({
         
     | 
| 
      
 10 
     | 
    
         
            +
                      url: $(this).attr('src'),
         
     | 
| 
      
 11 
     | 
    
         
            +
                      title: $(this).attr('alt')});
         
     | 
| 
      
 12 
     | 
    
         
            +
                  });
         
     | 
| 
      
 13 
     | 
    
         
            +
                }
         
     | 
| 
      
 14 
     | 
    
         
            +
                $("textarea.editor").markdownEditor({allowPictures: allowPictures, pictures: pictures});
         
     | 
| 
      
 15 
     | 
    
         
            +
            });
         
     | 
| 
         @@ -0,0 +1,1904 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            //
         
     | 
| 
      
 2 
     | 
    
         
            +
            // showdown.js -- A javascript port of Markdown.
         
     | 
| 
      
 3 
     | 
    
         
            +
            //
         
     | 
| 
      
 4 
     | 
    
         
            +
            // Copyright (c) 2007 John Fraser.
         
     | 
| 
      
 5 
     | 
    
         
            +
            //
         
     | 
| 
      
 6 
     | 
    
         
            +
            // Original Markdown Copyright (c) 2004-2005 John Gruber
         
     | 
| 
      
 7 
     | 
    
         
            +
            //   <http://daringfireball.net/projects/markdown/>
         
     | 
| 
      
 8 
     | 
    
         
            +
            //
         
     | 
| 
      
 9 
     | 
    
         
            +
            // Redistributable under a BSD-style open source license.
         
     | 
| 
      
 10 
     | 
    
         
            +
            // See license.txt for more information.
         
     | 
| 
      
 11 
     | 
    
         
            +
            //
         
     | 
| 
      
 12 
     | 
    
         
            +
            // The full source distribution is at:
         
     | 
| 
      
 13 
     | 
    
         
            +
            //
         
     | 
| 
      
 14 
     | 
    
         
            +
            //				A A L
         
     | 
| 
      
 15 
     | 
    
         
            +
            //				T C A
         
     | 
| 
      
 16 
     | 
    
         
            +
            //				T K B
         
     | 
| 
      
 17 
     | 
    
         
            +
            //
         
     | 
| 
      
 18 
     | 
    
         
            +
            //   <http://www.attacklab.net/>
         
     | 
| 
      
 19 
     | 
    
         
            +
            //
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            //
         
     | 
| 
      
 22 
     | 
    
         
            +
            // Wherever possible, Showdown is a straight, line-by-line port
         
     | 
| 
      
 23 
     | 
    
         
            +
            // of the Perl version of Markdown.
         
     | 
| 
      
 24 
     | 
    
         
            +
            //
         
     | 
| 
      
 25 
     | 
    
         
            +
            // This is not a normal parser design; it's basically just a
         
     | 
| 
      
 26 
     | 
    
         
            +
            // series of string substitutions.  It's hard to read and
         
     | 
| 
      
 27 
     | 
    
         
            +
            // maintain this way,  but keeping Showdown close to the original
         
     | 
| 
      
 28 
     | 
    
         
            +
            // design makes it easier to port new features.
         
     | 
| 
      
 29 
     | 
    
         
            +
            //
         
     | 
| 
      
 30 
     | 
    
         
            +
            // More importantly, Showdown behaves like markdown.pl in most
         
     | 
| 
      
 31 
     | 
    
         
            +
            // edge cases.  So web applications can do client-side preview
         
     | 
| 
      
 32 
     | 
    
         
            +
            // in Javascript, and then build identical HTML on the server.
         
     | 
| 
      
 33 
     | 
    
         
            +
            //
         
     | 
| 
      
 34 
     | 
    
         
            +
            // This port needs the new RegExp functionality of ECMA 262,
         
     | 
| 
      
 35 
     | 
    
         
            +
            // 3rd Edition (i.e. Javascript 1.5).  Most modern web browsers
         
     | 
| 
      
 36 
     | 
    
         
            +
            // should do fine.  Even with the new regular expression features,
         
     | 
| 
      
 37 
     | 
    
         
            +
            // We do a lot of work to emulate Perl's regex functionality.
         
     | 
| 
      
 38 
     | 
    
         
            +
            // The tricky changes in this file mostly have the "attacklab:"
         
     | 
| 
      
 39 
     | 
    
         
            +
            // label.  Major or self-explanatory changes don't.
         
     | 
| 
      
 40 
     | 
    
         
            +
            //
         
     | 
| 
      
 41 
     | 
    
         
            +
            // Smart diff tools like Araxis Merge will be able to match up
         
     | 
| 
      
 42 
     | 
    
         
            +
            // this file with markdown.pl in a useful way.  A little tweaking
         
     | 
| 
      
 43 
     | 
    
         
            +
            // helps: in a copy of markdown.pl, replace "#" with "//" and
         
     | 
| 
      
 44 
     | 
    
         
            +
            // replace "$text" with "text".  Be sure to ignore whitespace
         
     | 
| 
      
 45 
     | 
    
         
            +
            // and line endings.
         
     | 
| 
      
 46 
     | 
    
         
            +
            //
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
            //
         
     | 
| 
      
 50 
     | 
    
         
            +
            // Showdown usage:
         
     | 
| 
      
 51 
     | 
    
         
            +
            //
         
     | 
| 
      
 52 
     | 
    
         
            +
            //   var text = "Markdown *rocks*.";
         
     | 
| 
      
 53 
     | 
    
         
            +
            //
         
     | 
| 
      
 54 
     | 
    
         
            +
            //   var converter = new Showdown.converter();
         
     | 
| 
      
 55 
     | 
    
         
            +
            //   var html = converter.makeHtml(text);
         
     | 
| 
      
 56 
     | 
    
         
            +
            //
         
     | 
| 
      
 57 
     | 
    
         
            +
            //   alert(html);
         
     | 
| 
      
 58 
     | 
    
         
            +
            //
         
     | 
| 
      
 59 
     | 
    
         
            +
            // Note: move the sample code to the bottom of this
         
     | 
| 
      
 60 
     | 
    
         
            +
            // file before uncommenting it.
         
     | 
| 
      
 61 
     | 
    
         
            +
            //
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
            //
         
     | 
| 
      
 65 
     | 
    
         
            +
            // Showdown namespace
         
     | 
| 
      
 66 
     | 
    
         
            +
            //
         
     | 
| 
      
 67 
     | 
    
         
            +
            var Showdown = {};
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
            //
         
     | 
| 
      
 70 
     | 
    
         
            +
            // converter
         
     | 
| 
      
 71 
     | 
    
         
            +
            //
         
     | 
| 
      
 72 
     | 
    
         
            +
            // Wraps all "globals" so that the only thing
         
     | 
| 
      
 73 
     | 
    
         
            +
            // exposed is makeHtml().
         
     | 
| 
      
 74 
     | 
    
         
            +
            //
         
     | 
| 
      
 75 
     | 
    
         
            +
            Showdown.converter = function() {
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
            //
         
     | 
| 
      
 78 
     | 
    
         
            +
            // Globals:
         
     | 
| 
      
 79 
     | 
    
         
            +
            //
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
            // Global hashes, used by various utility routines
         
     | 
| 
      
 82 
     | 
    
         
            +
            var g_urls;
         
     | 
| 
      
 83 
     | 
    
         
            +
            var g_titles;
         
     | 
| 
      
 84 
     | 
    
         
            +
            var g_html_blocks;
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
            // Used to track when we're inside an ordered or unordered list
         
     | 
| 
      
 87 
     | 
    
         
            +
            // (see _ProcessListItems() for details):
         
     | 
| 
      
 88 
     | 
    
         
            +
            var g_list_level = 0;
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
            this.makeHtml = function(text) {
         
     | 
| 
      
 92 
     | 
    
         
            +
            //
         
     | 
| 
      
 93 
     | 
    
         
            +
            // Main function. The order in which other subs are called here is
         
     | 
| 
      
 94 
     | 
    
         
            +
            // essential. Link and image substitutions need to happen before
         
     | 
| 
      
 95 
     | 
    
         
            +
            // _EscapeSpecialCharsWithinTagAttributes(), so that any *'s or _'s in the <a>
         
     | 
| 
      
 96 
     | 
    
         
            +
            // and <img> tags get encoded.
         
     | 
| 
      
 97 
     | 
    
         
            +
            //
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
            	// Clear the global hashes. If we don't clear these, you get conflicts
         
     | 
| 
      
 100 
     | 
    
         
            +
            	// from other articles when generating a page which contains more than
         
     | 
| 
      
 101 
     | 
    
         
            +
            	// one article (e.g. an index page that shows the N most recent
         
     | 
| 
      
 102 
     | 
    
         
            +
            	// articles):
         
     | 
| 
      
 103 
     | 
    
         
            +
            	g_urls = new Array();
         
     | 
| 
      
 104 
     | 
    
         
            +
            	g_titles = new Array();
         
     | 
| 
      
 105 
     | 
    
         
            +
            	g_html_blocks = new Array();
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
            	// attacklab: Replace ~ with ~T
         
     | 
| 
      
 108 
     | 
    
         
            +
            	// This lets us use tilde as an escape char to avoid md5 hashes
         
     | 
| 
      
 109 
     | 
    
         
            +
            	// The choice of character is arbitray; anything that isn't
         
     | 
| 
      
 110 
     | 
    
         
            +
                // magic in Markdown will work.
         
     | 
| 
      
 111 
     | 
    
         
            +
            	text = text.replace(/~/g,"~T");
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
            	// attacklab: Replace $ with ~D
         
     | 
| 
      
 114 
     | 
    
         
            +
            	// RegExp interprets $ as a special character
         
     | 
| 
      
 115 
     | 
    
         
            +
            	// when it's in a replacement string
         
     | 
| 
      
 116 
     | 
    
         
            +
            	text = text.replace(/\$/g,"~D");
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
            	// Standardize line endings
         
     | 
| 
      
 119 
     | 
    
         
            +
            	text = text.replace(/\r\n/g,"\n"); // DOS to Unix
         
     | 
| 
      
 120 
     | 
    
         
            +
            	text = text.replace(/\r/g,"\n"); // Mac to Unix
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
            	// Make sure text begins and ends with a couple of newlines:
         
     | 
| 
      
 123 
     | 
    
         
            +
            	text = "\n\n" + text + "\n\n";
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
            	// Convert all tabs to spaces.
         
     | 
| 
      
 126 
     | 
    
         
            +
            	text = _Detab(text);
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
            	// Strip any lines consisting only of spaces and tabs.
         
     | 
| 
      
 129 
     | 
    
         
            +
            	// This makes subsequent regexen easier to write, because we can
         
     | 
| 
      
 130 
     | 
    
         
            +
            	// match consecutive blank lines with /\n+/ instead of something
         
     | 
| 
      
 131 
     | 
    
         
            +
            	// contorted like /[ \t]*\n+/ .
         
     | 
| 
      
 132 
     | 
    
         
            +
            	text = text.replace(/^[ \t]+$/mg,"");
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
            	// Turn block-level HTML blocks into hash entries
         
     | 
| 
      
 135 
     | 
    
         
            +
            	text = _HashHTMLBlocks(text);
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
            	// Strip link definitions, store in hashes.
         
     | 
| 
      
 138 
     | 
    
         
            +
            	text = _StripLinkDefinitions(text);
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
            	text = _RunBlockGamut(text);
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
            	text = _UnescapeSpecialChars(text);
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
            	// attacklab: Restore dollar signs
         
     | 
| 
      
 145 
     | 
    
         
            +
            	text = text.replace(/~D/g,"$$");
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
            	// attacklab: Restore tildes
         
     | 
| 
      
 148 
     | 
    
         
            +
            	text = text.replace(/~T/g,"~");
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
            	return text;
         
     | 
| 
      
 151 
     | 
    
         
            +
            }
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
            var _StripLinkDefinitions = function(text) {
         
     | 
| 
      
 155 
     | 
    
         
            +
            //
         
     | 
| 
      
 156 
     | 
    
         
            +
            // Strips link definitions from text, stores the URLs and titles in
         
     | 
| 
      
 157 
     | 
    
         
            +
            // hash references.
         
     | 
| 
      
 158 
     | 
    
         
            +
            //
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
            	// Link defs are in the form: ^[id]: url "optional title"
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
            	/*
         
     | 
| 
      
 163 
     | 
    
         
            +
            		var text = text.replace(/
         
     | 
| 
      
 164 
     | 
    
         
            +
            				^[ ]{0,3}\[(.+)\]:  // id = $1  attacklab: g_tab_width - 1
         
     | 
| 
      
 165 
     | 
    
         
            +
            				  [ \t]*
         
     | 
| 
      
 166 
     | 
    
         
            +
            				  \n?				// maybe *one* newline
         
     | 
| 
      
 167 
     | 
    
         
            +
            				  [ \t]*
         
     | 
| 
      
 168 
     | 
    
         
            +
            				<?(\S+?)>?			// url = $2
         
     | 
| 
      
 169 
     | 
    
         
            +
            				  [ \t]*
         
     | 
| 
      
 170 
     | 
    
         
            +
            				  \n?				// maybe one newline
         
     | 
| 
      
 171 
     | 
    
         
            +
            				  [ \t]*
         
     | 
| 
      
 172 
     | 
    
         
            +
            				(?:
         
     | 
| 
      
 173 
     | 
    
         
            +
            				  (\n*)				// any lines skipped = $3 attacklab: lookbehind removed
         
     | 
| 
      
 174 
     | 
    
         
            +
            				  ["(]
         
     | 
| 
      
 175 
     | 
    
         
            +
            				  (.+?)				// title = $4
         
     | 
| 
      
 176 
     | 
    
         
            +
            				  [")]
         
     | 
| 
      
 177 
     | 
    
         
            +
            				  [ \t]*
         
     | 
| 
      
 178 
     | 
    
         
            +
            				)?					// title is optional
         
     | 
| 
      
 179 
     | 
    
         
            +
            				(?:\n+|$)
         
     | 
| 
      
 180 
     | 
    
         
            +
            			  /gm,
         
     | 
| 
      
 181 
     | 
    
         
            +
            			  function(){...});
         
     | 
| 
      
 182 
     | 
    
         
            +
            	*/
         
     | 
| 
      
 183 
     | 
    
         
            +
            	var text = text.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|\Z)/gm,
         
     | 
| 
      
 184 
     | 
    
         
            +
            		function (wholeMatch,m1,m2,m3,m4) {
         
     | 
| 
      
 185 
     | 
    
         
            +
            			m1 = m1.toLowerCase();
         
     | 
| 
      
 186 
     | 
    
         
            +
            			g_urls[m1] = _EncodeAmpsAndAngles(m2);  // Link IDs are case-insensitive
         
     | 
| 
      
 187 
     | 
    
         
            +
            			if (m3) {
         
     | 
| 
      
 188 
     | 
    
         
            +
            				// Oops, found blank lines, so it's not a title.
         
     | 
| 
      
 189 
     | 
    
         
            +
            				// Put back the parenthetical statement we stole.
         
     | 
| 
      
 190 
     | 
    
         
            +
            				return m3+m4;
         
     | 
| 
      
 191 
     | 
    
         
            +
            			} else if (m4) {
         
     | 
| 
      
 192 
     | 
    
         
            +
            				g_titles[m1] = m4.replace(/"/g,""");
         
     | 
| 
      
 193 
     | 
    
         
            +
            			}
         
     | 
| 
      
 194 
     | 
    
         
            +
            			
         
     | 
| 
      
 195 
     | 
    
         
            +
            			// Completely remove the definition from the text
         
     | 
| 
      
 196 
     | 
    
         
            +
            			return "";
         
     | 
| 
      
 197 
     | 
    
         
            +
            		}
         
     | 
| 
      
 198 
     | 
    
         
            +
            	);
         
     | 
| 
      
 199 
     | 
    
         
            +
             
     | 
| 
      
 200 
     | 
    
         
            +
            	return text;
         
     | 
| 
      
 201 
     | 
    
         
            +
            }
         
     | 
| 
      
 202 
     | 
    
         
            +
             
     | 
| 
      
 203 
     | 
    
         
            +
             
     | 
| 
      
 204 
     | 
    
         
            +
            var _HashHTMLBlocks = function(text) {
         
     | 
| 
      
 205 
     | 
    
         
            +
            	// attacklab: Double up blank lines to reduce lookaround
         
     | 
| 
      
 206 
     | 
    
         
            +
            	text = text.replace(/\n/g,"\n\n");
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
      
 208 
     | 
    
         
            +
            	// Hashify HTML blocks:
         
     | 
| 
      
 209 
     | 
    
         
            +
            	// We only want to do this for block-level HTML tags, such as headers,
         
     | 
| 
      
 210 
     | 
    
         
            +
            	// lists, and tables. That's because we still want to wrap <p>s around
         
     | 
| 
      
 211 
     | 
    
         
            +
            	// "paragraphs" that are wrapped in non-block-level tags, such as anchors,
         
     | 
| 
      
 212 
     | 
    
         
            +
            	// phrase emphasis, and spans. The list of tags we're looking for is
         
     | 
| 
      
 213 
     | 
    
         
            +
            	// hard-coded:
         
     | 
| 
      
 214 
     | 
    
         
            +
            	var block_tags_a = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del"
         
     | 
| 
      
 215 
     | 
    
         
            +
            	var block_tags_b = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math"
         
     | 
| 
      
 216 
     | 
    
         
            +
             
     | 
| 
      
 217 
     | 
    
         
            +
            	// First, look for nested blocks, e.g.:
         
     | 
| 
      
 218 
     | 
    
         
            +
            	//   <div>
         
     | 
| 
      
 219 
     | 
    
         
            +
            	//     <div>
         
     | 
| 
      
 220 
     | 
    
         
            +
            	//     tags for inner block must be indented.
         
     | 
| 
      
 221 
     | 
    
         
            +
            	//     </div>
         
     | 
| 
      
 222 
     | 
    
         
            +
            	//   </div>
         
     | 
| 
      
 223 
     | 
    
         
            +
            	//
         
     | 
| 
      
 224 
     | 
    
         
            +
            	// The outermost tags must start at the left margin for this to match, and
         
     | 
| 
      
 225 
     | 
    
         
            +
            	// the inner nested divs must be indented.
         
     | 
| 
      
 226 
     | 
    
         
            +
            	// We need to do this before the next, more liberal match, because the next
         
     | 
| 
      
 227 
     | 
    
         
            +
            	// match will start at the first `<div>` and stop at the first `</div>`.
         
     | 
| 
      
 228 
     | 
    
         
            +
             
     | 
| 
      
 229 
     | 
    
         
            +
            	// attacklab: This regex can be expensive when it fails.
         
     | 
| 
      
 230 
     | 
    
         
            +
            	/*
         
     | 
| 
      
 231 
     | 
    
         
            +
            		var text = text.replace(/
         
     | 
| 
      
 232 
     | 
    
         
            +
            		(						// save in $1
         
     | 
| 
      
 233 
     | 
    
         
            +
            			^					// start of line  (with /m)
         
     | 
| 
      
 234 
     | 
    
         
            +
            			<($block_tags_a)	// start tag = $2
         
     | 
| 
      
 235 
     | 
    
         
            +
            			\b					// word break
         
     | 
| 
      
 236 
     | 
    
         
            +
            								// attacklab: hack around khtml/pcre bug...
         
     | 
| 
      
 237 
     | 
    
         
            +
            			[^\r]*?\n			// any number of lines, minimally matching
         
     | 
| 
      
 238 
     | 
    
         
            +
            			</\2>				// the matching end tag
         
     | 
| 
      
 239 
     | 
    
         
            +
            			[ \t]*				// trailing spaces/tabs
         
     | 
| 
      
 240 
     | 
    
         
            +
            			(?=\n+)				// followed by a newline
         
     | 
| 
      
 241 
     | 
    
         
            +
            		)						// attacklab: there are sentinel newlines at end of document
         
     | 
| 
      
 242 
     | 
    
         
            +
            		/gm,function(){...}};
         
     | 
| 
      
 243 
     | 
    
         
            +
            	*/
         
     | 
| 
      
 244 
     | 
    
         
            +
            	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);
         
     | 
| 
      
 245 
     | 
    
         
            +
             
     | 
| 
      
 246 
     | 
    
         
            +
            	//
         
     | 
| 
      
 247 
     | 
    
         
            +
            	// Now match more liberally, simply from `\n<tag>` to `</tag>\n`
         
     | 
| 
      
 248 
     | 
    
         
            +
            	//
         
     | 
| 
      
 249 
     | 
    
         
            +
             
     | 
| 
      
 250 
     | 
    
         
            +
            	/*
         
     | 
| 
      
 251 
     | 
    
         
            +
            		var text = text.replace(/
         
     | 
| 
      
 252 
     | 
    
         
            +
            		(						// save in $1
         
     | 
| 
      
 253 
     | 
    
         
            +
            			^					// start of line  (with /m)
         
     | 
| 
      
 254 
     | 
    
         
            +
            			<($block_tags_b)	// start tag = $2
         
     | 
| 
      
 255 
     | 
    
         
            +
            			\b					// word break
         
     | 
| 
      
 256 
     | 
    
         
            +
            								// attacklab: hack around khtml/pcre bug...
         
     | 
| 
      
 257 
     | 
    
         
            +
            			[^\r]*?				// any number of lines, minimally matching
         
     | 
| 
      
 258 
     | 
    
         
            +
            			.*</\2>				// the matching end tag
         
     | 
| 
      
 259 
     | 
    
         
            +
            			[ \t]*				// trailing spaces/tabs
         
     | 
| 
      
 260 
     | 
    
         
            +
            			(?=\n+)				// followed by a newline
         
     | 
| 
      
 261 
     | 
    
         
            +
            		)						// attacklab: there are sentinel newlines at end of document
         
     | 
| 
      
 262 
     | 
    
         
            +
            		/gm,function(){...}};
         
     | 
| 
      
 263 
     | 
    
         
            +
            	*/
         
     | 
| 
      
 264 
     | 
    
         
            +
            	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);
         
     | 
| 
      
 265 
     | 
    
         
            +
             
     | 
| 
      
 266 
     | 
    
         
            +
            	// Special case just for <hr />. It was easier to make a special case than
         
     | 
| 
      
 267 
     | 
    
         
            +
            	// to make the other regex more complicated.  
         
     | 
| 
      
 268 
     | 
    
         
            +
             
     | 
| 
      
 269 
     | 
    
         
            +
            	/*
         
     | 
| 
      
 270 
     | 
    
         
            +
            		text = text.replace(/
         
     | 
| 
      
 271 
     | 
    
         
            +
            		(						// save in $1
         
     | 
| 
      
 272 
     | 
    
         
            +
            			\n\n				// Starting after a blank line
         
     | 
| 
      
 273 
     | 
    
         
            +
            			[ ]{0,3}
         
     | 
| 
      
 274 
     | 
    
         
            +
            			(<(hr)				// start tag = $2
         
     | 
| 
      
 275 
     | 
    
         
            +
            			\b					// word break
         
     | 
| 
      
 276 
     | 
    
         
            +
            			([^<>])*?			// 
         
     | 
| 
      
 277 
     | 
    
         
            +
            			\/?>)				// the matching end tag
         
     | 
| 
      
 278 
     | 
    
         
            +
            			[ \t]*
         
     | 
| 
      
 279 
     | 
    
         
            +
            			(?=\n{2,})			// followed by a blank line
         
     | 
| 
      
 280 
     | 
    
         
            +
            		)
         
     | 
| 
      
 281 
     | 
    
         
            +
            		/g,hashElement);
         
     | 
| 
      
 282 
     | 
    
         
            +
            	*/
         
     | 
| 
      
 283 
     | 
    
         
            +
            	text = text.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,hashElement);
         
     | 
| 
      
 284 
     | 
    
         
            +
             
     | 
| 
      
 285 
     | 
    
         
            +
            	// Special case for standalone HTML comments:
         
     | 
| 
      
 286 
     | 
    
         
            +
             
     | 
| 
      
 287 
     | 
    
         
            +
            	/*
         
     | 
| 
      
 288 
     | 
    
         
            +
            		text = text.replace(/
         
     | 
| 
      
 289 
     | 
    
         
            +
            		(						// save in $1
         
     | 
| 
      
 290 
     | 
    
         
            +
            			\n\n				// Starting after a blank line
         
     | 
| 
      
 291 
     | 
    
         
            +
            			[ ]{0,3}			// attacklab: g_tab_width - 1
         
     | 
| 
      
 292 
     | 
    
         
            +
            			<!
         
     | 
| 
      
 293 
     | 
    
         
            +
            			(--[^\r]*?--\s*)+
         
     | 
| 
      
 294 
     | 
    
         
            +
            			>
         
     | 
| 
      
 295 
     | 
    
         
            +
            			[ \t]*
         
     | 
| 
      
 296 
     | 
    
         
            +
            			(?=\n{2,})			// followed by a blank line
         
     | 
| 
      
 297 
     | 
    
         
            +
            		)
         
     | 
| 
      
 298 
     | 
    
         
            +
            		/g,hashElement);
         
     | 
| 
      
 299 
     | 
    
         
            +
            	*/
         
     | 
| 
      
 300 
     | 
    
         
            +
            	text = text.replace(/(\n\n[ ]{0,3}<!(--[^\r]*?--\s*)+>[ \t]*(?=\n{2,}))/g,hashElement);
         
     | 
| 
      
 301 
     | 
    
         
            +
             
     | 
| 
      
 302 
     | 
    
         
            +
            	// PHP and ASP-style processor instructions (<?...?> and <%...%>)
         
     | 
| 
      
 303 
     | 
    
         
            +
             
     | 
| 
      
 304 
     | 
    
         
            +
            	/*
         
     | 
| 
      
 305 
     | 
    
         
            +
            		text = text.replace(/
         
     | 
| 
      
 306 
     | 
    
         
            +
            		(?:
         
     | 
| 
      
 307 
     | 
    
         
            +
            			\n\n				// Starting after a blank line
         
     | 
| 
      
 308 
     | 
    
         
            +
            		)
         
     | 
| 
      
 309 
     | 
    
         
            +
            		(						// save in $1
         
     | 
| 
      
 310 
     | 
    
         
            +
            			[ ]{0,3}			// attacklab: g_tab_width - 1
         
     | 
| 
      
 311 
     | 
    
         
            +
            			(?:
         
     | 
| 
      
 312 
     | 
    
         
            +
            				<([?%])			// $2
         
     | 
| 
      
 313 
     | 
    
         
            +
            				[^\r]*?
         
     | 
| 
      
 314 
     | 
    
         
            +
            				\2>
         
     | 
| 
      
 315 
     | 
    
         
            +
            			)
         
     | 
| 
      
 316 
     | 
    
         
            +
            			[ \t]*
         
     | 
| 
      
 317 
     | 
    
         
            +
            			(?=\n{2,})			// followed by a blank line
         
     | 
| 
      
 318 
     | 
    
         
            +
            		)
         
     | 
| 
      
 319 
     | 
    
         
            +
            		/g,hashElement);
         
     | 
| 
      
 320 
     | 
    
         
            +
            	*/
         
     | 
| 
      
 321 
     | 
    
         
            +
            	text = text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,hashElement);
         
     | 
| 
      
 322 
     | 
    
         
            +
             
     | 
| 
      
 323 
     | 
    
         
            +
            	// attacklab: Undo double lines (see comment at top of this function)
         
     | 
| 
      
 324 
     | 
    
         
            +
            	text = text.replace(/\n\n/g,"\n");
         
     | 
| 
      
 325 
     | 
    
         
            +
            	return text;
         
     | 
| 
      
 326 
     | 
    
         
            +
            }
         
     | 
| 
      
 327 
     | 
    
         
            +
             
     | 
| 
      
 328 
     | 
    
         
            +
            var hashElement = function(wholeMatch,m1) {
         
     | 
| 
      
 329 
     | 
    
         
            +
            	var blockText = m1;
         
     | 
| 
      
 330 
     | 
    
         
            +
             
     | 
| 
      
 331 
     | 
    
         
            +
            	// Undo double lines
         
     | 
| 
      
 332 
     | 
    
         
            +
            	blockText = blockText.replace(/\n\n/g,"\n");
         
     | 
| 
      
 333 
     | 
    
         
            +
            	blockText = blockText.replace(/^\n/,"");
         
     | 
| 
      
 334 
     | 
    
         
            +
            	
         
     | 
| 
      
 335 
     | 
    
         
            +
            	// strip trailing blank lines
         
     | 
| 
      
 336 
     | 
    
         
            +
            	blockText = blockText.replace(/\n+$/g,"");
         
     | 
| 
      
 337 
     | 
    
         
            +
            	
         
     | 
| 
      
 338 
     | 
    
         
            +
            	// Replace the element text with a marker ("~KxK" where x is its key)
         
     | 
| 
      
 339 
     | 
    
         
            +
            	blockText = "\n\n~K" + (g_html_blocks.push(blockText)-1) + "K\n\n";
         
     | 
| 
      
 340 
     | 
    
         
            +
            	
         
     | 
| 
      
 341 
     | 
    
         
            +
            	return blockText;
         
     | 
| 
      
 342 
     | 
    
         
            +
            };
         
     | 
| 
      
 343 
     | 
    
         
            +
             
     | 
| 
      
 344 
     | 
    
         
            +
            var _RunBlockGamut = function(text) {
         
     | 
| 
      
 345 
     | 
    
         
            +
            //
         
     | 
| 
      
 346 
     | 
    
         
            +
            // These are all the transformations that form block-level
         
     | 
| 
      
 347 
     | 
    
         
            +
            // tags like paragraphs, headers, and list items.
         
     | 
| 
      
 348 
     | 
    
         
            +
            //
         
     | 
| 
      
 349 
     | 
    
         
            +
            	text = _DoHeaders(text);
         
     | 
| 
      
 350 
     | 
    
         
            +
             
     | 
| 
      
 351 
     | 
    
         
            +
            	// Do Horizontal Rules:
         
     | 
| 
      
 352 
     | 
    
         
            +
            	var key = hashBlock("<hr />");
         
     | 
| 
      
 353 
     | 
    
         
            +
            	text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm,key);
         
     | 
| 
      
 354 
     | 
    
         
            +
            	text = text.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm,key);
         
     | 
| 
      
 355 
     | 
    
         
            +
            	text = text.replace(/^[ ]{0,2}([ ]?\_[ ]?){3,}[ \t]*$/gm,key);
         
     | 
| 
      
 356 
     | 
    
         
            +
             
     | 
| 
      
 357 
     | 
    
         
            +
            	text = _DoLists(text);
         
     | 
| 
      
 358 
     | 
    
         
            +
            	text = _DoCodeBlocks(text);
         
     | 
| 
      
 359 
     | 
    
         
            +
            	text = _DoBlockQuotes(text);
         
     | 
| 
      
 360 
     | 
    
         
            +
             
     | 
| 
      
 361 
     | 
    
         
            +
            	// We already ran _HashHTMLBlocks() before, in Markdown(), but that
         
     | 
| 
      
 362 
     | 
    
         
            +
            	// was to escape raw HTML in the original Markdown source. This time,
         
     | 
| 
      
 363 
     | 
    
         
            +
            	// we're escaping the markup we've just created, so that we don't wrap
         
     | 
| 
      
 364 
     | 
    
         
            +
            	// <p> tags around block-level tags.
         
     | 
| 
      
 365 
     | 
    
         
            +
            	text = _HashHTMLBlocks(text);
         
     | 
| 
      
 366 
     | 
    
         
            +
            	text = _FormParagraphs(text);
         
     | 
| 
      
 367 
     | 
    
         
            +
             
     | 
| 
      
 368 
     | 
    
         
            +
            	return text;
         
     | 
| 
      
 369 
     | 
    
         
            +
            }
         
     | 
| 
      
 370 
     | 
    
         
            +
             
     | 
| 
      
 371 
     | 
    
         
            +
             
     | 
| 
      
 372 
     | 
    
         
            +
            var _RunSpanGamut = function(text) {
         
     | 
| 
      
 373 
     | 
    
         
            +
            //
         
     | 
| 
      
 374 
     | 
    
         
            +
            // These are all the transformations that occur *within* block-level
         
     | 
| 
      
 375 
     | 
    
         
            +
            // tags like paragraphs, headers, and list items.
         
     | 
| 
      
 376 
     | 
    
         
            +
            //
         
     | 
| 
      
 377 
     | 
    
         
            +
             
     | 
| 
      
 378 
     | 
    
         
            +
            	text = _DoCodeSpans(text);
         
     | 
| 
      
 379 
     | 
    
         
            +
            	text = _EscapeSpecialCharsWithinTagAttributes(text);
         
     | 
| 
      
 380 
     | 
    
         
            +
            	text = _EncodeBackslashEscapes(text);
         
     | 
| 
      
 381 
     | 
    
         
            +
             
     | 
| 
      
 382 
     | 
    
         
            +
            	// Process anchor and image tags. Images must come first,
         
     | 
| 
      
 383 
     | 
    
         
            +
            	// because ![foo][f] looks like an anchor.
         
     | 
| 
      
 384 
     | 
    
         
            +
            	text = _DoImages(text);
         
     | 
| 
      
 385 
     | 
    
         
            +
            	text = _DoAnchors(text);
         
     | 
| 
      
 386 
     | 
    
         
            +
             
     | 
| 
      
 387 
     | 
    
         
            +
            	// Make links out of things like `<http://example.com/>`
         
     | 
| 
      
 388 
     | 
    
         
            +
            	// Must come after _DoAnchors(), because you can use < and >
         
     | 
| 
      
 389 
     | 
    
         
            +
            	// delimiters in inline links like [this](<url>).
         
     | 
| 
      
 390 
     | 
    
         
            +
            	text = _DoAutoLinks(text);
         
     | 
| 
      
 391 
     | 
    
         
            +
            	text = _EncodeAmpsAndAngles(text);
         
     | 
| 
      
 392 
     | 
    
         
            +
            	text = _DoItalicsAndBold(text);
         
     | 
| 
      
 393 
     | 
    
         
            +
             
     | 
| 
      
 394 
     | 
    
         
            +
            	// Do hard breaks:
         
     | 
| 
      
 395 
     | 
    
         
            +
            	text = text.replace(/  +\n/g," <br />\n");
         
     | 
| 
      
 396 
     | 
    
         
            +
             
     | 
| 
      
 397 
     | 
    
         
            +
            	return text;
         
     | 
| 
      
 398 
     | 
    
         
            +
            }
         
     | 
| 
      
 399 
     | 
    
         
            +
             
     | 
| 
      
 400 
     | 
    
         
            +
            var _EscapeSpecialCharsWithinTagAttributes = function(text) {
         
     | 
| 
      
 401 
     | 
    
         
            +
            //
         
     | 
| 
      
 402 
     | 
    
         
            +
            // Within tags -- meaning between < and > -- encode [\ ` * _] so they
         
     | 
| 
      
 403 
     | 
    
         
            +
            // don't conflict with their use in Markdown for code, italics and strong.
         
     | 
| 
      
 404 
     | 
    
         
            +
            //
         
     | 
| 
      
 405 
     | 
    
         
            +
             
     | 
| 
      
 406 
     | 
    
         
            +
            	// Build a regex to find HTML tags and comments.  See Friedl's 
         
     | 
| 
      
 407 
     | 
    
         
            +
            	// "Mastering Regular Expressions", 2nd Ed., pp. 200-201.
         
     | 
| 
      
 408 
     | 
    
         
            +
            	var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi;
         
     | 
| 
      
 409 
     | 
    
         
            +
             
     | 
| 
      
 410 
     | 
    
         
            +
            	text = text.replace(regex, function(wholeMatch) {
         
     | 
| 
      
 411 
     | 
    
         
            +
            		var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g,"$1`");
         
     | 
| 
      
 412 
     | 
    
         
            +
            		tag = escapeCharacters(tag,"\\`*_");
         
     | 
| 
      
 413 
     | 
    
         
            +
            		return tag;
         
     | 
| 
      
 414 
     | 
    
         
            +
            	});
         
     | 
| 
      
 415 
     | 
    
         
            +
             
     | 
| 
      
 416 
     | 
    
         
            +
            	return text;
         
     | 
| 
      
 417 
     | 
    
         
            +
            }
         
     | 
| 
      
 418 
     | 
    
         
            +
             
     | 
| 
      
 419 
     | 
    
         
            +
            var _DoAnchors = function(text) {
         
     | 
| 
      
 420 
     | 
    
         
            +
            //
         
     | 
| 
      
 421 
     | 
    
         
            +
            // Turn Markdown link shortcuts into XHTML <a> tags.
         
     | 
| 
      
 422 
     | 
    
         
            +
            //
         
     | 
| 
      
 423 
     | 
    
         
            +
            	//
         
     | 
| 
      
 424 
     | 
    
         
            +
            	// First, handle reference-style links: [link text] [id]
         
     | 
| 
      
 425 
     | 
    
         
            +
            	//
         
     | 
| 
      
 426 
     | 
    
         
            +
             
     | 
| 
      
 427 
     | 
    
         
            +
            	/*
         
     | 
| 
      
 428 
     | 
    
         
            +
            		text = text.replace(/
         
     | 
| 
      
 429 
     | 
    
         
            +
            		(							// wrap whole match in $1
         
     | 
| 
      
 430 
     | 
    
         
            +
            			\[
         
     | 
| 
      
 431 
     | 
    
         
            +
            			(
         
     | 
| 
      
 432 
     | 
    
         
            +
            				(?:
         
     | 
| 
      
 433 
     | 
    
         
            +
            					\[[^\]]*\]		// allow brackets nested one level
         
     | 
| 
      
 434 
     | 
    
         
            +
            					|
         
     | 
| 
      
 435 
     | 
    
         
            +
            					[^\[]			// or anything else
         
     | 
| 
      
 436 
     | 
    
         
            +
            				)*
         
     | 
| 
      
 437 
     | 
    
         
            +
            			)
         
     | 
| 
      
 438 
     | 
    
         
            +
            			\]
         
     | 
| 
      
 439 
     | 
    
         
            +
             
     | 
| 
      
 440 
     | 
    
         
            +
            			[ ]?					// one optional space
         
     | 
| 
      
 441 
     | 
    
         
            +
            			(?:\n[ ]*)?				// one optional newline followed by spaces
         
     | 
| 
      
 442 
     | 
    
         
            +
             
     | 
| 
      
 443 
     | 
    
         
            +
            			\[
         
     | 
| 
      
 444 
     | 
    
         
            +
            			(.*?)					// id = $3
         
     | 
| 
      
 445 
     | 
    
         
            +
            			\]
         
     | 
| 
      
 446 
     | 
    
         
            +
            		)()()()()					// pad remaining backreferences
         
     | 
| 
      
 447 
     | 
    
         
            +
            		/g,_DoAnchors_callback);
         
     | 
| 
      
 448 
     | 
    
         
            +
            	*/
         
     | 
| 
      
 449 
     | 
    
         
            +
            	text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,writeAnchorTag);
         
     | 
| 
      
 450 
     | 
    
         
            +
             
     | 
| 
      
 451 
     | 
    
         
            +
            	//
         
     | 
| 
      
 452 
     | 
    
         
            +
            	// Next, inline-style links: [link text](url "optional title")
         
     | 
| 
      
 453 
     | 
    
         
            +
            	//
         
     | 
| 
      
 454 
     | 
    
         
            +
             
     | 
| 
      
 455 
     | 
    
         
            +
            	/*
         
     | 
| 
      
 456 
     | 
    
         
            +
            		text = text.replace(/
         
     | 
| 
      
 457 
     | 
    
         
            +
            			(						// wrap whole match in $1
         
     | 
| 
      
 458 
     | 
    
         
            +
            				\[
         
     | 
| 
      
 459 
     | 
    
         
            +
            				(
         
     | 
| 
      
 460 
     | 
    
         
            +
            					(?:
         
     | 
| 
      
 461 
     | 
    
         
            +
            						\[[^\]]*\]	// allow brackets nested one level
         
     | 
| 
      
 462 
     | 
    
         
            +
            					|
         
     | 
| 
      
 463 
     | 
    
         
            +
            					[^\[\]]			// or anything else
         
     | 
| 
      
 464 
     | 
    
         
            +
            				)
         
     | 
| 
      
 465 
     | 
    
         
            +
            			)
         
     | 
| 
      
 466 
     | 
    
         
            +
            			\]
         
     | 
| 
      
 467 
     | 
    
         
            +
            			\(						// literal paren
         
     | 
| 
      
 468 
     | 
    
         
            +
            			[ \t]*
         
     | 
| 
      
 469 
     | 
    
         
            +
            			()						// no id, so leave $3 empty
         
     | 
| 
      
 470 
     | 
    
         
            +
            			<?(.*?)>?				// href = $4
         
     | 
| 
      
 471 
     | 
    
         
            +
            			[ \t]*
         
     | 
| 
      
 472 
     | 
    
         
            +
            			(						// $5
         
     | 
| 
      
 473 
     | 
    
         
            +
            				(['"])				// quote char = $6
         
     | 
| 
      
 474 
     | 
    
         
            +
            				(.*?)				// Title = $7
         
     | 
| 
      
 475 
     | 
    
         
            +
            				\6					// matching quote
         
     | 
| 
      
 476 
     | 
    
         
            +
            				[ \t]*				// ignore any spaces/tabs between closing quote and )
         
     | 
| 
      
 477 
     | 
    
         
            +
            			)?						// title is optional
         
     | 
| 
      
 478 
     | 
    
         
            +
            			\)
         
     | 
| 
      
 479 
     | 
    
         
            +
            		)
         
     | 
| 
      
 480 
     | 
    
         
            +
            		/g,writeAnchorTag);
         
     | 
| 
      
 481 
     | 
    
         
            +
            	*/
         
     | 
| 
      
 482 
     | 
    
         
            +
            	text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?(.*?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,writeAnchorTag);
         
     | 
| 
      
 483 
     | 
    
         
            +
             
     | 
| 
      
 484 
     | 
    
         
            +
            	//
         
     | 
| 
      
 485 
     | 
    
         
            +
            	// Last, handle reference-style shortcuts: [link text]
         
     | 
| 
      
 486 
     | 
    
         
            +
            	// These must come last in case you've also got [link test][1]
         
     | 
| 
      
 487 
     | 
    
         
            +
            	// or [link test](/foo)
         
     | 
| 
      
 488 
     | 
    
         
            +
            	//
         
     | 
| 
      
 489 
     | 
    
         
            +
             
     | 
| 
      
 490 
     | 
    
         
            +
            	/*
         
     | 
| 
      
 491 
     | 
    
         
            +
            		text = text.replace(/
         
     | 
| 
      
 492 
     | 
    
         
            +
            		(		 					// wrap whole match in $1
         
     | 
| 
      
 493 
     | 
    
         
            +
            			\[
         
     | 
| 
      
 494 
     | 
    
         
            +
            			([^\[\]]+)				// link text = $2; can't contain '[' or ']'
         
     | 
| 
      
 495 
     | 
    
         
            +
            			\]
         
     | 
| 
      
 496 
     | 
    
         
            +
            		)()()()()()					// pad rest of backreferences
         
     | 
| 
      
 497 
     | 
    
         
            +
            		/g, writeAnchorTag);
         
     | 
| 
      
 498 
     | 
    
         
            +
            	*/
         
     | 
| 
      
 499 
     | 
    
         
            +
            	text = text.replace(/(\[([^\[\]]+)\])()()()()()/g, writeAnchorTag);
         
     | 
| 
      
 500 
     | 
    
         
            +
             
     | 
| 
      
 501 
     | 
    
         
            +
            	return text;
         
     | 
| 
      
 502 
     | 
    
         
            +
            }
         
     | 
| 
      
 503 
     | 
    
         
            +
             
     | 
| 
      
 504 
     | 
    
         
            +
            var writeAnchorTag = function(wholeMatch,m1,m2,m3,m4,m5,m6,m7) {
         
     | 
| 
      
 505 
     | 
    
         
            +
            	if (m7 == undefined) m7 = "";
         
     | 
| 
      
 506 
     | 
    
         
            +
            	var whole_match = m1;
         
     | 
| 
      
 507 
     | 
    
         
            +
            	var link_text   = m2;
         
     | 
| 
      
 508 
     | 
    
         
            +
            	var link_id	 = m3.toLowerCase();
         
     | 
| 
      
 509 
     | 
    
         
            +
            	var url		= m4;
         
     | 
| 
      
 510 
     | 
    
         
            +
            	var title	= m7;
         
     | 
| 
      
 511 
     | 
    
         
            +
            	
         
     | 
| 
      
 512 
     | 
    
         
            +
            	if (url == "") {
         
     | 
| 
      
 513 
     | 
    
         
            +
            		if (link_id == "") {
         
     | 
| 
      
 514 
     | 
    
         
            +
            			// lower-case and turn embedded newlines into spaces
         
     | 
| 
      
 515 
     | 
    
         
            +
            			link_id = link_text.toLowerCase().replace(/ ?\n/g," ");
         
     | 
| 
      
 516 
     | 
    
         
            +
            		}
         
     | 
| 
      
 517 
     | 
    
         
            +
            		url = "#"+link_id;
         
     | 
| 
      
 518 
     | 
    
         
            +
            		
         
     | 
| 
      
 519 
     | 
    
         
            +
            		if (g_urls[link_id] != undefined) {
         
     | 
| 
      
 520 
     | 
    
         
            +
            			url = g_urls[link_id];
         
     | 
| 
      
 521 
     | 
    
         
            +
            			if (g_titles[link_id] != undefined) {
         
     | 
| 
      
 522 
     | 
    
         
            +
            				title = g_titles[link_id];
         
     | 
| 
      
 523 
     | 
    
         
            +
            			}
         
     | 
| 
      
 524 
     | 
    
         
            +
            		}
         
     | 
| 
      
 525 
     | 
    
         
            +
            		else {
         
     | 
| 
      
 526 
     | 
    
         
            +
            			if (whole_match.search(/\(\s*\)$/m)>-1) {
         
     | 
| 
      
 527 
     | 
    
         
            +
            				// Special case for explicit empty url
         
     | 
| 
      
 528 
     | 
    
         
            +
            				url = "";
         
     | 
| 
      
 529 
     | 
    
         
            +
            			} else {
         
     | 
| 
      
 530 
     | 
    
         
            +
            				return whole_match;
         
     | 
| 
      
 531 
     | 
    
         
            +
            			}
         
     | 
| 
      
 532 
     | 
    
         
            +
            		}
         
     | 
| 
      
 533 
     | 
    
         
            +
            	}	
         
     | 
| 
      
 534 
     | 
    
         
            +
            	
         
     | 
| 
      
 535 
     | 
    
         
            +
            	url = escapeCharacters(url,"*_");
         
     | 
| 
      
 536 
     | 
    
         
            +
            	var result = "<a href=\"" + url + "\"";
         
     | 
| 
      
 537 
     | 
    
         
            +
            	
         
     | 
| 
      
 538 
     | 
    
         
            +
            	if (title != "") {
         
     | 
| 
      
 539 
     | 
    
         
            +
            		title = title.replace(/"/g,""");
         
     | 
| 
      
 540 
     | 
    
         
            +
            		title = escapeCharacters(title,"*_");
         
     | 
| 
      
 541 
     | 
    
         
            +
            		result +=  " title=\"" + title + "\"";
         
     | 
| 
      
 542 
     | 
    
         
            +
            	}
         
     | 
| 
      
 543 
     | 
    
         
            +
            	
         
     | 
| 
      
 544 
     | 
    
         
            +
            	result += ">" + link_text + "</a>";
         
     | 
| 
      
 545 
     | 
    
         
            +
            	
         
     | 
| 
      
 546 
     | 
    
         
            +
            	return result;
         
     | 
| 
      
 547 
     | 
    
         
            +
            }
         
     | 
| 
      
 548 
     | 
    
         
            +
             
     | 
| 
      
 549 
     | 
    
         
            +
             
     | 
| 
      
 550 
     | 
    
         
            +
            var _DoImages = function(text) {
         
     | 
| 
      
 551 
     | 
    
         
            +
            //
         
     | 
| 
      
 552 
     | 
    
         
            +
            // Turn Markdown image shortcuts into <img> tags.
         
     | 
| 
      
 553 
     | 
    
         
            +
            //
         
     | 
| 
      
 554 
     | 
    
         
            +
             
     | 
| 
      
 555 
     | 
    
         
            +
            	//
         
     | 
| 
      
 556 
     | 
    
         
            +
            	// First, handle reference-style labeled images: ![alt text][id]
         
     | 
| 
      
 557 
     | 
    
         
            +
            	//
         
     | 
| 
      
 558 
     | 
    
         
            +
             
     | 
| 
      
 559 
     | 
    
         
            +
            	/*
         
     | 
| 
      
 560 
     | 
    
         
            +
            		text = text.replace(/
         
     | 
| 
      
 561 
     | 
    
         
            +
            		(						// wrap whole match in $1
         
     | 
| 
      
 562 
     | 
    
         
            +
            			!\[
         
     | 
| 
      
 563 
     | 
    
         
            +
            			(.*?)				// alt text = $2
         
     | 
| 
      
 564 
     | 
    
         
            +
            			\]
         
     | 
| 
      
 565 
     | 
    
         
            +
             
     | 
| 
      
 566 
     | 
    
         
            +
            			[ ]?				// one optional space
         
     | 
| 
      
 567 
     | 
    
         
            +
            			(?:\n[ ]*)?			// one optional newline followed by spaces
         
     | 
| 
      
 568 
     | 
    
         
            +
             
     | 
| 
      
 569 
     | 
    
         
            +
            			\[
         
     | 
| 
      
 570 
     | 
    
         
            +
            			(.*?)				// id = $3
         
     | 
| 
      
 571 
     | 
    
         
            +
            			\]
         
     | 
| 
      
 572 
     | 
    
         
            +
            		)()()()()				// pad rest of backreferences
         
     | 
| 
      
 573 
     | 
    
         
            +
            		/g,writeImageTag);
         
     | 
| 
      
 574 
     | 
    
         
            +
            	*/
         
     | 
| 
      
 575 
     | 
    
         
            +
            	text = text.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,writeImageTag);
         
     | 
| 
      
 576 
     | 
    
         
            +
             
     | 
| 
      
 577 
     | 
    
         
            +
            	//
         
     | 
| 
      
 578 
     | 
    
         
            +
            	// Next, handle inline images:  
         
     | 
| 
      
 579 
     | 
    
         
            +
            	// Don't forget: encode * and _
         
     | 
| 
      
 580 
     | 
    
         
            +
             
     | 
| 
      
 581 
     | 
    
         
            +
            	/*
         
     | 
| 
      
 582 
     | 
    
         
            +
            		text = text.replace(/
         
     | 
| 
      
 583 
     | 
    
         
            +
            		(						// wrap whole match in $1
         
     | 
| 
      
 584 
     | 
    
         
            +
            			!\[
         
     | 
| 
      
 585 
     | 
    
         
            +
            			(.*?)				// alt text = $2
         
     | 
| 
      
 586 
     | 
    
         
            +
            			\]
         
     | 
| 
      
 587 
     | 
    
         
            +
            			\s?					// One optional whitespace character
         
     | 
| 
      
 588 
     | 
    
         
            +
            			\(					// literal paren
         
     | 
| 
      
 589 
     | 
    
         
            +
            			[ \t]*
         
     | 
| 
      
 590 
     | 
    
         
            +
            			()					// no id, so leave $3 empty
         
     | 
| 
      
 591 
     | 
    
         
            +
            			<?(\S+?)>?			// src url = $4
         
     | 
| 
      
 592 
     | 
    
         
            +
            			[ \t]*
         
     | 
| 
      
 593 
     | 
    
         
            +
            			(					// $5
         
     | 
| 
      
 594 
     | 
    
         
            +
            				(['"])			// quote char = $6
         
     | 
| 
      
 595 
     | 
    
         
            +
            				(.*?)			// title = $7
         
     | 
| 
      
 596 
     | 
    
         
            +
            				\6				// matching quote
         
     | 
| 
      
 597 
     | 
    
         
            +
            				[ \t]*
         
     | 
| 
      
 598 
     | 
    
         
            +
            			)?					// title is optional
         
     | 
| 
      
 599 
     | 
    
         
            +
            		\)
         
     | 
| 
      
 600 
     | 
    
         
            +
            		)
         
     | 
| 
      
 601 
     | 
    
         
            +
            		/g,writeImageTag);
         
     | 
| 
      
 602 
     | 
    
         
            +
            	*/
         
     | 
| 
      
 603 
     | 
    
         
            +
            	text = text.replace(/(!\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,writeImageTag);
         
     | 
| 
      
 604 
     | 
    
         
            +
             
     | 
| 
      
 605 
     | 
    
         
            +
            	return text;
         
     | 
| 
      
 606 
     | 
    
         
            +
            }
         
     | 
| 
      
 607 
     | 
    
         
            +
             
     | 
| 
      
 608 
     | 
    
         
            +
            var writeImageTag = function(wholeMatch,m1,m2,m3,m4,m5,m6,m7) {
         
     | 
| 
      
 609 
     | 
    
         
            +
            	var whole_match = m1;
         
     | 
| 
      
 610 
     | 
    
         
            +
            	var alt_text   = m2;
         
     | 
| 
      
 611 
     | 
    
         
            +
            	var link_id	 = m3.toLowerCase();
         
     | 
| 
      
 612 
     | 
    
         
            +
            	var url		= m4;
         
     | 
| 
      
 613 
     | 
    
         
            +
            	var title	= m7;
         
     | 
| 
      
 614 
     | 
    
         
            +
             
     | 
| 
      
 615 
     | 
    
         
            +
            	if (!title) title = "";
         
     | 
| 
      
 616 
     | 
    
         
            +
            	
         
     | 
| 
      
 617 
     | 
    
         
            +
            	if (url == "") {
         
     | 
| 
      
 618 
     | 
    
         
            +
            		if (link_id == "") {
         
     | 
| 
      
 619 
     | 
    
         
            +
            			// lower-case and turn embedded newlines into spaces
         
     | 
| 
      
 620 
     | 
    
         
            +
            			link_id = alt_text.toLowerCase().replace(/ ?\n/g," ");
         
     | 
| 
      
 621 
     | 
    
         
            +
            		}
         
     | 
| 
      
 622 
     | 
    
         
            +
            		url = "#"+link_id;
         
     | 
| 
      
 623 
     | 
    
         
            +
            		
         
     | 
| 
      
 624 
     | 
    
         
            +
            		if (g_urls[link_id] != undefined) {
         
     | 
| 
      
 625 
     | 
    
         
            +
            			url = g_urls[link_id];
         
     | 
| 
      
 626 
     | 
    
         
            +
            			if (g_titles[link_id] != undefined) {
         
     | 
| 
      
 627 
     | 
    
         
            +
            				title = g_titles[link_id];
         
     | 
| 
      
 628 
     | 
    
         
            +
            			}
         
     | 
| 
      
 629 
     | 
    
         
            +
            		}
         
     | 
| 
      
 630 
     | 
    
         
            +
            		else {
         
     | 
| 
      
 631 
     | 
    
         
            +
            			return whole_match;
         
     | 
| 
      
 632 
     | 
    
         
            +
            		}
         
     | 
| 
      
 633 
     | 
    
         
            +
            	}	
         
     | 
| 
      
 634 
     | 
    
         
            +
            	
         
     | 
| 
      
 635 
     | 
    
         
            +
            	alt_text = alt_text.replace(/"/g,""");
         
     | 
| 
      
 636 
     | 
    
         
            +
            	url = escapeCharacters(url,"*_");
         
     | 
| 
      
 637 
     | 
    
         
            +
            	var result = "<img src=\"" + url + "\" alt=\"" + alt_text + "\"";
         
     | 
| 
      
 638 
     | 
    
         
            +
             
     | 
| 
      
 639 
     | 
    
         
            +
            	// attacklab: Markdown.pl adds empty title attributes to images.
         
     | 
| 
      
 640 
     | 
    
         
            +
            	// Replicate this bug.
         
     | 
| 
      
 641 
     | 
    
         
            +
             
     | 
| 
      
 642 
     | 
    
         
            +
            	//if (title != "") {
         
     | 
| 
      
 643 
     | 
    
         
            +
            		title = title.replace(/"/g,""");
         
     | 
| 
      
 644 
     | 
    
         
            +
            		title = escapeCharacters(title,"*_");
         
     | 
| 
      
 645 
     | 
    
         
            +
            		result +=  " title=\"" + title + "\"";
         
     | 
| 
      
 646 
     | 
    
         
            +
            	//}
         
     | 
| 
      
 647 
     | 
    
         
            +
            	
         
     | 
| 
      
 648 
     | 
    
         
            +
            	result += " />";
         
     | 
| 
      
 649 
     | 
    
         
            +
            	
         
     | 
| 
      
 650 
     | 
    
         
            +
            	return result;
         
     | 
| 
      
 651 
     | 
    
         
            +
            }
         
     | 
| 
      
 652 
     | 
    
         
            +
             
     | 
| 
      
 653 
     | 
    
         
            +
             
     | 
| 
      
 654 
     | 
    
         
            +
            var _DoHeaders = function(text) {
         
     | 
| 
      
 655 
     | 
    
         
            +
             
     | 
| 
      
 656 
     | 
    
         
            +
            	// Setext-style headers:
         
     | 
| 
      
 657 
     | 
    
         
            +
            	//	Header 1
         
     | 
| 
      
 658 
     | 
    
         
            +
            	//	========
         
     | 
| 
      
 659 
     | 
    
         
            +
            	//  
         
     | 
| 
      
 660 
     | 
    
         
            +
            	//	Header 2
         
     | 
| 
      
 661 
     | 
    
         
            +
            	//	--------
         
     | 
| 
      
 662 
     | 
    
         
            +
            	//
         
     | 
| 
      
 663 
     | 
    
         
            +
            	text = text.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,
         
     | 
| 
      
 664 
     | 
    
         
            +
            		function(wholeMatch,m1){return hashBlock("<h1>" + _RunSpanGamut(m1) + "</h1>");});
         
     | 
| 
      
 665 
     | 
    
         
            +
             
     | 
| 
      
 666 
     | 
    
         
            +
            	text = text.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,
         
     | 
| 
      
 667 
     | 
    
         
            +
            		function(matchFound,m1){return hashBlock("<h2>" + _RunSpanGamut(m1) + "</h2>");});
         
     | 
| 
      
 668 
     | 
    
         
            +
             
     | 
| 
      
 669 
     | 
    
         
            +
            	// atx-style headers:
         
     | 
| 
      
 670 
     | 
    
         
            +
            	//  # Header 1
         
     | 
| 
      
 671 
     | 
    
         
            +
            	//  ## Header 2
         
     | 
| 
      
 672 
     | 
    
         
            +
            	//  ## Header 2 with closing hashes ##
         
     | 
| 
      
 673 
     | 
    
         
            +
            	//  ...
         
     | 
| 
      
 674 
     | 
    
         
            +
            	//  ###### Header 6
         
     | 
| 
      
 675 
     | 
    
         
            +
            	//
         
     | 
| 
      
 676 
     | 
    
         
            +
             
     | 
| 
      
 677 
     | 
    
         
            +
            	/*
         
     | 
| 
      
 678 
     | 
    
         
            +
            		text = text.replace(/
         
     | 
| 
      
 679 
     | 
    
         
            +
            			^(\#{1,6})				// $1 = string of #'s
         
     | 
| 
      
 680 
     | 
    
         
            +
            			[ \t]*
         
     | 
| 
      
 681 
     | 
    
         
            +
            			(.+?)					// $2 = Header text
         
     | 
| 
      
 682 
     | 
    
         
            +
            			[ \t]*
         
     | 
| 
      
 683 
     | 
    
         
            +
            			\#*						// optional closing #'s (not counted)
         
     | 
| 
      
 684 
     | 
    
         
            +
            			\n+
         
     | 
| 
      
 685 
     | 
    
         
            +
            		/gm, function() {...});
         
     | 
| 
      
 686 
     | 
    
         
            +
            	*/
         
     | 
| 
      
 687 
     | 
    
         
            +
             
     | 
| 
      
 688 
     | 
    
         
            +
            	text = text.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,
         
     | 
| 
      
 689 
     | 
    
         
            +
            		function(wholeMatch,m1,m2) {
         
     | 
| 
      
 690 
     | 
    
         
            +
            			var h_level = m1.length;
         
     | 
| 
      
 691 
     | 
    
         
            +
            			return hashBlock("<h" + h_level + ">" + _RunSpanGamut(m2) + "</h" + h_level + ">");
         
     | 
| 
      
 692 
     | 
    
         
            +
            		});
         
     | 
| 
      
 693 
     | 
    
         
            +
             
     | 
| 
      
 694 
     | 
    
         
            +
            	return text;
         
     | 
| 
      
 695 
     | 
    
         
            +
            }
         
     | 
| 
      
 696 
     | 
    
         
            +
             
     | 
| 
      
 697 
     | 
    
         
            +
            // This declaration keeps Dojo compressor from outputting garbage:
         
     | 
| 
      
 698 
     | 
    
         
            +
            var _ProcessListItems;
         
     | 
| 
      
 699 
     | 
    
         
            +
             
     | 
| 
      
 700 
     | 
    
         
            +
            var _DoLists = function(text) {
         
     | 
| 
      
 701 
     | 
    
         
            +
            //
         
     | 
| 
      
 702 
     | 
    
         
            +
            // Form HTML ordered (numbered) and unordered (bulleted) lists.
         
     | 
| 
      
 703 
     | 
    
         
            +
            //
         
     | 
| 
      
 704 
     | 
    
         
            +
             
     | 
| 
      
 705 
     | 
    
         
            +
            	// attacklab: add sentinel to hack around khtml/safari bug:
         
     | 
| 
      
 706 
     | 
    
         
            +
            	// http://bugs.webkit.org/show_bug.cgi?id=11231
         
     | 
| 
      
 707 
     | 
    
         
            +
            	text += "~0";
         
     | 
| 
      
 708 
     | 
    
         
            +
             
     | 
| 
      
 709 
     | 
    
         
            +
            	// Re-usable pattern to match any entirel ul or ol list:
         
     | 
| 
      
 710 
     | 
    
         
            +
             
     | 
| 
      
 711 
     | 
    
         
            +
            	/*
         
     | 
| 
      
 712 
     | 
    
         
            +
            		var whole_list = /
         
     | 
| 
      
 713 
     | 
    
         
            +
            		(									// $1 = whole list
         
     | 
| 
      
 714 
     | 
    
         
            +
            			(								// $2
         
     | 
| 
      
 715 
     | 
    
         
            +
            				[ ]{0,3}					// attacklab: g_tab_width - 1
         
     | 
| 
      
 716 
     | 
    
         
            +
            				([*+-]|\d+[.])				// $3 = first list item marker
         
     | 
| 
      
 717 
     | 
    
         
            +
            				[ \t]+
         
     | 
| 
      
 718 
     | 
    
         
            +
            			)
         
     | 
| 
      
 719 
     | 
    
         
            +
            			[^\r]+?
         
     | 
| 
      
 720 
     | 
    
         
            +
            			(								// $4
         
     | 
| 
      
 721 
     | 
    
         
            +
            				~0							// sentinel for workaround; should be $
         
     | 
| 
      
 722 
     | 
    
         
            +
            			|
         
     | 
| 
      
 723 
     | 
    
         
            +
            				\n{2,}
         
     | 
| 
      
 724 
     | 
    
         
            +
            				(?=\S)
         
     | 
| 
      
 725 
     | 
    
         
            +
            				(?!							// Negative lookahead for another list item marker
         
     | 
| 
      
 726 
     | 
    
         
            +
            					[ \t]*
         
     | 
| 
      
 727 
     | 
    
         
            +
            					(?:[*+-]|\d+[.])[ \t]+
         
     | 
| 
      
 728 
     | 
    
         
            +
            				)
         
     | 
| 
      
 729 
     | 
    
         
            +
            			)
         
     | 
| 
      
 730 
     | 
    
         
            +
            		)/g
         
     | 
| 
      
 731 
     | 
    
         
            +
            	*/
         
     | 
| 
      
 732 
     | 
    
         
            +
            	var whole_list = /^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;
         
     | 
| 
      
 733 
     | 
    
         
            +
             
     | 
| 
      
 734 
     | 
    
         
            +
            	if (g_list_level) {
         
     | 
| 
      
 735 
     | 
    
         
            +
            		text = text.replace(whole_list,function(wholeMatch,m1,m2) {
         
     | 
| 
      
 736 
     | 
    
         
            +
            			var list = m1;
         
     | 
| 
      
 737 
     | 
    
         
            +
            			var list_type = (m2.search(/[*+-]/g)>-1) ? "ul" : "ol";
         
     | 
| 
      
 738 
     | 
    
         
            +
             
     | 
| 
      
 739 
     | 
    
         
            +
            			// Turn double returns into triple returns, so that we can make a
         
     | 
| 
      
 740 
     | 
    
         
            +
            			// paragraph for the last item in a list, if necessary:
         
     | 
| 
      
 741 
     | 
    
         
            +
            			list = list.replace(/\n{2,}/g,"\n\n\n");;
         
     | 
| 
      
 742 
     | 
    
         
            +
            			var result = _ProcessListItems(list);
         
     | 
| 
      
 743 
     | 
    
         
            +
            	
         
     | 
| 
      
 744 
     | 
    
         
            +
            			// Trim any trailing whitespace, to put the closing `</$list_type>`
         
     | 
| 
      
 745 
     | 
    
         
            +
            			// up on the preceding line, to get it past the current stupid
         
     | 
| 
      
 746 
     | 
    
         
            +
            			// HTML block parser. This is a hack to work around the terrible
         
     | 
| 
      
 747 
     | 
    
         
            +
            			// hack that is the HTML block parser.
         
     | 
| 
      
 748 
     | 
    
         
            +
            			result = result.replace(/\s+$/,"");
         
     | 
| 
      
 749 
     | 
    
         
            +
            			result = "<"+list_type+">" + result + "</"+list_type+">\n";
         
     | 
| 
      
 750 
     | 
    
         
            +
            			return result;
         
     | 
| 
      
 751 
     | 
    
         
            +
            		});
         
     | 
| 
      
 752 
     | 
    
         
            +
            	} else {
         
     | 
| 
      
 753 
     | 
    
         
            +
            		whole_list = /(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g;
         
     | 
| 
      
 754 
     | 
    
         
            +
            		text = text.replace(whole_list,function(wholeMatch,m1,m2,m3) {
         
     | 
| 
      
 755 
     | 
    
         
            +
            			var runup = m1;
         
     | 
| 
      
 756 
     | 
    
         
            +
            			var list = m2;
         
     | 
| 
      
 757 
     | 
    
         
            +
             
     | 
| 
      
 758 
     | 
    
         
            +
            			var list_type = (m3.search(/[*+-]/g)>-1) ? "ul" : "ol";
         
     | 
| 
      
 759 
     | 
    
         
            +
            			// Turn double returns into triple returns, so that we can make a
         
     | 
| 
      
 760 
     | 
    
         
            +
            			// paragraph for the last item in a list, if necessary:
         
     | 
| 
      
 761 
     | 
    
         
            +
            			var list = list.replace(/\n{2,}/g,"\n\n\n");;
         
     | 
| 
      
 762 
     | 
    
         
            +
            			var result = _ProcessListItems(list);
         
     | 
| 
      
 763 
     | 
    
         
            +
            			result = runup + "<"+list_type+">\n" + result + "</"+list_type+">\n";	
         
     | 
| 
      
 764 
     | 
    
         
            +
            			return result;
         
     | 
| 
      
 765 
     | 
    
         
            +
            		});
         
     | 
| 
      
 766 
     | 
    
         
            +
            	}
         
     | 
| 
      
 767 
     | 
    
         
            +
             
     | 
| 
      
 768 
     | 
    
         
            +
            	// attacklab: strip sentinel
         
     | 
| 
      
 769 
     | 
    
         
            +
            	text = text.replace(/~0/,"");
         
     | 
| 
      
 770 
     | 
    
         
            +
             
     | 
| 
      
 771 
     | 
    
         
            +
            	return text;
         
     | 
| 
      
 772 
     | 
    
         
            +
            }
         
     | 
| 
      
 773 
     | 
    
         
            +
             
     | 
| 
      
 774 
     | 
    
         
            +
            _ProcessListItems = function(list_str) {
         
     | 
| 
      
 775 
     | 
    
         
            +
            //
         
     | 
| 
      
 776 
     | 
    
         
            +
            //  Process the contents of a single ordered or unordered list, splitting it
         
     | 
| 
      
 777 
     | 
    
         
            +
            //  into individual list items.
         
     | 
| 
      
 778 
     | 
    
         
            +
            //
         
     | 
| 
      
 779 
     | 
    
         
            +
            	// The $g_list_level global keeps track of when we're inside a list.
         
     | 
| 
      
 780 
     | 
    
         
            +
            	// Each time we enter a list, we increment it; when we leave a list,
         
     | 
| 
      
 781 
     | 
    
         
            +
            	// we decrement. If it's zero, we're not in a list anymore.
         
     | 
| 
      
 782 
     | 
    
         
            +
            	//
         
     | 
| 
      
 783 
     | 
    
         
            +
            	// We do this because when we're not inside a list, we want to treat
         
     | 
| 
      
 784 
     | 
    
         
            +
            	// something like this:
         
     | 
| 
      
 785 
     | 
    
         
            +
            	//
         
     | 
| 
      
 786 
     | 
    
         
            +
            	//    I recommend upgrading to version
         
     | 
| 
      
 787 
     | 
    
         
            +
            	//    8. Oops, now this line is treated
         
     | 
| 
      
 788 
     | 
    
         
            +
            	//    as a sub-list.
         
     | 
| 
      
 789 
     | 
    
         
            +
            	//
         
     | 
| 
      
 790 
     | 
    
         
            +
            	// As a single paragraph, despite the fact that the second line starts
         
     | 
| 
      
 791 
     | 
    
         
            +
            	// with a digit-period-space sequence.
         
     | 
| 
      
 792 
     | 
    
         
            +
            	//
         
     | 
| 
      
 793 
     | 
    
         
            +
            	// Whereas when we're inside a list (or sub-list), that line will be
         
     | 
| 
      
 794 
     | 
    
         
            +
            	// treated as the start of a sub-list. What a kludge, huh? This is
         
     | 
| 
      
 795 
     | 
    
         
            +
            	// an aspect of Markdown's syntax that's hard to parse perfectly
         
     | 
| 
      
 796 
     | 
    
         
            +
            	// without resorting to mind-reading. Perhaps the solution is to
         
     | 
| 
      
 797 
     | 
    
         
            +
            	// change the syntax rules such that sub-lists must start with a
         
     | 
| 
      
 798 
     | 
    
         
            +
            	// starting cardinal number; e.g. "1." or "a.".
         
     | 
| 
      
 799 
     | 
    
         
            +
             
     | 
| 
      
 800 
     | 
    
         
            +
            	g_list_level++;
         
     | 
| 
      
 801 
     | 
    
         
            +
             
     | 
| 
      
 802 
     | 
    
         
            +
            	// trim trailing blank lines:
         
     | 
| 
      
 803 
     | 
    
         
            +
            	list_str = list_str.replace(/\n{2,}$/,"\n");
         
     | 
| 
      
 804 
     | 
    
         
            +
             
     | 
| 
      
 805 
     | 
    
         
            +
            	// attacklab: add sentinel to emulate \z
         
     | 
| 
      
 806 
     | 
    
         
            +
            	list_str += "~0";
         
     | 
| 
      
 807 
     | 
    
         
            +
             
     | 
| 
      
 808 
     | 
    
         
            +
            	/*
         
     | 
| 
      
 809 
     | 
    
         
            +
            		list_str = list_str.replace(/
         
     | 
| 
      
 810 
     | 
    
         
            +
            			(\n)?							// leading line = $1
         
     | 
| 
      
 811 
     | 
    
         
            +
            			(^[ \t]*)						// leading whitespace = $2
         
     | 
| 
      
 812 
     | 
    
         
            +
            			([*+-]|\d+[.]) [ \t]+			// list marker = $3
         
     | 
| 
      
 813 
     | 
    
         
            +
            			([^\r]+?						// list item text   = $4
         
     | 
| 
      
 814 
     | 
    
         
            +
            			(\n{1,2}))
         
     | 
| 
      
 815 
     | 
    
         
            +
            			(?= \n* (~0 | \2 ([*+-]|\d+[.]) [ \t]+))
         
     | 
| 
      
 816 
     | 
    
         
            +
            		/gm, function(){...});
         
     | 
| 
      
 817 
     | 
    
         
            +
            	*/
         
     | 
| 
      
 818 
     | 
    
         
            +
            	list_str = list_str.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,
         
     | 
| 
      
 819 
     | 
    
         
            +
            		function(wholeMatch,m1,m2,m3,m4){
         
     | 
| 
      
 820 
     | 
    
         
            +
            			var item = m4;
         
     | 
| 
      
 821 
     | 
    
         
            +
            			var leading_line = m1;
         
     | 
| 
      
 822 
     | 
    
         
            +
            			var leading_space = m2;
         
     | 
| 
      
 823 
     | 
    
         
            +
             
     | 
| 
      
 824 
     | 
    
         
            +
            			if (leading_line || (item.search(/\n{2,}/)>-1)) {
         
     | 
| 
      
 825 
     | 
    
         
            +
            				item = _RunBlockGamut(_Outdent(item));
         
     | 
| 
      
 826 
     | 
    
         
            +
            			}
         
     | 
| 
      
 827 
     | 
    
         
            +
            			else {
         
     | 
| 
      
 828 
     | 
    
         
            +
            				// Recursion for sub-lists:
         
     | 
| 
      
 829 
     | 
    
         
            +
            				item = _DoLists(_Outdent(item));
         
     | 
| 
      
 830 
     | 
    
         
            +
            				item = item.replace(/\n$/,""); // chomp(item)
         
     | 
| 
      
 831 
     | 
    
         
            +
            				item = _RunSpanGamut(item);
         
     | 
| 
      
 832 
     | 
    
         
            +
            			}
         
     | 
| 
      
 833 
     | 
    
         
            +
             
     | 
| 
      
 834 
     | 
    
         
            +
            			return  "<li>" + item + "</li>\n";
         
     | 
| 
      
 835 
     | 
    
         
            +
            		}
         
     | 
| 
      
 836 
     | 
    
         
            +
            	);
         
     | 
| 
      
 837 
     | 
    
         
            +
             
     | 
| 
      
 838 
     | 
    
         
            +
            	// attacklab: strip sentinel
         
     | 
| 
      
 839 
     | 
    
         
            +
            	list_str = list_str.replace(/~0/g,"");
         
     | 
| 
      
 840 
     | 
    
         
            +
             
     | 
| 
      
 841 
     | 
    
         
            +
            	g_list_level--;
         
     | 
| 
      
 842 
     | 
    
         
            +
            	return list_str;
         
     | 
| 
      
 843 
     | 
    
         
            +
            }
         
     | 
| 
      
 844 
     | 
    
         
            +
             
     | 
| 
      
 845 
     | 
    
         
            +
             
     | 
| 
      
 846 
     | 
    
         
            +
            var _DoCodeBlocks = function(text) {
         
     | 
| 
      
 847 
     | 
    
         
            +
            //
         
     | 
| 
      
 848 
     | 
    
         
            +
            //  Process Markdown `<pre><code>` blocks.
         
     | 
| 
      
 849 
     | 
    
         
            +
            //  
         
     | 
| 
      
 850 
     | 
    
         
            +
             
     | 
| 
      
 851 
     | 
    
         
            +
            	/*
         
     | 
| 
      
 852 
     | 
    
         
            +
            		text = text.replace(text,
         
     | 
| 
      
 853 
     | 
    
         
            +
            			/(?:\n\n|^)
         
     | 
| 
      
 854 
     | 
    
         
            +
            			(								// $1 = the code block -- one or more lines, starting with a space/tab
         
     | 
| 
      
 855 
     | 
    
         
            +
            				(?:
         
     | 
| 
      
 856 
     | 
    
         
            +
            					(?:[ ]{4}|\t)			// Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width
         
     | 
| 
      
 857 
     | 
    
         
            +
            					.*\n+
         
     | 
| 
      
 858 
     | 
    
         
            +
            				)+
         
     | 
| 
      
 859 
     | 
    
         
            +
            			)
         
     | 
| 
      
 860 
     | 
    
         
            +
            			(\n*[ ]{0,3}[^ \t\n]|(?=~0))	// attacklab: g_tab_width
         
     | 
| 
      
 861 
     | 
    
         
            +
            		/g,function(){...});
         
     | 
| 
      
 862 
     | 
    
         
            +
            	*/
         
     | 
| 
      
 863 
     | 
    
         
            +
             
     | 
| 
      
 864 
     | 
    
         
            +
            	// attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
         
     | 
| 
      
 865 
     | 
    
         
            +
            	text += "~0";
         
     | 
| 
      
 866 
     | 
    
         
            +
            	
         
     | 
| 
      
 867 
     | 
    
         
            +
            	text = text.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,
         
     | 
| 
      
 868 
     | 
    
         
            +
            		function(wholeMatch,m1,m2) {
         
     | 
| 
      
 869 
     | 
    
         
            +
            			var codeblock = m1;
         
     | 
| 
      
 870 
     | 
    
         
            +
            			var nextChar = m2;
         
     | 
| 
      
 871 
     | 
    
         
            +
            		
         
     | 
| 
      
 872 
     | 
    
         
            +
            			codeblock = _EncodeCode( _Outdent(codeblock));
         
     | 
| 
      
 873 
     | 
    
         
            +
            			codeblock = _Detab(codeblock);
         
     | 
| 
      
 874 
     | 
    
         
            +
            			codeblock = codeblock.replace(/^\n+/g,""); // trim leading newlines
         
     | 
| 
      
 875 
     | 
    
         
            +
            			codeblock = codeblock.replace(/\n+$/g,""); // trim trailing whitespace
         
     | 
| 
      
 876 
     | 
    
         
            +
             
     | 
| 
      
 877 
     | 
    
         
            +
            			codeblock = "<pre><code>" + codeblock + "\n</code></pre>";
         
     | 
| 
      
 878 
     | 
    
         
            +
             
     | 
| 
      
 879 
     | 
    
         
            +
            			return hashBlock(codeblock) + nextChar;
         
     | 
| 
      
 880 
     | 
    
         
            +
            		}
         
     | 
| 
      
 881 
     | 
    
         
            +
            	);
         
     | 
| 
      
 882 
     | 
    
         
            +
             
     | 
| 
      
 883 
     | 
    
         
            +
            	// attacklab: strip sentinel
         
     | 
| 
      
 884 
     | 
    
         
            +
            	text = text.replace(/~0/,"");
         
     | 
| 
      
 885 
     | 
    
         
            +
             
     | 
| 
      
 886 
     | 
    
         
            +
            	return text;
         
     | 
| 
      
 887 
     | 
    
         
            +
            }
         
     | 
| 
      
 888 
     | 
    
         
            +
             
     | 
| 
      
 889 
     | 
    
         
            +
            var hashBlock = function(text) {
         
     | 
| 
      
 890 
     | 
    
         
            +
            	text = text.replace(/(^\n+|\n+$)/g,"");
         
     | 
| 
      
 891 
     | 
    
         
            +
            	return "\n\n~K" + (g_html_blocks.push(text)-1) + "K\n\n";
         
     | 
| 
      
 892 
     | 
    
         
            +
            }
         
     | 
| 
      
 893 
     | 
    
         
            +
             
     | 
| 
      
 894 
     | 
    
         
            +
             
     | 
| 
      
 895 
     | 
    
         
            +
            var _DoCodeSpans = function(text) {
         
     | 
| 
      
 896 
     | 
    
         
            +
            //
         
     | 
| 
      
 897 
     | 
    
         
            +
            //   *  Backtick quotes are used for <code></code> spans.
         
     | 
| 
      
 898 
     | 
    
         
            +
            // 
         
     | 
| 
      
 899 
     | 
    
         
            +
            //   *  You can use multiple backticks as the delimiters if you want to
         
     | 
| 
      
 900 
     | 
    
         
            +
            //	 include literal backticks in the code span. So, this input:
         
     | 
| 
      
 901 
     | 
    
         
            +
            //	 
         
     | 
| 
      
 902 
     | 
    
         
            +
            //		 Just type ``foo `bar` baz`` at the prompt.
         
     | 
| 
      
 903 
     | 
    
         
            +
            //	 
         
     | 
| 
      
 904 
     | 
    
         
            +
            //	   Will translate to:
         
     | 
| 
      
 905 
     | 
    
         
            +
            //	 
         
     | 
| 
      
 906 
     | 
    
         
            +
            //		 <p>Just type <code>foo `bar` baz</code> at the prompt.</p>
         
     | 
| 
      
 907 
     | 
    
         
            +
            //	 
         
     | 
| 
      
 908 
     | 
    
         
            +
            //	There's no arbitrary limit to the number of backticks you
         
     | 
| 
      
 909 
     | 
    
         
            +
            //	can use as delimters. If you need three consecutive backticks
         
     | 
| 
      
 910 
     | 
    
         
            +
            //	in your code, use four for delimiters, etc.
         
     | 
| 
      
 911 
     | 
    
         
            +
            //
         
     | 
| 
      
 912 
     | 
    
         
            +
            //  *  You can use spaces to get literal backticks at the edges:
         
     | 
| 
      
 913 
     | 
    
         
            +
            //	 
         
     | 
| 
      
 914 
     | 
    
         
            +
            //		 ... type `` `bar` `` ...
         
     | 
| 
      
 915 
     | 
    
         
            +
            //	 
         
     | 
| 
      
 916 
     | 
    
         
            +
            //	   Turns to:
         
     | 
| 
      
 917 
     | 
    
         
            +
            //	 
         
     | 
| 
      
 918 
     | 
    
         
            +
            //		 ... type <code>`bar`</code> ...
         
     | 
| 
      
 919 
     | 
    
         
            +
            //
         
     | 
| 
      
 920 
     | 
    
         
            +
             
     | 
| 
      
 921 
     | 
    
         
            +
            	/*
         
     | 
| 
      
 922 
     | 
    
         
            +
            		text = text.replace(/
         
     | 
| 
      
 923 
     | 
    
         
            +
            			(^|[^\\])					// Character before opening ` can't be a backslash
         
     | 
| 
      
 924 
     | 
    
         
            +
            			(`+)						// $2 = Opening run of `
         
     | 
| 
      
 925 
     | 
    
         
            +
            			(							// $3 = The code block
         
     | 
| 
      
 926 
     | 
    
         
            +
            				[^\r]*?
         
     | 
| 
      
 927 
     | 
    
         
            +
            				[^`]					// attacklab: work around lack of lookbehind
         
     | 
| 
      
 928 
     | 
    
         
            +
            			)
         
     | 
| 
      
 929 
     | 
    
         
            +
            			\2							// Matching closer
         
     | 
| 
      
 930 
     | 
    
         
            +
            			(?!`)
         
     | 
| 
      
 931 
     | 
    
         
            +
            		/gm, function(){...});
         
     | 
| 
      
 932 
     | 
    
         
            +
            	*/
         
     | 
| 
      
 933 
     | 
    
         
            +
             
     | 
| 
      
 934 
     | 
    
         
            +
            	text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,
         
     | 
| 
      
 935 
     | 
    
         
            +
            		function(wholeMatch,m1,m2,m3,m4) {
         
     | 
| 
      
 936 
     | 
    
         
            +
            			var c = m3;
         
     | 
| 
      
 937 
     | 
    
         
            +
            			c = c.replace(/^([ \t]*)/g,"");	// leading whitespace
         
     | 
| 
      
 938 
     | 
    
         
            +
            			c = c.replace(/[ \t]*$/g,"");	// trailing whitespace
         
     | 
| 
      
 939 
     | 
    
         
            +
            			c = _EncodeCode(c);
         
     | 
| 
      
 940 
     | 
    
         
            +
            			return m1+"<code>"+c+"</code>";
         
     | 
| 
      
 941 
     | 
    
         
            +
            		});
         
     | 
| 
      
 942 
     | 
    
         
            +
             
     | 
| 
      
 943 
     | 
    
         
            +
            	return text;
         
     | 
| 
      
 944 
     | 
    
         
            +
            }
         
     | 
| 
      
 945 
     | 
    
         
            +
             
     | 
| 
      
 946 
     | 
    
         
            +
             
     | 
| 
      
 947 
     | 
    
         
            +
            var _EncodeCode = function(text) {
         
     | 
| 
      
 948 
     | 
    
         
            +
            //
         
     | 
| 
      
 949 
     | 
    
         
            +
            // Encode/escape certain characters inside Markdown code runs.
         
     | 
| 
      
 950 
     | 
    
         
            +
            // The point is that in code, these characters are literals,
         
     | 
| 
      
 951 
     | 
    
         
            +
            // and lose their special Markdown meanings.
         
     | 
| 
      
 952 
     | 
    
         
            +
            //
         
     | 
| 
      
 953 
     | 
    
         
            +
            	// Encode all ampersands; HTML entities are not
         
     | 
| 
      
 954 
     | 
    
         
            +
            	// entities within a Markdown code span.
         
     | 
| 
      
 955 
     | 
    
         
            +
            	text = text.replace(/&/g,"&");
         
     | 
| 
      
 956 
     | 
    
         
            +
             
     | 
| 
      
 957 
     | 
    
         
            +
            	// Do the angle bracket song and dance:
         
     | 
| 
      
 958 
     | 
    
         
            +
            	text = text.replace(/</g,"<");
         
     | 
| 
      
 959 
     | 
    
         
            +
            	text = text.replace(/>/g,">");
         
     | 
| 
      
 960 
     | 
    
         
            +
             
     | 
| 
      
 961 
     | 
    
         
            +
            	// Now, escape characters that are magic in Markdown:
         
     | 
| 
      
 962 
     | 
    
         
            +
            	text = escapeCharacters(text,"\*_{}[]\\",false);
         
     | 
| 
      
 963 
     | 
    
         
            +
             
     | 
| 
      
 964 
     | 
    
         
            +
            // jj the line above breaks this:
         
     | 
| 
      
 965 
     | 
    
         
            +
            //---
         
     | 
| 
      
 966 
     | 
    
         
            +
             
     | 
| 
      
 967 
     | 
    
         
            +
            //* Item
         
     | 
| 
      
 968 
     | 
    
         
            +
             
     | 
| 
      
 969 
     | 
    
         
            +
            //   1. Subitem
         
     | 
| 
      
 970 
     | 
    
         
            +
             
     | 
| 
      
 971 
     | 
    
         
            +
            //            special char: *
         
     | 
| 
      
 972 
     | 
    
         
            +
            //---
         
     | 
| 
      
 973 
     | 
    
         
            +
             
     | 
| 
      
 974 
     | 
    
         
            +
            	return text;
         
     | 
| 
      
 975 
     | 
    
         
            +
            }
         
     | 
| 
      
 976 
     | 
    
         
            +
             
     | 
| 
      
 977 
     | 
    
         
            +
             
     | 
| 
      
 978 
     | 
    
         
            +
            var _DoItalicsAndBold = function(text) {
         
     | 
| 
      
 979 
     | 
    
         
            +
             
     | 
| 
      
 980 
     | 
    
         
            +
            	// <strong> must go first:
         
     | 
| 
      
 981 
     | 
    
         
            +
            	text = text.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g,
         
     | 
| 
      
 982 
     | 
    
         
            +
            		"<strong>$2</strong>");
         
     | 
| 
      
 983 
     | 
    
         
            +
             
     | 
| 
      
 984 
     | 
    
         
            +
            	text = text.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g,
         
     | 
| 
      
 985 
     | 
    
         
            +
            		"<em>$2</em>");
         
     | 
| 
      
 986 
     | 
    
         
            +
             
     | 
| 
      
 987 
     | 
    
         
            +
            	return text;
         
     | 
| 
      
 988 
     | 
    
         
            +
            }
         
     | 
| 
      
 989 
     | 
    
         
            +
             
     | 
| 
      
 990 
     | 
    
         
            +
             
     | 
| 
      
 991 
     | 
    
         
            +
            var _DoBlockQuotes = function(text) {
         
     | 
| 
      
 992 
     | 
    
         
            +
             
     | 
| 
      
 993 
     | 
    
         
            +
            	/*
         
     | 
| 
      
 994 
     | 
    
         
            +
            		text = text.replace(/
         
     | 
| 
      
 995 
     | 
    
         
            +
            		(								// Wrap whole match in $1
         
     | 
| 
      
 996 
     | 
    
         
            +
            			(
         
     | 
| 
      
 997 
     | 
    
         
            +
            				^[ \t]*>[ \t]?			// '>' at the start of a line
         
     | 
| 
      
 998 
     | 
    
         
            +
            				.+\n					// rest of the first line
         
     | 
| 
      
 999 
     | 
    
         
            +
            				(.+\n)*					// subsequent consecutive lines
         
     | 
| 
      
 1000 
     | 
    
         
            +
            				\n*						// blanks
         
     | 
| 
      
 1001 
     | 
    
         
            +
            			)+
         
     | 
| 
      
 1002 
     | 
    
         
            +
            		)
         
     | 
| 
      
 1003 
     | 
    
         
            +
            		/gm, function(){...});
         
     | 
| 
      
 1004 
     | 
    
         
            +
            	*/
         
     | 
| 
      
 1005 
     | 
    
         
            +
             
     | 
| 
      
 1006 
     | 
    
         
            +
            	text = text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,
         
     | 
| 
      
 1007 
     | 
    
         
            +
            		function(wholeMatch,m1) {
         
     | 
| 
      
 1008 
     | 
    
         
            +
            			var bq = m1;
         
     | 
| 
      
 1009 
     | 
    
         
            +
             
     | 
| 
      
 1010 
     | 
    
         
            +
            			// attacklab: hack around Konqueror 3.5.4 bug:
         
     | 
| 
      
 1011 
     | 
    
         
            +
            			// "----------bug".replace(/^-/g,"") == "bug"
         
     | 
| 
      
 1012 
     | 
    
         
            +
             
     | 
| 
      
 1013 
     | 
    
         
            +
            			bq = bq.replace(/^[ \t]*>[ \t]?/gm,"~0");	// trim one level of quoting
         
     | 
| 
      
 1014 
     | 
    
         
            +
             
     | 
| 
      
 1015 
     | 
    
         
            +
            			// attacklab: clean up hack
         
     | 
| 
      
 1016 
     | 
    
         
            +
            			bq = bq.replace(/~0/g,"");
         
     | 
| 
      
 1017 
     | 
    
         
            +
             
     | 
| 
      
 1018 
     | 
    
         
            +
            			bq = bq.replace(/^[ \t]+$/gm,"");		// trim whitespace-only lines
         
     | 
| 
      
 1019 
     | 
    
         
            +
            			bq = _RunBlockGamut(bq);				// recurse
         
     | 
| 
      
 1020 
     | 
    
         
            +
            			
         
     | 
| 
      
 1021 
     | 
    
         
            +
            			bq = bq.replace(/(^|\n)/g,"$1  ");
         
     | 
| 
      
 1022 
     | 
    
         
            +
            			// These leading spaces screw with <pre> content, so we need to fix that:
         
     | 
| 
      
 1023 
     | 
    
         
            +
            			bq = bq.replace(
         
     | 
| 
      
 1024 
     | 
    
         
            +
            					/(\s*<pre>[^\r]+?<\/pre>)/gm,
         
     | 
| 
      
 1025 
     | 
    
         
            +
            				function(wholeMatch,m1) {
         
     | 
| 
      
 1026 
     | 
    
         
            +
            					var pre = m1;
         
     | 
| 
      
 1027 
     | 
    
         
            +
            					// attacklab: hack around Konqueror 3.5.4 bug:
         
     | 
| 
      
 1028 
     | 
    
         
            +
            					pre = pre.replace(/^  /mg,"~0");
         
     | 
| 
      
 1029 
     | 
    
         
            +
            					pre = pre.replace(/~0/g,"");
         
     | 
| 
      
 1030 
     | 
    
         
            +
            					return pre;
         
     | 
| 
      
 1031 
     | 
    
         
            +
            				});
         
     | 
| 
      
 1032 
     | 
    
         
            +
            			
         
     | 
| 
      
 1033 
     | 
    
         
            +
            			return hashBlock("<blockquote>\n" + bq + "\n</blockquote>");
         
     | 
| 
      
 1034 
     | 
    
         
            +
            		});
         
     | 
| 
      
 1035 
     | 
    
         
            +
            	return text;
         
     | 
| 
      
 1036 
     | 
    
         
            +
            }
         
     | 
| 
      
 1037 
     | 
    
         
            +
             
     | 
| 
      
 1038 
     | 
    
         
            +
             
     | 
| 
      
 1039 
     | 
    
         
            +
            var _FormParagraphs = function(text) {
         
     | 
| 
      
 1040 
     | 
    
         
            +
            //
         
     | 
| 
      
 1041 
     | 
    
         
            +
            //  Params:
         
     | 
| 
      
 1042 
     | 
    
         
            +
            //    $text - string to process with html <p> tags
         
     | 
| 
      
 1043 
     | 
    
         
            +
            //
         
     | 
| 
      
 1044 
     | 
    
         
            +
             
     | 
| 
      
 1045 
     | 
    
         
            +
            	// Strip leading and trailing lines:
         
     | 
| 
      
 1046 
     | 
    
         
            +
            	text = text.replace(/^\n+/g,"");
         
     | 
| 
      
 1047 
     | 
    
         
            +
            	text = text.replace(/\n+$/g,"");
         
     | 
| 
      
 1048 
     | 
    
         
            +
             
     | 
| 
      
 1049 
     | 
    
         
            +
            	var grafs = text.split(/\n{2,}/g);
         
     | 
| 
      
 1050 
     | 
    
         
            +
            	var grafsOut = new Array();
         
     | 
| 
      
 1051 
     | 
    
         
            +
             
     | 
| 
      
 1052 
     | 
    
         
            +
            	//
         
     | 
| 
      
 1053 
     | 
    
         
            +
            	// Wrap <p> tags.
         
     | 
| 
      
 1054 
     | 
    
         
            +
            	//
         
     | 
| 
      
 1055 
     | 
    
         
            +
            	var end = grafs.length;
         
     | 
| 
      
 1056 
     | 
    
         
            +
            	for (var i=0; i<end; i++) {
         
     | 
| 
      
 1057 
     | 
    
         
            +
            		var str = grafs[i];
         
     | 
| 
      
 1058 
     | 
    
         
            +
             
     | 
| 
      
 1059 
     | 
    
         
            +
            		// if this is an HTML marker, copy it
         
     | 
| 
      
 1060 
     | 
    
         
            +
            		if (str.search(/~K(\d+)K/g) >= 0) {
         
     | 
| 
      
 1061 
     | 
    
         
            +
            			grafsOut.push(str);
         
     | 
| 
      
 1062 
     | 
    
         
            +
            		}
         
     | 
| 
      
 1063 
     | 
    
         
            +
            		else if (str.search(/\S/) >= 0) {
         
     | 
| 
      
 1064 
     | 
    
         
            +
            			str = _RunSpanGamut(str);
         
     | 
| 
      
 1065 
     | 
    
         
            +
            			str = str.replace(/^([ \t]*)/g,"<p>");
         
     | 
| 
      
 1066 
     | 
    
         
            +
            			str += "</p>"
         
     | 
| 
      
 1067 
     | 
    
         
            +
            			grafsOut.push(str);
         
     | 
| 
      
 1068 
     | 
    
         
            +
            		}
         
     | 
| 
      
 1069 
     | 
    
         
            +
             
     | 
| 
      
 1070 
     | 
    
         
            +
            	}
         
     | 
| 
      
 1071 
     | 
    
         
            +
             
     | 
| 
      
 1072 
     | 
    
         
            +
            	//
         
     | 
| 
      
 1073 
     | 
    
         
            +
            	// Unhashify HTML blocks
         
     | 
| 
      
 1074 
     | 
    
         
            +
            	//
         
     | 
| 
      
 1075 
     | 
    
         
            +
            	end = grafsOut.length;
         
     | 
| 
      
 1076 
     | 
    
         
            +
            	for (var i=0; i<end; i++) {
         
     | 
| 
      
 1077 
     | 
    
         
            +
            		// if this is a marker for an html block...
         
     | 
| 
      
 1078 
     | 
    
         
            +
            		while (grafsOut[i].search(/~K(\d+)K/) >= 0) {
         
     | 
| 
      
 1079 
     | 
    
         
            +
            			var blockText = g_html_blocks[RegExp.$1];
         
     | 
| 
      
 1080 
     | 
    
         
            +
            			blockText = blockText.replace(/\$/g,"$$$$"); // Escape any dollar signs
         
     | 
| 
      
 1081 
     | 
    
         
            +
            			grafsOut[i] = grafsOut[i].replace(/~K\d+K/,blockText);
         
     | 
| 
      
 1082 
     | 
    
         
            +
            		}
         
     | 
| 
      
 1083 
     | 
    
         
            +
            	}
         
     | 
| 
      
 1084 
     | 
    
         
            +
             
     | 
| 
      
 1085 
     | 
    
         
            +
            	return grafsOut.join("\n\n");
         
     | 
| 
      
 1086 
     | 
    
         
            +
            }
         
     | 
| 
      
 1087 
     | 
    
         
            +
             
     | 
| 
      
 1088 
     | 
    
         
            +
             
     | 
| 
      
 1089 
     | 
    
         
            +
            var _EncodeAmpsAndAngles = function(text) {
         
     | 
| 
      
 1090 
     | 
    
         
            +
            // Smart processing for ampersands and angle brackets that need to be encoded.
         
     | 
| 
      
 1091 
     | 
    
         
            +
            	
         
     | 
| 
      
 1092 
     | 
    
         
            +
            	// Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:
         
     | 
| 
      
 1093 
     | 
    
         
            +
            	//   http://bumppo.net/projects/amputator/
         
     | 
| 
      
 1094 
     | 
    
         
            +
            	text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g,"&");
         
     | 
| 
      
 1095 
     | 
    
         
            +
            	
         
     | 
| 
      
 1096 
     | 
    
         
            +
            	// Encode naked <'s
         
     | 
| 
      
 1097 
     | 
    
         
            +
            	text = text.replace(/<(?![a-z\/?\$!])/gi,"<");
         
     | 
| 
      
 1098 
     | 
    
         
            +
            	
         
     | 
| 
      
 1099 
     | 
    
         
            +
            	return text;
         
     | 
| 
      
 1100 
     | 
    
         
            +
            }
         
     | 
| 
      
 1101 
     | 
    
         
            +
             
     | 
| 
      
 1102 
     | 
    
         
            +
             
     | 
| 
      
 1103 
     | 
    
         
            +
            var _EncodeBackslashEscapes = function(text) {
         
     | 
| 
      
 1104 
     | 
    
         
            +
            //
         
     | 
| 
      
 1105 
     | 
    
         
            +
            //   Parameter:  String.
         
     | 
| 
      
 1106 
     | 
    
         
            +
            //   Returns:	The string, with after processing the following backslash
         
     | 
| 
      
 1107 
     | 
    
         
            +
            //			   escape sequences.
         
     | 
| 
      
 1108 
     | 
    
         
            +
            //
         
     | 
| 
      
 1109 
     | 
    
         
            +
             
     | 
| 
      
 1110 
     | 
    
         
            +
            	// attacklab: The polite way to do this is with the new
         
     | 
| 
      
 1111 
     | 
    
         
            +
            	// escapeCharacters() function:
         
     | 
| 
      
 1112 
     | 
    
         
            +
            	//
         
     | 
| 
      
 1113 
     | 
    
         
            +
            	// 	text = escapeCharacters(text,"\\",true);
         
     | 
| 
      
 1114 
     | 
    
         
            +
            	// 	text = escapeCharacters(text,"`*_{}[]()>#+-.!",true);
         
     | 
| 
      
 1115 
     | 
    
         
            +
            	//
         
     | 
| 
      
 1116 
     | 
    
         
            +
            	// ...but we're sidestepping its use of the (slow) RegExp constructor
         
     | 
| 
      
 1117 
     | 
    
         
            +
            	// as an optimization for Firefox.  This function gets called a LOT.
         
     | 
| 
      
 1118 
     | 
    
         
            +
             
     | 
| 
      
 1119 
     | 
    
         
            +
            	text = text.replace(/\\(\\)/g,escapeCharacters_callback);
         
     | 
| 
      
 1120 
     | 
    
         
            +
            	text = text.replace(/\\([`*_{}\[\]()>#+-.!])/g,escapeCharacters_callback);
         
     | 
| 
      
 1121 
     | 
    
         
            +
            	return text;
         
     | 
| 
      
 1122 
     | 
    
         
            +
            }
         
     | 
| 
      
 1123 
     | 
    
         
            +
             
     | 
| 
      
 1124 
     | 
    
         
            +
             
     | 
| 
      
 1125 
     | 
    
         
            +
            var _DoAutoLinks = function(text) {
         
     | 
| 
      
 1126 
     | 
    
         
            +
             
     | 
| 
      
 1127 
     | 
    
         
            +
            	text = text.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi,"<a href=\"$1\">$1</a>");
         
     | 
| 
      
 1128 
     | 
    
         
            +
             
     | 
| 
      
 1129 
     | 
    
         
            +
            	// Email addresses: <address@domain.foo>
         
     | 
| 
      
 1130 
     | 
    
         
            +
             
     | 
| 
      
 1131 
     | 
    
         
            +
            	/*
         
     | 
| 
      
 1132 
     | 
    
         
            +
            		text = text.replace(/
         
     | 
| 
      
 1133 
     | 
    
         
            +
            			<
         
     | 
| 
      
 1134 
     | 
    
         
            +
            			(?:mailto:)?
         
     | 
| 
      
 1135 
     | 
    
         
            +
            			(
         
     | 
| 
      
 1136 
     | 
    
         
            +
            				[-.\w]+
         
     | 
| 
      
 1137 
     | 
    
         
            +
            				\@
         
     | 
| 
      
 1138 
     | 
    
         
            +
            				[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+
         
     | 
| 
      
 1139 
     | 
    
         
            +
            			)
         
     | 
| 
      
 1140 
     | 
    
         
            +
            			>
         
     | 
| 
      
 1141 
     | 
    
         
            +
            		/gi, _DoAutoLinks_callback());
         
     | 
| 
      
 1142 
     | 
    
         
            +
            	*/
         
     | 
| 
      
 1143 
     | 
    
         
            +
            	text = text.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,
         
     | 
| 
      
 1144 
     | 
    
         
            +
            		function(wholeMatch,m1) {
         
     | 
| 
      
 1145 
     | 
    
         
            +
            			return _EncodeEmailAddress( _UnescapeSpecialChars(m1) );
         
     | 
| 
      
 1146 
     | 
    
         
            +
            		}
         
     | 
| 
      
 1147 
     | 
    
         
            +
            	);
         
     | 
| 
      
 1148 
     | 
    
         
            +
             
     | 
| 
      
 1149 
     | 
    
         
            +
            	return text;
         
     | 
| 
      
 1150 
     | 
    
         
            +
            }
         
     | 
| 
      
 1151 
     | 
    
         
            +
             
     | 
| 
      
 1152 
     | 
    
         
            +
             
     | 
| 
      
 1153 
     | 
    
         
            +
            var _EncodeEmailAddress = function(addr) {
         
     | 
| 
      
 1154 
     | 
    
         
            +
            //
         
     | 
| 
      
 1155 
     | 
    
         
            +
            //  Input: an email address, e.g. "foo@example.com"
         
     | 
| 
      
 1156 
     | 
    
         
            +
            //
         
     | 
| 
      
 1157 
     | 
    
         
            +
            //  Output: the email address as a mailto link, with each character
         
     | 
| 
      
 1158 
     | 
    
         
            +
            //	of the address encoded as either a decimal or hex entity, in
         
     | 
| 
      
 1159 
     | 
    
         
            +
            //	the hopes of foiling most address harvesting spam bots. E.g.:
         
     | 
| 
      
 1160 
     | 
    
         
            +
            //
         
     | 
| 
      
 1161 
     | 
    
         
            +
            //	<a href="mailto:foo@e
         
     | 
| 
      
 1162 
     | 
    
         
            +
            //	   xample.com">foo
         
     | 
| 
      
 1163 
     | 
    
         
            +
            //	   @example.com</a>
         
     | 
| 
      
 1164 
     | 
    
         
            +
            //
         
     | 
| 
      
 1165 
     | 
    
         
            +
            //  Based on a filter by Matthew Wickline, posted to the BBEdit-Talk
         
     | 
| 
      
 1166 
     | 
    
         
            +
            //  mailing list: <http://tinyurl.com/yu7ue>
         
     | 
| 
      
 1167 
     | 
    
         
            +
            //
         
     | 
| 
      
 1168 
     | 
    
         
            +
             
     | 
| 
      
 1169 
     | 
    
         
            +
            	// attacklab: why can't javascript speak hex?
         
     | 
| 
      
 1170 
     | 
    
         
            +
            	function char2hex(ch) {
         
     | 
| 
      
 1171 
     | 
    
         
            +
            		var hexDigits = '0123456789ABCDEF';
         
     | 
| 
      
 1172 
     | 
    
         
            +
            		var dec = ch.charCodeAt(0);
         
     | 
| 
      
 1173 
     | 
    
         
            +
            		return(hexDigits.charAt(dec>>4) + hexDigits.charAt(dec&15));
         
     | 
| 
      
 1174 
     | 
    
         
            +
            	}
         
     | 
| 
      
 1175 
     | 
    
         
            +
             
     | 
| 
      
 1176 
     | 
    
         
            +
            	var encode = [
         
     | 
| 
      
 1177 
     | 
    
         
            +
            		function(ch){return "&#"+ch.charCodeAt(0)+";";},
         
     | 
| 
      
 1178 
     | 
    
         
            +
            		function(ch){return "&#x"+char2hex(ch)+";";},
         
     | 
| 
      
 1179 
     | 
    
         
            +
            		function(ch){return ch;}
         
     | 
| 
      
 1180 
     | 
    
         
            +
            	];
         
     | 
| 
      
 1181 
     | 
    
         
            +
             
     | 
| 
      
 1182 
     | 
    
         
            +
            	addr = "mailto:" + addr;
         
     | 
| 
      
 1183 
     | 
    
         
            +
             
     | 
| 
      
 1184 
     | 
    
         
            +
            	addr = addr.replace(/./g, function(ch) {
         
     | 
| 
      
 1185 
     | 
    
         
            +
            		if (ch == "@") {
         
     | 
| 
      
 1186 
     | 
    
         
            +
            		   	// this *must* be encoded. I insist.
         
     | 
| 
      
 1187 
     | 
    
         
            +
            			ch = encode[Math.floor(Math.random()*2)](ch);
         
     | 
| 
      
 1188 
     | 
    
         
            +
            		} else if (ch !=":") {
         
     | 
| 
      
 1189 
     | 
    
         
            +
            			// leave ':' alone (to spot mailto: later)
         
     | 
| 
      
 1190 
     | 
    
         
            +
            			var r = Math.random();
         
     | 
| 
      
 1191 
     | 
    
         
            +
            			// roughly 10% raw, 45% hex, 45% dec
         
     | 
| 
      
 1192 
     | 
    
         
            +
            			ch =  (
         
     | 
| 
      
 1193 
     | 
    
         
            +
            					r > .9  ?	encode[2](ch)   :
         
     | 
| 
      
 1194 
     | 
    
         
            +
            					r > .45 ?	encode[1](ch)   :
         
     | 
| 
      
 1195 
     | 
    
         
            +
            								encode[0](ch)
         
     | 
| 
      
 1196 
     | 
    
         
            +
            				);
         
     | 
| 
      
 1197 
     | 
    
         
            +
            		}
         
     | 
| 
      
 1198 
     | 
    
         
            +
            		return ch;
         
     | 
| 
      
 1199 
     | 
    
         
            +
            	});
         
     | 
| 
      
 1200 
     | 
    
         
            +
             
     | 
| 
      
 1201 
     | 
    
         
            +
            	addr = "<a href=\"" + addr + "\">" + addr + "</a>";
         
     | 
| 
      
 1202 
     | 
    
         
            +
            	addr = addr.replace(/">.+:/g,"\">"); // strip the mailto: from the visible part
         
     | 
| 
      
 1203 
     | 
    
         
            +
             
     | 
| 
      
 1204 
     | 
    
         
            +
            	return addr;
         
     | 
| 
      
 1205 
     | 
    
         
            +
            }
         
     | 
| 
      
 1206 
     | 
    
         
            +
             
     | 
| 
      
 1207 
     | 
    
         
            +
             
     | 
| 
      
 1208 
     | 
    
         
            +
            var _UnescapeSpecialChars = function(text) {
         
     | 
| 
      
 1209 
     | 
    
         
            +
            //
         
     | 
| 
      
 1210 
     | 
    
         
            +
            // Swap back in all the special characters we've hidden.
         
     | 
| 
      
 1211 
     | 
    
         
            +
            //
         
     | 
| 
      
 1212 
     | 
    
         
            +
            	text = text.replace(/~E(\d+)E/g,
         
     | 
| 
      
 1213 
     | 
    
         
            +
            		function(wholeMatch,m1) {
         
     | 
| 
      
 1214 
     | 
    
         
            +
            			var charCodeToReplace = parseInt(m1);
         
     | 
| 
      
 1215 
     | 
    
         
            +
            			return String.fromCharCode(charCodeToReplace);
         
     | 
| 
      
 1216 
     | 
    
         
            +
            		}
         
     | 
| 
      
 1217 
     | 
    
         
            +
            	);
         
     | 
| 
      
 1218 
     | 
    
         
            +
            	return text;
         
     | 
| 
      
 1219 
     | 
    
         
            +
            }
         
     | 
| 
      
 1220 
     | 
    
         
            +
             
     | 
| 
      
 1221 
     | 
    
         
            +
             
     | 
| 
      
 1222 
     | 
    
         
            +
            var _Outdent = function(text) {
         
     | 
| 
      
 1223 
     | 
    
         
            +
            //
         
     | 
| 
      
 1224 
     | 
    
         
            +
            // Remove one level of line-leading tabs or spaces
         
     | 
| 
      
 1225 
     | 
    
         
            +
            //
         
     | 
| 
      
 1226 
     | 
    
         
            +
             
     | 
| 
      
 1227 
     | 
    
         
            +
            	// attacklab: hack around Konqueror 3.5.4 bug:
         
     | 
| 
      
 1228 
     | 
    
         
            +
            	// "----------bug".replace(/^-/g,"") == "bug"
         
     | 
| 
      
 1229 
     | 
    
         
            +
             
     | 
| 
      
 1230 
     | 
    
         
            +
            	text = text.replace(/^(\t|[ ]{1,4})/gm,"~0"); // attacklab: g_tab_width
         
     | 
| 
      
 1231 
     | 
    
         
            +
             
     | 
| 
      
 1232 
     | 
    
         
            +
            	// attacklab: clean up hack
         
     | 
| 
      
 1233 
     | 
    
         
            +
            	text = text.replace(/~0/g,"")
         
     | 
| 
      
 1234 
     | 
    
         
            +
             
     | 
| 
      
 1235 
     | 
    
         
            +
            	return text;
         
     | 
| 
      
 1236 
     | 
    
         
            +
            }
         
     | 
| 
      
 1237 
     | 
    
         
            +
             
     | 
| 
      
 1238 
     | 
    
         
            +
            var _Detab = function(text) {
         
     | 
| 
      
 1239 
     | 
    
         
            +
            // attacklab: Detab's completely rewritten for speed.
         
     | 
| 
      
 1240 
     | 
    
         
            +
            // In perl we could fix it by anchoring the regexp with \G.
         
     | 
| 
      
 1241 
     | 
    
         
            +
            // In javascript we're less fortunate.
         
     | 
| 
      
 1242 
     | 
    
         
            +
             
     | 
| 
      
 1243 
     | 
    
         
            +
            	// expand first n-1 tabs
         
     | 
| 
      
 1244 
     | 
    
         
            +
            	text = text.replace(/\t(?=\t)/g,"    "); // attacklab: g_tab_width
         
     | 
| 
      
 1245 
     | 
    
         
            +
             
     | 
| 
      
 1246 
     | 
    
         
            +
            	// replace the nth with two sentinels
         
     | 
| 
      
 1247 
     | 
    
         
            +
            	text = text.replace(/\t/g,"~A~B");
         
     | 
| 
      
 1248 
     | 
    
         
            +
             
     | 
| 
      
 1249 
     | 
    
         
            +
            	// use the sentinel to anchor our regex so it doesn't explode
         
     | 
| 
      
 1250 
     | 
    
         
            +
            	text = text.replace(/~B(.+?)~A/g,
         
     | 
| 
      
 1251 
     | 
    
         
            +
            		function(wholeMatch,m1,m2) {
         
     | 
| 
      
 1252 
     | 
    
         
            +
            			var leadingText = m1;
         
     | 
| 
      
 1253 
     | 
    
         
            +
            			var numSpaces = 4 - leadingText.length % 4;  // attacklab: g_tab_width
         
     | 
| 
      
 1254 
     | 
    
         
            +
             
     | 
| 
      
 1255 
     | 
    
         
            +
            			// there *must* be a better way to do this:
         
     | 
| 
      
 1256 
     | 
    
         
            +
            			for (var i=0; i<numSpaces; i++) leadingText+=" ";
         
     | 
| 
      
 1257 
     | 
    
         
            +
             
     | 
| 
      
 1258 
     | 
    
         
            +
            			return leadingText;
         
     | 
| 
      
 1259 
     | 
    
         
            +
            		}
         
     | 
| 
      
 1260 
     | 
    
         
            +
            	);
         
     | 
| 
      
 1261 
     | 
    
         
            +
             
     | 
| 
      
 1262 
     | 
    
         
            +
            	// clean up sentinels
         
     | 
| 
      
 1263 
     | 
    
         
            +
            	text = text.replace(/~A/g,"    ");  // attacklab: g_tab_width
         
     | 
| 
      
 1264 
     | 
    
         
            +
            	text = text.replace(/~B/g,"");
         
     | 
| 
      
 1265 
     | 
    
         
            +
             
     | 
| 
      
 1266 
     | 
    
         
            +
            	return text;
         
     | 
| 
      
 1267 
     | 
    
         
            +
            }
         
     | 
| 
      
 1268 
     | 
    
         
            +
             
     | 
| 
      
 1269 
     | 
    
         
            +
             
     | 
| 
      
 1270 
     | 
    
         
            +
            //
         
     | 
| 
      
 1271 
     | 
    
         
            +
            //  attacklab: Utility functions
         
     | 
| 
      
 1272 
     | 
    
         
            +
            //
         
     | 
| 
      
 1273 
     | 
    
         
            +
             
     | 
| 
      
 1274 
     | 
    
         
            +
             
     | 
| 
      
 1275 
     | 
    
         
            +
            var escapeCharacters = function(text, charsToEscape, afterBackslash) {
         
     | 
| 
      
 1276 
     | 
    
         
            +
            	// First we have to escape the escape characters so that
         
     | 
| 
      
 1277 
     | 
    
         
            +
            	// we can build a character class out of them
         
     | 
| 
      
 1278 
     | 
    
         
            +
            	var regexString = "([" + charsToEscape.replace(/([\[\]\\])/g,"\\$1") + "])";
         
     | 
| 
      
 1279 
     | 
    
         
            +
             
     | 
| 
      
 1280 
     | 
    
         
            +
            	if (afterBackslash) {
         
     | 
| 
      
 1281 
     | 
    
         
            +
            		regexString = "\\\\" + regexString;
         
     | 
| 
      
 1282 
     | 
    
         
            +
            	}
         
     | 
| 
      
 1283 
     | 
    
         
            +
             
     | 
| 
      
 1284 
     | 
    
         
            +
            	var regex = new RegExp(regexString,"g");
         
     | 
| 
      
 1285 
     | 
    
         
            +
            	text = text.replace(regex,escapeCharacters_callback);
         
     | 
| 
      
 1286 
     | 
    
         
            +
             
     | 
| 
      
 1287 
     | 
    
         
            +
            	return text;
         
     | 
| 
      
 1288 
     | 
    
         
            +
            }
         
     | 
| 
      
 1289 
     | 
    
         
            +
             
     | 
| 
      
 1290 
     | 
    
         
            +
             
     | 
| 
      
 1291 
     | 
    
         
            +
            var escapeCharacters_callback = function(wholeMatch,m1) {
         
     | 
| 
      
 1292 
     | 
    
         
            +
            	var charCodeToEscape = m1.charCodeAt(0);
         
     | 
| 
      
 1293 
     | 
    
         
            +
            	return "~E"+charCodeToEscape+"E";
         
     | 
| 
      
 1294 
     | 
    
         
            +
            }
         
     | 
| 
      
 1295 
     | 
    
         
            +
             
     | 
| 
      
 1296 
     | 
    
         
            +
            }; // end of Showdown.converter
         
     | 
| 
      
 1297 
     | 
    
         
            +
             
     | 
| 
      
 1298 
     | 
    
         
            +
             
     | 
| 
      
 1299 
     | 
    
         
            +
            // ----------------------------------------------------------------------------
         
     | 
| 
      
 1300 
     | 
    
         
            +
            // markItUp! Universal MarkUp Engine, JQuery plugin
         
     | 
| 
      
 1301 
     | 
    
         
            +
            // v 1.1.x
         
     | 
| 
      
 1302 
     | 
    
         
            +
            // Dual licensed under the MIT and GPL licenses.
         
     | 
| 
      
 1303 
     | 
    
         
            +
            // ----------------------------------------------------------------------------
         
     | 
| 
      
 1304 
     | 
    
         
            +
            // Copyright (C) 2007-2010 Jay Salvat
         
     | 
| 
      
 1305 
     | 
    
         
            +
            // http://markitup.jaysalvat.com/
         
     | 
| 
      
 1306 
     | 
    
         
            +
            // ----------------------------------------------------------------------------
         
     | 
| 
      
 1307 
     | 
    
         
            +
            // Permission is hereby granted, free of charge, to any person obtaining a copy
         
     | 
| 
      
 1308 
     | 
    
         
            +
            // of this software and associated documentation files (the "Software"), to deal
         
     | 
| 
      
 1309 
     | 
    
         
            +
            // in the Software without restriction, including without limitation the rights
         
     | 
| 
      
 1310 
     | 
    
         
            +
            // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         
     | 
| 
      
 1311 
     | 
    
         
            +
            // copies of the Software, and to permit persons to whom the Software is
         
     | 
| 
      
 1312 
     | 
    
         
            +
            // furnished to do so, subject to the following conditions:
         
     | 
| 
      
 1313 
     | 
    
         
            +
            // 
         
     | 
| 
      
 1314 
     | 
    
         
            +
            // The above copyright notice and this permission notice shall be included in
         
     | 
| 
      
 1315 
     | 
    
         
            +
            // all copies or substantial portions of the Software.
         
     | 
| 
      
 1316 
     | 
    
         
            +
            // 
         
     | 
| 
      
 1317 
     | 
    
         
            +
            // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         
     | 
| 
      
 1318 
     | 
    
         
            +
            // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         
     | 
| 
      
 1319 
     | 
    
         
            +
            // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         
     | 
| 
      
 1320 
     | 
    
         
            +
            // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         
     | 
| 
      
 1321 
     | 
    
         
            +
            // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         
     | 
| 
      
 1322 
     | 
    
         
            +
            // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
         
     | 
| 
      
 1323 
     | 
    
         
            +
            // THE SOFTWARE.
         
     | 
| 
      
 1324 
     | 
    
         
            +
            // ----------------------------------------------------------------------------
         
     | 
| 
      
 1325 
     | 
    
         
            +
            (function($) {
         
     | 
| 
      
 1326 
     | 
    
         
            +
            	$.fn.markItUp = function(settings, extraSettings) {
         
     | 
| 
      
 1327 
     | 
    
         
            +
                var converter = new Showdown.converter();
         
     | 
| 
      
 1328 
     | 
    
         
            +
            		var options, ctrlKey, shiftKey, altKey;
         
     | 
| 
      
 1329 
     | 
    
         
            +
            		ctrlKey = shiftKey = altKey = false;
         
     | 
| 
      
 1330 
     | 
    
         
            +
            	
         
     | 
| 
      
 1331 
     | 
    
         
            +
            		options = {	id:						'',
         
     | 
| 
      
 1332 
     | 
    
         
            +
            					nameSpace:				'',
         
     | 
| 
      
 1333 
     | 
    
         
            +
            					root:					'',
         
     | 
| 
      
 1334 
     | 
    
         
            +
            					previewInWindow:		'', // 'width=800, height=600, resizable=yes, scrollbars=yes'
         
     | 
| 
      
 1335 
     | 
    
         
            +
            					previewAutoRefresh:		true,
         
     | 
| 
      
 1336 
     | 
    
         
            +
            					previewPosition:		'after',
         
     | 
| 
      
 1337 
     | 
    
         
            +
            					previewTemplatePath:	'~/templates/preview.html',
         
     | 
| 
      
 1338 
     | 
    
         
            +
            					previewParserPath:		'',
         
     | 
| 
      
 1339 
     | 
    
         
            +
            					previewParserVar:		'data',
         
     | 
| 
      
 1340 
     | 
    
         
            +
            					resizeHandle:			true,
         
     | 
| 
      
 1341 
     | 
    
         
            +
            					beforeInsert:			'',
         
     | 
| 
      
 1342 
     | 
    
         
            +
            					afterInsert:			'',
         
     | 
| 
      
 1343 
     | 
    
         
            +
            					onEnter:				{},
         
     | 
| 
      
 1344 
     | 
    
         
            +
            					onShiftEnter:			{},
         
     | 
| 
      
 1345 
     | 
    
         
            +
            					onCtrlEnter:			{},
         
     | 
| 
      
 1346 
     | 
    
         
            +
            					onTab:					{},
         
     | 
| 
      
 1347 
     | 
    
         
            +
            					markupSet:			[	{ /* set */ } ]
         
     | 
| 
      
 1348 
     | 
    
         
            +
            				};
         
     | 
| 
      
 1349 
     | 
    
         
            +
            		$.extend(options, settings, extraSettings);
         
     | 
| 
      
 1350 
     | 
    
         
            +
             
     | 
| 
      
 1351 
     | 
    
         
            +
            		// compute markItUp! path
         
     | 
| 
      
 1352 
     | 
    
         
            +
            		if (!options.root) {
         
     | 
| 
      
 1353 
     | 
    
         
            +
            			$('script').each(function(a, tag) {
         
     | 
| 
      
 1354 
     | 
    
         
            +
            				miuScript = $(tag).get(0).src.match(/(.*)jquery\.markitup(\.pack)?\.js$/);
         
     | 
| 
      
 1355 
     | 
    
         
            +
            				if (miuScript !== null) {
         
     | 
| 
      
 1356 
     | 
    
         
            +
            					options.root = miuScript[1];
         
     | 
| 
      
 1357 
     | 
    
         
            +
            				}
         
     | 
| 
      
 1358 
     | 
    
         
            +
            			});
         
     | 
| 
      
 1359 
     | 
    
         
            +
            		}
         
     | 
| 
      
 1360 
     | 
    
         
            +
             
     | 
| 
      
 1361 
     | 
    
         
            +
            		return this.each(function() {
         
     | 
| 
      
 1362 
     | 
    
         
            +
            			var $$, textarea, levels, scrollPosition, caretPosition, caretOffset,
         
     | 
| 
      
 1363 
     | 
    
         
            +
            				clicked, hash, header, footer, previewWindow, template, previewDiv, abort;
         
     | 
| 
      
 1364 
     | 
    
         
            +
            			$$ = $(this);
         
     | 
| 
      
 1365 
     | 
    
         
            +
            			textarea = this;
         
     | 
| 
      
 1366 
     | 
    
         
            +
            			levels = [];
         
     | 
| 
      
 1367 
     | 
    
         
            +
            			abort = false;
         
     | 
| 
      
 1368 
     | 
    
         
            +
            			scrollPosition = caretPosition = 0;
         
     | 
| 
      
 1369 
     | 
    
         
            +
            			caretOffset = -1;
         
     | 
| 
      
 1370 
     | 
    
         
            +
             
     | 
| 
      
 1371 
     | 
    
         
            +
            			options.previewParserPath = localize(options.previewParserPath);
         
     | 
| 
      
 1372 
     | 
    
         
            +
            			options.previewTemplatePath = localize(options.previewTemplatePath);
         
     | 
| 
      
 1373 
     | 
    
         
            +
             
     | 
| 
      
 1374 
     | 
    
         
            +
            			// apply the computed path to ~/
         
     | 
| 
      
 1375 
     | 
    
         
            +
            			function localize(data, inText) {
         
     | 
| 
      
 1376 
     | 
    
         
            +
            				if (inText) {
         
     | 
| 
      
 1377 
     | 
    
         
            +
            					return 	data.replace(/("|')~\//g, "$1"+options.root);
         
     | 
| 
      
 1378 
     | 
    
         
            +
            				}
         
     | 
| 
      
 1379 
     | 
    
         
            +
            				return 	data.replace(/^~\//, options.root);
         
     | 
| 
      
 1380 
     | 
    
         
            +
            			}
         
     | 
| 
      
 1381 
     | 
    
         
            +
             
     | 
| 
      
 1382 
     | 
    
         
            +
            			// init and build editor
         
     | 
| 
      
 1383 
     | 
    
         
            +
            			function init() {
         
     | 
| 
      
 1384 
     | 
    
         
            +
            				id = ''; nameSpace = '';
         
     | 
| 
      
 1385 
     | 
    
         
            +
            				if (options.id) {
         
     | 
| 
      
 1386 
     | 
    
         
            +
            					id = 'id="'+options.id+'"';
         
     | 
| 
      
 1387 
     | 
    
         
            +
            				} else if ($$.attr("id")) {
         
     | 
| 
      
 1388 
     | 
    
         
            +
            					id = 'id="markItUp'+($$.attr("id").substr(0, 1).toUpperCase())+($$.attr("id").substr(1))+'"';
         
     | 
| 
      
 1389 
     | 
    
         
            +
             
     | 
| 
      
 1390 
     | 
    
         
            +
            				}
         
     | 
| 
      
 1391 
     | 
    
         
            +
            				if (options.nameSpace) {
         
     | 
| 
      
 1392 
     | 
    
         
            +
            					nameSpace = 'class="'+options.nameSpace+'"';
         
     | 
| 
      
 1393 
     | 
    
         
            +
            				}
         
     | 
| 
      
 1394 
     | 
    
         
            +
            				$$.wrap('<div '+nameSpace+'></div>');
         
     | 
| 
      
 1395 
     | 
    
         
            +
            				$$.wrap('<div '+id+' class="markItUp"></div>');
         
     | 
| 
      
 1396 
     | 
    
         
            +
            				$$.wrap('<div class="markItUpContainer"></div>');
         
     | 
| 
      
 1397 
     | 
    
         
            +
            				$$.addClass("markItUpEditor");
         
     | 
| 
      
 1398 
     | 
    
         
            +
             
     | 
| 
      
 1399 
     | 
    
         
            +
            				// add the header before the textarea
         
     | 
| 
      
 1400 
     | 
    
         
            +
            				header = $('<div class="markItUpHeader"></div>').insertBefore($$);
         
     | 
| 
      
 1401 
     | 
    
         
            +
            				$(dropMenus(options.markupSet)).appendTo(header);
         
     | 
| 
      
 1402 
     | 
    
         
            +
             
     | 
| 
      
 1403 
     | 
    
         
            +
            				// add the footer after the textarea
         
     | 
| 
      
 1404 
     | 
    
         
            +
            				footer = $('<div class="markItUpFooter"></div>').insertAfter($$);
         
     | 
| 
      
 1405 
     | 
    
         
            +
             
     | 
| 
      
 1406 
     | 
    
         
            +
            				// add the resize handle after textarea
         
     | 
| 
      
 1407 
     | 
    
         
            +
            				if (options.resizeHandle === true && $.browser.safari !== true) {
         
     | 
| 
      
 1408 
     | 
    
         
            +
            					resizeHandle = $('<div class="markItUpResizeHandle"></div>')
         
     | 
| 
      
 1409 
     | 
    
         
            +
            						.insertAfter($$)
         
     | 
| 
      
 1410 
     | 
    
         
            +
            						.bind("mousedown", function(e) {
         
     | 
| 
      
 1411 
     | 
    
         
            +
            							var h = $$.height(), y = e.clientY, mouseMove, mouseUp;
         
     | 
| 
      
 1412 
     | 
    
         
            +
            							mouseMove = function(e) {
         
     | 
| 
      
 1413 
     | 
    
         
            +
            								$$.css("height", Math.max(20, e.clientY+h-y)+"px");
         
     | 
| 
      
 1414 
     | 
    
         
            +
            								return false;
         
     | 
| 
      
 1415 
     | 
    
         
            +
            							};
         
     | 
| 
      
 1416 
     | 
    
         
            +
            							mouseUp = function(e) {
         
     | 
| 
      
 1417 
     | 
    
         
            +
            								$("html").unbind("mousemove", mouseMove).unbind("mouseup", mouseUp);
         
     | 
| 
      
 1418 
     | 
    
         
            +
            								return false;
         
     | 
| 
      
 1419 
     | 
    
         
            +
            							};
         
     | 
| 
      
 1420 
     | 
    
         
            +
            							$("html").bind("mousemove", mouseMove).bind("mouseup", mouseUp);
         
     | 
| 
      
 1421 
     | 
    
         
            +
            					});
         
     | 
| 
      
 1422 
     | 
    
         
            +
            					footer.append(resizeHandle);
         
     | 
| 
      
 1423 
     | 
    
         
            +
            				}
         
     | 
| 
      
 1424 
     | 
    
         
            +
             
     | 
| 
      
 1425 
     | 
    
         
            +
            				// listen key events
         
     | 
| 
      
 1426 
     | 
    
         
            +
            				$$.keydown(keyPressed).keyup(keyPressed);
         
     | 
| 
      
 1427 
     | 
    
         
            +
            				
         
     | 
| 
      
 1428 
     | 
    
         
            +
            				// bind an event to catch external calls
         
     | 
| 
      
 1429 
     | 
    
         
            +
            				$$.bind("insertion", function(e, settings) {
         
     | 
| 
      
 1430 
     | 
    
         
            +
            					if (settings.target !== false) {
         
     | 
| 
      
 1431 
     | 
    
         
            +
            						get();
         
     | 
| 
      
 1432 
     | 
    
         
            +
            					}
         
     | 
| 
      
 1433 
     | 
    
         
            +
            					if (textarea === $.markItUp.focused) {
         
     | 
| 
      
 1434 
     | 
    
         
            +
            						markup(settings);
         
     | 
| 
      
 1435 
     | 
    
         
            +
            					}
         
     | 
| 
      
 1436 
     | 
    
         
            +
            				});
         
     | 
| 
      
 1437 
     | 
    
         
            +
             
     | 
| 
      
 1438 
     | 
    
         
            +
                    if (options.previewAutoRefresh) {
         
     | 
| 
      
 1439 
     | 
    
         
            +
                      preview();
         
     | 
| 
      
 1440 
     | 
    
         
            +
                    }
         
     | 
| 
      
 1441 
     | 
    
         
            +
             
     | 
| 
      
 1442 
     | 
    
         
            +
            				// remember the last focus
         
     | 
| 
      
 1443 
     | 
    
         
            +
            				$$.focus(function() {
         
     | 
| 
      
 1444 
     | 
    
         
            +
            					$.markItUp.focused = this;
         
     | 
| 
      
 1445 
     | 
    
         
            +
            				});
         
     | 
| 
      
 1446 
     | 
    
         
            +
            			}
         
     | 
| 
      
 1447 
     | 
    
         
            +
             
     | 
| 
      
 1448 
     | 
    
         
            +
            			// recursively build header with dropMenus from markupset
         
     | 
| 
      
 1449 
     | 
    
         
            +
            			function dropMenus(markupSet) {
         
     | 
| 
      
 1450 
     | 
    
         
            +
            				var ul = $('<ul></ul>'), i = 0;
         
     | 
| 
      
 1451 
     | 
    
         
            +
            				$('li:hover > ul', ul).css('display', 'block');
         
     | 
| 
      
 1452 
     | 
    
         
            +
            				$.each(markupSet, function() {
         
     | 
| 
      
 1453 
     | 
    
         
            +
            					var button = this, t = '', title, li, j;
         
     | 
| 
      
 1454 
     | 
    
         
            +
            					title = (button.key) ? (button.name||'')+' [Ctrl+'+button.key+']' : (button.name||'');
         
     | 
| 
      
 1455 
     | 
    
         
            +
            					key   = (button.key) ? 'accesskey="'+button.key+'"' : '';
         
     | 
| 
      
 1456 
     | 
    
         
            +
            					if (button.separator) {
         
     | 
| 
      
 1457 
     | 
    
         
            +
            						li = $('<li class="markItUpSeparator">'+(button.separator||'')+'</li>').appendTo(ul);
         
     | 
| 
      
 1458 
     | 
    
         
            +
            					} else {
         
     | 
| 
      
 1459 
     | 
    
         
            +
            						i++;
         
     | 
| 
      
 1460 
     | 
    
         
            +
            						for (j = levels.length -1; j >= 0; j--) {
         
     | 
| 
      
 1461 
     | 
    
         
            +
            							t += levels[j]+"-";
         
     | 
| 
      
 1462 
     | 
    
         
            +
            						}
         
     | 
| 
      
 1463 
     | 
    
         
            +
            						li = $('<li class="markItUpButton markItUpButton'+t+(i)+' '+(button.className||'')+'"><a href="" '+key+' title="'+title+'">'+(button.name||'')+'</a></li>')
         
     | 
| 
      
 1464 
     | 
    
         
            +
            						.bind("contextmenu", function() { // prevent contextmenu on mac and allow ctrl+click
         
     | 
| 
      
 1465 
     | 
    
         
            +
            							return false;
         
     | 
| 
      
 1466 
     | 
    
         
            +
            						}).click(function() {
         
     | 
| 
      
 1467 
     | 
    
         
            +
            							return false;
         
     | 
| 
      
 1468 
     | 
    
         
            +
            						}).bind("focusin", function(){
         
     | 
| 
      
 1469 
     | 
    
         
            +
                                        $$.focus();
         
     | 
| 
      
 1470 
     | 
    
         
            +
            						}).mousedown(function() {
         
     | 
| 
      
 1471 
     | 
    
         
            +
            							if (button.call) {
         
     | 
| 
      
 1472 
     | 
    
         
            +
            								eval(button.call)();
         
     | 
| 
      
 1473 
     | 
    
         
            +
            							}
         
     | 
| 
      
 1474 
     | 
    
         
            +
            							setTimeout(function() { markup(button) },1);
         
     | 
| 
      
 1475 
     | 
    
         
            +
            							return false;
         
     | 
| 
      
 1476 
     | 
    
         
            +
            						}).hover(function() {
         
     | 
| 
      
 1477 
     | 
    
         
            +
            								$('> ul', this).show();
         
     | 
| 
      
 1478 
     | 
    
         
            +
            								$(document).one('click', function() { // close dropmenu if click outside
         
     | 
| 
      
 1479 
     | 
    
         
            +
            										$('ul ul', header).hide();
         
     | 
| 
      
 1480 
     | 
    
         
            +
            									}
         
     | 
| 
      
 1481 
     | 
    
         
            +
            								);
         
     | 
| 
      
 1482 
     | 
    
         
            +
            							}, function() {
         
     | 
| 
      
 1483 
     | 
    
         
            +
            								$('> ul', this).hide();
         
     | 
| 
      
 1484 
     | 
    
         
            +
            							}
         
     | 
| 
      
 1485 
     | 
    
         
            +
            						).appendTo(ul);
         
     | 
| 
      
 1486 
     | 
    
         
            +
            						if (button.dropMenu) {
         
     | 
| 
      
 1487 
     | 
    
         
            +
            							levels.push(i);
         
     | 
| 
      
 1488 
     | 
    
         
            +
            							$(li).addClass('markItUpDropMenu').append(dropMenus(button.dropMenu));
         
     | 
| 
      
 1489 
     | 
    
         
            +
            						}
         
     | 
| 
      
 1490 
     | 
    
         
            +
            					}
         
     | 
| 
      
 1491 
     | 
    
         
            +
            				}); 
         
     | 
| 
      
 1492 
     | 
    
         
            +
            				levels.pop();
         
     | 
| 
      
 1493 
     | 
    
         
            +
            				return ul;
         
     | 
| 
      
 1494 
     | 
    
         
            +
            			}
         
     | 
| 
      
 1495 
     | 
    
         
            +
             
     | 
| 
      
 1496 
     | 
    
         
            +
            			// markItUp! markups
         
     | 
| 
      
 1497 
     | 
    
         
            +
            			function magicMarkups(string) {
         
     | 
| 
      
 1498 
     | 
    
         
            +
            				if (string) {
         
     | 
| 
      
 1499 
     | 
    
         
            +
            					string = string.toString();
         
     | 
| 
      
 1500 
     | 
    
         
            +
            					string = string.replace(/\(\!\(([\s\S]*?)\)\!\)/g,
         
     | 
| 
      
 1501 
     | 
    
         
            +
            						function(x, a) {
         
     | 
| 
      
 1502 
     | 
    
         
            +
            							var b = a.split('|!|');
         
     | 
| 
      
 1503 
     | 
    
         
            +
            							if (altKey === true) {
         
     | 
| 
      
 1504 
     | 
    
         
            +
            								return (b[1] !== undefined) ? b[1] : b[0];
         
     | 
| 
      
 1505 
     | 
    
         
            +
            							} else {
         
     | 
| 
      
 1506 
     | 
    
         
            +
            								return (b[1] === undefined) ? "" : b[0];
         
     | 
| 
      
 1507 
     | 
    
         
            +
            							}
         
     | 
| 
      
 1508 
     | 
    
         
            +
            						}
         
     | 
| 
      
 1509 
     | 
    
         
            +
            					);
         
     | 
| 
      
 1510 
     | 
    
         
            +
            					// [![prompt]!], [![prompt:!:value]!]
         
     | 
| 
      
 1511 
     | 
    
         
            +
            					string = string.replace(/\[\!\[([\s\S]*?)\]\!\]/g,
         
     | 
| 
      
 1512 
     | 
    
         
            +
            						function(x, a) {
         
     | 
| 
      
 1513 
     | 
    
         
            +
            							var b = a.split(':!:');
         
     | 
| 
      
 1514 
     | 
    
         
            +
            							if (abort === true) {
         
     | 
| 
      
 1515 
     | 
    
         
            +
            								return false;
         
     | 
| 
      
 1516 
     | 
    
         
            +
            							}
         
     | 
| 
      
 1517 
     | 
    
         
            +
            							value = prompt(b[0], (b[1]) ? b[1] : '');
         
     | 
| 
      
 1518 
     | 
    
         
            +
            							if (value === null) {
         
     | 
| 
      
 1519 
     | 
    
         
            +
            								abort = true;
         
     | 
| 
      
 1520 
     | 
    
         
            +
            							}
         
     | 
| 
      
 1521 
     | 
    
         
            +
            							return value;
         
     | 
| 
      
 1522 
     | 
    
         
            +
            						}
         
     | 
| 
      
 1523 
     | 
    
         
            +
            					);
         
     | 
| 
      
 1524 
     | 
    
         
            +
            					return string;
         
     | 
| 
      
 1525 
     | 
    
         
            +
            				}
         
     | 
| 
      
 1526 
     | 
    
         
            +
            				return "";
         
     | 
| 
      
 1527 
     | 
    
         
            +
            			}
         
     | 
| 
      
 1528 
     | 
    
         
            +
             
     | 
| 
      
 1529 
     | 
    
         
            +
            			// prepare action
         
     | 
| 
      
 1530 
     | 
    
         
            +
            			function prepare(action) {
         
     | 
| 
      
 1531 
     | 
    
         
            +
            				if ($.isFunction(action)) {
         
     | 
| 
      
 1532 
     | 
    
         
            +
            					action = action(hash);
         
     | 
| 
      
 1533 
     | 
    
         
            +
            				}
         
     | 
| 
      
 1534 
     | 
    
         
            +
            				return magicMarkups(action);
         
     | 
| 
      
 1535 
     | 
    
         
            +
            			}
         
     | 
| 
      
 1536 
     | 
    
         
            +
             
     | 
| 
      
 1537 
     | 
    
         
            +
            			// build block to insert
         
     | 
| 
      
 1538 
     | 
    
         
            +
            			function build(string) {
         
     | 
| 
      
 1539 
     | 
    
         
            +
            				openWith 	= prepare(clicked.openWith);
         
     | 
| 
      
 1540 
     | 
    
         
            +
            				placeHolder = prepare(clicked.placeHolder);
         
     | 
| 
      
 1541 
     | 
    
         
            +
            				replaceWith = prepare(clicked.replaceWith);
         
     | 
| 
      
 1542 
     | 
    
         
            +
            				closeWith 	= prepare(clicked.closeWith);
         
     | 
| 
      
 1543 
     | 
    
         
            +
            				if (replaceWith !== "") {
         
     | 
| 
      
 1544 
     | 
    
         
            +
            					block = openWith + replaceWith + closeWith;
         
     | 
| 
      
 1545 
     | 
    
         
            +
            				} else if (selection === '' && placeHolder !== '') {
         
     | 
| 
      
 1546 
     | 
    
         
            +
            					block = openWith + placeHolder + closeWith;
         
     | 
| 
      
 1547 
     | 
    
         
            +
            				} else {
         
     | 
| 
      
 1548 
     | 
    
         
            +
            					block = openWith + (string||selection) + closeWith;
         
     | 
| 
      
 1549 
     | 
    
         
            +
            				}
         
     | 
| 
      
 1550 
     | 
    
         
            +
            				return {	block:block, 
         
     | 
| 
      
 1551 
     | 
    
         
            +
            							openWith:openWith, 
         
     | 
| 
      
 1552 
     | 
    
         
            +
            							replaceWith:replaceWith, 
         
     | 
| 
      
 1553 
     | 
    
         
            +
            							placeHolder:placeHolder,
         
     | 
| 
      
 1554 
     | 
    
         
            +
            							closeWith:closeWith
         
     | 
| 
      
 1555 
     | 
    
         
            +
            					};
         
     | 
| 
      
 1556 
     | 
    
         
            +
            			}
         
     | 
| 
      
 1557 
     | 
    
         
            +
             
     | 
| 
      
 1558 
     | 
    
         
            +
            			// define markup to insert
         
     | 
| 
      
 1559 
     | 
    
         
            +
            			function markup(button) {
         
     | 
| 
      
 1560 
     | 
    
         
            +
            				var len, j, n, i;
         
     | 
| 
      
 1561 
     | 
    
         
            +
            				hash = clicked = button;
         
     | 
| 
      
 1562 
     | 
    
         
            +
            				get();
         
     | 
| 
      
 1563 
     | 
    
         
            +
             
     | 
| 
      
 1564 
     | 
    
         
            +
            				$.extend(hash, {	line:"", 
         
     | 
| 
      
 1565 
     | 
    
         
            +
            						 			root:options.root,
         
     | 
| 
      
 1566 
     | 
    
         
            +
            									textarea:textarea, 
         
     | 
| 
      
 1567 
     | 
    
         
            +
            									selection:(selection||''), 
         
     | 
| 
      
 1568 
     | 
    
         
            +
            									caretPosition:caretPosition,
         
     | 
| 
      
 1569 
     | 
    
         
            +
            									ctrlKey:ctrlKey, 
         
     | 
| 
      
 1570 
     | 
    
         
            +
            									shiftKey:shiftKey, 
         
     | 
| 
      
 1571 
     | 
    
         
            +
            									altKey:altKey
         
     | 
| 
      
 1572 
     | 
    
         
            +
            								}
         
     | 
| 
      
 1573 
     | 
    
         
            +
            							);
         
     | 
| 
      
 1574 
     | 
    
         
            +
            				// callbacks before insertion
         
     | 
| 
      
 1575 
     | 
    
         
            +
            				prepare(options.beforeInsert);
         
     | 
| 
      
 1576 
     | 
    
         
            +
            				prepare(clicked.beforeInsert);
         
     | 
| 
      
 1577 
     | 
    
         
            +
            				if (ctrlKey === true && shiftKey === true) {
         
     | 
| 
      
 1578 
     | 
    
         
            +
            					prepare(clicked.beforeMultiInsert);
         
     | 
| 
      
 1579 
     | 
    
         
            +
            				}			
         
     | 
| 
      
 1580 
     | 
    
         
            +
            				$.extend(hash, { line:1 });
         
     | 
| 
      
 1581 
     | 
    
         
            +
            				
         
     | 
| 
      
 1582 
     | 
    
         
            +
            				if (ctrlKey === true && shiftKey === true) {
         
     | 
| 
      
 1583 
     | 
    
         
            +
            					lines = selection.split(/\r?\n/);
         
     | 
| 
      
 1584 
     | 
    
         
            +
            					for (j = 0, n = lines.length, i = 0; i < n; i++) {
         
     | 
| 
      
 1585 
     | 
    
         
            +
            						if ($.trim(lines[i]) !== '') {
         
     | 
| 
      
 1586 
     | 
    
         
            +
            							$.extend(hash, { line:++j, selection:lines[i] } );
         
     | 
| 
      
 1587 
     | 
    
         
            +
            							lines[i] = build(lines[i]).block;
         
     | 
| 
      
 1588 
     | 
    
         
            +
            						} else {
         
     | 
| 
      
 1589 
     | 
    
         
            +
            							lines[i] = "";
         
     | 
| 
      
 1590 
     | 
    
         
            +
            						}
         
     | 
| 
      
 1591 
     | 
    
         
            +
            					}
         
     | 
| 
      
 1592 
     | 
    
         
            +
            					string = { block:lines.join('\n')};
         
     | 
| 
      
 1593 
     | 
    
         
            +
            					start = caretPosition;
         
     | 
| 
      
 1594 
     | 
    
         
            +
            					len = string.block.length + (($.browser.opera) ? n-1 : 0);
         
     | 
| 
      
 1595 
     | 
    
         
            +
            				} else if (ctrlKey === true) {
         
     | 
| 
      
 1596 
     | 
    
         
            +
            					string = build(selection);
         
     | 
| 
      
 1597 
     | 
    
         
            +
            					start = caretPosition + string.openWith.length;
         
     | 
| 
      
 1598 
     | 
    
         
            +
            					len = string.block.length - string.openWith.length - string.closeWith.length;
         
     | 
| 
      
 1599 
     | 
    
         
            +
            					len -= fixIeBug(string.block);
         
     | 
| 
      
 1600 
     | 
    
         
            +
            				} else if (shiftKey === true) {
         
     | 
| 
      
 1601 
     | 
    
         
            +
            					string = build(selection);
         
     | 
| 
      
 1602 
     | 
    
         
            +
            					start = caretPosition;
         
     | 
| 
      
 1603 
     | 
    
         
            +
            					len = string.block.length;
         
     | 
| 
      
 1604 
     | 
    
         
            +
            					len -= fixIeBug(string.block);
         
     | 
| 
      
 1605 
     | 
    
         
            +
            				} else {
         
     | 
| 
      
 1606 
     | 
    
         
            +
            					string = build(selection);
         
     | 
| 
      
 1607 
     | 
    
         
            +
            					start = caretPosition + string.block.length ;
         
     | 
| 
      
 1608 
     | 
    
         
            +
            					len = 0;
         
     | 
| 
      
 1609 
     | 
    
         
            +
            					start -= fixIeBug(string.block);
         
     | 
| 
      
 1610 
     | 
    
         
            +
            				}
         
     | 
| 
      
 1611 
     | 
    
         
            +
            				if ((selection === '' && string.replaceWith === '')) {
         
     | 
| 
      
 1612 
     | 
    
         
            +
            					caretOffset += fixOperaBug(string.block);
         
     | 
| 
      
 1613 
     | 
    
         
            +
            					
         
     | 
| 
      
 1614 
     | 
    
         
            +
            					start = caretPosition + string.openWith.length;
         
     | 
| 
      
 1615 
     | 
    
         
            +
            					len = string.block.length - string.openWith.length - string.closeWith.length;
         
     | 
| 
      
 1616 
     | 
    
         
            +
             
     | 
| 
      
 1617 
     | 
    
         
            +
            					caretOffset = $$.val().substring(caretPosition,  $$.val().length).length;
         
     | 
| 
      
 1618 
     | 
    
         
            +
            					caretOffset -= fixOperaBug($$.val().substring(0, caretPosition));
         
     | 
| 
      
 1619 
     | 
    
         
            +
            				}
         
     | 
| 
      
 1620 
     | 
    
         
            +
            				$.extend(hash, { caretPosition:caretPosition, scrollPosition:scrollPosition } );
         
     | 
| 
      
 1621 
     | 
    
         
            +
             
     | 
| 
      
 1622 
     | 
    
         
            +
            				if (string.block !== selection && abort === false) {
         
     | 
| 
      
 1623 
     | 
    
         
            +
            					insert(string.block);
         
     | 
| 
      
 1624 
     | 
    
         
            +
            					set(start, len);
         
     | 
| 
      
 1625 
     | 
    
         
            +
            				} else {
         
     | 
| 
      
 1626 
     | 
    
         
            +
            					caretOffset = -1;
         
     | 
| 
      
 1627 
     | 
    
         
            +
            				}
         
     | 
| 
      
 1628 
     | 
    
         
            +
            				get();
         
     | 
| 
      
 1629 
     | 
    
         
            +
             
     | 
| 
      
 1630 
     | 
    
         
            +
            				$.extend(hash, { line:'', selection:selection });
         
     | 
| 
      
 1631 
     | 
    
         
            +
             
     | 
| 
      
 1632 
     | 
    
         
            +
            				// callbacks after insertion
         
     | 
| 
      
 1633 
     | 
    
         
            +
            				if (ctrlKey === true && shiftKey === true) {
         
     | 
| 
      
 1634 
     | 
    
         
            +
            					prepare(clicked.afterMultiInsert);
         
     | 
| 
      
 1635 
     | 
    
         
            +
            				}
         
     | 
| 
      
 1636 
     | 
    
         
            +
            				prepare(clicked.afterInsert);
         
     | 
| 
      
 1637 
     | 
    
         
            +
            				prepare(options.afterInsert);
         
     | 
| 
      
 1638 
     | 
    
         
            +
             
     | 
| 
      
 1639 
     | 
    
         
            +
            				// refresh preview if opened
         
     | 
| 
      
 1640 
     | 
    
         
            +
            				if (previewDiv && options.previewAutoRefresh) {
         
     | 
| 
      
 1641 
     | 
    
         
            +
            					refreshPreview(); 
         
     | 
| 
      
 1642 
     | 
    
         
            +
            				}
         
     | 
| 
      
 1643 
     | 
    
         
            +
            																									
         
     | 
| 
      
 1644 
     | 
    
         
            +
            				// reinit keyevent
         
     | 
| 
      
 1645 
     | 
    
         
            +
            				shiftKey = altKey = ctrlKey = abort = false;
         
     | 
| 
      
 1646 
     | 
    
         
            +
            			}
         
     | 
| 
      
 1647 
     | 
    
         
            +
             
     | 
| 
      
 1648 
     | 
    
         
            +
            			// Substract linefeed in Opera
         
     | 
| 
      
 1649 
     | 
    
         
            +
            			function fixOperaBug(string) {
         
     | 
| 
      
 1650 
     | 
    
         
            +
            				if ($.browser.opera) {
         
     | 
| 
      
 1651 
     | 
    
         
            +
            					return string.length - string.replace(/\n*/g, '').length;
         
     | 
| 
      
 1652 
     | 
    
         
            +
            				}
         
     | 
| 
      
 1653 
     | 
    
         
            +
            				return 0;
         
     | 
| 
      
 1654 
     | 
    
         
            +
            			}
         
     | 
| 
      
 1655 
     | 
    
         
            +
            			// Substract linefeed in IE
         
     | 
| 
      
 1656 
     | 
    
         
            +
            			function fixIeBug(string) {
         
     | 
| 
      
 1657 
     | 
    
         
            +
            				if ($.browser.msie) {
         
     | 
| 
      
 1658 
     | 
    
         
            +
            					return string.length - string.replace(/\r/g, '').length;
         
     | 
| 
      
 1659 
     | 
    
         
            +
            				}
         
     | 
| 
      
 1660 
     | 
    
         
            +
            				return 0;
         
     | 
| 
      
 1661 
     | 
    
         
            +
            			}
         
     | 
| 
      
 1662 
     | 
    
         
            +
            				
         
     | 
| 
      
 1663 
     | 
    
         
            +
            			// add markup
         
     | 
| 
      
 1664 
     | 
    
         
            +
            			function insert(block) {	
         
     | 
| 
      
 1665 
     | 
    
         
            +
            				if (document.selection) {
         
     | 
| 
      
 1666 
     | 
    
         
            +
            					var newSelection = document.selection.createRange();
         
     | 
| 
      
 1667 
     | 
    
         
            +
            					newSelection.text = block;
         
     | 
| 
      
 1668 
     | 
    
         
            +
            				} else {
         
     | 
| 
      
 1669 
     | 
    
         
            +
            					textarea.value =  textarea.value.substring(0, caretPosition)  + block + textarea.value.substring(caretPosition + selection.length, textarea.value.length);
         
     | 
| 
      
 1670 
     | 
    
         
            +
            				}
         
     | 
| 
      
 1671 
     | 
    
         
            +
            			}
         
     | 
| 
      
 1672 
     | 
    
         
            +
             
     | 
| 
      
 1673 
     | 
    
         
            +
            			// set a selection
         
     | 
| 
      
 1674 
     | 
    
         
            +
            			function set(start, len) {
         
     | 
| 
      
 1675 
     | 
    
         
            +
            				if (textarea.createTextRange){
         
     | 
| 
      
 1676 
     | 
    
         
            +
            					// quick fix to make it work on Opera 9.5
         
     | 
| 
      
 1677 
     | 
    
         
            +
            					if ($.browser.opera && $.browser.version >= 9.5 && len == 0) {
         
     | 
| 
      
 1678 
     | 
    
         
            +
            						return false;
         
     | 
| 
      
 1679 
     | 
    
         
            +
            					}
         
     | 
| 
      
 1680 
     | 
    
         
            +
            					range = textarea.createTextRange();
         
     | 
| 
      
 1681 
     | 
    
         
            +
            					range.collapse(true);
         
     | 
| 
      
 1682 
     | 
    
         
            +
            					range.moveStart('character', start); 
         
     | 
| 
      
 1683 
     | 
    
         
            +
            					range.moveEnd('character', len); 
         
     | 
| 
      
 1684 
     | 
    
         
            +
            					range.select();
         
     | 
| 
      
 1685 
     | 
    
         
            +
            				} else if (textarea.setSelectionRange ){
         
     | 
| 
      
 1686 
     | 
    
         
            +
            					textarea.setSelectionRange(start, start + len);
         
     | 
| 
      
 1687 
     | 
    
         
            +
            				}
         
     | 
| 
      
 1688 
     | 
    
         
            +
            				textarea.scrollTop = scrollPosition;
         
     | 
| 
      
 1689 
     | 
    
         
            +
            				textarea.focus();
         
     | 
| 
      
 1690 
     | 
    
         
            +
            			}
         
     | 
| 
      
 1691 
     | 
    
         
            +
             
     | 
| 
      
 1692 
     | 
    
         
            +
            			// get the selection
         
     | 
| 
      
 1693 
     | 
    
         
            +
            			function get() {
         
     | 
| 
      
 1694 
     | 
    
         
            +
            				textarea.focus();
         
     | 
| 
      
 1695 
     | 
    
         
            +
             
     | 
| 
      
 1696 
     | 
    
         
            +
            				scrollPosition = textarea.scrollTop;
         
     | 
| 
      
 1697 
     | 
    
         
            +
            				if (document.selection) {
         
     | 
| 
      
 1698 
     | 
    
         
            +
            					selection = document.selection;	
         
     | 
| 
      
 1699 
     | 
    
         
            +
            					if ($.browser.msie) { // ie	
         
     | 
| 
      
 1700 
     | 
    
         
            +
            						var range = selection.createRange();
         
     | 
| 
      
 1701 
     | 
    
         
            +
            						var stored_range = range.duplicate();
         
     | 
| 
      
 1702 
     | 
    
         
            +
            						stored_range.moveToElementText(textarea);
         
     | 
| 
      
 1703 
     | 
    
         
            +
            						stored_range.setEndPoint('EndToEnd', range);
         
     | 
| 
      
 1704 
     | 
    
         
            +
            						var s = stored_range.text.length - range.text.length;
         
     | 
| 
      
 1705 
     | 
    
         
            +
            	
         
     | 
| 
      
 1706 
     | 
    
         
            +
            						caretPosition = s - (textarea.value.substr(0, s).length - textarea.value.substr(0, s).replace(/\r/g, '').length);
         
     | 
| 
      
 1707 
     | 
    
         
            +
            						selection = range.text;
         
     | 
| 
      
 1708 
     | 
    
         
            +
            					} else { // opera
         
     | 
| 
      
 1709 
     | 
    
         
            +
            						caretPosition = textarea.selectionStart;
         
     | 
| 
      
 1710 
     | 
    
         
            +
            					}
         
     | 
| 
      
 1711 
     | 
    
         
            +
            				} else { // gecko & webkit
         
     | 
| 
      
 1712 
     | 
    
         
            +
            					caretPosition = textarea.selectionStart;
         
     | 
| 
      
 1713 
     | 
    
         
            +
            					selection = textarea.value.substring(caretPosition, textarea.selectionEnd);
         
     | 
| 
      
 1714 
     | 
    
         
            +
            				} 
         
     | 
| 
      
 1715 
     | 
    
         
            +
            				return selection;
         
     | 
| 
      
 1716 
     | 
    
         
            +
            			}
         
     | 
| 
      
 1717 
     | 
    
         
            +
             
     | 
| 
      
 1718 
     | 
    
         
            +
            			// open preview window
         
     | 
| 
      
 1719 
     | 
    
         
            +
            			function preview() {
         
     | 
| 
      
 1720 
     | 
    
         
            +
            				if (!previewDiv) {
         
     | 
| 
      
 1721 
     | 
    
         
            +
                      previewDiv = $('<div class="markItUpPreview"></div>');
         
     | 
| 
      
 1722 
     | 
    
         
            +
             
     | 
| 
      
 1723 
     | 
    
         
            +
                      if (options.previewPosition == 'after') {
         
     | 
| 
      
 1724 
     | 
    
         
            +
                        previewDiv.insertAfter(footer);
         
     | 
| 
      
 1725 
     | 
    
         
            +
                      } else {
         
     | 
| 
      
 1726 
     | 
    
         
            +
                        previewDiv.insertBefore(header);
         
     | 
| 
      
 1727 
     | 
    
         
            +
                      }	
         
     | 
| 
      
 1728 
     | 
    
         
            +
            				} else if (altKey === true) {
         
     | 
| 
      
 1729 
     | 
    
         
            +
            					if (previewDiv) {
         
     | 
| 
      
 1730 
     | 
    
         
            +
            						previewDiv.remove();
         
     | 
| 
      
 1731 
     | 
    
         
            +
            					} 
         
     | 
| 
      
 1732 
     | 
    
         
            +
            					previewDiv = false;
         
     | 
| 
      
 1733 
     | 
    
         
            +
            				}
         
     | 
| 
      
 1734 
     | 
    
         
            +
                    refreshPreview(); 
         
     | 
| 
      
 1735 
     | 
    
         
            +
            			}
         
     | 
| 
      
 1736 
     | 
    
         
            +
             
     | 
| 
      
 1737 
     | 
    
         
            +
            			// refresh Preview window
         
     | 
| 
      
 1738 
     | 
    
         
            +
            			function refreshPreview() {
         
     | 
| 
      
 1739 
     | 
    
         
            +
             				renderPreview();
         
     | 
| 
      
 1740 
     | 
    
         
            +
            			}
         
     | 
| 
      
 1741 
     | 
    
         
            +
             
     | 
| 
      
 1742 
     | 
    
         
            +
            			function renderPreview() {		
         
     | 
| 
      
 1743 
     | 
    
         
            +
                    previewDiv.html(converter.makeHtml($$.val()));
         
     | 
| 
      
 1744 
     | 
    
         
            +
             
     | 
| 
      
 1745 
     | 
    
         
            +
            				return false;
         
     | 
| 
      
 1746 
     | 
    
         
            +
            			}
         
     | 
| 
      
 1747 
     | 
    
         
            +
            			
         
     | 
| 
      
 1748 
     | 
    
         
            +
            			// set keys pressed
         
     | 
| 
      
 1749 
     | 
    
         
            +
            			function keyPressed(e) { 
         
     | 
| 
      
 1750 
     | 
    
         
            +
            				shiftKey = e.shiftKey;
         
     | 
| 
      
 1751 
     | 
    
         
            +
            				altKey = e.altKey;
         
     | 
| 
      
 1752 
     | 
    
         
            +
            				ctrlKey = (!(e.altKey && e.ctrlKey)) ? e.ctrlKey : false;
         
     | 
| 
      
 1753 
     | 
    
         
            +
             
     | 
| 
      
 1754 
     | 
    
         
            +
            				if (e.type === 'keydown') {
         
     | 
| 
      
 1755 
     | 
    
         
            +
            					if (ctrlKey === true) {
         
     | 
| 
      
 1756 
     | 
    
         
            +
            						li = $("a[accesskey="+String.fromCharCode(e.keyCode)+"]", header).parent('li');
         
     | 
| 
      
 1757 
     | 
    
         
            +
            						if (li.length !== 0) {
         
     | 
| 
      
 1758 
     | 
    
         
            +
            							ctrlKey = false;
         
     | 
| 
      
 1759 
     | 
    
         
            +
            							setTimeout(function() {
         
     | 
| 
      
 1760 
     | 
    
         
            +
            								li.triggerHandler('mousedown');
         
     | 
| 
      
 1761 
     | 
    
         
            +
            							},1);
         
     | 
| 
      
 1762 
     | 
    
         
            +
            							return false;
         
     | 
| 
      
 1763 
     | 
    
         
            +
            						}
         
     | 
| 
      
 1764 
     | 
    
         
            +
            					}
         
     | 
| 
      
 1765 
     | 
    
         
            +
            					if (e.keyCode === 13 || e.keyCode === 10) { // Enter key
         
     | 
| 
      
 1766 
     | 
    
         
            +
            						if (ctrlKey === true) {  // Enter + Ctrl
         
     | 
| 
      
 1767 
     | 
    
         
            +
            							ctrlKey = false;
         
     | 
| 
      
 1768 
     | 
    
         
            +
            							markup(options.onCtrlEnter);
         
     | 
| 
      
 1769 
     | 
    
         
            +
            							return options.onCtrlEnter.keepDefault;
         
     | 
| 
      
 1770 
     | 
    
         
            +
            						} else if (shiftKey === true) { // Enter + Shift
         
     | 
| 
      
 1771 
     | 
    
         
            +
            							shiftKey = false;
         
     | 
| 
      
 1772 
     | 
    
         
            +
            							markup(options.onShiftEnter);
         
     | 
| 
      
 1773 
     | 
    
         
            +
            							return options.onShiftEnter.keepDefault;
         
     | 
| 
      
 1774 
     | 
    
         
            +
            						} else { // only Enter
         
     | 
| 
      
 1775 
     | 
    
         
            +
            							markup(options.onEnter);
         
     | 
| 
      
 1776 
     | 
    
         
            +
            							return options.onEnter.keepDefault;
         
     | 
| 
      
 1777 
     | 
    
         
            +
            						}
         
     | 
| 
      
 1778 
     | 
    
         
            +
            					}
         
     | 
| 
      
 1779 
     | 
    
         
            +
            					if (e.keyCode === 9) { // Tab key
         
     | 
| 
      
 1780 
     | 
    
         
            +
            						if (shiftKey == true || ctrlKey == true || altKey == true) {
         
     | 
| 
      
 1781 
     | 
    
         
            +
            							return false; 
         
     | 
| 
      
 1782 
     | 
    
         
            +
            						}
         
     | 
| 
      
 1783 
     | 
    
         
            +
            						if (caretOffset !== -1) {
         
     | 
| 
      
 1784 
     | 
    
         
            +
            							get();
         
     | 
| 
      
 1785 
     | 
    
         
            +
            							caretOffset = $$.val().length - caretOffset;
         
     | 
| 
      
 1786 
     | 
    
         
            +
            							set(caretOffset, 0);
         
     | 
| 
      
 1787 
     | 
    
         
            +
            							caretOffset = -1;
         
     | 
| 
      
 1788 
     | 
    
         
            +
            							return false;
         
     | 
| 
      
 1789 
     | 
    
         
            +
            						} else {
         
     | 
| 
      
 1790 
     | 
    
         
            +
            							markup(options.onTab);
         
     | 
| 
      
 1791 
     | 
    
         
            +
            							return options.onTab.keepDefault;
         
     | 
| 
      
 1792 
     | 
    
         
            +
            						}
         
     | 
| 
      
 1793 
     | 
    
         
            +
            					}
         
     | 
| 
      
 1794 
     | 
    
         
            +
            				}
         
     | 
| 
      
 1795 
     | 
    
         
            +
                    refreshPreview();
         
     | 
| 
      
 1796 
     | 
    
         
            +
            			}
         
     | 
| 
      
 1797 
     | 
    
         
            +
             
     | 
| 
      
 1798 
     | 
    
         
            +
            			init();
         
     | 
| 
      
 1799 
     | 
    
         
            +
            		});
         
     | 
| 
      
 1800 
     | 
    
         
            +
            	};
         
     | 
| 
      
 1801 
     | 
    
         
            +
             
     | 
| 
      
 1802 
     | 
    
         
            +
            	$.fn.markItUpRemove = function() {
         
     | 
| 
      
 1803 
     | 
    
         
            +
            		return this.each(function() {
         
     | 
| 
      
 1804 
     | 
    
         
            +
            				var $$ = $(this).unbind().removeClass('markItUpEditor');
         
     | 
| 
      
 1805 
     | 
    
         
            +
            				$$.parent('div').parent('div.markItUp').parent('div').replaceWith($$);
         
     | 
| 
      
 1806 
     | 
    
         
            +
            			}
         
     | 
| 
      
 1807 
     | 
    
         
            +
            		);
         
     | 
| 
      
 1808 
     | 
    
         
            +
            	};
         
     | 
| 
      
 1809 
     | 
    
         
            +
             
     | 
| 
      
 1810 
     | 
    
         
            +
            	$.markItUp = function(settings) {
         
     | 
| 
      
 1811 
     | 
    
         
            +
            		var options = { target:false };
         
     | 
| 
      
 1812 
     | 
    
         
            +
            		$.extend(options, settings);
         
     | 
| 
      
 1813 
     | 
    
         
            +
            		if (options.target) {
         
     | 
| 
      
 1814 
     | 
    
         
            +
            			return $(options.target).each(function() {
         
     | 
| 
      
 1815 
     | 
    
         
            +
            				$(this).focus();
         
     | 
| 
      
 1816 
     | 
    
         
            +
            				$(this).trigger('insertion', [options]);
         
     | 
| 
      
 1817 
     | 
    
         
            +
            			});
         
     | 
| 
      
 1818 
     | 
    
         
            +
            		} else {
         
     | 
| 
      
 1819 
     | 
    
         
            +
            			$('textarea').trigger('insertion', [options]);
         
     | 
| 
      
 1820 
     | 
    
         
            +
            		}
         
     | 
| 
      
 1821 
     | 
    
         
            +
            	};
         
     | 
| 
      
 1822 
     | 
    
         
            +
             
     | 
| 
      
 1823 
     | 
    
         
            +
             
     | 
| 
      
 1824 
     | 
    
         
            +
            $.fn.markdownEditor = function(settings) {
         
     | 
| 
      
 1825 
     | 
    
         
            +
              var options = {
         
     | 
| 
      
 1826 
     | 
    
         
            +
                headings: [1,2,3,4,5,6],
         
     | 
| 
      
 1827 
     | 
    
         
            +
                allowPictures: true,
         
     | 
| 
      
 1828 
     | 
    
         
            +
                pictures: []
         
     | 
| 
      
 1829 
     | 
    
         
            +
              };
         
     | 
| 
      
 1830 
     | 
    
         
            +
              $.extend(options, settings);
         
     | 
| 
      
 1831 
     | 
    
         
            +
             
     | 
| 
      
 1832 
     | 
    
         
            +
              var markups = []
         
     | 
| 
      
 1833 
     | 
    
         
            +
             
     | 
| 
      
 1834 
     | 
    
         
            +
              if (options.headings.indexOf(1) > -1) {
         
     | 
| 
      
 1835 
     | 
    
         
            +
                markups.push({name:'Heading 1', key:"1", className: 'heading1', placeHolder:'Your title here...', closeWith:function(markItUp) { return miu.markdownTitle(markItUp, '=') } });
         
     | 
| 
      
 1836 
     | 
    
         
            +
              }
         
     | 
| 
      
 1837 
     | 
    
         
            +
              if (options.headings.indexOf(2) > -1) {
         
     | 
| 
      
 1838 
     | 
    
         
            +
                markups.push({name:'Heading 2', key:"2", className: 'heading2', placeHolder:'Your title here...', closeWith:function(markItUp) { return miu.markdownTitle(markItUp, '-') } });
         
     | 
| 
      
 1839 
     | 
    
         
            +
              }
         
     | 
| 
      
 1840 
     | 
    
         
            +
              if (options.headings.indexOf(3) > -1) {
         
     | 
| 
      
 1841 
     | 
    
         
            +
                markups.push({name:'Heading 3', key:"3", className: 'heading3', openWith:'### ', placeHolder:'Your title here...' });
         
     | 
| 
      
 1842 
     | 
    
         
            +
              }
         
     | 
| 
      
 1843 
     | 
    
         
            +
              if (options.headings.indexOf(4) > -1) {
         
     | 
| 
      
 1844 
     | 
    
         
            +
                markups.push({name:'Heading 4', key:"4", className: 'heading4', openWith:'#### ', placeHolder:'Your title here...' });
         
     | 
| 
      
 1845 
     | 
    
         
            +
              }
         
     | 
| 
      
 1846 
     | 
    
         
            +
              if (options.headings.indexOf(5) > -1) {
         
     | 
| 
      
 1847 
     | 
    
         
            +
                markups.push({name:'Heading 5', key:"5", className: 'heading5', openWith:'##### ', placeHolder:'Your title here...' });
         
     | 
| 
      
 1848 
     | 
    
         
            +
              }
         
     | 
| 
      
 1849 
     | 
    
         
            +
              if (options.headings.indexOf(6) > -1) {
         
     | 
| 
      
 1850 
     | 
    
         
            +
                markups.push({name:'Heading 6', key:"6", className: 'heading6', openWith:'###### ', placeHolder:'Your title here...' });
         
     | 
| 
      
 1851 
     | 
    
         
            +
              }
         
     | 
| 
      
 1852 
     | 
    
         
            +
              if (options.headings.length > 0 ) {
         
     | 
| 
      
 1853 
     | 
    
         
            +
                markups.push({separator:'---------------' });  
         
     | 
| 
      
 1854 
     | 
    
         
            +
              }
         
     | 
| 
      
 1855 
     | 
    
         
            +
              markups.push({name:'Bold', key:"B", className: 'bold', openWith:'**', closeWith:'**'});
         
     | 
| 
      
 1856 
     | 
    
         
            +
              markups.push({name:'Italic', key:"I", className: 'italic', openWith:'_', closeWith:'_'});
         
     | 
| 
      
 1857 
     | 
    
         
            +
              markups.push({name:'Paragraph', key:"6", className: 'paragraph', openWith:'\n\n', placeHolder:'Your paragraph here...' });
         
     | 
| 
      
 1858 
     | 
    
         
            +
              markups.push({name:'Quotes', className: 'quotes', openWith:'> '});
         
     | 
| 
      
 1859 
     | 
    
         
            +
              markups.push({separator:'---------------' });
         
     | 
| 
      
 1860 
     | 
    
         
            +
              markups.push({name:'Bulleted List', className: 'bullet-list', openWith:'- ' });
         
     | 
| 
      
 1861 
     | 
    
         
            +
              markups.push({name:'Numeric List', className: 'number-list', openWith:function(markItUp) {
         
     | 
| 
      
 1862 
     | 
    
         
            +
                  return markItUp.line+'. ';
         
     | 
| 
      
 1863 
     | 
    
         
            +
              }});
         
     | 
| 
      
 1864 
     | 
    
         
            +
              markups.push({separator:'---------------' });
         
     | 
| 
      
 1865 
     | 
    
         
            +
             
     | 
| 
      
 1866 
     | 
    
         
            +
              if (options.allowPictures) {
         
     | 
| 
      
 1867 
     | 
    
         
            +
                var pictureTab = {name: 'Picture', key: "P", className: 'picture', dropMenu: []};
         
     | 
| 
      
 1868 
     | 
    
         
            +
             
     | 
| 
      
 1869 
     | 
    
         
            +
                $.each(options.pictures, function(_, picture) {
         
     | 
| 
      
 1870 
     | 
    
         
            +
                  console.log(picture.title);
         
     | 
| 
      
 1871 
     | 
    
         
            +
                  pictureTab.dropMenu.push({name: picture.title, replaceWith:''});
         
     | 
| 
      
 1872 
     | 
    
         
            +
                });
         
     | 
| 
      
 1873 
     | 
    
         
            +
                
         
     | 
| 
      
 1874 
     | 
    
         
            +
                pictureTab.dropMenu.push({name: 'External Image URL', replaceWith:'![[![Alternative text]!]]([![Url:!:http://]!] "[![Title]!]")'});
         
     | 
| 
      
 1875 
     | 
    
         
            +
             
     | 
| 
      
 1876 
     | 
    
         
            +
                markups.push(pictureTab);
         
     | 
| 
      
 1877 
     | 
    
         
            +
              }
         
     | 
| 
      
 1878 
     | 
    
         
            +
             
     | 
| 
      
 1879 
     | 
    
         
            +
              markups.push({name:'Link', key:"L", className: 'link', openWith:'[', closeWith:']([![Url:!:http://]!])', placeHolder:'Your text to link here...' });
         
     | 
| 
      
 1880 
     | 
    
         
            +
              markups.push({separator:'---------------'});
         
     | 
| 
      
 1881 
     | 
    
         
            +
              markups.push({name:'Preview', call:'preview', className:"preview"});
         
     | 
| 
      
 1882 
     | 
    
         
            +
             
     | 
| 
      
 1883 
     | 
    
         
            +
              markdownSettings = {
         
     | 
| 
      
 1884 
     | 
    
         
            +
                  nameSpace:          'markdown', // Useful to prevent multi-instances CSS conflict
         
     | 
| 
      
 1885 
     | 
    
         
            +
                  onShiftEnter:       {keepDefault:false, openWith:'\n\n'},
         
     | 
| 
      
 1886 
     | 
    
         
            +
                  markupSet: markups
         
     | 
| 
      
 1887 
     | 
    
         
            +
              }
         
     | 
| 
      
 1888 
     | 
    
         
            +
              // mIu nameSpace to avoid conflict.
         
     | 
| 
      
 1889 
     | 
    
         
            +
              miu = {
         
     | 
| 
      
 1890 
     | 
    
         
            +
                  markdownTitle: function(markItUp, char) {
         
     | 
| 
      
 1891 
     | 
    
         
            +
                      heading = '';
         
     | 
| 
      
 1892 
     | 
    
         
            +
                      n = $.trim(markItUp.selection||markItUp.placeHolder).length;
         
     | 
| 
      
 1893 
     | 
    
         
            +
                      for(i = 0; i < n; i++) {
         
     | 
| 
      
 1894 
     | 
    
         
            +
                          heading += char;
         
     | 
| 
      
 1895 
     | 
    
         
            +
                      }
         
     | 
| 
      
 1896 
     | 
    
         
            +
                      return '\n'+heading+'\n';
         
     | 
| 
      
 1897 
     | 
    
         
            +
                  }
         
     | 
| 
      
 1898 
     | 
    
         
            +
              }
         
     | 
| 
      
 1899 
     | 
    
         
            +
             
     | 
| 
      
 1900 
     | 
    
         
            +
            	$(this).markItUp(markdownSettings);
         
     | 
| 
      
 1901 
     | 
    
         
            +
             
     | 
| 
      
 1902 
     | 
    
         
            +
            };
         
     | 
| 
      
 1903 
     | 
    
         
            +
             
     | 
| 
      
 1904 
     | 
    
         
            +
            })(jQuery);
         
     |