diff --git a/Changes b/Changes index cc4c6e6..c5dd6a0 100644 --- a/Changes +++ b/Changes @@ -1,9 +1,13 @@ Revision history for pmarkdown and the Markdown::Perl module. +1.07 - 2024-05-25 + + - Allow to specify a link content through the resolve_link_ref hook. + 1.06 - 2024-05-17 - Add support for setting processing hooks. - - Add a hook to resolve unresolved link reference. + - Add a hook to resolve otherwise unresolved link references. 1.05 - 2024-05-16 diff --git a/lib/Markdown/Perl.pm b/lib/Markdown/Perl.pm index 0611a2b..3f388e2 100644 --- a/lib/Markdown/Perl.pm +++ b/lib/Markdown/Perl.pm @@ -320,7 +320,9 @@ C: this hook will receive a single string an argument, containing the label of a link reference in case where there was no matching link definition in the document and it must returns either C or a hash-reference containing a C key, pointing to the link destination and -optionally a C key containing the title of the key. +optionally a C<title> key containing the title of the key. The hash-ref can also +contain a C<content> key, in which case its value should be a span of HTML which +will replace whatever would have been used for the link content. =back diff --git a/lib/Markdown/Perl/InlineTree.pm b/lib/Markdown/Perl/InlineTree.pm index 89d958c..9923f5f 100644 --- a/lib/Markdown/Perl/InlineTree.pm +++ b/lib/Markdown/Perl/InlineTree.pm @@ -93,6 +93,7 @@ package Markdown::Perl::InlineNode { ## no critic (ProhibitMultiplePackages) unless exists $options{target}; hashpush %{$this}, target => delete $options{target}; hashpush %{$this}, title => delete $options{title} if exists $options{title}; + hashpush %{$this}, content => delete $options{content} if exists $options{content}; confess 'Unexpected parameters for inline link node: '.join(', ', %options) if keys %options; } elsif ($type eq 'style') { confess 'Unexpected parameters for inline style node: '.join(', ', %options) @@ -175,7 +176,7 @@ package Markdown::Perl::InlineNode { ## no critic (ProhibitMultiplePackages) my $text_node = new_text('text content'); my $code_node = new_code('code content'); my $link_node = new_link('text content', type=> 'type', target => 'the target'[, title => 'the title']); - my $link_node = new_link($subtree_content, type=> 'type', target => 'the target'[, title => 'the title']); + my $link_node = new_link($subtree_content, type=> 'type', target => 'the target'[, title => 'the title'][, content => 'override content']); my $html_node = new_html('<raw html content>'); my $style_node = new_literal($subtree_content, 'html_tag'); my $literal_node = new_literal('literal content'); @@ -663,22 +664,21 @@ sub render_node_html { } elsif ($n->{type} eq 'code') { return $acc.'<code>'.$n->{content}.'</code>'; } elsif ($n->{type} eq 'link') { - if ($n->{linktype} eq 'autolink') { - return $acc.'<a href="'.($n->{target}).'">'.($n->{content}).'</a>'; + my $title = ''; + if (exists $n->{title}) { + $title = " title=\"$n->{title}\""; + } + if ($n->{linktype} eq 'link' || $n->{linktype} eq 'autolink') { + # $n->{content} can only be set in the case of autolink or through the + # resolve_link_ref hook (in which case it takes precedence over whatever + # was in the link definition). + my $content = exists $n->{content} ? $n->{content} : $n->{subtree}->render_html(); + return $acc."<a href=\"$n->{target}\"${title}>${content}</a>"; + } elsif ($n->{linktype} eq 'img') { + my $content = $n->{subtree}->to_text(); + return $acc."<img src=\"$n->{target}\" alt=\"${content}\"${title} />"; } else { - my $title = ''; - if (exists $n->{title}) { - $title = " title=\"$n->{title}\""; - } - if ($n->{linktype} eq 'link') { - my $content = $n->{subtree}->render_html(); - return $acc."<a href=\"$n->{target}\"${title}>${content}</a>"; - } elsif ($n->{linktype} eq 'img') { - my $content = $n->{subtree}->to_text(); - return $acc."<img src=\"$n->{target}\" alt=\"${content}\"${title} />"; - } else { - confess 'Unexpected link type in render_node_html: '.$n->{linktype}; - } + confess 'Unexpected link type in render_node_html: '.$n->{linktype}; } } elsif ($n->{type} eq 'style') { my $content = $n->{subtree}->render_html(); diff --git a/t/500-hooks-resolve_link_ref.t b/t/500-hooks-resolve_link_ref.t index 96c2cc8..3987477 100644 --- a/t/500-hooks-resolve_link_ref.t +++ b/t/500-hooks-resolve_link_ref.t @@ -11,6 +11,8 @@ sub hook { return { target => 'http://foo' }; } elsif ($ref eq 'bar') { return { target => 'http://bar', title => 'BAR' }; + } elsif ($ref eq 'baz') { + return { target => 'http://baz', content => '<em>baz</em>' }; } return; } @@ -21,6 +23,7 @@ is(convert("[foo][]"), "<p><a href=\"http://foo\">foo</a></p>\n", 'resolved in c is(convert("[foo]"), "<p><a href=\"http://foo\">foo</a></p>\n", 'resolved in shortcut link reference'); is(convert("[bar]"), "<p><a href=\"http://bar\" title=\"BAR\">bar</a></p>\n", 'resolved with title'); +is(convert("[text][baz]"), "<p><a href=\"http://baz\"><em>baz</em></a></p>\n", 'resolved with content'); is(convert("[none]"), "<p>[none]</p>\n", 'not resolved'); is(convert("[foo]\n\n[foo]: http://other"), "<p><a href=\"http://other\">foo</a></p>\n", 'source has precedence');