html_toc 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/html_toc.rb +168 -0
- metadata +48 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: c62fb2eeee42d1e49865ac7dd47360b2509f2336
|
|
4
|
+
data.tar.gz: 8aa27790eb4ea76551f091fe092edda139eb8eb4
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: ecf0a363447ad1ad85b3f4c79ea0e8103622cdff38b360d067b99e77aad3b3d796407defc315b72ee35dd8d194b1a57a8c9550f81f6122f44dc3fbdc8d89036f
|
|
7
|
+
data.tar.gz: f9866cfd75f3fcbdf92a85eeca90752b0e160cc226af0b144485269f3b0d7ec3a3794ae1877d557f9bc8ec033d650ea0653850533ef47b7b58d381328a51a158
|
data/lib/html_toc.rb
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
require 'rexml/document'
|
|
2
|
+
|
|
3
|
+
module HtmlToc
|
|
4
|
+
|
|
5
|
+
#Primary method call
|
|
6
|
+
def self.process source, h_tags=Range.new(2, 6), show_toggle=false, use_numbers=false
|
|
7
|
+
|
|
8
|
+
#Search regex for {{toc}}
|
|
9
|
+
token = /\[\[[tT][oO][cC]\]\]/
|
|
10
|
+
|
|
11
|
+
#If there is no token, just return the source
|
|
12
|
+
if source !~ token then
|
|
13
|
+
return source
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
#Initialize here for later
|
|
17
|
+
toc = ""
|
|
18
|
+
refnum = ""
|
|
19
|
+
d1 = 0
|
|
20
|
+
d2 = 0
|
|
21
|
+
d3 = 0
|
|
22
|
+
d4 = 0
|
|
23
|
+
d5 = 0
|
|
24
|
+
d6 = 0
|
|
25
|
+
|
|
26
|
+
#Make a copy of the source, in case we need to
|
|
27
|
+
#preserve the original string
|
|
28
|
+
result = source
|
|
29
|
+
|
|
30
|
+
#Loop through the tags range to get the header tags
|
|
31
|
+
tags_hash = Hash.new
|
|
32
|
+
|
|
33
|
+
depth = 0
|
|
34
|
+
h_tags.each do |x|
|
|
35
|
+
#Get the depth
|
|
36
|
+
depth += 1
|
|
37
|
+
|
|
38
|
+
#Regex for indexed header tags
|
|
39
|
+
test = /<h#{x}(?: .*?)?>(.*?)<\/h#{x}>/
|
|
40
|
+
|
|
41
|
+
#Scan, and use the resulting MatchData objects
|
|
42
|
+
#to populate the hash
|
|
43
|
+
result.scan(test) do
|
|
44
|
+
m=Regexp.last_match
|
|
45
|
+
tags_hash[m.begin(0)] = Hx.new(m, depth)
|
|
46
|
+
end #result.scan(test) do
|
|
47
|
+
end #tags.each do
|
|
48
|
+
|
|
49
|
+
#Execute this block only if we have indexed headers
|
|
50
|
+
if tags_hash.length > 0 then
|
|
51
|
+
#Sort the hash. tags becomes an array with each element consisting
|
|
52
|
+
#of an array with two objects: the integer key and the Hx value
|
|
53
|
+
tags = tags_hash.sort_by { |k, v| k }
|
|
54
|
+
|
|
55
|
+
#Start with the last tag and work towards the front: this way,
|
|
56
|
+
#the begin index of subsequent headers will not be moved.
|
|
57
|
+
tags.reverse.each do |elem|
|
|
58
|
+
#Replace the section in the text with the corresponding d_anchor
|
|
59
|
+
result[elem[1].start_index..elem[1].end_index]=elem[1].text
|
|
60
|
+
end #tags.reverse.each do
|
|
61
|
+
|
|
62
|
+
#Now move forward through the array and build the toc itself
|
|
63
|
+
toc = "<div id='__toc'>\n"
|
|
64
|
+
toc += "<div id='__toc_header'>Contents"
|
|
65
|
+
if show_toggle then
|
|
66
|
+
toc+=" [<span id='__toc_toggle' onclick='ShowHideToc();'>Hide</span>]"
|
|
67
|
+
end
|
|
68
|
+
toc+="</div>\n"
|
|
69
|
+
toc+="<div id='__toc_content' style='display:block'>\n"
|
|
70
|
+
tags.each do |elem|
|
|
71
|
+
if use_numbers
|
|
72
|
+
case elem[1].depth
|
|
73
|
+
when 1
|
|
74
|
+
d1+=1
|
|
75
|
+
d2 = 0
|
|
76
|
+
d3 = 0
|
|
77
|
+
d4 = 0
|
|
78
|
+
d5 = 0
|
|
79
|
+
d6 = 0
|
|
80
|
+
refnum = "#{d1} "
|
|
81
|
+
when 2
|
|
82
|
+
d2+=1
|
|
83
|
+
d3 = 0
|
|
84
|
+
d4 = 0
|
|
85
|
+
d5 = 0
|
|
86
|
+
d6 = 0
|
|
87
|
+
refnum = "#{d1}.#{d2} "
|
|
88
|
+
when 3
|
|
89
|
+
d3+=1
|
|
90
|
+
d4 = 0
|
|
91
|
+
d5 = 0
|
|
92
|
+
d6 = 0
|
|
93
|
+
refnum = "#{d1}.#{d2}.#{d3} "
|
|
94
|
+
when 4
|
|
95
|
+
d4+=1
|
|
96
|
+
d5 = 0
|
|
97
|
+
d6 = 0
|
|
98
|
+
refnum = "#{d1}.#{d2}.#{d3}.#{d4} "
|
|
99
|
+
when 5
|
|
100
|
+
d5+=1
|
|
101
|
+
d6 = 0
|
|
102
|
+
refnum = "#{d1}.#{d2}.#{d3}.#{d4}.#{d5} "
|
|
103
|
+
when 6
|
|
104
|
+
d6+=1
|
|
105
|
+
refnum = "#{d1}.#{d2}.#{d3}.#{d4}.#{d5}.#{d6} "
|
|
106
|
+
end #case elem[1].depth
|
|
107
|
+
end #if use_numbers
|
|
108
|
+
|
|
109
|
+
toc+=elem[1].l_anchor refnum
|
|
110
|
+
end
|
|
111
|
+
toc+="</div>\n" #end __toc_content
|
|
112
|
+
toc+="</div>\n" #end __toc
|
|
113
|
+
|
|
114
|
+
end #if tags_hash.length > 0
|
|
115
|
+
|
|
116
|
+
#The location of the toc token may have changed, so get its location
|
|
117
|
+
toc_md = result.match(token)
|
|
118
|
+
result[toc_md.begin(0)..toc_md.end(0)] = toc
|
|
119
|
+
|
|
120
|
+
result
|
|
121
|
+
end #self.process
|
|
122
|
+
|
|
123
|
+
private
|
|
124
|
+
|
|
125
|
+
class Hx
|
|
126
|
+
attr_reader :depth, :text, :start_index, :end_index
|
|
127
|
+
|
|
128
|
+
@@unique_id = 0
|
|
129
|
+
|
|
130
|
+
def initialize md, d
|
|
131
|
+
@depth = d
|
|
132
|
+
@text = md.to_s
|
|
133
|
+
@start_index = md.begin(0)
|
|
134
|
+
@end_index = md.end(0)
|
|
135
|
+
|
|
136
|
+
#If the tag does not have an ID, give it one
|
|
137
|
+
tag_id = @text.match(/\bid(\s*?)=(\s*?)(["'])(.*?)\3/)
|
|
138
|
+
if tag_id == nil
|
|
139
|
+
@@unique_id += 1
|
|
140
|
+
id = " id='_id__#{@@unique_id}'"
|
|
141
|
+
snip = @text.index('>') #get the location of the first >
|
|
142
|
+
@text.insert(snip, id)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def id
|
|
147
|
+
#TODO Allow for undelimited attribute values, as in HTML5
|
|
148
|
+
tag_id = @text.match(/\bid(\s*?)=(\s*?)(["'])(.*?)\3/)
|
|
149
|
+
|
|
150
|
+
if tag_id == nil
|
|
151
|
+
""
|
|
152
|
+
else
|
|
153
|
+
tag_id[0].to_s.match(/(["'])(.*?)\1/)[0].to_s[1..-2]
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def inner_text
|
|
158
|
+
snip_start = @text.to_s.index('>') #Get the index of the first >
|
|
159
|
+
snip_end = @text.to_s.rindex('<') #Get the index of the last <
|
|
160
|
+
@text.to_s[(snip_start+1)..(snip_end-1)] #return everyting in between
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def l_anchor refnum=""
|
|
164
|
+
"<div class='__toc_level_#{@depth}'><a href='##{id}'>#{refnum}#{inner_text}</a></div>\n"
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
end
|
|
168
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: html_toc
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Gregory Gadow
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2014-12-09 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: Do a case-insensitive search on an HTML document for the token [[toc]].
|
|
14
|
+
If present, scan the document for header tags in a given range, verify that they
|
|
15
|
+
have an id attribute and give them one if needed, then generate a group of links
|
|
16
|
+
pointing to those headers with the header text used as the link text. This group
|
|
17
|
+
of links then replaces the token.
|
|
18
|
+
email: gpg@gregory-gadow.net
|
|
19
|
+
executables: []
|
|
20
|
+
extensions: []
|
|
21
|
+
extra_rdoc_files: []
|
|
22
|
+
files:
|
|
23
|
+
- lib/html_toc.rb
|
|
24
|
+
homepage: http://rubygems.org/gems/html_toc
|
|
25
|
+
licenses:
|
|
26
|
+
- MIT
|
|
27
|
+
metadata: {}
|
|
28
|
+
post_install_message:
|
|
29
|
+
rdoc_options: []
|
|
30
|
+
require_paths:
|
|
31
|
+
- lib
|
|
32
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
33
|
+
requirements:
|
|
34
|
+
- - ">="
|
|
35
|
+
- !ruby/object:Gem::Version
|
|
36
|
+
version: '0'
|
|
37
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
38
|
+
requirements:
|
|
39
|
+
- - ">="
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '0'
|
|
42
|
+
requirements: []
|
|
43
|
+
rubyforge_project:
|
|
44
|
+
rubygems_version: 2.2.2
|
|
45
|
+
signing_key:
|
|
46
|
+
specification_version: 4
|
|
47
|
+
summary: Generate and Insert a Table of Contents into a HTML Document
|
|
48
|
+
test_files: []
|