Skip to content

Commit 73be694

Browse files
committed
Refactor element constructor pattern
Slight change to the pattern to dynamically create exporter objects. This is now aligned with the oembed resolver: - `Base.build(element)` -> create a exporter object - `Base.exporter_by_type(type)` -> find exporter class for element - `Base#export` -> create a exporter object (if necessary) and call `#export` on it - `*#export` -> export a nokogiri node
1 parent 36d9545 commit 73be694

File tree

20 files changed

+141
-44
lines changed

20 files changed

+141
-44
lines changed

lib/article_json/export/html/elements/base.rb

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ def initialize(element)
88
@element = element
99
end
1010

11-
# Build a HTML node out of the given element
11+
# Export a HTML node out of the given element
1212
# Dynamically looks up the right export-element-class, instantiates it
1313
# and then calls the #build method.
1414
# @return [Nokogiri::HTML::Node]
15-
def build
16-
klass = self.class.element_classes[@element.type]
17-
klass.new(@element).build unless klass.nil?
15+
def export
16+
exporter = self.class == Base ? self.class.build(@element) : self
17+
exporter.export unless exporter.nil?
1818
end
1919

2020
private
@@ -28,7 +28,18 @@ def create_text_node(text)
2828
end
2929

3030
class << self
31-
def element_classes
31+
# Instantiate the correct sub class for a given element
32+
# @param [ArticleJSON::Elements::Base] element
33+
# @return [ArticleJSON::Export::HTML::Elements::Base]
34+
def build(element)
35+
klass = exporter_by_type(element.type)
36+
klass.new(element) unless klass.nil?
37+
end
38+
39+
# Look up the correct exporter class based on the element type
40+
# @param [Symbol] type
41+
# @return [ArticleJSON::Export::HTML::Elements::Base]
42+
def exporter_by_type(type)
3243
{
3344
text: Text,
3445
paragraph: Paragraph,
@@ -38,7 +49,7 @@ def element_classes
3849
text_box: TextBox,
3950
quote: Quote,
4051
embed: Embed,
41-
}
52+
}[type.to_sym]
4253
end
4354
end
4455
end

lib/article_json/export/html/elements/embed.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module Elements
55
class Embed < Base
66
include Shared::Caption
77

8-
def build
8+
def export
99
create_element(:figure).tap do |figure|
1010
figure.add_child(embed_node)
1111
figure.add_child(caption_node(:figcaption))

lib/article_json/export/html/elements/heading.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module Export
33
module HTML
44
module Elements
55
class Heading < Base
6-
def build
6+
def export
77
create_element(tag_name, @element.content)
88
end
99

lib/article_json/export/html/elements/image.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class Image < Base
77
include Shared::Float
88

99
# @return [Nokogiri::HTML::Node]
10-
def build
10+
def export
1111
create_element(:figure, node_opts).tap do |figure|
1212
figure.add_child(image_node)
1313
figure.add_child(caption_node(:figcaption))

lib/article_json/export/html/elements/list.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ module Export
33
module HTML
44
module Elements
55
class List < Base
6-
def build
6+
def export
77
create_element(tag_name).tap do |list|
88
@element.content.each do |child_element|
99
item = create_element(:li)
10-
item.add_child(Paragraph.new(child_element).build)
10+
item.add_child(Paragraph.new(child_element).export)
1111
list.add_child(item)
1212
end
1313
end

lib/article_json/export/html/elements/paragraph.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ module Export
33
module HTML
44
module Elements
55
class Paragraph < Base
6-
def build
6+
def export
77
create_element(:p).tap do |p|
88
@element.content.each do |child_element|
9-
p.add_child(Text.new(child_element).build)
9+
p.add_child(Text.new(child_element).export)
1010
end
1111
end
1212
end

lib/article_json/export/html/elements/quote.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ class Quote < Base
66
include Shared::Caption
77
include Shared::Float
88

9-
def build
9+
def export
1010
create_element(:aside, node_opts).tap do |aside|
1111
@element.content.each do |child_element|
12-
aside.add_child(Base.new(child_element).build)
12+
aside.add_child(Base.new(child_element).export)
1313
end
1414
aside.add_child(caption_node(:small))
1515
end

lib/article_json/export/html/elements/shared/caption.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ module Caption
1010
def caption_node(tag_name)
1111
create_element(tag_name).tap do |caption|
1212
@element.caption.each do |child_element|
13-
caption.add_child(Text.new(child_element).build)
13+
caption.add_child(Text.new(child_element).export)
1414
end
1515
end
1616
end

lib/article_json/export/html/elements/text.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module HTML
44
module Elements
55
class Text < Base
66
# @return [Nokogiri::HTML::Node]
7-
def build
7+
def export
88
return bold_and_italic_node if @element.bold && @element.italic
99
return bold_node if @element.bold
1010
return italic_node if @element.italic

lib/article_json/export/html/elements/text_box.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ module Elements
55
class TextBox < Base
66
include Shared::Float
77

8-
def build
8+
def export
99
create_element(:div, node_opts).tap do |div|
1010
@element.content.each do |child_element|
11-
div.add_child(Base.new(child_element).build)
11+
div.add_child(Base.new(child_element).export)
1212
end
1313
end
1414
end

lib/article_json/export/html/exporter.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def initialize(elements)
1212
def html
1313
doc = Nokogiri::HTML.fragment('')
1414
@elements.each do |element|
15-
doc.add_child(Elements::Base.new(element).build)
15+
doc.add_child(Elements::Base.new(element).export)
1616
end
1717
doc.to_html(save_with: 0)
1818
end

spec/article_json/export/html/elements/base_spec.rb

Lines changed: 94 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
describe ArticleJSON::Export::HTML::Elements::Base do
22
subject(:element) { described_class.new(source_element) }
33

4-
describe '#build' do
5-
subject { element.build.to_html(save_with: 0) }
4+
describe '#export' do
5+
subject { element.export.to_html(save_with: 0) }
66

77
let(:sample_text) { ArticleJSON::Elements::Text.new(content: 'Foo Bar') }
88
let(:sample_paragraph) do
@@ -80,12 +80,98 @@
8080
end
8181
end
8282

83-
describe '#element_classes' do
84-
subject { described_class.element_classes }
85-
it { should be_a Hash }
86-
it('should have Symbol-keys') { expect(subject.keys).to all be_a Symbol }
87-
it('should have sub classes as values') do
88-
expect(subject.values.map(&:allocate)).to all be_a described_class
83+
describe '.build' do
84+
subject { described_class.build(element) }
85+
86+
context 'when the element type is text' do
87+
let(:element) { ArticleJSON::Elements::Text.new(content: '') }
88+
it { should be_a ArticleJSON::Export::HTML::Elements::Text }
89+
end
90+
91+
context 'when the element type is heading' do
92+
let(:element) { ArticleJSON::Elements::Heading.new(content: 1, level: 1) }
93+
it { should be_a ArticleJSON::Export::HTML::Elements::Heading }
94+
end
95+
96+
context 'when the element type is paragraph' do
97+
let(:element) { ArticleJSON::Elements::Paragraph.new(content: []) }
98+
it { should be_a ArticleJSON::Export::HTML::Elements::Paragraph }
99+
end
100+
101+
context 'when the element type is list' do
102+
let(:element) { ArticleJSON::Elements::List.new(content: []) }
103+
it { should be_a ArticleJSON::Export::HTML::Elements::List }
104+
end
105+
106+
context 'when the element type is image' do
107+
let(:element) do
108+
ArticleJSON::Elements::Image.new(source_url: '', caption: [])
109+
end
110+
it { should be_a ArticleJSON::Export::HTML::Elements::Image }
111+
end
112+
113+
context 'when the element type is text_box' do
114+
let(:element) { ArticleJSON::Elements::TextBox.new(content: []) }
115+
it { should be_a ArticleJSON::Export::HTML::Elements::TextBox }
116+
end
117+
118+
context 'when the element type is quote' do
119+
let(:element) do
120+
ArticleJSON::Elements::Quote.new(content: [], caption: [])
121+
end
122+
it { should be_a ArticleJSON::Export::HTML::Elements::Quote }
123+
end
124+
125+
context 'when the element type is embed' do
126+
let(:element) do
127+
ArticleJSON::Elements::Embed
128+
.new(embed_type: '', embed_id: '', caption: [])
129+
end
130+
it { should be_a ArticleJSON::Export::HTML::Elements::Embed }
131+
end
132+
end
133+
134+
describe '.exporter_by_type' do
135+
subject { described_class.exporter_by_type(element_type) }
136+
137+
context 'when the element type is text' do
138+
let(:element_type) { :text }
139+
it { should be ArticleJSON::Export::HTML::Elements::Text }
140+
end
141+
142+
context 'when the element type is heading' do
143+
let(:element_type) { :heading }
144+
it { should be ArticleJSON::Export::HTML::Elements::Heading }
145+
end
146+
147+
context 'when the element type is paragraph' do
148+
let(:element_type) { :paragraph }
149+
it { should be ArticleJSON::Export::HTML::Elements::Paragraph }
150+
end
151+
152+
context 'when the element type is list' do
153+
let(:element_type) { :list }
154+
it { should be ArticleJSON::Export::HTML::Elements::List }
155+
end
156+
157+
context 'when the element type is image' do
158+
let(:element_type) { :image }
159+
it { should be ArticleJSON::Export::HTML::Elements::Image }
160+
end
161+
162+
context 'when the element type is text_box' do
163+
let(:element_type) { :text_box }
164+
it { should be ArticleJSON::Export::HTML::Elements::TextBox }
165+
end
166+
167+
context 'when the element type is quote' do
168+
let(:element_type) { :quote }
169+
it { should be ArticleJSON::Export::HTML::Elements::Quote }
170+
end
171+
172+
context 'when the element type is embed' do
173+
let(:element_type) { :embed }
174+
it { should be ArticleJSON::Export::HTML::Elements::Embed }
89175
end
90176
end
91177
end

spec/article_json/export/html/elements/embed_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
)
1111
end
1212

13-
describe '#build' do
14-
subject { element.build.to_html(save_with: 0) }
13+
describe '#export' do
14+
subject { element.export.to_html(save_with: 0) }
1515
let(:expected_html) do
1616
'<figure><div class="embed">Embedded Object: something-666</div>' \
1717
'<figcaption>Foo Bar</figcaption></figure>'

spec/article_json/export/html/elements/heading_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
ArticleJSON::Elements::Heading.new(content: 'Foo Bar', level: level)
66
end
77

8-
describe '#build' do
9-
subject { element.build.to_html }
8+
describe '#export' do
9+
subject { element.export.to_html(save_with: 0) }
1010

1111
(1..6).each do |i|
1212
context "when the heading level is #{i}" do

spec/article_json/export/html/elements/image_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
let(:float) { nil }
1212
let(:caption) { ArticleJSON::Elements::Text.new(content: 'Foo Bar') }
1313

14-
describe '#build' do
15-
subject { element.build.to_html(save_with: 0) }
14+
describe '#export' do
15+
subject { element.export.to_html(save_with: 0) }
1616

1717
context 'when the image is not floating' do
1818
let(:expected_html) do

spec/article_json/export/html/elements/list_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
end
2323
end
2424

25-
describe '#build' do
26-
subject { element.build.to_html(save_with: 0) }
25+
describe '#export' do
26+
subject { element.export.to_html(save_with: 0) }
2727

2828
context 'when it is an ordered list' do
2929
let(:list_type) { :ordered }

spec/article_json/export/html/elements/paragraph_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
ArticleJSON::Elements::Text.new(content: 'Foo Bar', href: '/foo/bar')
1212
end
1313

14-
describe '#build' do
15-
subject { element.build.to_html(save_with: 0) }
14+
describe '#export' do
15+
subject { element.export.to_html(save_with: 0) }
1616
let(:expected_html) do
1717
'<p><strong>Check this out: </strong><a href="/foo/bar">Foo Bar</a></p>'
1818
end

spec/article_json/export/html/elements/quote_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
)
1414
end
1515

16-
describe '#build' do
17-
subject { element.build.to_html(save_with: 0) }
16+
describe '#export' do
17+
subject { element.export.to_html(save_with: 0) }
1818

1919
context 'when the quote is not floating' do
2020
let(:float) { nil }

spec/article_json/export/html/elements/text_box_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
)
1313
end
1414

15-
describe '#build' do
16-
subject { element.build.to_html(save_with: 0) }
15+
describe '#export' do
16+
subject { element.export.to_html(save_with: 0) }
1717

1818
context 'when the box is not floating' do
1919
let(:float) { nil }

spec/article_json/export/html/elements/text_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
let(:italic) { false }
1414
let(:href) { nil }
1515

16-
describe '#build' do
17-
subject { element.build.to_html }
16+
describe '#export' do
17+
subject { element.export.to_html(save_with: 0) }
1818

1919
context 'when the source element is plain text' do
2020
it { should eq 'Foo Bar' }

0 commit comments

Comments
 (0)