diff --git a/lib/rdoc/generator/template/rails/_context.rhtml b/lib/rdoc/generator/template/rails/_context.rhtml index 4e5bc6d6..503ece06 100644 --- a/lib/rdoc/generator/template/rails/_context.rhtml +++ b/lib/rdoc/generator/template/rails/_context.rhtml @@ -1,5 +1,5 @@
- <% unless (description = context.description).empty? %> + <% unless (description = @context.description).empty? %>
<%= description %>
@@ -7,10 +7,10 @@ <%# File only: requires %> - <% unless context.requires.empty? %> + <% unless @context.requires.empty? %>
Required Files
@@ -18,7 +18,7 @@ <%# Module only: ancestors %> - <% unless context.is_a?(RDoc::TopLevel) || (ancestors = module_ancestors(context)).empty? %> + <% unless @context.is_a?(RDoc::TopLevel) || (ancestors = module_ancestors(@context)).empty? %>
Inherits From
<% end %> - <% unless context.method_list.empty? %> + <% unless @context.method_list.empty? %>
Methods
- <% group_by_first_letter(context.method_list).each do |letter, methods| %> + <% group_by_first_letter(@context.method_list).each do |letter, methods| %>
<%= letter %>
    @@ -64,7 +64,7 @@ - <% context.each_section do |section, constants, attributes| %> + <% @context.each_section do |section, constants, attributes| %> <% if section.title then %>
    @@ -117,7 +117,7 @@ <% - context.methods_by_type(section).each do |type, visibilities| + @context.methods_by_type(section).each do |type, visibilities| next if visibilities.empty? visibilities.each do |visibility, methods| @@ -174,11 +174,11 @@ <% end %><%# context.methods_by_type %> <% end %><%# context.each_section %> - <% unless context.classes_and_modules.empty? %> + <% unless @context.classes_and_modules.empty? %>
    Namespace
      - <% (context.modules.sort + context.classes.sort).each do |mod| %> + <% (@context.modules.sort + @context.classes.sort).each do |mod| %>
    • <%= mod.type %> <%= link_to mod %> diff --git a/lib/rdoc/generator/template/rails/_head.rhtml b/lib/rdoc/generator/template/rails/_head.rhtml index 5be0661a..f298ec24 100644 --- a/lib/rdoc/generator/template/rails/_head.rhtml +++ b/lib/rdoc/generator/template/rails/_head.rhtml @@ -1,4 +1,4 @@ -<%= base_tag_for_context(context) %> +<%= base_tag_for_context(@context) %> @@ -11,13 +11,13 @@ -<% if canonical = canonical_url(context) %> +<% if canonical = canonical_url(@context) %> "> <% end %> -<% if description = page_description(context.description) %> +<% if description = page_description(@context.description) %> <% end %> diff --git a/lib/rdoc/generator/template/rails/class.rhtml b/lib/rdoc/generator/template/rails/class.rhtml index 8f630ba1..205c5e2a 100644 --- a/lib/rdoc/generator/template/rails/class.rhtml +++ b/lib/rdoc/generator/template/rails/class.rhtml @@ -2,28 +2,28 @@ - <%= page_title klass.full_name %> + <%= page_title @context.full_name %> - <%= include_template '_head.rhtml', {:context => klass, :tree_keys => klass.full_name.split('::') } %> + <%= render "_head.rhtml", { :tree_keys => @context.full_name.split('::') } %> - + Skip to Content Skip to Search - <%= include_template '_panel.rhtml' %> + <%= render "_panel.rhtml" %>
      -

      <%= klass.type %> <%= module_breadcrumbs klass %>

      +

      <%= @context.type %> <%= module_breadcrumbs @context %>

      - <%= include_template '_context.rhtml', {:context => klass} %> + <%= render "_context.rhtml" %>
      Definition files
      - <%= more_less_ul klass.in_files.map { |file| link_to file }, 5..9 %> + <%= more_less_ul @context.in_files.map { |file| link_to file }, 5..9 %>
      diff --git a/lib/rdoc/generator/template/rails/file.rhtml b/lib/rdoc/generator/template/rails/file.rhtml index cfb7b3aa..c2a5637b 100644 --- a/lib/rdoc/generator/template/rails/file.rhtml +++ b/lib/rdoc/generator/template/rails/file.rhtml @@ -2,31 +2,31 @@ - <%= page_title file.name %> + <%= page_title @context.name %> - <%= include_template '_head.rhtml', {:context => file, :tree_keys => [] } %> + <%= render "_head.rhtml", { :tree_keys => [] } %> - + Skip to Content Skip to Search - <%= include_template '_panel.rhtml' %> + <%= render "_panel.rhtml" %>
      - <%= "

      " if file.comment.empty? %> - <%= full_name file %> - <%= "

      " if file.comment.empty? %> + <%= "

      " if @context.comment.empty? %> + <%= full_name @context %> + <%= "

      " if @context.comment.empty? %>
      - <% if source_url = github_url(file.relative_name) %> + <% if source_url = github_url(@context.relative_name) %> <% end %> - <%= include_template '_context.rhtml', {:context => file} %> + <%= render "_context.rhtml" %>
      diff --git a/lib/rdoc/generator/template/rails/file_links.rhtml b/lib/rdoc/generator/template/rails/file_links.rhtml index 2cbb4f9b..376dcc2b 100644 --- a/lib/rdoc/generator/template/rails/file_links.rhtml +++ b/lib/rdoc/generator/template/rails/file_links.rhtml @@ -6,7 +6,7 @@ - <% @files.each do |file| %> + <% @context.each do |file| %> <%= file.relative_name %> <% end %> diff --git a/lib/rdoc/generator/template/rails/index.rhtml b/lib/rdoc/generator/template/rails/index.rhtml index 32ab2f72..88ac6c42 100644 --- a/lib/rdoc/generator/template/rails/index.rhtml +++ b/lib/rdoc/generator/template/rails/index.rhtml @@ -4,17 +4,17 @@ <%= page_title %> - <%= include_template '_head.rhtml', {:context => index, tree_keys: []} %> + <%= render "_head.rhtml", {tree_keys: []} %> Skip to Content Skip to Search - <%= include_template '_panel.rhtml' %> + <%= render "_panel.rhtml" %>
      - <%= include_template '_context.rhtml', {:context => index } %> + <%= render "_context.rhtml" %>
      diff --git a/lib/sdoc/generator.rb b/lib/sdoc/generator.rb index d46fef68..582625fa 100644 --- a/lib/sdoc/generator.rb +++ b/lib/sdoc/generator.rb @@ -1,4 +1,3 @@ -require 'erb' require 'pathname' require 'fileutils' require 'json' @@ -6,10 +5,10 @@ require "rdoc" require_relative "rdoc_monkey_patches" -require 'sdoc/templatable' -require 'sdoc/helpers' -require 'sdoc/search_index' -require 'sdoc/version' +require "sdoc/postprocessor" +require "sdoc/renderer" +require "sdoc/search_index" +require "sdoc/version" class RDoc::ClassModule def with_documentation? @@ -27,10 +26,6 @@ class RDoc::Generator::SDoc DESCRIPTION = 'Searchable HTML documentation' - include ERB::Util - include SDoc::Templatable - include SDoc::Helpers - TREE_FILE = File.join 'panel', 'tree.js' FILE_DIR = 'files' @@ -38,8 +33,6 @@ class RDoc::Generator::SDoc RESOURCES_DIR = File.join('resources', '.') - attr_reader :base_dir - attr_reader :options ## @@ -81,17 +74,15 @@ def initialize(store, options) @options.pipe = true @original_dir = Pathname.pwd - @template_dir = Pathname.new(options.template_dir) - @base_dir = options.root + @template_dir = Pathname(options.template_dir) + @output_dir = Pathname(@options.op_dir).expand_path(options.root) end def generate - @outputdir = Pathname.new(@options.op_dir).expand_path(@base_dir) - FileUtils.mkdir_p @outputdir @files = @store.all_files.sort @classes = @store.all_classes_and_modules.sort - # Now actually write the output + FileUtils.mkdir_p(@output_dir) copy_resources generate_search_index generate_file_links @@ -131,50 +122,45 @@ def debug_msg( *msg ) $stderr.puts( *msg ) end + def render_file(template_path, output_path, context = nil) + return if @options.dry_run + + result = SDoc::Renderer.new(context, @options).render(template_path) + result = SDoc::Postprocessor.process(result) + + output_path = @output_dir.join(output_path) + output_path.dirname.mkpath + output_path.write(result) + end + ### Create index.html with frameset def generate_index_file - debug_msg "Generating index file in #{@outputdir}" - templatefile = @template_dir + 'index.rhtml' - outfile = @outputdir + 'index.html' - - render_template(templatefile, binding, outfile) + debug_msg "Generating index file in #{@output_dir}" + render_file("index.rhtml", "index.html", index) end ### Generate a documentation file for each class def generate_class_files - debug_msg "Generating class documentation in #{@outputdir}" - templatefile = @template_dir + 'class.rhtml' - + debug_msg "Generating class documentation in #{@output_dir}" @classes.each do |klass| - debug_msg " working on %s (%s)" % [ klass.full_name, klass.path ] - outfile = @outputdir + klass.path - - debug_msg " rendering #{outfile}" - render_template(templatefile, binding, outfile) + debug_msg " rendering #{klass.path}" + render_file("class.rhtml", klass.path, klass) end end ### Generate a documentation file for each file def generate_file_files - debug_msg "Generating file documentation in #{@outputdir}" - templatefile = @template_dir + 'file.rhtml' - + debug_msg "Generating file documentation in #{@output_dir}" @files.each do |file| - outfile = @outputdir + file.path - debug_msg " working on %s (%s)" % [ file.full_name, outfile ] - - debug_msg " rendering #{outfile}" - render_template(templatefile, binding, outfile) + debug_msg " rendering #{file.path}" + render_file("file.rhtml", file.path, file) end end ### Generate file with links for the search engine def generate_file_links - debug_msg "Generating search engine index in #{@outputdir}" - templatefile = @template_dir + 'file_links.rhtml' - outfile = @outputdir + 'panel/file_links.html' - - render_template(templatefile, binding, outfile) + debug_msg "Generating search engine index in #{@output_dir}" + render_file("file_links.rhtml", "panel/file_links.html", @files) end ### Create class tree structure and write it as json @@ -182,7 +168,7 @@ def generate_class_tree debug_msg "Generating class tree" topclasses = @classes.select {|klass| !(RDoc::ClassModule === klass.parent) } tree = generate_file_tree + generate_class_tree_level(topclasses) - file = @outputdir + TREE_FILE + file = @output_dir + TREE_FILE debug_msg " writing class tree to %s" % file File.open(file, "w", 0644) do |f| f.write('var tree = '); f.write(tree.to_json(:max_nesting => 0)) @@ -212,7 +198,7 @@ def generate_search_index unless @options.dry_run index = SDoc::SearchIndex.generate(@store.all_classes_and_modules) - @outputdir.join("js/search-index.js").open("w") do |file| + @output_dir.join("js/search-index.js").open("w") do |file| file.write("export default ") JSON.dump(index, file) file.write(";") @@ -223,8 +209,8 @@ def generate_search_index ### Copy all the resource files to output dir def copy_resources resources_path = @template_dir + RESOURCES_DIR - debug_msg "Copying #{resources_path}/** to #{@outputdir}/**" - FileUtils.cp_r resources_path.to_s, @outputdir.to_s unless @options.dry_run + debug_msg "Copying #{resources_path}/** to #{@output_dir}/**" + FileUtils.cp_r resources_path.to_s, @output_dir.to_s unless @options.dry_run end class FilesTree diff --git a/lib/sdoc/helpers.rb b/lib/sdoc/helpers.rb index 42c95693..96879ce8 100644 --- a/lib/sdoc/helpers.rb +++ b/lib/sdoc/helpers.rb @@ -1,4 +1,8 @@ +require "erb" + module SDoc::Helpers + include ERB::Util + require_relative "helpers/git" include SDoc::Helpers::Git diff --git a/lib/sdoc/renderer.rb b/lib/sdoc/renderer.rb new file mode 100644 index 00000000..774df17c --- /dev/null +++ b/lib/sdoc/renderer.rb @@ -0,0 +1,27 @@ +require "erb" +require_relative "helpers" + +class SDoc::Renderer + include SDoc::Helpers + + def self.compile_erb(path) + @compiled_erb ||= {} + @compiled_erb[path] ||= begin + erb = ERB.new(File.read(path), trim_mode: "<>") + erb.filename = path + erb + end + end + + def initialize(context, rdoc_options) + @context = context + @options = rdoc_options + end + + def render(template_path, local_assigns = {}) + template_path = File.expand_path(template_path, @options.template_dir) + _binding = binding + local_assigns.each { |name, value| _binding.local_variable_set(name, value) } + self.class.compile_erb(template_path).result(_binding) + end +end diff --git a/lib/sdoc/templatable.rb b/lib/sdoc/templatable.rb deleted file mode 100644 index 3b5158d1..00000000 --- a/lib/sdoc/templatable.rb +++ /dev/null @@ -1,41 +0,0 @@ -require 'erb' -require_relative "postprocessor" - -module SDoc::Templatable - ### Load and render the erb template in the given +templatefile+ within the - ### specified +context+ (a Binding object) and return output - ### Both +templatefile+ and +outfile+ should be Pathname-like objects. - def eval_template(templatefile, context) - template_src = templatefile.read - template = ERB.new(template_src, trim_mode: "<>") - template.filename = templatefile.to_s - - begin - template.result( context ) - rescue NoMethodError => err - raise RDoc::Error, "Error while evaluating %s: %s (at %p)" % [ - templatefile.to_s, - err.message, - eval( "_erbout[-50,50]", context ) - ], err.backtrace - end - end - - ### Load and render the erb template with the given +template_name+ within - ### current context. Adds all +local_assigns+ to context - def include_template(template_name, local_assigns = {}) - source = local_assigns.keys.map { |key| "#{key} = local_assigns[:#{key}];" }.join - templatefile = templatefile = @template_dir + template_name - eval("#{source};eval_template(templatefile, binding)") - end - - ### Load and render the erb template in the given +templatefile+ within the - ### specified +context+ (a Binding object) and write it out to +outfile+. - ### Both +templatefile+ and +outfile+ should be Pathname-like objects. - def render_template(templatefile, context, outfile) - return if @options.dry_run - output = SDoc::Postprocessor.process(eval_template(templatefile, context)) - outfile.dirname.mkpath - outfile.write(output) - end -end diff --git a/spec/helpers_spec.rb b/spec/helpers_spec.rb index 7539f0f0..bd014ae1 100644 --- a/spec/helpers_spec.rb +++ b/spec/helpers_spec.rb @@ -3,7 +3,6 @@ describe SDoc::Helpers do before :each do @helpers = Class.new do - include ERB::Util include SDoc::Helpers attr_accessor :options diff --git a/spec/rdoc_generator_spec.rb b/spec/rdoc_generator_spec.rb index 2ce4c50d..6b12e569 100644 --- a/spec/rdoc_generator_spec.rb +++ b/spec/rdoc_generator_spec.rb @@ -113,8 +113,7 @@ def parse_options(*options) end it "raises when the default value is not a file" do - sdoc = rdoc_dry_run("--files", @dir, "--exclude=(js|css|svg)$").generator - error = _{ sdoc.index }.must_raise + error = _{ rdoc_dry_run("--files", @dir, "--exclude=(js|css|svg)$") }.must_raise _(error.message).must_include @dir end @@ -127,8 +126,7 @@ def parse_options(*options) it "raises when the main page is not among the rendered files" do Dir.chdir(@dir) do - sdoc = rdoc_dry_run("--main", @files.first, "--files", @files.last).generator - error = _{ sdoc.index }.must_raise + error = _{ rdoc_dry_run("--main", @files.first, "--files", @files.last) }.must_raise _(error.message).must_include @files.first end end diff --git a/spec/renderer_spec.rb b/spec/renderer_spec.rb new file mode 100644 index 00000000..3e417f1f --- /dev/null +++ b/spec/renderer_spec.rb @@ -0,0 +1,55 @@ +require "spec_helper" + +describe SDoc::Renderer do + before do + @template_dir = Dir.mktmpdir + @rdoc_options = RDoc::Options.new.tap do |options| + options.template_dir = @template_dir + end + end + + after do + FileUtils.remove_entry(@template_dir) + end + + def create_template(name, erb) + File.write(File.join(@template_dir, name), erb) + end + + describe "#render" do + it "renders an ERB template" do + create_template "foo.erb", %(<%= "foo".upcase %>) + + _(SDoc::Renderer.new(nil, @rdoc_options).render("foo.erb")). + must_equal "FOO" + end + + it "supports local variables" do + create_template "foo.erb", %(<%= foo.upcase %>) + + _(SDoc::Renderer.new(nil, @rdoc_options).render("foo.erb", { foo: "bar" })). + must_equal "BAR" + end + + it "provides access to @context" do + create_template "foo.erb", %(<%= @context[:foo] %>) + + _(SDoc::Renderer.new({ foo: "bar" }, @rdoc_options).render("foo.erb")). + must_equal "bar" + end + + it "provides access to @options" do + create_template "foo.erb", %(<%= @options.object_id %>) + + _(SDoc::Renderer.new(nil, @rdoc_options).render("foo.erb")). + must_equal @rdoc_options.object_id.to_s + end + + it "provides access to helper methods" do + create_template "foo.erb", %(<%= h "foo & bar" %>) + + _(SDoc::Renderer.new(nil, @rdoc_options).render("foo.erb")). + must_equal "foo & bar" + end + end +end