Module: HtmlToc

Defined in:
lib/html_toc.rb

Defined Under Namespace

Classes: Hx

Class Method Summary collapse

Class Method Details

.process(source:, h_tags: Range.new(2, 6), show_toggle: false, use_numbers: false) ⇒ Object

Primary method call



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/html_toc.rb', line 6

def self.process(source:, h_tags: Range.new(2, 6), show_toggle: false, use_numbers: false)

  #Search regex for {{toc}}
   token = /<toc\s*\/>|\[\[toc\]\]/i #Allow for a token of either <toc/> or [[toc]]

    #If there is no token, just return the source
  if source !~ token then 
    return source
  end
  
  #Initialize here for later 
  toc = ""
  refnum = ""
  d1 = 0
  d2 = 0
  d3 = 0
  d4 = 0
  d5 = 0
  d6 = 0 

   #Make a copy of the source, in case we need to 
  #preserve the original string
  result = source  

  #Loop through the tags range to get the header tags
  tags_hash = Hash.new

  depth = 0
  h_tags.each do |x|
    #Get the depth
    depth += 1

    #Regex for indexed header tags
    test = /<h#{x}(?: .*?)?>(.*?)<\/h#{x}>/i
  
    #Scan, and use the resulting MatchData objects 
    #to populate the hash
    result.scan(test) do
      m=Regexp.last_match
      tags_hash[m.begin(0)] = Hx.new(m, depth)
    end #result.scan(test) do
  end #tags.each do

  #Execute this block only if we have indexed headers
  if tags_hash.length > 0 then
    #Sort the hash. tags becomes an array with each element consisting
    #of an array with two objects: the integer key and the Hx value
    tags = tags_hash.sort_by { |k, v| k }

    #Start with the last tag and work towards the front: this way,
    #the begin index of subsequent headers will not be moved.
    tags.reverse.each do |elem|
      #Replace the section in the text with the corresponding d_anchor
      result[elem[1].start_index..elem[1].end_index]=elem[1].text
    end #tags.reverse.each do

    #Now move forward through the array and build the toc itself
    toc = "<div id='__toc'>\n"
    toc += "<div id='__toc_header'>Contents"
    if show_toggle then
      toc+=" [<span id='__toc_toggle' onclick='ShowHideToc();'>Hide</span>]"
    end
    toc+="</div>\n"
    toc+="<div id='__toc_content' style='display:block'>\n"
    tags.each do |elem|
      if use_numbers
        case elem[1].depth
          when 1 
            d1+=1
            d2 = 0
            d3 = 0
            d4 = 0
            d5 = 0
            d6 = 0    
            refnum = "#{d1} "
          when 2
            d2+=1
            d3 = 0
            d4 = 0
            d5 = 0
            d6 = 0    
            refnum = "#{d1}.#{d2} "
          when 3
            d3+=1
            d4 = 0
            d5 = 0
            d6 = 0    
            refnum = "#{d1}.#{d2}.#{d3} "
          when 4
            d4+=1
            d5 = 0
            d6 = 0    
            refnum = "#{d1}.#{d2}.#{d3}.#{d4} "
          when 5
            d5+=1
            d6 = 0    
            refnum = "#{d1}.#{d2}.#{d3}.#{d4}.#{d5} "
          when 6
            d6+=1
            refnum = "#{d1}.#{d2}.#{d3}.#{d4}.#{d5}.#{d6} "
        end #case elem[1].depth
      end #if use_numbers

      toc+=elem[1].l_anchor refnum
    end
    toc+="</div>\n" #end __toc_content
    toc+="</div>\n" #end __toc
    
  end #if tags_hash.length > 0

  #The location of the toc token may have changed, so get its location
  toc_md = result.match(token)
  result[toc_md.begin(0)..toc_md.end(0)] = toc
  
  result
end