html_toc 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|