diff --git a/Markdown.pl b/Markdown.pl index 8cdb8f8..2a5a82d 100755 --- a/Markdown.pl +++ b/Markdown.pl @@ -27,7 +27,7 @@ All rights reserved. } require Exporter; -use Digest::MD5 qw(md5); +use Digest::MD5 qw(md5 md5_hex); use File::Basename qw(basename); use Scalar::Util qw(refaddr looks_like_number); use Pod::Usage; @@ -64,6 +64,7 @@ my %g_perm_block_ids; # Global hashes, used by various utility routines my %g_urls; my %g_titles; +my %g_anchors; my %g_block_ids; my %g_html_blocks; my %g_code_blocks; @@ -343,6 +344,7 @@ sub Markdown { # articles): %g_urls = (); %g_titles = (); + %g_anchors = (); %g_block_ids = (); %g_html_blocks = (); %g_code_blocks = (); @@ -373,7 +375,7 @@ sub Markdown { # Strip link definitions, store in hashes. $text = _StripLinkDefinitions($text); - $text = _RunBlockGamut("\n".$text); + $text = _RunBlockGamut("\n".$text, 1); # Unhashify code blocks $text =~ s/(\005\d+\006)/$g_code_blocks{$1}/g; @@ -575,9 +577,9 @@ sub _RunBlockGamut { # These are all the transformations that form block-level # tags like paragraphs, headers, and list items. # - my $text = shift; + my ($text, $anchors) = @_; - $text = _DoHeaders($text); + $text = _DoHeaders($text, $anchors); # Do Horizontal Rules: $text =~ s{^ {0,3}\*(?: {0,2}\*){2,}[ \t]*$}{\n 64; + "_".$link."_"; +} + + +sub _GetNewAnchorId { + my $link = lc(shift); + return '' if defined($g_anchors{$link}); + my $id = _MakeAnchorId($link); + return '' unless $id; + $g_anchors{$link} = '#'.$id; + $id; +} + + sub _DoHeaders { - my $text = shift; + my ($text, $anchors) = @_; # Setext-style headers: # Header 1 @@ -880,15 +906,24 @@ sub _DoHeaders { # ~~~~~~~~ # $text =~ s{ ^(?:=+[ \t]*\n)?(.+)[ \t]*\n=+[ \t]*\n+ }{ - "

" . _RunSpanGamut($1) . "

\n\n"; + my $h = $1; + my $id = _GetNewAnchorId($h); + $id = " id=\"$id\"" if $id ne ""; + "" . _RunSpanGamut($h) . "\n\n"; }egmx; $text =~ s{ ^(?:-+[ \t]*\n)?(.+)[ \t]*\n-+[ \t]*\n+ }{ - "

" . _RunSpanGamut($1) . "

\n\n"; + my $h = $1; + my $id = _GetNewAnchorId($h); + $id = " id=\"$id\"" if $id ne ""; + "" . _RunSpanGamut($h) . "\n\n"; }egmx; $text =~ s{ ^(?:~+[ \t]*\n)?(.+)[ \t]*\n~+[ \t]*\n+ }{ - "

" . _RunSpanGamut($1) . "

\n\n"; + my $h = $1; + my $id = _GetNewAnchorId($h); + $id = " id=\"$id\"" if $id ne ""; + "" . _RunSpanGamut($h) . "\n\n"; }egmx; @@ -907,8 +942,11 @@ sub _DoHeaders { \#* # optional closing #'s (not counted) \n+ }{ + my $h = $2; my $h_level = length($1); - "" . _RunSpanGamut($2) . "\n\n"; + my $id = $h_level <= 3 ? _GetNewAnchorId($h) : ''; + $id = " id=\"$id\"" if $id ne ""; + "" . _RunSpanGamut($h) . "\n\n"; }egmx; return $text; diff --git a/syntax.md b/syntax.md index 45b8617..d1fee7f 100644 --- a/syntax.md +++ b/syntax.md @@ -687,6 +687,14 @@ tend to put them immediately after each paragraph in which they're used, but if you want, you can put them all at the end of your document, sort of like footnotes. +All first, second and third level headers defined at the top-level +(in other words they are not in lists and start at the left margin) +using either the setext-style or atx-style automatically have an +anchor id and link definition added for them provided there is not +already a previous definition with the same id. You can use this +to place a table-of-contents at the top of the document that links +to subsections later in the document. + Here's an example of reference links in action: I get 10 times more traffic from [Google] [1] than from