Skip to content

Commit

Permalink
Add SDoc::Renderer#inline
Browse files Browse the repository at this point in the history
`SDoc::Renderer#inline` renders a template to the current output buffer
instead of as a separate string.  It also allows a block to be specified
so that the template can `yield` to perform interleaved rendering.  For
example:

  ```erb
  <% inline "_partial.erb" do %>
    content
  <% end %>
  ```

  ```erb
  <%# _partial.erb %>
  <div><% yield %></div>
  ```

Renders:

  ```html
  <div>
    content
  </div>
  ```
  • Loading branch information
jonathanhefner committed Oct 2, 2023
1 parent 7ebabb1 commit eed2539
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 11 deletions.
6 changes: 3 additions & 3 deletions lib/rdoc/generator/template/rails/class.rhtml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="<%= @options.charset %>">
<title><%= page_title @context.full_name %></title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= render "_head.rhtml", { :tree_keys => @context.full_name.split('::') } %>
<% inline "_head.rhtml", { :tree_keys => @context.full_name.split('::') } %>

<meta property="og:title" value="<%= og_title @context.full_name %>">
</head>
Expand All @@ -13,14 +13,14 @@
<a class="sr-only sr-only-focusable" href="#context" data-turbo="false">Skip to Content</a>
<a class="sr-only sr-only-focusable" href="#search" data-turbo="false">Skip to Search</a>

<%= render "_panel.rhtml" %>
<% inline "_panel.rhtml" %>

<main id="content">
<hgroup class="content__title">
<h1><span class="kind"><%= @context.type %></span> <%= module_breadcrumbs @context %></h1>
</hgroup>

<%= render "_context.rhtml" %>
<% inline "_context.rhtml" %>

<div class="content__divider">Definition files</div>
<%= more_less_ul @context.in_files.map { |file| link_to file }, 5..9 %>
Expand Down
6 changes: 3 additions & 3 deletions lib/rdoc/generator/template/rails/file.rhtml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="<%= @options.charset %>">
<title><%= page_title @context.name %></title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= render "_head.rhtml", { :tree_keys => [] } %>
<% inline "_head.rhtml", { :tree_keys => [] } %>

<meta property="og:title" value="<%= og_title @context.name %>">
</head>
Expand All @@ -13,7 +13,7 @@
<a class="sr-only sr-only-focusable" href="#context" data-turbo="false">Skip to Content</a>
<a class="sr-only sr-only-focusable" href="#search" data-turbo="false">Skip to Search</a>

<%= render "_panel.rhtml" %>
<% inline "_panel.rhtml" %>

<main id="content">
<div class="content__title">
Expand All @@ -26,7 +26,7 @@
<p class="content__source-link"><%= link_to_external "View on GitHub", source_url %></p>
<% end %>

<%= render "_context.rhtml" %>
<% inline "_context.rhtml" %>
</main>
</body>
</html>
6 changes: 3 additions & 3 deletions lib/rdoc/generator/template/rails/index.rhtml
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
<meta charset="<%= @options.charset %>">
<title><%= page_title %></title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= render "_head.rhtml", {tree_keys: []} %>
<% inline "_head.rhtml", {tree_keys: []} %>
</head>

<body>
<a class="sr-only sr-only-focusable" href="#context" data-turbo="false">Skip to Content</a>
<a class="sr-only sr-only-focusable" href="#search" data-turbo="false">Skip to Search</a>

<%= render "_panel.rhtml" %>
<% inline "_panel.rhtml" %>

<main id="content">
<%= render "_context.rhtml" %>
<% inline "_context.rhtml" %>
</main>
</body>
</html>
15 changes: 13 additions & 2 deletions lib/sdoc/renderer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,29 @@ class SDoc::Renderer
def self.compile_erb(path)
@compiled_erb ||= {}
@compiled_erb[path] ||= begin
erb = ERB.new(File.read(path), trim_mode: "<>")
erb = ERB.new(File.read(path), trim_mode: "<>", eoutvar: "self.buffer")
erb.filename = path
erb
end
end

attr_reader :buffer
def buffer=(*); end # Ignore buffer reset from ERB itself.

def initialize(context, rdoc_options)
@context = context
@options = rdoc_options
@buffer = nil
end

def render(...)
original_buffer, @buffer = @buffer, +""
inline(...)
ensure
@buffer = original_buffer
end

def render(template_path, local_assigns = {})
def inline(template_path, local_assigns = {}, &block)
template_path = File.expand_path(template_path, @options.template_dir)
_binding = binding
local_assigns.each { |name, value| _binding.local_variable_set(name, value) }
Expand Down
63 changes: 63 additions & 0 deletions spec/renderer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,68 @@ def create_template(name, erb)
_(SDoc::Renderer.new(nil, @rdoc_options).render("foo.erb")).
must_equal "foo &amp; bar"
end

it "is reentrant" do
create_template "foo.erb", %(1 + 1 = <%= render "two.erb" %>)
create_template "two.erb", %(<%= 1 + 1 %>)

_(SDoc::Renderer.new(nil, @rdoc_options).render("foo.erb")).
must_equal "1 + 1 = 2"
end
end

describe "#inline" do
it "supports isolated local variables" do
create_template "outer.erb", %(<%= foo %> <% inline "inner.erb", bar: "BAR" %> <%= foo %>)
create_template "inner.erb", %(<%= foo = bar %>)

_(SDoc::Renderer.new(nil, @rdoc_options).render("outer.erb", { foo: "FOO" })).
must_equal "FOO BAR FOO"
end

it "provides access to the same non-local values as #render" do
create_template "outer.erb", %(<% inline "inner.erb" %>)
create_template "inner.erb", %(<%= h @context[:foobar] %>)

_(SDoc::Renderer.new({ foobar: "foo & bar" }, @rdoc_options).render("outer.erb")).
must_equal "foo &amp; bar"
end

it "supports yield" do
# There is currently a bug in TruffleRuby wherein `binding` does not
# capture the block that `yield` will call.
skip if RUBY_ENGINE == "truffleruby"

create_template "outer.erb", '1 <% inline("inner.erb") { 3 } %> 5'
create_template "inner.erb", %(2 <%= yield %> 4)

_(SDoc::Renderer.new(nil, @rdoc_options).render("outer.erb")).
must_equal "1 2 3 4 5"
end

it "supports block.call" do
create_template "outer.erb", '1 <% inline("inner.erb") { 3 } %> 5'
create_template "inner.erb", %(2 <%= block.call %> 4)

_(SDoc::Renderer.new(nil, @rdoc_options).render("outer.erb")).
must_equal "1 2 3 4 5"
end

it "supports interleaved rendering" do
create_template "outer.erb", '1 <% inline("inner.erb") do %>3<% end %> 5'
create_template "inner.erb", %(2 <% block.call %> 4)

_(SDoc::Renderer.new(nil, @rdoc_options).render("outer.erb")).
must_equal "1 2 3 4 5"
end

it "supports interleaved rendering with nested #inline calls" do
create_template "outer.erb", '1 <% inline("middle.erb") { inline("inner.erb") } %> 5'
create_template "middle.erb", %(2 <% block.call %> 4)
create_template "inner.erb", %(3)

_(SDoc::Renderer.new(nil, @rdoc_options).render("outer.erb")).
must_equal "1 2 3 4 5"
end
end
end

0 comments on commit eed2539

Please sign in to comment.