Skip to content

Add toc link when enable set to true. #69

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Markd.to_html(markdown, options)
| prettyprint | `Bool` | false | if **true**, code tags generated by code blocks will have a `prettyprint` class added to them, to be used by [Google code-prettify](https://github.com/google/code-prettify). |
| gfm | `Bool` | false | **Partial support** |
| autolink | `Bool` | false | if **true**, more autolinks are detected, like bare email addresses or http links. Requires `gfm` be set to `true` |
| toc | `Bool` | false | **Not supported for now** |
| toc | `Bool` | false | **Partial support**, if **true**, show only a anchor text to the beginning of the head tag(as github markdown does) for now. |
| base_url | `URI?` | nil | if not **nil**, relative URLs of links are resolved against this `URI`. It act's like HTML's `<base href="base_url">` in the context of a Markdown document. |

## Advanced
Expand Down
51 changes: 51 additions & 0 deletions spec/markd_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,55 @@

Markd.to_html(raw).should eq(html)
end

it "should add a anchor text to the beginning of the head tag" do
raw = <<-'HEREDOC'
## foo
## bar
### 标题1
### 标题2
HEREDOC

options = Markd::Options.new(toc: true)

html = <<-'HEREDOC'
<h2><a id="anchor-f" class="anchor" href="#anchor-f">§ </a>foo</h2>
<h2><a id="anchor-bar" class="anchor" href="#anchor-bar">§ </a>bar</h2>
<h3><a id="anchor-%E6%A0%87%E9%A2%981" class="anchor" href="#anchor-%E6%A0%87%E9%A2%981">§ </a>标题1</h3>
<h3><a id="anchor-%E6%A0%87%E9%A2%982" class="anchor" href="#anchor-%E6%A0%87%E9%A2%982">§ </a>标题2</h3>

HEREDOC

Markd.to_html(raw, options).should eq(html)

Check failure on line 47 in spec/markd_spec.cr

View workflow job for this annotation

GitHub Actions / Crystal specs on windows-latest

"<h3><a id=\"anchor-%E6%A0%87%E9%A2%982\" class=\"anchor\" href=\"#anchor-%E6%A0%87%E9%A2%982\">§ </a>标题2</h3>\n"

options = Markd::Options.new(toc: "@")

html = <<-'HEREDOC'
<h2><a id="anchor-f" class="anchor" href="#anchor-f">@ </a>foo</h2>
<h2><a id="anchor-bar" class="anchor" href="#anchor-bar">@ </a>bar</h2>
<h3><a id="anchor-%E6%A0%87%E9%A2%981" class="anchor" href="#anchor-%E6%A0%87%E9%A2%981">@ </a>标题1</h3>
<h3><a id="anchor-%E6%A0%87%E9%A2%982" class="anchor" href="#anchor-%E6%A0%87%E9%A2%982">@ </a>标题2</h3>

HEREDOC

Markd.to_html(raw, options).should eq(html)
end

it "should generate a correct anchor on the beginning of the head tag" do
raw = <<-'HEREDOC'
# h1
# h2
# hh3
HEREDOC

options = Markd::Options.new(toc: true)

html = <<-'HEREDOC'
<h1><a id="anchor-h1" class="anchor" href="#anchor-h1">§ </a>h1</h1>
<h2><a id="anchor-h2" class="anchor" href="#anchor-h2">§ </a>h2</h2>
<h2><a id="anchor-hh3" class="anchor" href="#anchor-hh3">§ </a>hh3</h2>
HEREDOC

Markd.to_html(raw, options).should eq(html)

Check failure on line 77 in spec/markd_spec.cr

View workflow job for this annotation

GitHub Actions / Crystal nightly specs on ubuntu-latest

"<h1><a id=\"anchor-h\" class=\"anchor\" href=\"#anchor-h\">§ </a>hh3</h1>\n"

Check failure on line 77 in spec/markd_spec.cr

View workflow job for this annotation

GitHub Actions / Crystal specs on windows-latest

"<h1><a id=\"anchor-h\" class=\"anchor\" href=\"#anchor-h\">§ </a>hh3</h1>\n"

Check failure on line 77 in spec/markd_spec.cr

View workflow job for this annotation

GitHub Actions / Crystal specs on macos-latest

"<h1><a id=\"anchor-h\" class=\"anchor\" href=\"#anchor-h\">§ </a>hh3</h1>\n"

Check failure on line 77 in spec/markd_spec.cr

View workflow job for this annotation

GitHub Actions / Crystal latest specs on ubuntu-latest

"<h1><a id=\"anchor-h\" class=\"anchor\" href=\"#anchor-h\">§ </a>hh3</h1>\n"
end
end
6 changes: 5 additions & 1 deletion src/markd/options.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ require "uri"
module Markd
# Markdown rendering options.
class Options
property time, gfm, toc
property time, gfm

# if `true', show a anchor text to the beginning of the head tag
# You can specify a String as the anchor text to this option too.
property toc : String | Bool

# If `true`:
# - straight quotes will be made curly
Expand Down
25 changes: 16 additions & 9 deletions src/markd/renderers/html_renderer.cr
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,17 @@ module Markd

def heading(node : Node, entering : Bool) : Nil
tag_name = HEADINGS[node.data["level"].as(Int32) - 1]
toc = @options.toc

if entering
newline
tag(tag_name, attrs(node))
toc(node) if @options.toc
case toc
when String
toc(node, toc)
when true
toc(node)
end
else
tag(tag_name, end_tag: true)
newline
Expand Down Expand Up @@ -308,16 +315,16 @@ module Markd
url.match(Rule::UNSAFE_PROTOCOL) && !url.match(Rule::UNSAFE_DATA_PROTOCOL)
end

private def toc(node : Node)
private def toc(node : Node, anchor_text = "§")
return unless node.type.heading?

{% if compare_versions(Crystal::VERSION, "1.2.0") < 0 %}
title = URI.encode(node.first_child.text)
@output_io << %(<a id="anchor-) << title << %(" class="anchor" href="#anchor-) << title << %("></a>)
{% else %}
title = URI.encode_path(node.first_child.text)
@output_io << %(<a id="anchor-) << title << %(" class="anchor" href="#anchor-) << title << %("></a>)
{% end %}
title = {% if compare_versions(Crystal::VERSION, "1.2.0") < 0 %}
URI.encode(node.first_child.text)
{% else %}
URI.encode_path(node.first_child.text)
{% end %}

@output_io << %(<a id="anchor-) << title << %(" class="anchor" href="#anchor-) << title << %(">) << anchor_text << %( </a>)
@last_output = ">"
end

Expand Down
Loading