draftjs_exporter 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f8d59bea7ea1b40766a3e78d33535290d288026b
4
- data.tar.gz: 96f8e16bfede94708c613c5205fc6450d22f428e
3
+ metadata.gz: 09a55e5243dc77a0e6b9711abced8fd26cab0776
4
+ data.tar.gz: d0f789f42a140cfcc4bd92bd8f1aa653bd2e033a
5
5
  SHA512:
6
- metadata.gz: 0133625911008a1a5f663dc5356dd47c54c9fc3abd097ab6f6f52f770a89fd89c4f329827d24e416c83988f29acbd9abafc471fac1e08717c23e5f6eeeed43e4
7
- data.tar.gz: 4b6ca1fed16749d841f3ad4b58af395bb927a12ad5cf88b869a26901635a93c70f6042358b841c322f0311430d69c152a40685c55548dd891ef6c83c4bf9275b
6
+ metadata.gz: 5bf865cb2d2a3a1305e13698800d028c38695a694212cdd5534eb1bdeef4a40c04dadbaa5f1bfbc913f022cb64555a9ef864aa26e06a346b78afcb7be275061a
7
+ data.tar.gz: 565b824cbd6355dd65bef816aa553dca4ca9562b9981557594145bb8f797fb31b67221b97d0eefeeeb12370f322ece790e4538374d707af852a0ac8913b0f754
@@ -1,7 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
  require 'draftjs_exporter/entities/null'
3
+ require 'draftjs_exporter/error'
3
4
 
4
5
  module DraftjsExporter
6
+ class InvalidEntity < DraftjsExporter::Error; end
7
+
5
8
  class EntityState
6
9
  attr_reader :entity_decorators, :entity_map, :entity_stack, :root_element
7
10
 
@@ -40,7 +43,7 @@ module DraftjsExporter
40
43
  _element, expected_entity_details = entity_stack.last
41
44
 
42
45
  if expected_entity_details != entity_details
43
- raise "Invalid entity. Expected #{expected_entity_details.inspect} got #{entity_details.inspect}"
46
+ raise InvalidEntity, "Expected #{expected_entity_details.inspect} got #{entity_details.inspect}"
44
47
  end
45
48
 
46
49
  entity_stack.pop
@@ -0,0 +1,3 @@
1
+ module DraftjsExporter
2
+ class Error < StandardError; end
3
+ end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require 'nokogiri'
3
+ require 'draftjs_exporter/wrapper_state'
3
4
  require 'draftjs_exporter/entity_state'
4
5
  require 'draftjs_exporter/style_state'
5
6
  require 'draftjs_exporter/command'
@@ -15,23 +16,17 @@ module DraftjsExporter
15
16
  end
16
17
 
17
18
  def call(content_state)
18
- content_state.fetch(:blocks, []).map { |block|
19
- content_state_block(block, content_state.fetch(:entityMap, {}))
20
- }.inject(:+)
19
+ wrapper_state = WrapperState.new(block_map)
20
+ content_state.fetch(:blocks, []).each do |block|
21
+ element = wrapper_state.element_for(block)
22
+ entity_map = content_state.fetch(:entityMap, {})
23
+ block_contents(element, block, entity_map)
24
+ end
25
+ wrapper_state.to_s
21
26
  end
22
27
 
23
28
  private
24
29
 
25
- def content_state_block(block, entity_map)
26
- document = Nokogiri::HTML::Document.new
27
- fragment = Nokogiri::HTML::DocumentFragment.new(document)
28
- type = block.fetch(:type, 'unstyled')
29
- element = document.create_element(*block_options(type)) { |e|
30
- block_contents(e, block, entity_map)
31
- }
32
- fragment.add_child(element).to_s
33
- end
34
-
35
30
  def block_contents(element, block, entity_map)
36
31
  style_state = StyleState.new(style_map)
37
32
  entity_state = EntityState.new(element, entity_decorators, entity_map)
@@ -45,18 +40,6 @@ module DraftjsExporter
45
40
  end
46
41
  end
47
42
 
48
- def block_options(type)
49
- options = block_map.fetch(type)
50
- return [options.fetch(:element)] unless options.key?(:wrapper)
51
-
52
- wrapper = options.fetch(:wrapper)
53
- name = wrapper[0]
54
- config = wrapper[1] || {}
55
- options = {}
56
- options[:class] = config.fetch(:className) if config.key?(:className)
57
- [name, options]
58
- end
59
-
60
43
  def add_node(element, text, state)
61
44
  document = element.document
62
45
  node = if state.text?
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module DraftjsExporter
3
- VERSION = '0.0.2'.freeze
3
+ VERSION = '0.0.3'.freeze
4
4
  end
@@ -0,0 +1,70 @@
1
+ module DraftjsExporter
2
+ class WrapperState
3
+ def initialize(block_map)
4
+ @block_map = block_map
5
+ @document = Nokogiri::HTML::Document.new
6
+ @fragment = Nokogiri::HTML::DocumentFragment.new(document)
7
+ reset_wrapper
8
+ end
9
+
10
+ def element_for(block)
11
+ type = block.fetch(:type, 'unstyled')
12
+ document.create_element(block_options(type)).tap do |e|
13
+ parent_for(type).add_child(e)
14
+ end
15
+ end
16
+
17
+ def to_s
18
+ fragment.to_s
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :fragment, :document, :block_map, :wrapper
24
+
25
+ def set_wrapper(element, options = {})
26
+ @wrapper = [element, options]
27
+ end
28
+
29
+ def wrapper_element
30
+ @wrapper[0] || fragment
31
+ end
32
+
33
+ def wrapper_options
34
+ @wrapper[1]
35
+ end
36
+
37
+ def parent_for(type)
38
+ options = block_map.fetch(type)
39
+ return reset_wrapper unless options.key?(:wrapper)
40
+
41
+ new_options = nokogiri_options(*options.fetch(:wrapper))
42
+ return wrapper_element if new_options == wrapper_options
43
+
44
+ create_wrapper(new_options)
45
+ end
46
+
47
+ def reset_wrapper
48
+ set_wrapper(fragment)
49
+ wrapper_element
50
+ end
51
+
52
+ def nokogiri_options(element_name, element_attributes)
53
+ config = element_attributes || {}
54
+ options = {}
55
+ options[:class] = config.fetch(:className) if config.key?(:className)
56
+ [element_name, options]
57
+ end
58
+
59
+ def block_options(type)
60
+ block_map.fetch(type).fetch(:element)
61
+ end
62
+
63
+ def create_wrapper(options)
64
+ document.create_element(*options).tap do |new_element|
65
+ reset_wrapper.add_child(new_element)
66
+ set_wrapper(new_element, options)
67
+ end
68
+ end
69
+ end
70
+ end
@@ -24,55 +24,181 @@ RSpec.describe DraftjsExporter::HTML do
24
24
  end
25
25
 
26
26
  describe '#call' do
27
- it 'decodes the content_state to html' do
28
- input = {
29
- entityMap: {
30
- '0' => {
31
- type: 'LINK',
32
- mutability: 'MUTABLE',
33
- data: {
34
- url: 'http://example.com'
27
+ context 'with different blocks' do
28
+ it 'decodes the content_state to html' do
29
+ input = {
30
+ entityMap: {},
31
+ blocks: [
32
+ {
33
+ key: '5s7g9',
34
+ text: 'Header',
35
+ type: 'header-one',
36
+ depth: 0,
37
+ inlineStyleRanges: [],
38
+ entityRanges: []
39
+ },
40
+ {
41
+ key: 'dem5p',
42
+ text: 'some paragraph text',
43
+ type: 'unstyled',
44
+ depth: 0,
45
+ inlineStyleRanges: [],
46
+ entityRanges: []
47
+ }
48
+ ]
49
+ }
50
+
51
+ expected_output = <<-OUTPUT.strip
52
+ <h1>Header</h1><div>some paragraph text</div>
53
+ OUTPUT
54
+
55
+ expect(mapper.call(input)).to eq(expected_output)
56
+ end
57
+ end
58
+
59
+ context 'with inline styles' do
60
+ it 'decodes the content_state to html' do
61
+ input = {
62
+ entityMap: {},
63
+ blocks: [
64
+ {
65
+ key: 'dem5p',
66
+ text: 'some paragraph text',
67
+ type: 'unstyled',
68
+ depth: 0,
69
+ inlineStyleRanges: [
70
+ {
71
+ offset: 0,
72
+ length: 4,
73
+ style: 'ITALIC'
74
+ }
75
+ ],
76
+ entityRanges: []
77
+ }
78
+ ]
79
+ }
80
+
81
+ expected_output = <<-OUTPUT.strip
82
+ <div>
83
+ <span style="fontStyle: italic;">some</span> paragraph text</div>
84
+ OUTPUT
85
+
86
+ expect(mapper.call(input)).to eq(expected_output)
87
+ end
88
+ end
89
+
90
+ context 'with entities' do
91
+ it 'decodes the content_state to html' do
92
+ input = {
93
+ entityMap: {
94
+ '0' => {
95
+ type: 'LINK',
96
+ mutability: 'MUTABLE',
97
+ data: {
98
+ url: 'http://example.com'
99
+ }
35
100
  }
36
- }
37
- },
38
- blocks: [
39
- {
40
- key: '5s7g9',
41
- text: 'Header',
42
- type: 'header-one',
43
- depth: 0,
44
- inlineStyleRanges: [],
45
- entityRanges: []
46
101
  },
47
- {
48
- key: 'dem5p',
49
- text: 'some paragraph text',
50
- type: 'unstyled',
51
- depth: 0,
52
- inlineStyleRanges: [
53
- {
54
- offset: 0,
55
- length: 4,
56
- style: 'ITALIC'
102
+ blocks: [
103
+ {
104
+ key: 'dem5p',
105
+ text: 'some paragraph text',
106
+ type: 'unstyled',
107
+ depth: 0,
108
+ inlineStyleRanges: [],
109
+ entityRanges: [
110
+ {
111
+ offset: 5,
112
+ length: 9,
113
+ key: 0
114
+ }
115
+ ]
116
+ }
117
+ ]
118
+ }
119
+
120
+ expected_output = <<-OUTPUT.strip
121
+ <div>some <a href="http://example.com">paragraph</a> text</div>
122
+ OUTPUT
123
+
124
+ expect(mapper.call(input)).to eq(expected_output)
125
+ end
126
+
127
+ it 'throws an error if entities cross over' do
128
+ input = {
129
+ entityMap: {
130
+ '0' => {
131
+ type: 'LINK',
132
+ mutability: 'MUTABLE',
133
+ data: {
134
+ url: 'http://foo.example.com'
57
135
  }
58
- ],
59
- entityRanges: [
60
- {
61
- offset: 5,
62
- length: 9,
63
- key: 0
136
+ },
137
+ '1' => {
138
+ type: 'LINK',
139
+ mutability: 'MUTABLE',
140
+ data: {
141
+ url: 'http://bar.example.com'
64
142
  }
65
- ]
66
- }
67
- ]
68
- }
143
+ }
144
+ },
145
+ blocks: [
146
+ {
147
+ key: 'dem5p',
148
+ text: 'some paragraph text',
149
+ type: 'unstyled',
150
+ depth: 0,
151
+ inlineStyleRanges: [],
152
+ entityRanges: [
153
+ {
154
+ offset: 5,
155
+ length: 9,
156
+ key: 0
157
+ },
158
+ {
159
+ offset: 2,
160
+ length: 9,
161
+ key: 1
162
+ }
163
+ ]
164
+ }
165
+ ]
166
+ }
167
+
168
+ expect { mapper.call(input) }.to raise_error(DraftjsExporter::InvalidEntity)
169
+ end
170
+ end
171
+
172
+ context 'with wrapped blocks' do
173
+ it 'decodes the content_state to html' do
174
+ input = {
175
+ entityMap: {},
176
+ blocks: [
177
+ {
178
+ key: 'dem5p',
179
+ text: 'item1',
180
+ type: 'unordered-list-item',
181
+ depth: 0,
182
+ inlineStyleRanges: [],
183
+ entityRanges: []
184
+ },
185
+ {
186
+ key: 'dem5p',
187
+ text: 'item2',
188
+ type: 'unordered-list-item',
189
+ depth: 0,
190
+ inlineStyleRanges: [],
191
+ entityRanges: []
192
+ }
193
+ ]
194
+ }
69
195
 
70
- expected_output = <<-OUTPUT.strip
71
- <h1>Header</h1><div>
72
- <span style="fontStyle: italic;">some</span> <a href="http://example.com">paragraph</a> text</div>
73
- OUTPUT
196
+ expected_output = <<-EOS.strip
197
+ <ul class="public-DraftStyleDefault-ul">\n<li>item1</li>\n<li>item2</li>\n</ul>
198
+ EOS
74
199
 
75
- expect(mapper.call(input)).to eq(expected_output)
200
+ expect(mapper.call(input)).to eq(expected_output)
201
+ end
76
202
  end
77
203
  end
78
204
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: draftjs_exporter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Theo Cushion
@@ -126,9 +126,11 @@ files:
126
126
  - lib/draftjs_exporter/entities/link.rb
127
127
  - lib/draftjs_exporter/entities/null.rb
128
128
  - lib/draftjs_exporter/entity_state.rb
129
+ - lib/draftjs_exporter/error.rb
129
130
  - lib/draftjs_exporter/html.rb
130
131
  - lib/draftjs_exporter/style_state.rb
131
132
  - lib/draftjs_exporter/version.rb
133
+ - lib/draftjs_exporter/wrapper_state.rb
132
134
  - spec/integrations/html_spec.rb
133
135
  - spec/integrations/requires_spec.rb
134
136
  - spec/spec_helper.rb
@@ -152,7 +154,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
152
154
  version: '0'
153
155
  requirements: []
154
156
  rubyforge_project:
155
- rubygems_version: 2.5.1
157
+ rubygems_version: 2.2.5
156
158
  signing_key:
157
159
  specification_version: 4
158
160
  summary: Export Draft.js content state into HTML