Skip to content
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

Add a simple way to customize anchor injection #75

Open
wants to merge 1 commit into
base: main
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
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,3 +201,28 @@ The general `toc-entry` is applied to all `li` elements in the `ul.section-nav`.

Depending on the heading level each specific entry refers to, it has a second CSS class `toc-XX`, where `XX` is the HTML heading tag name. For example, the TOC entry linking to a heading `<h1>...</h1>` (a single
`#` in Markdown) will get the CSS class `toc-h1`.

#### Anchor injection

Anchor injection can be customized with a liquid template:

```yml
toc:
injection_template: 'path/to/template.html'
```

The template is supplied with the original text content (`heading_text`) and id (`heading_id`) for each heading element:

```liquid
<!-- Append an anchor pilcrow after the heading text, Sphinx style: -->
{{ heading_text }} <a class="anchor" aria-hidden="true" href="{{ page.url }}{{ heading_id }}">¶</a>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering why you need to configure page.url.

I think anchor's href should be #heading-title, for instance. 🤔

Copy link
Author

@gandalf3 gandalf3 Mar 24, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this example, the idea is for the anchor to provide an absolute reference so right click -> copy link gives something which can be pasted anywhere. Of course, the goal is for customization; you could of course just use #{{ heading_id }} to get a relative reference, if that is what one wishes.

```

The above template, when injected on an `<h1>`, yeilds html like the following:

```html
<h1 id="this-is-a-heading">
<!-- Append an anchor pilcrow after the heading text, Sphinx style: -->
This is a heading <a class="anchor" aria-hidden="true" href="example.com/this/page.html#this-is-a-heading">¶</a>
</h1>
```
2 changes: 1 addition & 1 deletion lib/jekyll-toc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def toc_only(html)
def inject_anchors(html)
return html unless toc_enabled?

::Jekyll::TableOfContents::Parser.new(html, toc_config).inject_anchors_into_html
::Jekyll::TableOfContents::Parser.new(html, toc_config).inject_anchors_into_html @context
end

def toc(html)
Expand Down
17 changes: 13 additions & 4 deletions lib/table_of_contents/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class Parser
'max_level' => 6,
'list_class' => 'section-nav',
'sublist_class' => '',
'injection_template' => '',
'item_class' => 'toc-entry',
'item_prefix' => 'toc-'
}.freeze
Expand All @@ -23,6 +24,7 @@ def initialize(html, options = {})
@toc_levels = options['min_level']..options['max_level']
@no_toc_section_class = options['no_toc_section_class']
@list_class = options['list_class']
@injection_template = options['injection_template']
@sublist_class = options['sublist_class']
@item_class = options['item_class']
@item_prefix = options['item_prefix']
Expand All @@ -37,11 +39,18 @@ def build_toc
%(<ul class="#{@list_class}">\n#{build_toc_list(@entries)}</ul>)
end

def inject_anchors_into_html
def inject_anchors_into_html(context)
@entries.each do |entry|
entry[:content_node].add_previous_sibling(
%(<a id="#{entry[:id]}#{entry[:uniq]}" class="anchor" href="##{entry[:id]}#{entry[:uniq]}" aria-hidden="true"><span class="octicon octicon-link"></span></a>)
)
if @injection_template == ''
entry[:content_node].add_previous_sibling(
%(<a id="#{entry[:id]}#{entry[:uniq]}" class="anchor" href="##{entry[:id]}#{entry[:uniq]}" aria-hidden="true"><span class="octicon octicon-link"></span></a>)
)
else
template = File.read(@injection_template)
context.merge('heading_id' => entry[:id].value, 'heading_text' => entry[:content_node].content)
inject_markup = Liquid::Template.parse(template).render(context)
entry[:content_node].replace(inject_markup)
end
end

@doc.inner_html
Expand Down