aboutsummaryrefslogtreecommitdiffstats
path: root/guides/rails_guides/indexer.rb
diff options
context:
space:
mode:
Diffstat (limited to 'guides/rails_guides/indexer.rb')
-rw-r--r--guides/rails_guides/indexer.rb68
1 files changed, 68 insertions, 0 deletions
diff --git a/guides/rails_guides/indexer.rb b/guides/rails_guides/indexer.rb
new file mode 100644
index 0000000000..89fbccbb1d
--- /dev/null
+++ b/guides/rails_guides/indexer.rb
@@ -0,0 +1,68 @@
+require 'active_support/core_ext/object/blank'
+require 'active_support/core_ext/string/inflections'
+
+module RailsGuides
+ class Indexer
+ attr_reader :body, :result, :warnings, :level_hash
+
+ def initialize(body, warnings)
+ @body = body
+ @result = @body.dup
+ @warnings = warnings
+ end
+
+ def index
+ @level_hash = process(body)
+ end
+
+ private
+
+ def process(string, current_level=3, counters=[1])
+ s = StringScanner.new(string)
+
+ level_hash = {}
+
+ while !s.eos?
+ re = %r{^h(\d)(?:\((#.*?)\))?\s*\.\s*(.*)$}
+ s.match?(re)
+ if matched = s.matched
+ matched =~ re
+ level, idx, title = $1.to_i, $2, $3.strip
+
+ if level < current_level
+ # This is needed. Go figure.
+ return level_hash
+ elsif level == current_level
+ index = counters.join(".")
+ idx ||= '#' + title_to_idx(title)
+
+ raise "Parsing Fail" unless @result.sub!(matched, "h#{level}(#{idx}). #{index} #{title}")
+
+ key = {
+ :title => title,
+ :id => idx
+ }
+ # Recurse
+ counters << 1
+ level_hash[key] = 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
+
+ def title_to_idx(title)
+ idx = title.strip.parameterize.sub(/^\d+/, '')
+ if warnings && idx.blank?
+ puts "BLANK ID: please put an explicit ID for section #{title}, as in h5(#my-id)"
+ end
+ idx
+ end
+ end
+end