prosemirror_to_html 0.2.1 → 0.3.0

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
  SHA256:
3
- metadata.gz: 0ad426b14cb9437e9e87da4de83e2c2e7ad2a434e9f0e182f52ea9c5ef191bbe
4
- data.tar.gz: 8e15b4ea153075170aa91f14d8508f2f1b7b9c93421791338453ac2ead11ec1b
3
+ metadata.gz: 32c2b7bb3c4e6605b5be4eeb87d5529b3457400f335a4cb581a2fae039cbd47b
4
+ data.tar.gz: b64c662ea99e41371edf715e830aea49390c35dc546b197b10c98dbc8246632d
5
5
  SHA512:
6
- metadata.gz: 23465c8179834d71d61598fdac357fa5bcd6b9042d60bf00871fa91ca0123bd1a0eeed2f9d035c53d8b7282682106199afb06f40cd6b96ef1c57f6cb3eea42ff
7
- data.tar.gz: bb64c1659950a072825a36bffbbd7f0ecaa0631534eec22f50ff1c5bec0d59ab14699053c7dab0951f1aed6c182a94c0c4561898228d5bf37cc7c338e6bdf9c6
6
+ metadata.gz: 771cebd6d454024922deb4c937b26ae624c2b5ee754ab74e74c24d6e8197ee8cfd8531ae75cff8fa96273e2f2f8f43d4fe99e24301a1b464649660f58c749ef9
7
+ data.tar.gz: 8de0c80c0c76f7ca9b87d641796b77d98982d915876663cea5d204e47e4b759026ead473c64c9dc572162661e8300c1c3dc291e73fe98753f186c678d81fb4d9
data/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## [0.3.0] - 2026-02-18
2
+
3
+ ### Changed
4
+
5
+ - Remove dependency to `OpenStruct`
6
+
7
+ ### Fixed
8
+
9
+ - Fix mark grouping: marks shared across adjacent text nodes (e.g. a `link` spanning multiple runs) are now correctly rendered as a single wrapping tag instead of being reopened for each node
10
+
11
+ ## [0.2.1] - 2025-11-05
12
+
13
+ - Escape attributes values [CVE-2025-64501]
14
+
1
15
  ## [0.2.0] - 2023-07-03
2
16
 
3
17
  Hans Lemuet (@Spone) is the new maintainer. The fork is now hosted at https://github.com/etaminstudio/prosemirror_to_html
data/Gemfile.lock CHANGED
@@ -1,33 +1,33 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- prosemirror_to_html (0.2.1)
4
+ prosemirror_to_html (0.3.0)
5
5
  nokogiri
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- diff-lcs (1.5.0)
11
- mini_portile2 (2.8.8)
12
- nokogiri (1.18.3)
10
+ diff-lcs (1.6.2)
11
+ mini_portile2 (2.8.9)
12
+ nokogiri (1.19.1)
13
13
  mini_portile2 (~> 2.8.2)
14
14
  racc (~> 1.4)
15
15
  racc (1.8.1)
16
- rake (13.0.6)
17
- rspec (3.12.0)
18
- rspec-core (~> 3.12.0)
19
- rspec-expectations (~> 3.12.0)
20
- rspec-mocks (~> 3.12.0)
21
- rspec-core (3.12.2)
22
- rspec-support (~> 3.12.0)
23
- rspec-expectations (3.12.3)
16
+ rake (13.3.1)
17
+ rspec (3.13.2)
18
+ rspec-core (~> 3.13.0)
19
+ rspec-expectations (~> 3.13.0)
20
+ rspec-mocks (~> 3.13.0)
21
+ rspec-core (3.13.6)
22
+ rspec-support (~> 3.13.0)
23
+ rspec-expectations (3.13.5)
24
24
  diff-lcs (>= 1.2.0, < 2.0)
25
- rspec-support (~> 3.12.0)
26
- rspec-mocks (3.12.5)
25
+ rspec-support (~> 3.13.0)
26
+ rspec-mocks (3.13.7)
27
27
  diff-lcs (>= 1.2.0, < 2.0)
28
- rspec-support (~> 3.12.0)
29
- rspec-support (3.12.1)
30
- yard (0.9.36)
28
+ rspec-support (~> 3.13.0)
29
+ rspec-support (3.13.7)
30
+ yard (0.9.38)
31
31
 
32
32
  PLATFORMS
33
33
  ruby
@@ -5,18 +5,10 @@ module ProsemirrorToHtml
5
5
  @tag_name = 'a'
6
6
 
7
7
  def tag
8
- attrs = {}
9
-
10
- attrs['href'] = @mark.attrs.href
11
-
12
- attrs['target'] = @mark.attrs.target if @mark.attrs.target
13
- attrs['title'] = @mark.attrs.title if @mark.attrs.title
14
- attrs['rel'] = @mark.attrs.rel if @mark.attrs.rel
15
-
16
8
  [
17
9
  {
18
10
  tag: self.class.tag_name,
19
- attrs: attrs
11
+ attrs: @mark[:attrs]
20
12
  }
21
13
  ]
22
14
  end
@@ -13,7 +13,7 @@ module ProsemirrorToHtml
13
13
  end
14
14
 
15
15
  def matching
16
- return @mark.type == self.class.mark_type if @mark.type
16
+ return @mark[:type] == self.class.mark_type if @mark[:type]
17
17
 
18
18
  false
19
19
  end
@@ -6,7 +6,7 @@ module ProsemirrorToHtml
6
6
  def tag
7
7
  [
8
8
  {
9
- tag: "h#{@node.attrs.level}",
9
+ tag: "h#{@node[:attrs][:level]}",
10
10
  attrs: tag_attrs
11
11
  }
12
12
  ]
@@ -15,7 +15,7 @@ module ProsemirrorToHtml
15
15
  private
16
16
 
17
17
  def tag_attrs
18
- attrs_hash = @node.attrs.to_h
18
+ attrs_hash = @node[:attrs].to_h
19
19
  attrs_hash.slice(*attrs_hash.keys - %i[level])
20
20
  end
21
21
  end
@@ -8,7 +8,7 @@ module ProsemirrorToHtml
8
8
  [
9
9
  {
10
10
  tag: self.class.tag_name,
11
- attrs: @node.attrs
11
+ attrs: @node[:attrs]
12
12
  }
13
13
  ]
14
14
  end
@@ -13,7 +13,7 @@ module ProsemirrorToHtml
13
13
  end
14
14
 
15
15
  def matching
16
- return underscore(@node.type) == self.class.node_type if @node.type
16
+ return underscore(@node[:type]) == self.class.node_type if @node[:type]
17
17
 
18
18
  false
19
19
  end
@@ -8,7 +8,7 @@ module ProsemirrorToHtml
8
8
  [
9
9
  {
10
10
  tag: self.class.tag_name,
11
- attrs: @node.attrs
11
+ attrs: @node[:attrs]
12
12
  }
13
13
  ]
14
14
  end
@@ -8,7 +8,7 @@ module ProsemirrorToHtml
8
8
  [
9
9
  {
10
10
  tag: self.class.tag_name,
11
- attrs: @node.attrs
11
+ attrs: @node[:attrs]
12
12
  }
13
13
  ]
14
14
  end
@@ -8,7 +8,7 @@ module ProsemirrorToHtml
8
8
  [
9
9
  {
10
10
  tag: self.class.tag_name,
11
- attrs: @node.attrs
11
+ attrs: @node[:attrs]
12
12
  }
13
13
  ]
14
14
  end
@@ -1,3 +1,3 @@
1
1
  module ProsemirrorToHtml
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -25,7 +25,6 @@ require "prosemirror_to_html/nodes/table_header"
25
25
  require "prosemirror_to_html/nodes/table_row"
26
26
  require 'nokogiri'
27
27
  require 'json'
28
- require "ostruct"
29
28
 
30
29
  module ProsemirrorToHtml
31
30
  class Error < StandardError; end
@@ -82,14 +81,14 @@ module ProsemirrorToHtml
82
81
  else raise Error
83
82
  end
84
83
 
85
- @document = JSON.parse(json, object_class: OpenStruct)
84
+ @document = JSON.parse(json, symbolize_names: true)
86
85
 
87
86
  html = ''
88
87
 
89
- content = @document.content.is_a?(Array) ? @document.content : []
88
+ content = @document[:content].is_a?(Array) ? @document[:content] : []
90
89
 
91
90
  content.each_with_index do |node, index|
92
- prev_node = content[index - 1]
91
+ prev_node = index > 0 ? content[index - 1] : nil
93
92
  next_node = content[index + 1]
94
93
 
95
94
  html << render_node(node, prev_node, next_node)
@@ -148,14 +147,12 @@ module ProsemirrorToHtml
148
147
  html = ''
149
148
  render_klass = nil
150
149
 
151
- if node&.marks
152
- node.marks.each do |mark|
153
- @marks.each do |klass|
154
- render_klass = klass.new(mark)
150
+ node[:marks]&.each do |mark|
151
+ @marks.each do |klass|
152
+ render_klass = klass.new(mark)
155
153
 
156
- if render_klass.matching && mark_should_open(mark, prev_node)
157
- html << render_opening_tag(render_klass.tag)
158
- end
154
+ if render_klass.matching && mark_should_open(mark, prev_node)
155
+ html << render_opening_tag(render_klass.tag)
159
156
  end
160
157
  end
161
158
  end
@@ -169,17 +166,16 @@ module ProsemirrorToHtml
169
166
  end
170
167
  end
171
168
 
172
- if node&.content
173
- node.content.each_with_index do |nested_node, index|
174
- prev_nested_node = node.content[index - 1]
175
- next_nested_node = node.content[index + 1]
169
+ if node[:content]
170
+ node[:content].each_with_index do |nested_node, index|
171
+ prev_nested_node = index > 0 ? node[:content][index - 1] : nil
172
+ next_nested_node = node[:content][index + 1]
176
173
 
177
174
  html << render_node(nested_node, prev_nested_node, next_nested_node)
178
- prev_node = nested_node
179
175
  end
180
- elsif node&.text
181
- html << CGI.escapeHTML(node.text)
182
- elsif text = render_klass.text
176
+ elsif node[:text]
177
+ html << CGI.escapeHTML(node[:text])
178
+ elsif (text = render_klass.text)
183
179
  html << text
184
180
  end
185
181
 
@@ -195,14 +191,12 @@ module ProsemirrorToHtml
195
191
  end
196
192
  end
197
193
 
198
- if node&.marks
199
- node.marks.reverse.each do |mark|
200
- @marks.each do |klass|
201
- render_klass = klass.new(mark)
194
+ node[:marks]&.reverse&.each do |mark|
195
+ @marks.each do |klass|
196
+ render_klass = klass.new(mark)
202
197
 
203
- if render_klass.matching && mark_should_close(mark, next_node)
204
- html << render_closing_tag(render_klass.tag)
205
- end
198
+ if render_klass.matching && mark_should_close(mark, next_node)
199
+ html << render_closing_tag(render_klass.tag)
206
200
  end
207
201
  end
208
202
  end
@@ -220,14 +214,9 @@ module ProsemirrorToHtml
220
214
 
221
215
  def node_has_mark(node, mark)
222
216
  return true unless node
223
- return true if node.respond_to?(:marks)
224
217
 
225
- # Other node has same mark
226
- node.marks&.each do |other_mark|
227
- if mark == other_mark
228
- return false
229
- end
230
- end
218
+ # Don't open/close if the adjacent node shares the same mark
219
+ return false if node[:marks]&.map(&:to_json)&.include?(mark.to_json)
231
220
 
232
221
  true
233
222
  end
@@ -241,23 +230,20 @@ module ProsemirrorToHtml
241
230
  if tag.is_a? String
242
231
  "<#{tag}>"
243
232
  else
244
- tag = OpenStruct.new(tag) unless tag.is_a?(OpenStruct)
245
-
246
233
  attrs = ''
247
- if tag&.attrs
248
- tag.attrs.each_pair do |attr, value|
249
- escaped_value = CGI.escapeHTML(value.to_s)
250
- attrs << " #{attr}=\"#{escaped_value}\""
251
- end
234
+ tag[:attrs]&.each_pair do |attr, value|
235
+ escaped_value = CGI.escapeHTML(value.to_s)
236
+ attrs << " #{attr}=\"#{escaped_value}\""
252
237
  end
253
238
 
254
- "<#{tag.tag}#{attrs}>"
239
+ "<#{tag[:tag]}#{attrs}>"
255
240
  end
256
241
  end.join
257
242
  end
258
243
 
259
244
  def render_closing_tag(tags)
260
245
  tags = array_wrap(tags).reverse
246
+ p ["render_closing_tag", tags]
261
247
 
262
248
  return nil if tags.empty?
263
249
 
@@ -265,9 +251,7 @@ module ProsemirrorToHtml
265
251
  if tag.is_a? String
266
252
  "</#{tag}>"
267
253
  else
268
- tag = OpenStruct.new(tag) unless tag.is_a?(OpenStruct)
269
-
270
- "</#{tag.tag}>"
254
+ "</#{tag[:tag]}>"
271
255
  end
272
256
  end.join
273
257
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prosemirror_to_html
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hans Lemuet
@@ -148,7 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
148
148
  - !ruby/object:Gem::Version
149
149
  version: '0'
150
150
  requirements: []
151
- rubygems_version: 3.7.2
151
+ rubygems_version: 4.0.3
152
152
  specification_version: 4
153
153
  summary: Takes ProseMirror compatible JSON and outputs HTML.
154
154
  test_files: []