diff --git a/Commands/Generate.plist b/Commands/Generate.plist
new file mode 100644
index 0000000..ffe0927
--- /dev/null
+++ b/Commands/Generate.plist
@@ -0,0 +1,132 @@
+
+
+
+
+ beforeRunningCommand
+ saveActiveFile
+ command
+ #!/usr/bin/env ruby -s
+
+require 'erb'
+
+def markdown_text (text)
+ text.gsub(/`(.*?)`/, '<code>\1</code>')
+end
+
+def make_id (text)
+ text = text.gsub(/`(.*?)`/, '\1')
+ text.gsub!(/[- \/_]+/, '_')
+ text.gsub!(/[^a-zA-Z0-9_]+/, '')
+ text.downcase
+end
+
+Dir.chdir(ENV['TM_PROJECT_DIRECTORY'])
+
+$toc = [ "<h1>Table of Contents</h1>" ]
+$chapters = [ ]
+
+$toc_template = "templates/toc.rhtml" if $toc_template.nil?
+$chapter_template = "templates/chapter.rhtml" if $chapter_template.nil?
+$all_template = "templates/all.rhtml" if $all_template.nil?
+$output_dir = "html" if $output_dir.nil?
+
+files = Dir.entries("pages").sort.grep(/.*\.markdown/)
+files.each_with_index do |file, i|
+
+ def html_link (markdown_file)
+ markdown_file.sub(/^(?:\d+ )?(.*?)\.markdown$/, '\1.html')
+ end
+
+ puts "• Convert #{file}…"
+
+ $page_toc = [ ]
+
+ IO.popen('"' + ENV['TM_BUNDLE_SUPPORT'] + '/bin/MultiMarkdown.pl"| "' + ENV['TM_SUPPORT_PATH'] + '/bin/SmartyPants.pl"| "' + ENV['TM_BUNDLE_SUPPORT'] + '"/add_image_size.rb', "r+") do |f|
+
+ Thread.fork do
+ heading_stack = [ i ]
+ lastlevel = 0;
+ File.open("pages/#{file}").each_line do |line|
+
+ if(m = line.match(/^(#+)\s+(.*)$/))
+ level = m[1].length
+ title = m[2]
+
+ if heading_stack.length < level
+ heading_stack.push(0)
+# $toc.push("<ol>")
+ else
+ while heading_stack.length > level
+ heading_stack.pop
+# $toc.push("</ol>")
+ end
+ end
+
+ heading_stack.push(heading_stack.pop + 1)
+ prefix = heading_stack.join(".")
+ puts(" #{prefix} #{title}")
+
+ toc_entry = "#{"<ul><li>" if(level > lastlevel)}#{"</li><li>" if(level == lastlevel)}#{"</li></ul>" * (lastlevel - level) if(level < lastlevel)}<span class='toc_number'>#{prefix}</span><a href='#{html_link file}##{make_id title}'>#{markdown_text title}</a>";
+
+ $toc.push(toc_entry)
+ $page_toc.push(toc_entry)
+
+ f.write("#{m[1]} <span id='#{make_id title}'>#{prefix}</span> #{title}")
+ lastlevel = level;
+ else
+ f.write(line)
+ end
+
+ end
+
+ lastlevel.times {$page_toc.push("</li></ul>")}
+ begin
+ f.write("\n"+File.open("markdown.references").read)
+ rescue
+
+ end
+ f.close_write
+
+ lastlevel.times {$toc.push("</li></ul>")}
+# heading_stack.length.times { $toc.push("</ol>") }
+ end
+
+ $page = { :title => %x{ grep '^#' 'pages/#{file}'|head -n1 }.sub(/^#+\s+(.*)\n/, '\1'), :content => f.read, :name => "chapter", :page_toc => $page_toc.join("\n") }
+ $prev = i > 0 ? { :link => "#{html_link files[i-1]}", :title => markdown_text(%x{ grep '^#' 'pages/#{files[i-1]}'|head -n1 }.sub(/^#+\s+(.*)\n/, '\1')) } : nil
+ $next = i + 1 < files.length ? { :link => "#{html_link files[i+1]}", :title => markdown_text(%x{ grep '^#' 'pages/#{files[i+1]}'|head -n1 }.sub(/^#+\s+(.*)\n/, '\1')) } : nil
+
+ File.open("#{$output_dir}/#{html_link file}", "w") do |f|
+ f.write(ERB.new(File.open($chapter_template), 0, '<>').result)
+ end
+
+ $chapters.push($page)
+
+ end
+
+end
+
+$alltoc = { :toc => $toc.join("\n") }
+File.open("#{$output_dir}/all_pages.html", "w") do |f|
+ f.write(ERB.new(File.open($all_template), 0, '<>').result)
+end
+
+
+File.open("#{$output_dir}/index.html", "w") do |f|
+ $page = { :content => $toc.join("\n"), :name => "toc", :title => "Table of Contents" }
+ f.write(ERB.new(File.open($toc_template), 0, '<>').result)
+end
+
+ input
+ none
+ keyEquivalent
+ ^G
+ name
+ Generate
+ output
+ showAsTooltip
+ scope
+ text.html.markdown
+ uuid
+ C445442D-06BF-4CEE-A642-6209B84632A6
+
+
diff --git a/Commands/Open Generated Stuff.plist b/Commands/Open Generated Stuff.plist
new file mode 100644
index 0000000..5f13402
--- /dev/null
+++ b/Commands/Open Generated Stuff.plist
@@ -0,0 +1,22 @@
+
+
+
+
+ beforeRunningCommand
+ nop
+ command
+ open "$TM_PROJECT_DIRECTORY/html/index.html"
+ input
+ none
+ keyEquivalent
+ ^O
+ name
+ Open Generated Files
+ output
+ discard
+ scope
+ text.html.markdown
+ uuid
+ B3AF90C8-A1B0-4583-A5E4-74374B68B015
+
+
diff --git a/Commands/Readme.plist b/Commands/Readme.plist
new file mode 100644
index 0000000..7e44dc5
--- /dev/null
+++ b/Commands/Readme.plist
@@ -0,0 +1,21 @@
+
+
+
+
+ beforeRunningCommand
+ nop
+ command
+ . "$TM_SUPPORT_PATH/lib/webpreview.sh"
+html_header "Markdown2Book Help file" "Markdown2Book"
+Markdown.pl "$TM_BUNDLE_SUPPORT/help.markdown"|SmartyPants.pl
+html_footer
+ input
+ none
+ name
+ Readme
+ output
+ showAsHTML
+ uuid
+ B9B57AA0-0024-41F6-B6AE-C60FCDC1E8B1
+
+
diff --git a/Commands/Show References.plist b/Commands/Show References.plist
new file mode 100644
index 0000000..ef31d40
--- /dev/null
+++ b/Commands/Show References.plist
@@ -0,0 +1,34 @@
+
+
+
+
+ beforeRunningCommand
+ nop
+ command
+ res=$(CocoaDialog dropdown --text "References" --items `cat "$TM_PROJECT_DIRECTORY/markdown.references"|sed 's/ /_/'` --button1 "Insert")
+
+[[ $(head -n1 <<<"$res") == "2" ]] && exit_discard
+
+res=$(tail -n1 <<<"$res")
+
+let "res += 2"
+
+res=$(head -n "$res" "$TM_PROJECT_DIRECTORY/markdown.references" |tail -n 1)
+
+res=$(sed 's/\[\(.*\)\].*/[${1:Reference text}][\1]/'<<<"$res")
+
+echo -n "$res"
+ input
+ none
+ keyEquivalent
+ ^l
+ name
+ Show References
+ output
+ insertAsSnippet
+ scope
+ text.html.markdown
+ uuid
+ 3E0EDBF3-2018-46EA-95EE-C4EB20118789
+
+
diff --git a/Commands/Update References.plist b/Commands/Update References.plist
new file mode 100644
index 0000000..03d53da
--- /dev/null
+++ b/Commands/Update References.plist
@@ -0,0 +1,43 @@
+
+
+
+
+ beforeRunningCommand
+ nop
+ command
+ #!/bin/bash
+
+cd "$TM_PROJECT_DIRECTORY"
+
+if [ ! -f "markdown.references" ]; then touch "markdown.references"; fi
+
+all_refs=$(grep -ho '\[[^]]*\]\[[^]]*\]' pages/*.markdown|perl -pe 's/.*\[(.*)\]$/$1/'|sort|uniq)
+
+known_refs=$(grep '^\[.*\]' markdown.references|perl -pe 's/^\[(.*?)\].*/$1/')
+
+all_ptrn=$(tr <<<"$all_refs" '\n' '|')
+known_ptrn=$(tr <<<"$known_refs" '\n' '|')
+
+all_ptrn="${all_ptrn:0:${#all_ptrn}-1}"
+known_ptrn="${known_ptrn:0:${#known_ptrn}-1}"
+
+echo -e "Missing:\n"
+grep -Ev <<<"$all_refs" "^($known_ptrn)$"|perl -pe 's/.*/[$&]: MISSING/'|tee -a markdown.references
+
+echo -e "\nRedundant:\n"
+grep -Ev <<<"$known_refs" "^($all_ptrn)$"
+
+ input
+ none
+ keyEquivalent
+ ^U
+ name
+ Update References
+ output
+ showAsTooltip
+ scope
+ text
+ uuid
+ 749EA16A-700B-43B3-9457-FA12D8301CAE
+
+
diff --git a/README b/README
new file mode 100644
index 0000000..4fc0de2
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+This TextMate bundle is for compiling a Documentation project made of several Markdown files to HTML. It generates a TOC, a print version with all chapters on one page and HTML files for each chapter. You can use references to easily link between your pages.
\ No newline at end of file
diff --git a/Support/add_image_size.rb b/Support/add_image_size.rb
new file mode 100755
index 0000000..cd6edad
--- /dev/null
+++ b/Support/add_image_size.rb
@@ -0,0 +1,12 @@
+#!/usr/bin/env ruby
+
+STDIN.each_line do |line|
+ line.gsub!(/
]*?(?:width|height)=)[^>*]src="(.*?)"/) do |tag|
+ size = %x(sips -g pixelWidth -g pixelHeight "#{$1}")
+ size.gsub(/pixel(Width|Height): (\d+)/) { |str| tag += " #{$1.downcase}=\"#{$2}\"" }
+ # use the next line to change the image path
+ # tag.gsub(/src="([^"]+)"/, 'src="http://yoursite.com/path/to/images/\1"')
+ tag.gsub(/src="([^"]+)"/, 'src="\1"')
+ end
+ print line
+end
diff --git a/Support/bin/MultiMarkdown.pl b/Support/bin/MultiMarkdown.pl
new file mode 100755
index 0000000..620f5b9
--- /dev/null
+++ b/Support/bin/MultiMarkdown.pl
@@ -0,0 +1,2216 @@
+#!/usr/bin/env perl
+
+# MultiMarkdown -- A modification of John Gruber's original Markdown
+# that adds new features and an output format that can more readily
+# be converted into other document formats
+#
+# Original Code Copyright (c) 2004 John Gruber
+#
+#
+# MultiMarkdown changes Copyright (c) 2005-2006 Fletcher T. Penney
+#
+#
+
+
+package Markdown;
+require 5.006_000;
+use strict;
+use warnings;
+
+use Digest::MD5 qw(md5_hex);
+use vars qw($VERSION $g_use_metadata $g_use_wiki_links $g_base_url);
+$VERSION = '1.0.1Multi19.1';
+
+## Disabled; causes problems under Perl 5.6.1:
+# use utf8;
+# binmode( STDOUT, ":utf8" ); # c.f.: http://acis.openlib.org/dev/perl-unicode-struggle.html
+
+
+#
+# Global default settings:
+#
+my $g_empty_element_suffix = " />"; # Change to ">" for HTML output
+my $g_tab_width = 4;
+
+
+#
+# Globals:
+#
+
+# Regex to match balanced [brackets]. See Friedl's
+# "Mastering Regular Expressions", 2nd Ed., pp. 328-331.
+my $g_nested_brackets;
+$g_nested_brackets = qr{
+ (?> # Atomic matching
+ [^\[\]]+ # Anything other than brackets
+ |
+ \[
+ (??{ $g_nested_brackets }) # Recursive set of nested brackets
+ \]
+ )*
+}x;
+
+
+# Table of hash values for escaped characters:
+my %g_escape_table;
+foreach my $char (split //, '\\`*_{}[]()>#+-.!') {
+ $g_escape_table{$char} = md5_hex($char);
+}
+
+
+# Global hashes, used by various utility routines
+my %g_urls;
+my %g_titles;
+my %g_html_blocks;
+my %g_metadata = ();
+my %g_metadata_newline;
+my %g_crossrefs;
+my %g_footnotes;
+my %g_attributes;
+my @g_used_footnotes;
+my $g_footnote_counter = 0;
+my %g_citations;
+
+my $g_citation_counter = 0;
+my @g_used_references;
+my %g_references;
+
+$g_use_metadata = 1;
+$g_metadata_newline{default} = "\n";
+my $g_document_format = "";
+
+# For use with WikiWords and [[Wiki Links]]
+$g_use_wiki_links = 0;
+$g_base_url = ""; # This is the base url to be used for WikiLinks
+my $g_temp_no_wikiwords = 0;
+
+# NOTE:
+# You can use \WikiWord to prevent a WikiWord from being treated as a link
+
+
+# Used to track when we're inside an ordered or unordered list
+# (see _ProcessListItems() for details):
+my $g_list_level = 0;
+
+
+#### Blosxom plug-in interface ##########################################
+
+# Set $g_blosxom_use_meta to 1 to use Blosxom's meta plug-in to determine
+# which posts Markdown should process, using a "meta-markup: markdown"
+# header. If it's set to 0 (the default), Markdown will process all
+# entries.
+my $g_blosxom_use_meta = 0;
+
+sub start { 1; }
+sub story {
+ my($pkg, $path, $filename, $story_ref, $title_ref, $body_ref) = @_;
+
+ if ( (! $g_blosxom_use_meta) or
+ (defined($meta::markup) and ($meta::markup =~ /^\s*markdown\s*$/i))
+ ){
+ $$body_ref = Markdown($$body_ref);
+ }
+ 1;
+}
+
+
+#### Movable Type plug-in interface #####################################
+eval {require MT}; # Test to see if we're running in MT.
+unless ($@) {
+ require MT;
+ import MT;
+ require MT::Template::Context;
+ import MT::Template::Context;
+
+ eval {require MT::Plugin}; # Test to see if we're running >= MT 3.0.
+ unless ($@) {
+ require MT::Plugin;
+ import MT::Plugin;
+ my $plugin = new MT::Plugin({
+ name => "Markdown",
+ description => "A plain-text-to-HTML formatting plugin. (Version: $VERSION)",
+ doc_link => 'http://daringfireball.net/projects/markdown/'
+ });
+ MT->add_plugin( $plugin );
+ }
+
+ MT::Template::Context->add_container_tag(MarkdownOptions => sub {
+ my $ctx = shift;
+ my $args = shift;
+ my $builder = $ctx->stash('builder');
+ my $tokens = $ctx->stash('tokens');
+
+ if (defined ($args->{'output'}) ) {
+ $ctx->stash('markdown_output', lc $args->{'output'});
+ }
+
+ defined (my $str = $builder->build($ctx, $tokens) )
+ or return $ctx->error($builder->errstr);
+ $str; # return value
+ });
+
+ MT->add_text_filter('markdown' => {
+ label => 'Markdown',
+ docs => 'http://daringfireball.net/projects/markdown/',
+ on_format => sub {
+ my $text = shift;
+ my $ctx = shift;
+ my $raw = 0;
+ if (defined $ctx) {
+ my $output = $ctx->stash('markdown_output');
+ if (defined $output && $output =~ m/^html/i) {
+ $g_empty_element_suffix = ">";
+ $ctx->stash('markdown_output', '');
+ }
+ elsif (defined $output && $output eq 'raw') {
+ $raw = 1;
+ $ctx->stash('markdown_output', '');
+ }
+ else {
+ $raw = 0;
+ $g_empty_element_suffix = " />";
+ }
+ }
+ $text = $raw ? $text : Markdown($text);
+ $text;
+ },
+ });
+
+ # If SmartyPants is loaded, add a combo Markdown/SmartyPants text filter:
+ my $smartypants;
+
+ {
+ no warnings "once";
+ $smartypants = $MT::Template::Context::Global_filters{'smarty_pants'};
+ }
+
+ if ($smartypants) {
+ MT->add_text_filter('markdown_with_smartypants' => {
+ label => 'Markdown With SmartyPants',
+ docs => 'http://daringfireball.net/projects/markdown/',
+ on_format => sub {
+ my $text = shift;
+ my $ctx = shift;
+ if (defined $ctx) {
+ my $output = $ctx->stash('markdown_output');
+ if (defined $output && $output eq 'html') {
+ $g_empty_element_suffix = ">";
+ }
+ else {
+ $g_empty_element_suffix = " />";
+ }
+ }
+ $text = Markdown($text);
+ $text = $smartypants->($text, '1');
+ },
+ });
+ }
+}
+else {
+#### BBEdit/command-line text filter interface ##########################
+# Needs to be hidden from MT (and Blosxom when running in static mode).
+
+ # We're only using $blosxom::version once; tell Perl not to warn us:
+ no warnings 'once';
+ unless ( defined($blosxom::version) ) {
+ use warnings;
+
+ #### Check for command-line switches: #################
+ my %cli_opts;
+ use Getopt::Long;
+ Getopt::Long::Configure('pass_through');
+ GetOptions(\%cli_opts,
+ 'version',
+ 'shortversion',
+ 'html4tags',
+ );
+ if ($cli_opts{'version'}) { # Version info
+ print "\nThis is Markdown, version $VERSION.\n";
+ print "Copyright 2004 John Gruber\n";
+ print "http://daringfireball.net/projects/markdown/\n\n";
+ exit 0;
+ }
+ if ($cli_opts{'shortversion'}) { # Just the version number string.
+ print $VERSION;
+ exit 0;
+ }
+ if ($cli_opts{'html4tags'}) { # Use HTML tag style instead of XHTML
+ $g_empty_element_suffix = ">";
+ }
+
+
+ #### Process incoming text: ###########################
+ my $text;
+ {
+ local $/; # Slurp the whole file
+ $text = <>;
+ }
+ print Markdown($text);
+ }
+}
+
+
+
+sub Markdown {
+#
+# Main function. The order in which other subs are called here is
+# essential. Link and image substitutions need to happen before
+# _EscapeSpecialChars(), so that any *'s or _'s in the
+# and
tags get encoded.
+#
+ my $text = shift;
+
+ # Clear the global hashes. If we don't clear these, you get conflicts
+ # from other articles when generating a page which contains more than
+ # one article (e.g. an index page that shows the N most recent
+ # articles):
+ %g_urls = ();
+ %g_titles = ();
+ %g_html_blocks = ();
+ %g_metadata = ();
+ %g_crossrefs = ();
+ %g_footnotes = ();
+ @g_used_footnotes = ();
+
+
+
+ # Standardize line endings:
+ $text =~ s{\r\n}{\n}g; # DOS to Unix
+ $text =~ s{\r}{\n}g; # Mac to Unix
+
+ # Make sure $text ends with a couple of newlines:
+ $text .= "\n\n";
+
+ # Convert all tabs to spaces.
+ $text = _Detab($text);
+
+ # Strip any lines consisting only of spaces and tabs.
+ # This makes subsequent regexen easier to write, because we can
+ # match consecutive blank lines with /\n+/ instead of something
+ # contorted like /[ \t]*\n+/ .
+ $text =~ s/^[ \t]+$//mg;
+
+ # Strip leading blank lines
+ $text =~ s/^\n+//s;
+
+ # Strip out MetaData
+ $text = _ParseMetaData($text) if $g_use_metadata;
+
+ # And recheck for leading blank lines
+ $text =~ s/^\n+//s;
+
+ # Turn block-level HTML blocks into hash entries
+ $text = _HashHTMLBlocks($text);
+
+ # Strip link definitions, store in hashes.
+ $text = _StripLinkDefinitions($text);
+
+ $text = _StripFootnoteDefinitions($text);
+
+ $text = _StripMarkdownReferences($text);
+
+ $text = _RunBlockGamut($text);
+
+ $text = _DoMarkdownCitations($text);
+
+ $text = _DoFootnotes($text);
+
+ $text = _UnescapeSpecialChars($text);
+
+ # This must follow _UnescapeSpecialChars
+ $text = _UnescapeWikiWords($text);
+
+ $text = _FixFootnoteParagraphs($text);
+ $text .= _PrintFootnotes();
+
+ $text .= _PrintMarkdownBibliography();
+
+ $text = _ConvertCopyright($text);
+
+ if (lc($g_document_format) =~ /^complete\s*$/) {
+ return xhtmlMetaData() . "\n" . $text . "\n\n