aboutsummaryrefslogtreecommitdiffstats
path: root/railties/guides/rails_guides/indexer.rb
diff options
context:
space:
mode:
Diffstat (limited to 'railties/guides/rails_guides/indexer.rb')
-rw-r--r--railties/guides/rails_guides/indexer.rb51
1 files changed, 51 insertions, 0 deletions
diff --git a/railties/guides/rails_guides/indexer.rb b/railties/guides/rails_guides/indexer.rb
new file mode 100644
index 0000000000..52809829e2
--- /dev/null
+++ b/railties/guides/rails_guides/indexer.rb
@@ -0,0 +1,51 @@
+module RailsGuides
+ class Indexer
+ attr_reader :body, :result, :level_hash
+
+ def initialize(body)
+ @body = body
+ @result = @body.dup
+ end
+
+ def index
+ @level_hash = process(body)
+ end
+
+ private
+
+ def process(string, current_level= 3, counters = [1])
+ s = StringScanner.new(string)
+
+ level_hash = ActiveSupport::OrderedHash.new
+
+ while !s.eos?
+ s.match?(/\h[0-9]\..*$/)
+ if matched = s.matched
+ matched =~ /\h([0-9])\.(.*)$/
+ level, title = $1.to_i, $2
+
+ if level < current_level
+ # This is needed. Go figure.
+ return level_hash
+ elsif level == current_level
+ index = counters.join(".")
+ bookmark = '#' + title.gsub(/[^a-z0-9\-_\+]+/i, '').underscore.dasherize
+
+ raise "Parsing Fail" unless @result.sub!(matched, "h#{level}(#{bookmark}). #{index}#{title}")
+
+ # Recurse
+ counters << 1
+ level_hash[title.strip] = process(s.post_match, current_level + 1, counters)
+ counters.pop
+
+ # Increment the current level
+ last = counters.pop
+ counters << last + 1
+ end
+ end
+ s.getch
+ end
+ level_hash
+ end
+ end
+end