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 +4 -4
- data/CHANGELOG.md +14 -0
- data/Gemfile.lock +17 -17
- data/lib/prosemirror_to_html/marks/link.rb +1 -9
- data/lib/prosemirror_to_html/marks/mark.rb +1 -1
- data/lib/prosemirror_to_html/nodes/heading.rb +2 -2
- data/lib/prosemirror_to_html/nodes/image.rb +1 -1
- data/lib/prosemirror_to_html/nodes/node.rb +1 -1
- data/lib/prosemirror_to_html/nodes/ordered_list.rb +1 -1
- data/lib/prosemirror_to_html/nodes/table_cell.rb +1 -1
- data/lib/prosemirror_to_html/nodes/table_header.rb +1 -1
- data/lib/prosemirror_to_html/version.rb +1 -1
- data/lib/prosemirror_to_html.rb +28 -44
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 32c2b7bb3c4e6605b5be4eeb87d5529b3457400f335a4cb581a2fae039cbd47b
|
|
4
|
+
data.tar.gz: b64c662ea99e41371edf715e830aea49390c35dc546b197b10c98dbc8246632d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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.
|
|
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.
|
|
11
|
-
mini_portile2 (2.8.
|
|
12
|
-
nokogiri (1.
|
|
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.
|
|
17
|
-
rspec (3.
|
|
18
|
-
rspec-core (~> 3.
|
|
19
|
-
rspec-expectations (~> 3.
|
|
20
|
-
rspec-mocks (~> 3.
|
|
21
|
-
rspec-core (3.
|
|
22
|
-
rspec-support (~> 3.
|
|
23
|
-
rspec-expectations (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.
|
|
26
|
-
rspec-mocks (3.
|
|
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.
|
|
29
|
-
rspec-support (3.
|
|
30
|
-
yard (0.9.
|
|
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
|
|
@@ -6,7 +6,7 @@ module ProsemirrorToHtml
|
|
|
6
6
|
def tag
|
|
7
7
|
[
|
|
8
8
|
{
|
|
9
|
-
tag: "h#{@node
|
|
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
|
|
18
|
+
attrs_hash = @node[:attrs].to_h
|
|
19
19
|
attrs_hash.slice(*attrs_hash.keys - %i[level])
|
|
20
20
|
end
|
|
21
21
|
end
|
data/lib/prosemirror_to_html.rb
CHANGED
|
@@ -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,
|
|
84
|
+
@document = JSON.parse(json, symbolize_names: true)
|
|
86
85
|
|
|
87
86
|
html = ''
|
|
88
87
|
|
|
89
|
-
content = @document
|
|
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
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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
|
-
|
|
157
|
-
|
|
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
|
|
173
|
-
node
|
|
174
|
-
prev_nested_node = node
|
|
175
|
-
next_nested_node = node
|
|
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
|
|
181
|
-
html << CGI.escapeHTML(node
|
|
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
|
-
|
|
199
|
-
|
|
200
|
-
|
|
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
|
-
|
|
204
|
-
|
|
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
|
-
#
|
|
226
|
-
node
|
|
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
|
-
|
|
248
|
-
|
|
249
|
-
|
|
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
|
|
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
|
|
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.
|
|
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:
|
|
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: []
|