Skip to content

Commit

Permalink
Merge pull request #21 from toshimaru/rubocop-alert-fix
Browse files Browse the repository at this point in the history
💎 Version 0.3.0.pre1 release
  • Loading branch information
toshimaru authored Apr 11, 2017
2 parents 199b194 + 5efa82b commit 63495df
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 74 deletions.
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ rvm:
- 2.2
- 2.3.1
- 2.4.0
# Put this in your .travis.yml
# gemfile is generated by appraisal
gemfile:
- gemfiles/jekyll_3.4.gemfile
- gemfiles/jekyll_3.3.gemfile
- gemfiles/jekyll_3.2.gemfile
- gemfiles/jekyll_3.1.gemfile
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,19 @@ There are three Liquid filters available now, which all should be applied
to some HTML content, e.g. the Liquid variable `content` available in
Jekyll's templates.

## Basic Usage
## 1. Basic Usage

### `toc` filter

Add `toc` filter to your site's `{{ content }}` (e.g. `_layouts/post.html`).

```
```liquid
{{ content | toc }}
```

This filter places the TOC directly above the content.

## Advanced Usage
## 2. Advanced Usage

If you'd like separated TOC and content, you can use `toc_only` and `inject_anchors` filters.

Expand Down
129 changes: 62 additions & 67 deletions lib/table_of_contents/parser.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
module Jekyll
module TableOfContents
# Parse html contents and generate table of contents
class Parser
PUNCTUATION_REGEXP = RUBY_VERSION > '1.9' ? /[^\p{Word}\- ]/u : /[^\w\- ]/
PUNCTUATION_REGEXP = /[^\p{Word}\- ]/u

attr_reader :doc

Expand All @@ -11,54 +12,93 @@ def initialize(html)
end

def build_toc
toc = %Q{<ul class="section-nav">\n}
toc = %(<ul class="section-nav">\n)

min_h_num = 6
@entries.each do |entry|
h_num = entry[:node_name].delete("h").to_i
h_num = entry[:node_name].delete('h').to_i
min_h_num = [min_h_num, h_num].min
end
toc << build_lis(@entries, min_h_num)

toc << '</ul>'
end

def inject_anchors_into_html
@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>))
end

@doc.inner_html
end

def toc
build_toc + inject_anchors_into_html
end

private

# parse logic is from html-pipeline toc_filter
# https://github.com/jch/html-pipeline/blob/v1.1.0/lib/html/pipeline/toc_filter.rb
def parse_content
entries = []
headers = Hash.new(0)

@doc.css('h1, h2, h3, h4, h5, h6').each do |node|
text = node.text
id = text.downcase
id.gsub!(PUNCTUATION_REGEXP, '') # remove punctuation
id.gsub!(' ', '-') # replace spaces with dash

uniq = headers[id] > 0 ? "-#{headers[id]}" : ''
headers[id] += 1
header_content = node.children.first
next unless header_content

entries << {
id: id,
uniq: uniq,
text: text,
node_name: node.name,
content_node: header_content
}
end

entries
end

# Returns the list items for entries
def build_lis(entries, min_h_num)
lis = ""
lis = ''
i = 0
while i < entries.length do
while i < entries.length
entry = entries[i]
curr_h_num = entry[:node_name].delete("h").to_i
curr_h_num = entry[:node_name].delete('h').to_i
if curr_h_num == min_h_num

# If the current entry should not be indented in the list, add the entry to the list
lis << %Q{<li class="toc-entry toc-#{entry[:node_name]}"><a href="##{entry[:id]}#{entry[:uniq]}">#{entry[:text]}</a>}
lis << %(<li class="toc-entry toc-#{entry[:node_name]}"><a href="##{entry[:id]}#{entry[:uniq]}">#{entry[:text]}</a>)
# If the next entry should be indented in the list, generate a sublist
if i + 1 < entries.length
next_entry = entries[i + 1]
next_h_num = next_entry[:node_name].delete("h").to_i
next_h_num = next_entry[:node_name].delete('h').to_i
if next_h_num > min_h_num
lis << %Q{\n}
lis << %Q{<ul>\n}
lis << %(\n)
lis << %(<ul>\n)
nest_entries = get_nest_entries(entries[i + 1, entries.length], min_h_num)
lis << build_lis(nest_entries, min_h_num + 1)
lis << %Q{</ul>\n}
lis << %(</ul>\n)
i += nest_entries.length
end
end
# Add the closing tag for the current entry in the list
lis << %Q{</li>\n}

lis << %(</li>\n)
elsif curr_h_num > min_h_num

# If the current entry should be indented in the list, generate a sublist
lis << %Q{<ul>\n}
lis << %(<ul>\n)
nest_entries = get_nest_entries(entries[i, entries.length], min_h_num)
lis << build_lis(nest_entries, min_h_num + 1)
lis << %Q{</ul>\n}
lis << %(</ul>\n)
i += nest_entries.length - 1

end
i += 1
end
Expand All @@ -70,59 +110,14 @@ def build_lis(entries, min_h_num)
# The nested list ends at the first entry in entries with depth min_h_num or greater (exclusive)
def get_nest_entries(entries, min_h_num)
nest_entries = []
for i in 0..(entries.length - 1)
(0..(entries.length - 1)).each do |i|
nest_entry = entries[i]
nest_h_num = nest_entry[:node_name].delete("h").to_i
if nest_h_num > min_h_num
nest_entries.push(nest_entry)
else
break
end
nest_h_num = nest_entry[:node_name].delete('h').to_i
break unless nest_h_num > min_h_num
nest_entries.push(nest_entry)
end
nest_entries
end

def inject_anchors_into_html
@entries.each do |entry|
entry[:content_node].add_previous_sibling(%Q{<a id="#{entry[:id]}#{entry[:uniq]}" class="anchor" href="##{entry[:id]}#{entry[:uniq]}" aria-hidden="true"><span class="octicon octicon-link"></span></a>})
end

@doc.inner_html
end

def toc
build_toc + inject_anchors_into_html
end

# parse logic is from html-pipeline toc_filter
# https://github.com/jch/html-pipeline/blob/v1.1.0/lib/html/pipeline/toc_filter.rb
private

def parse_content
entries = []
headers = Hash.new(0)

@doc.css('h1, h2, h3, h4, h5, h6').each do |node|
text = node.text
id = text.downcase
id.gsub!(PUNCTUATION_REGEXP, '') # remove punctuation
id.gsub!(' ', '-') # replace spaces with dash

uniq = (headers[id] > 0) ? "-#{headers[id]}" : ''
headers[id] += 1
if header_content = node.children.first
entries << {
id: id,
uniq: uniq,
text: text,
node_name: node.name,
content_node: header_content
}
end
end

entries
end
end
end
end
2 changes: 1 addition & 1 deletion lib/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module JekyllToc
VERSION = '0.2.1'
VERSION = '0.3.0.pre1'
end
4 changes: 2 additions & 2 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
require 'jekyll'
require 'minitest/autorun'

SIMPLE_HTML = <<EOL
SIMPLE_HTML = <<HTML
<h1>Simple H1</h1>
<h2>Simple H2</h2>
<h3>Simple H3</h3>
<h4>Simple H4</h4>
<h5>Simple H5</h5>
<h6>Simple H6</h6>
EOL
HTML

module TestHelpers
def read_html_and_create_parser
Expand Down

0 comments on commit 63495df

Please sign in to comment.