From efa7717b7ab71f026df4e464046519e973c31f9a Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Fri, 31 Aug 2012 17:49:17 -0400 Subject: [PATCH] 4.0 release note now renders correctly with index --- guides/rails_guides/markdown.rb | 95 +++++++++++++++++++++--- guides/rails_guides/markdown/renderer.rb | 31 ++++++-- guides/source/4_0_release_notes.md | 2 + 3 files changed, 113 insertions(+), 15 deletions(-) diff --git a/guides/rails_guides/markdown.rb b/guides/rails_guides/markdown.rb index a56d0d2d85..12eabcbcc8 100644 --- a/guides/rails_guides/markdown.rb +++ b/guides/rails_guides/markdown.rb @@ -7,15 +7,25 @@ class Markdown def initialize(view, layout) @view = view @layout = layout + @index_counter = Hash.new(0) end def render(body) - @header, _, @body = body.partition(/^\-{40,}$/) - render_header - render_body + @raw_header, _, @raw_body = body.partition(/^\-{40,}$/).map(&:strip) + generate_header + generate_title + generate_body + generate_structure + generate_index + render_page end private + + def dom_id(nodes) + nodes.map{ |node| node.text.downcase.gsub(/[^a-z0-9]+/, '-') }.join('-') + end + def engine @engine ||= Redcarpet::Markdown.new(Renderer, { no_intra_emphasis: true, @@ -26,17 +36,82 @@ def engine }) end - def render_header - header_content = engine.render(@header) - @view.content_for(:header_section) { header_content.html_safe } + def generate_body + @body = engine.render(@raw_body) + end + + def generate_header + @header = engine.render(@raw_header).html_safe + end + + def generate_structure + @raw_index = '' + @body = Nokogiri::HTML(@body).tap do |doc| + hierarchy = [] + + doc.at('body').children.each do |node| + if node.name =~ /^h[3-6]$/ + case node.name + when 'h3' + hierarchy = [node] + node[:id] = dom_id(hierarchy) + @raw_index += "1. [#{node.text}](##{node[:id]})\n" + when 'h4' + hierarchy = hierarchy[0, 1] + [node] + node[:id] = dom_id(hierarchy) + @raw_index += " * [#{node.text}](##{node[:id]})\n" + when 'h5' + hierarchy = hierarchy[0, 2] + [node] + node[:id] = dom_id(hierarchy) + when 'h6' + hierarchy = hierarchy[0, 3] + [node] + node[:id] = dom_id(hierarchy) + end + + node.inner_html = "#{node_index(hierarchy)} #{node.text}" + end + end + end.to_html + end + + def generate_index + @index = Nokogiri::HTML(engine.render(@raw_index)).tap do |doc| + doc.at('ol')[:class] = 'chapters' + end.to_html + + @index = <<-INDEX.html_safe +
+

Chapters

+ #{@index} +
+ INDEX + end + + def generate_title + @title = "Ruby on Rails Guides: #{Nokogiri::HTML(@header).at(:h2).text}".html_safe + end - @view.content_for(:page_title) do - "Ruby on Rails Guides: #{Nokogiri::HTML(header_content).at(:h2).text}".html_safe + def node_index(hierarchy) + case hierarchy.size + when 1 + @index_counter[2] = @index_counter[3] = @index_counter[4] = 0 + "#{@index_counter[1] += 1}" + when 2 + @index_counter[3] = @index_counter[4] = 0 + "#{@index_counter[1]}.#{@index_counter[2] += 1}" + when 3 + @index_counter[4] = 0 + "#{@index_counter[1]}.#{@index_counter[2]}.#{@index_counter[3] += 1}" + when 4 + "#{@index_counter[1]}.#{@index_counter[2]}.#{@index_counter[3]}.#{@index_counter[4] += 1}" end end - def render_body - @view.render(:layout => @layout, :text => engine.render(@body)) + def render_page + @view.content_for(:header_section) { @header } + @view.content_for(:page_title) { @title } + @view.content_for(:index_section) { @index.html_safe } + @view.render(:layout => @layout, :text => @body) end end end diff --git a/guides/rails_guides/markdown/renderer.rb b/guides/rails_guides/markdown/renderer.rb index ea3b7fc044..ec0688f937 100644 --- a/guides/rails_guides/markdown/renderer.rb +++ b/guides/rails_guides/markdown/renderer.rb @@ -5,11 +5,23 @@ def initialize(options={}) super end + def block_code(code, language) + <<-HTML + +
+
+#{ERB::Util.h(code).strip}
+
+
+
+HTML + end + def header(text, header_level) # Always increase the heading level by, so we can use h1, h2 heading in the document header_level += 1 - %(#{text}) + %(#{text}) end def preprocess(full_document) @@ -18,6 +30,19 @@ def preprocess(full_document) private + def brush_for(code_type) + case code_type + when 'ruby', 'sql', 'plain' + code_type + when 'erb' + 'ruby; html-script: true' + when 'html' + 'xml' # html is understood, but there are .xml rules in the CSS + else + 'plain' + end + end + def convert_notes(body) # The following regexp detects special labels followed by a # paragraph, perhaps at the end of the document. @@ -39,10 +64,6 @@ def convert_notes(body) %Q(

#{$2.strip}

\n) end end - - def dom_id(text) - text.downcase.gsub(/[^a-z0-9]+/, '-').strip - end end end end diff --git a/guides/source/4_0_release_notes.md b/guides/source/4_0_release_notes.md index 01045c3dd6..52091289c9 100644 --- a/guides/source/4_0_release_notes.md +++ b/guides/source/4_0_release_notes.md @@ -12,6 +12,7 @@ Upgrading to Rails 4.0 TODO. This is a WIP guide. + If you're upgrading an existing application, it's a great idea to have good test coverage before going in. You should also first upgrade to Rails 3.2 in case you haven't and make sure your application still runs as expected before attempting an update to Rails 4.0. Then take heed of the following changes: ### Rails 4.0 requires at least Ruby 1.9.3 @@ -28,6 +29,7 @@ Rails 4.0 requires Ruby 1.9.3 or higher. Support for all of the previous Ruby ve TODO: Update the versions above. + * Rails 4.0 removes `vendor/plugins` completely. You have to replace these plugins by extracting them as gems and adding them in your Gemfile. If you choose not to make them gems, you can move them into, say, `lib/my_plugin/*` and add an appropriate initializer in `config/initializers/my_plugin.rb`. TODO: Configuration changes in environment files -- GitLab