Skip to content

Commit 3a8e0be

Browse files
committed
Add to_iruby_mimebundle support
1 parent 1205fa1 commit 3a8e0be

File tree

2 files changed

+215
-1
lines changed

2 files changed

+215
-1
lines changed

lib/iruby/display.rb

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def display(obj, options = {})
3030
render(data, obj, exact_mime, fuzzy_mime)
3131

3232
# IPython always requires a text representation
33-
render(data, obj, 'text/plain', nil) unless data['text/plain']
33+
render_by_registry(data, obj, 'text/plain', nil) unless data['text/plain']
3434

3535
# As a last resort, interpret string representation of the object
3636
# as the given mime type.
@@ -68,6 +68,32 @@ def ascii?(mime)
6868
end
6969

7070
def render(data, obj, exact_mime, fuzzy_mime)
71+
# First examine to_iruby_mimebundle
72+
73+
if obj.respond_to?(:to_iruby_mimebundle)
74+
# If the object can respond to to_iruby_mimebundle,
75+
# IRuby uses it and ignores all the registered renderer.
76+
kwargs = {}
77+
include_mime = [exact_mime, fuzzy_mime].compact
78+
kwargs[:include] = include_mime unless include_mime.empty?
79+
# TODO: support `exclude:` keyword argument to specify mime types to be excluded
80+
81+
# TODO: should handle metadata correctly
82+
formats, metadata = obj.to_iruby_mimebundle(**kwargs)
83+
84+
# formats should be a Hash that maps mime-type string to
85+
# the redered data.
86+
formats.each do |mime, value|
87+
data[mime] = value unless value.nil?
88+
end
89+
end
90+
91+
unless data.key?(exact_mime)
92+
render_by_registry(data, obj, exact_mime, fuzzy_mime)
93+
end
94+
end
95+
96+
private def render_by_registry(data, obj, exact_mime, fuzzy_mime)
7197
# Filter matching renderer by object type
7298
renderer = Registry.renderer.select { |r| r.match?(obj) }
7399

test/iruby/display_test.rb

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
module IRubyTest
2+
class DisplayTest < TestBase
3+
def setup
4+
@object = Object.new
5+
@object.instance_variable_set(:@to_html_called, false)
6+
@object.instance_variable_set(:@to_markdown_called, false)
7+
@object.instance_variable_set(:@to_iruby_called, false)
8+
@object.instance_variable_set(:@to_iruby_mimebundle_called, false)
9+
10+
class << @object
11+
attr_reader :to_html_called
12+
attr_reader :to_markdown_called
13+
attr_reader :to_iruby_called
14+
attr_reader :to_iruby_mimebundle_called
15+
16+
def html
17+
"<b>html</b>"
18+
end
19+
20+
def markdown
21+
"*markdown*"
22+
end
23+
24+
def inspect
25+
"!!! inspect !!!"
26+
end
27+
end
28+
end
29+
30+
def define_to_html
31+
class << @object
32+
def to_html
33+
@to_html_called = true
34+
html
35+
end
36+
end
37+
end
38+
39+
def define_to_markdown
40+
class << @object
41+
def to_markdown
42+
@to_markdown_called = true
43+
markdown
44+
end
45+
end
46+
end
47+
48+
def define_to_iruby
49+
class << @object
50+
def to_iruby
51+
@to_iruby_called = true
52+
["text/html", "<b>to_iruby</b>"]
53+
end
54+
end
55+
end
56+
57+
def define_to_iruby_mimebundle
58+
class << @object
59+
def to_iruby_mimebundle(include: [])
60+
@to_iruby_mimebundle_called = true
61+
mimes = if include.empty?
62+
["text/html", "text/markdown", "application/json"]
63+
else
64+
include
65+
end
66+
formats = mimes.map { |mime|
67+
result = case mime
68+
when "text/html"
69+
"<i>html</i>"
70+
when "text/markdown"
71+
"**markdown**"
72+
when "application/json"
73+
%Q[{"mimebundle": "json"}]
74+
end
75+
[mime, result]
76+
}.to_h
77+
metadata = {}
78+
return formats, metadata
79+
end
80+
end
81+
end
82+
83+
def assert_iruby_display(expected)
84+
assert_equal(expected,
85+
{
86+
result: IRuby::Display.display(@object),
87+
to_html_called: @object.to_html_called,
88+
to_markdown_called: @object.to_markdown_called,
89+
to_iruby_called: @object.to_iruby_called,
90+
to_iruby_mimebundle_called: @object.to_iruby_mimebundle_called
91+
})
92+
end
93+
94+
sub_test_case("the object cannot handle all the mime types") do
95+
def test_display
96+
assert_iruby_display({
97+
result: {"text/plain" => "!!! inspect !!!"},
98+
to_html_called: false,
99+
to_markdown_called: false,
100+
to_iruby_called: false,
101+
to_iruby_mimebundle_called: false
102+
})
103+
end
104+
end
105+
106+
sub_test_case("the object can respond to to_iruby") do
107+
def setup
108+
super
109+
define_to_iruby
110+
end
111+
112+
def test_display
113+
assert_iruby_display({
114+
result: {
115+
"text/html" => "<b>to_iruby</b>",
116+
"text/plain" => "!!! inspect !!!"
117+
},
118+
to_html_called: false,
119+
to_markdown_called: false,
120+
to_iruby_called: true,
121+
to_iruby_mimebundle_called: false
122+
})
123+
end
124+
125+
sub_test_case("the object can respond to to_markdown") do
126+
def setup
127+
super
128+
define_to_markdown
129+
end
130+
131+
def test_display
132+
assert_iruby_display({
133+
result: {
134+
"text/html" => "<b>to_iruby</b>",
135+
"text/plain" => "!!! inspect !!!"
136+
},
137+
to_html_called: false,
138+
to_markdown_called: false,
139+
to_iruby_called: true,
140+
to_iruby_mimebundle_called: false
141+
})
142+
end
143+
end
144+
145+
sub_test_case("the object can respond to to_html") do
146+
def setup
147+
super
148+
define_to_html
149+
end
150+
151+
def test_display
152+
assert_iruby_display({
153+
result: {
154+
"text/html" => "<b>html</b>",
155+
"text/plain" => "!!! inspect !!!"
156+
},
157+
to_html_called: true,
158+
to_markdown_called: false,
159+
to_iruby_called: false,
160+
to_iruby_mimebundle_called: false
161+
})
162+
end
163+
164+
sub_test_case("the object can respond to to_iruby_mimebundle") do
165+
def setup
166+
super
167+
define_to_iruby_mimebundle
168+
end
169+
170+
def test_display
171+
assert_iruby_display({
172+
result: {
173+
"text/html" => "<b>html</b>",
174+
"text/markdown" => "**markdown**",
175+
"application/json" => %Q[{"mimebundle": "json"}],
176+
"text/plain" => "!!! inspect !!!"
177+
},
178+
to_html_called: true,
179+
to_markdown_called: false,
180+
to_iruby_called: false,
181+
to_iruby_mimebundle_called: true
182+
})
183+
end
184+
end
185+
end
186+
end
187+
end
188+
end

0 commit comments

Comments
 (0)