prosemirror_to_html 0.1.0 → 0.2.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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -0
  3. data/Gemfile.lock +23 -21
  4. data/lib/prosemirror_to_html/marks/bold.rb +2 -8
  5. data/lib/prosemirror_to_html/marks/code.rb +2 -8
  6. data/lib/prosemirror_to_html/marks/italic.rb +2 -8
  7. data/lib/prosemirror_to_html/marks/link.rb +16 -8
  8. data/lib/prosemirror_to_html/marks/mark.rb +9 -7
  9. data/lib/prosemirror_to_html/marks/strike.rb +8 -0
  10. data/lib/prosemirror_to_html/marks/subscript.rb +8 -0
  11. data/lib/prosemirror_to_html/marks/superscript.rb +8 -0
  12. data/lib/prosemirror_to_html/marks/underline.rb +8 -0
  13. data/lib/prosemirror_to_html/nodes/blockquote.rb +8 -0
  14. data/lib/prosemirror_to_html/nodes/bullet_list.rb +2 -8
  15. data/lib/prosemirror_to_html/nodes/code_block.rb +2 -9
  16. data/lib/prosemirror_to_html/nodes/hard_break.rb +4 -6
  17. data/lib/prosemirror_to_html/nodes/heading.rb +13 -5
  18. data/lib/prosemirror_to_html/nodes/horizontal_rule.rb +12 -0
  19. data/lib/prosemirror_to_html/nodes/image.rb +11 -5
  20. data/lib/prosemirror_to_html/nodes/list_item.rb +2 -12
  21. data/lib/prosemirror_to_html/nodes/node.rb +27 -8
  22. data/lib/prosemirror_to_html/nodes/ordered_list.rb +9 -6
  23. data/lib/prosemirror_to_html/nodes/paragraph.rb +2 -8
  24. data/lib/prosemirror_to_html/nodes/table.rb +8 -0
  25. data/lib/prosemirror_to_html/nodes/table_cell.rb +17 -0
  26. data/lib/prosemirror_to_html/nodes/table_header.rb +17 -0
  27. data/lib/prosemirror_to_html/nodes/table_row.rb +8 -0
  28. data/lib/prosemirror_to_html/version.rb +1 -1
  29. data/lib/prosemirror_to_html.rb +223 -86
  30. data/prosemirror_to_html.gemspec +7 -7
  31. metadata +24 -15
  32. data/lib/prosemirror_to_html/nodes/code_block_wrapper.rb +0 -13
  33. data/lib/prosemirror_to_html/nodes/text.rb +0 -14
  34. data/lib/prosemirror_to_html/nodes/user.rb +0 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 310a6a3549a6e796525d9623874469d85368541498a971568dba4b037c0c7289
4
- data.tar.gz: 55412b082912e22860b238005c78aee0323d420bce0e8964f9e7d5c227c2cebd
3
+ metadata.gz: f284982bc72b18c9ef678e23833febc9f5326f7c02fa5fcd0f24d2b3b01a068c
4
+ data.tar.gz: 72026340795ebd8a342be9693ebf401f2c37fb75bcdf44c740cec2c351a046e3
5
5
  SHA512:
6
- metadata.gz: 99009e84b817e6d7a19cc168bdf1a1548ed70ae48b6f67240fbb7fa0ecfef9942b373232fb7d662d9c4df93922aa7864c7166e78b37c5ca26e4464ae9ea48ba5
7
- data.tar.gz: 435eba416a8990cf8c989596e0b5a6b02aeab2fa4e25dfec02472f710b80d2cf4a3937988c0baf29d9d159f795d63e0327722e3c56538a818871120adbdd4c5d
6
+ metadata.gz: 364d04e54e3c17755dca5365798cbb75f72b9b5597d8dda3c513a2a43e9092f90e45764fb06dda0626adc6b78bcc8af8962bf8c54bec74956716e22fff97e35c
7
+ data.tar.gz: 91a7c87d2527b9cf4350722e1f4d454405b7e88b1e8a3ab04524b60d1c76c19d89b527105a7c704c3cfbcdeef938a9a6245a13ffdadc29d098ddba260730b067
data/CHANGELOG.md ADDED
@@ -0,0 +1,24 @@
1
+ ## [0.2.0] - 2023-07-03
2
+
3
+ Hans Lemuet (@Spone) is the new maintainer. The fork is now hosted at https://github.com/etaminstudio/prosemirror_to_html
4
+
5
+ ### Added
6
+
7
+ - Added support for marks `Strike`, `Subscript`, `Superscript`, `Underline`
8
+ - Added support for nodes `Blockquote`, `HorizontalRule`, `Table`, `TableCell`, `TableHeader`, `TableRow`
9
+ - `Link` mark: added support for conditional `target`, `title`, `rel` attributes
10
+ - `Heading` node: added support for `level` attribute
11
+
12
+ ### Changed
13
+
14
+ - Improve code style (always use snake_case for methods)
15
+ - Refactor `Renderer`
16
+ - Refactor `Node`
17
+ - Refactor specs to have one spec file for each node and mark
18
+ - Update dependencies
19
+
20
+ ### Removed
21
+
22
+ - `CodeBlockWrapper` node removed in favor of `CodeBlock`
23
+ - `Text` node removed
24
+ - `User` node removed
data/Gemfile.lock CHANGED
@@ -1,41 +1,43 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- prosemirror_to_html (0.1.0)
4
+ prosemirror_to_html (0.2.0)
5
5
  nokogiri
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- diff-lcs (1.3)
11
- mini_portile2 (2.4.0)
12
- nokogiri (1.10.2)
13
- mini_portile2 (~> 2.4.0)
14
- rake (10.5.0)
15
- rspec (3.8.0)
16
- rspec-core (~> 3.8.0)
17
- rspec-expectations (~> 3.8.0)
18
- rspec-mocks (~> 3.8.0)
19
- rspec-core (3.8.0)
20
- rspec-support (~> 3.8.0)
21
- rspec-expectations (3.8.2)
10
+ diff-lcs (1.5.0)
11
+ mini_portile2 (2.8.2)
12
+ nokogiri (1.15.2)
13
+ mini_portile2 (~> 2.8.2)
14
+ racc (~> 1.4)
15
+ racc (1.7.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)
22
24
  diff-lcs (>= 1.2.0, < 2.0)
23
- rspec-support (~> 3.8.0)
24
- rspec-mocks (3.8.0)
25
+ rspec-support (~> 3.12.0)
26
+ rspec-mocks (3.12.5)
25
27
  diff-lcs (>= 1.2.0, < 2.0)
26
- rspec-support (~> 3.8.0)
27
- rspec-support (3.8.0)
28
- yard (0.9.19)
28
+ rspec-support (~> 3.12.0)
29
+ rspec-support (3.12.1)
30
+ yard (0.9.34)
29
31
 
30
32
  PLATFORMS
31
33
  ruby
32
34
 
33
35
  DEPENDENCIES
34
- bundler (~> 2.0.1)
36
+ bundler (~> 2.1.4)
35
37
  prosemirror_to_html!
36
- rake (~> 10.0)
38
+ rake (~> 13.0)
37
39
  rspec (~> 3.0)
38
40
  yard
39
41
 
40
42
  BUNDLED WITH
41
- 2.0.1
43
+ 2.1.4
@@ -1,14 +1,8 @@
1
1
  module ProsemirrorToHtml
2
2
  module Marks
3
3
  class Bold < Mark
4
-
5
- def matching
6
- @node.type === 'bold'
7
- end
8
-
9
- def tag
10
- 'strong'
11
- end
4
+ @mark_type = 'bold'
5
+ @tag_name = 'strong'
12
6
  end
13
7
  end
14
8
  end
@@ -1,14 +1,8 @@
1
1
  module ProsemirrorToHtml
2
2
  module Marks
3
3
  class Code < Mark
4
-
5
- def matching
6
- @node.type === 'code'
7
- end
8
-
9
- def tag
10
- 'code'
11
- end
4
+ @mark_type = 'code'
5
+ @tag_name = 'code'
12
6
  end
13
7
  end
14
8
  end
@@ -1,14 +1,8 @@
1
1
  module ProsemirrorToHtml
2
2
  module Marks
3
3
  class Italic < Mark
4
-
5
- def matching
6
- @node.type === 'italic'
7
- end
8
-
9
- def tag
10
- 'em'
11
- end
4
+ @mark_type = 'italic'
5
+ @tag_name = 'em'
12
6
  end
13
7
  end
14
8
  end
@@ -1,16 +1,24 @@
1
1
  module ProsemirrorToHtml
2
2
  module Marks
3
3
  class Link < Mark
4
-
5
- def matching
6
- @node.type === 'link'
7
- end
4
+ @mark_type = 'link'
5
+ @tag_name = 'a'
8
6
 
9
7
  def tag
10
- [{
11
- tag: "a",
12
- attrs: @node.attrs
13
- }]
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
+ [
17
+ {
18
+ tag: self.class.tag_name,
19
+ attrs: attrs
20
+ }
21
+ ]
14
22
  end
15
23
  end
16
24
  end
@@ -1,24 +1,26 @@
1
1
  module ProsemirrorToHtml
2
2
  module Marks
3
3
  class Mark
4
- attr_writer :type
4
+ @mark_type = nil
5
+ @tag_name = nil
5
6
 
6
- def type
7
- @type || 'mark'
7
+ class << self
8
+ attr_reader :mark_type, :tag_name
8
9
  end
9
10
 
10
- def initialize(data)
11
- @node = data
11
+ def initialize(mark)
12
+ @mark = mark
12
13
  end
13
14
 
14
15
  def matching
16
+ return @mark.type == self.class.mark_type if @mark.type
17
+
15
18
  false
16
19
  end
17
20
 
18
21
  def tag
19
- nil
22
+ self.class.tag_name
20
23
  end
21
-
22
24
  end
23
25
  end
24
26
  end
@@ -0,0 +1,8 @@
1
+ module ProsemirrorToHtml
2
+ module Marks
3
+ class Strike < Mark
4
+ @mark_type = 'strike'
5
+ @tag_name = 'strike'
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module ProsemirrorToHtml
2
+ module Marks
3
+ class Subscript < Mark
4
+ @mark_type = 'subscript'
5
+ @tag_name = 'sub'
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module ProsemirrorToHtml
2
+ module Marks
3
+ class Superscript < Mark
4
+ @mark_type = 'superscript'
5
+ @tag_name = 'sup'
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module ProsemirrorToHtml
2
+ module Marks
3
+ class Underline < Mark
4
+ @mark_type = 'underline'
5
+ @tag_name = 'u'
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module ProsemirrorToHtml
2
+ module Nodes
3
+ class Blockquote < Node
4
+ @node_type = 'blockquote'
5
+ @tag_name = 'blockquote'
6
+ end
7
+ end
8
+ end
@@ -1,14 +1,8 @@
1
1
  module ProsemirrorToHtml
2
2
  module Nodes
3
3
  class BulletList < Node
4
-
5
- def matching
6
- @node.type === 'bullet_list'
7
- end
8
-
9
- def data
10
- 'ul'
11
- end
4
+ @node_type = 'bullet_list'
5
+ @tag_name = 'ul'
12
6
  end
13
7
  end
14
8
  end
@@ -1,15 +1,8 @@
1
1
  module ProsemirrorToHtml
2
2
  module Nodes
3
3
  class CodeBlock < Node
4
-
5
- def matching
6
- @node.type === 'code_block'
7
- end
8
-
9
- def tag
10
- ['pre', 'tag']
11
- end
12
-
4
+ @node_type = 'code_block'
5
+ @tag_name = ['pre', 'code']
13
6
  end
14
7
  end
15
8
  end
@@ -1,13 +1,11 @@
1
1
  module ProsemirrorToHtml
2
2
  module Nodes
3
3
  class HardBreak < Node
4
+ @node_type = 'hard_break'
5
+ @tag_name = 'br'
4
6
 
5
- def matching
6
- @node.type === 'hard_break'
7
- end
8
-
9
- def data
10
- 'br'
7
+ def self_closing
8
+ true
11
9
  end
12
10
  end
13
11
  end
@@ -1,15 +1,23 @@
1
1
  module ProsemirrorToHtml
2
2
  module Nodes
3
3
  class Heading < Node
4
+ @node_type = 'heading'
4
5
 
5
- def matching
6
- @node.type === 'heading'
6
+ def tag
7
+ [
8
+ {
9
+ tag: "h#{@node.attrs.level}",
10
+ attrs: tag_attrs
11
+ }
12
+ ]
7
13
  end
8
14
 
9
- def tag
10
- "h#{@node.attrs.level}"
15
+ private
16
+
17
+ def tag_attrs
18
+ attrs_hash = @node.attrs.to_h
19
+ attrs_hash.slice(*attrs_hash.keys - %i[level])
11
20
  end
12
-
13
21
  end
14
22
  end
15
23
  end
@@ -0,0 +1,12 @@
1
+ module ProsemirrorToHtml
2
+ module Nodes
3
+ class HorizontalRule < Node
4
+ @node_type = 'horizontal_rule'
5
+ @tag_name = 'hr'
6
+
7
+ def self_closing
8
+ true
9
+ end
10
+ end
11
+ end
12
+ end
@@ -1,14 +1,20 @@
1
1
  module ProsemirrorToHtml
2
2
  module Nodes
3
3
  class Image < Node
4
+ @node_type = 'image'
5
+ @tag_name = 'img'
4
6
 
5
- def matching
6
- @node.type === 'img'
7
+ def tag
8
+ [
9
+ {
10
+ tag: self.class.tag_name,
11
+ attrs: @node.attrs
12
+ }
13
+ ]
7
14
  end
8
15
 
9
- def tag
10
- # doc.img(:src => @node.attrs.src)
11
- 'img'
16
+ def self_closing
17
+ true
12
18
  end
13
19
  end
14
20
  end
@@ -1,18 +1,8 @@
1
1
  module ProsemirrorToHtml
2
2
  module Nodes
3
3
  class ListItem < Node
4
- # def initialize(dom_node)
5
- # super(dom_node)
6
- # @wrapper = { type: 'paragraph' }
7
- # end
8
-
9
- def matching
10
- @node.type === 'list_item'
11
- end
12
-
13
- def tag
14
- 'li'
15
- end
4
+ @node_type = 'list_item'
5
+ @tag_name = 'li'
16
6
  end
17
7
  end
18
8
  end
@@ -1,29 +1,48 @@
1
1
  module ProsemirrorToHtml
2
2
  module Nodes
3
-
4
3
  class Node
5
- attr_writer :wrapper
6
- attr_writer :type
4
+ @node_type = nil
5
+ @tag_name = nil
7
6
 
8
- def type
9
- @type || 'node'
7
+ class << self
8
+ attr_reader :node_type, :tag_name
10
9
  end
11
10
 
12
- def initialize(data)
13
- @node = data
11
+ def initialize(node)
12
+ @node = node
14
13
  end
15
14
 
16
15
  def matching
16
+ return underscore(@node.type) == self.class.node_type if @node.type
17
+
18
+ false
19
+ end
20
+
21
+ def self_closing
17
22
  false
18
23
  end
19
24
 
20
25
  def tag
21
- nil
26
+ self.class.tag_name
22
27
  end
23
28
 
24
29
  def text
25
30
  nil
26
31
  end
32
+
33
+ private
34
+
35
+ # from https://github.com/rails/rails/blob/83217025a171593547d1268651b446d3533e2019/activesupport/lib/active_support/inflector/methods.rb#L92
36
+ def underscore(camel_cased_word)
37
+ return camel_cased_word unless /[A-Z-]|::/.match?(camel_cased_word)
38
+
39
+ word = camel_cased_word.to_s.gsub("::", "/")
40
+ word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
41
+ word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
42
+ word.tr!("-", "_")
43
+ word.downcase!
44
+ word
45
+ end
27
46
  end
28
47
  end
29
48
  end
@@ -1,13 +1,16 @@
1
1
  module ProsemirrorToHtml
2
2
  module Nodes
3
3
  class OrderedList < Node
4
+ @node_type = 'ordered_list'
5
+ @tag_name = 'ol'
4
6
 
5
- def matching
6
- @node.type === 'ordered_list'
7
- end
8
-
9
- def data
10
- 'ol'
7
+ def tag
8
+ [
9
+ {
10
+ tag: self.class.tag_name,
11
+ attrs: @node.attrs
12
+ }
13
+ ]
11
14
  end
12
15
  end
13
16
  end
@@ -1,14 +1,8 @@
1
1
  module ProsemirrorToHtml
2
2
  module Nodes
3
3
  class Paragraph < Node
4
-
5
- def matching
6
- @node.type === 'paragraph'
7
- end
8
-
9
- def tag
10
- 'p'
11
- end
4
+ @node_type = 'paragraph'
5
+ @tag_name = 'p'
12
6
  end
13
7
  end
14
8
  end
@@ -0,0 +1,8 @@
1
+ module ProsemirrorToHtml
2
+ module Nodes
3
+ class Table < Node
4
+ @node_type = 'table'
5
+ @tag_name = ['table', 'tbody']
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,17 @@
1
+ module ProsemirrorToHtml
2
+ module Nodes
3
+ class TableCell < Node
4
+ @node_type = 'table_cell'
5
+ @tag_name = 'td'
6
+
7
+ def tag
8
+ [
9
+ {
10
+ tag: self.class.tag_name,
11
+ attrs: @node.attrs
12
+ }
13
+ ]
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module ProsemirrorToHtml
2
+ module Nodes
3
+ class TableHeader < TableCell
4
+ @node_type = 'table_header'
5
+ @tag_name = 'th'
6
+
7
+ def tag
8
+ [
9
+ {
10
+ tag: self.class.tag_name,
11
+ attrs: @node.attrs
12
+ }
13
+ ]
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,8 @@
1
+ module ProsemirrorToHtml
2
+ module Nodes
3
+ class TableRow < Node
4
+ @node_type = 'table_row'
5
+ @tag_name = 'tr'
6
+ end
7
+ end
8
+ end
@@ -1,3 +1,3 @@
1
1
  module ProsemirrorToHtml
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -4,145 +4,282 @@ require "prosemirror_to_html/marks/bold"
4
4
  require "prosemirror_to_html/marks/code"
5
5
  require "prosemirror_to_html/marks/italic"
6
6
  require "prosemirror_to_html/marks/link"
7
+ require "prosemirror_to_html/marks/strike"
8
+ require "prosemirror_to_html/marks/subscript"
9
+ require "prosemirror_to_html/marks/superscript"
10
+ require "prosemirror_to_html/marks/underline"
7
11
  require "prosemirror_to_html/nodes/node"
12
+ require "prosemirror_to_html/nodes/blockquote"
8
13
  require "prosemirror_to_html/nodes/bullet_list"
9
- require "prosemirror_to_html/nodes/code_block_wrapper"
10
14
  require "prosemirror_to_html/nodes/code_block"
11
15
  require "prosemirror_to_html/nodes/hard_break"
16
+ require "prosemirror_to_html/nodes/horizontal_rule"
12
17
  require "prosemirror_to_html/nodes/heading"
13
18
  require "prosemirror_to_html/nodes/image"
14
19
  require "prosemirror_to_html/nodes/list_item"
15
20
  require "prosemirror_to_html/nodes/ordered_list"
16
21
  require "prosemirror_to_html/nodes/paragraph"
17
- require "prosemirror_to_html/nodes/text"
18
- require "prosemirror_to_html/nodes/user"
22
+ require "prosemirror_to_html/nodes/table"
23
+ require "prosemirror_to_html/nodes/table_cell"
24
+ require "prosemirror_to_html/nodes/table_header"
25
+ require "prosemirror_to_html/nodes/table_row"
19
26
  require 'nokogiri'
20
27
  require 'json'
21
28
  require "ostruct"
22
29
 
23
30
  module ProsemirrorToHtml
24
31
  class Error < StandardError; end
25
- # Your code goes here...
32
+
26
33
  class Renderer
27
- def initialize()
28
- @storedMarks = []
29
- @marks = [
30
- ProsemirrorToHtml::Marks::Bold,
31
- ProsemirrorToHtml::Marks::Code,
32
- ProsemirrorToHtml::Marks::Italic,
33
- ProsemirrorToHtml::Marks::Link
34
- ]
34
+ def initialize
35
+ @document = nil
36
+
35
37
  @nodes = [
38
+ ProsemirrorToHtml::Nodes::Blockquote,
36
39
  ProsemirrorToHtml::Nodes::BulletList,
37
- ProsemirrorToHtml::Nodes::CodeBlockWrapper,
38
40
  ProsemirrorToHtml::Nodes::CodeBlock,
39
41
  ProsemirrorToHtml::Nodes::HardBreak,
40
42
  ProsemirrorToHtml::Nodes::Heading,
43
+ ProsemirrorToHtml::Nodes::HorizontalRule,
41
44
  ProsemirrorToHtml::Nodes::Image,
42
45
  ProsemirrorToHtml::Nodes::ListItem,
43
46
  ProsemirrorToHtml::Nodes::OrderedList,
44
47
  ProsemirrorToHtml::Nodes::Paragraph,
45
- # ProsemirrorToHtml::Nodes::Text,
46
- ProsemirrorToHtml::Nodes::User
48
+ ProsemirrorToHtml::Nodes::Table,
49
+ ProsemirrorToHtml::Nodes::TableCell,
50
+ ProsemirrorToHtml::Nodes::TableHeader,
51
+ ProsemirrorToHtml::Nodes::TableRow,
47
52
  ]
53
+
54
+ @marks = [
55
+ ProsemirrorToHtml::Marks::Bold,
56
+ ProsemirrorToHtml::Marks::Code,
57
+ ProsemirrorToHtml::Marks::Italic,
58
+ ProsemirrorToHtml::Marks::Link,
59
+ ProsemirrorToHtml::Marks::Strike,
60
+ ProsemirrorToHtml::Marks::Subscript,
61
+ ProsemirrorToHtml::Marks::Superscript,
62
+ ProsemirrorToHtml::Marks::Underline,
63
+ ]
64
+ end
65
+
66
+ def with_marks(marks = nil)
67
+ @marks = marks if marks.is_a? Array
68
+
69
+ self
48
70
  end
49
71
 
50
- def addNode(node)
51
- @nodes.push(node)
72
+ def with_nodes(nodes = nil)
73
+ @nodes = nodes if nodes.is_a? Array
74
+
75
+ self
52
76
  end
53
- def addNodes(nodes)
54
- nodes.each do |node|
55
- addNode(node);
77
+
78
+ def render(value)
79
+ json = case value
80
+ when Hash then value.to_json
81
+ when String then value
82
+ else raise Error
83
+ end
84
+
85
+ @document = JSON.parse(json, object_class: OpenStruct)
86
+
87
+ html = ''
88
+
89
+ content = @document.content.is_a?(Array) ? @document.content : []
90
+
91
+ content.each_with_index do |node, index|
92
+ prev_node = content[index - 1]
93
+ next_node = content[index + 1]
94
+
95
+ html << render_node(node, prev_node, next_node)
56
96
  end
97
+
98
+ html
57
99
  end
58
- def addMark(mark)
59
- @marks.push(mark)
100
+
101
+ def add_node(node)
102
+ @nodes << node
103
+
104
+ self
60
105
  end
61
- def addMarks(marks)
62
- marks.each do |mark|
63
- addMark(mark);
106
+
107
+ def add_nodes(nodes)
108
+ @nodes.push nodes
109
+
110
+ self
111
+ end
112
+
113
+ def add_mark(mark)
114
+ @marks << mark
115
+
116
+ self
117
+ end
118
+
119
+ def add_marks(marks)
120
+ @marks.push marks
121
+
122
+ self
123
+ end
124
+
125
+ def replace_node(search_node, replace_node)
126
+ @nodes.each do |key, node_klass|
127
+ if node_klass == search_node
128
+ @nodes[key] = replace_node
129
+ end
64
130
  end
131
+
132
+ self
65
133
  end
66
134
 
67
- def render(hash)
68
- html = ""
69
- json = hash.to_json
70
- object = JSON.parse(json, object_class: OpenStruct)
71
- object.content.each do |node|
72
- html += renderNode(node)
135
+ def replace_mark(search_mark, replace_mark)
136
+ @marks.each do |key, mark_klass|
137
+ if mark_klass == search_mark
138
+ @marks[key] = replace_mark
139
+ end
73
140
  end
74
-
75
- html
141
+
142
+ self
76
143
  end
77
- private
78
- def renderNode(item)
79
- html = []
80
- if item.marks
81
- item.marks.each do |m|
82
- mark = get_matching_mark(m)
83
- html.push(renderOpeningTag(mark.tag)) if mark
144
+
145
+ private
146
+
147
+ def render_node(node, prev_node, next_node)
148
+ html = ''
149
+ render_klass = nil
150
+
151
+ if node&.marks
152
+ node.marks.each do |mark|
153
+ @marks.each do |klass|
154
+ render_klass = klass.new(mark)
155
+
156
+ if render_klass.matching && mark_should_open(mark, prev_node)
157
+ html << render_opening_tag(render_klass.tag)
158
+ end
84
159
  end
85
160
  end
86
-
87
- node = get_matching_node(item)
88
- html.push(renderOpeningTag(node.tag)) if node
161
+ end
89
162
 
90
- if item.content
91
- item.content.each do |content|
92
- html.push(renderNode(content))
93
- end
94
- elsif item.text
95
- html.push(item.text)
163
+ @nodes.each do |klass|
164
+ render_klass = klass.new(node)
165
+
166
+ if render_klass.matching
167
+ html << render_opening_tag(render_klass.tag)
168
+ break
96
169
  end
97
-
98
- html.push(renderClosingTag(node.tag)) if node
99
- if item.marks
100
- item.marks.reverse.each do |m|
101
- mark = get_matching_mark(m)
102
- html.push(renderClosingTag(mark.tag)) if mark
103
- end
170
+ end
171
+
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]
176
+
177
+ html << render_node(nested_node, prev_nested_node, next_nested_node)
178
+ prev_node = nested_node
104
179
  end
105
- return html.join("");
180
+ elsif node&.text
181
+ html << CGI.escapeHTML(node.text)
182
+ elsif text = render_klass.text
183
+ html << text
106
184
  end
107
185
 
108
- def renderOpeningTag(tags)
109
- return "<#{tags}>" if tags.is_a? String
110
- all = tags.map do |tag|
111
- return "<#{tags}>" if tag.is_a? String
112
- h = "<#{tag[:tag]}"
113
- tag[:attrs].to_h.each_pair { |key, value| h += " #{key}=\"#{value}\"" } if tag[:attrs]
114
- "#{h}>"
186
+ @nodes.each do |klass|
187
+ render_klass = klass.new(node)
188
+
189
+ if render_klass.self_closing
190
+ next
191
+ end
192
+
193
+ if render_klass.matching
194
+ html << render_closing_tag(render_klass.tag)
195
+ end
115
196
  end
116
- return all.join('')
117
- end
118
197
 
119
- def renderClosingTag(tags)
120
- return "</#{tags}>" if tags.is_a? String
121
- all = tags.reverse.map do |tag|
122
- return "</#{tag}>" if tag.is_a? String
123
- "</#{tag[:tag]}>"
198
+ if node&.marks
199
+ node.marks.reverse.each do |mark|
200
+ @marks.each do |klass|
201
+ render_klass = klass.new(mark)
202
+
203
+ if render_klass.matching && mark_should_close(mark, next_node)
204
+ html << render_closing_tag(render_klass.tag)
205
+ end
206
+ end
207
+ end
124
208
  end
125
- return all.join('')
209
+
210
+ html
126
211
  end
127
212
 
128
- # Find which Node matches the Html Node
129
- def get_matching_node(item)
130
- return get_matching_class(item, @nodes)
213
+ def mark_should_open(mark, prev_node)
214
+ node_has_mark(prev_node, mark)
131
215
  end
132
- # Find which Mark matches the HtmlElement
133
- def get_matching_mark(item)
134
- return get_matching_class(item, @marks)
216
+
217
+ def mark_should_close(mark, next_node)
218
+ node_has_mark(next_node, mark)
135
219
  end
136
- # Find which class matches the HtmlElement
137
- def get_matching_class(node, classes)
138
- found = classes.select do |clazz|
139
- instance = clazz.new(node)
140
- if (instance.matching())
141
- return instance
220
+
221
+ def node_has_mark(node, mark)
222
+ return true unless node
223
+ return true if node.respond_to?(:marks)
224
+
225
+ # Other node has same mark
226
+ node.marks&.each do |other_mark|
227
+ if mark == other_mark
228
+ return false
142
229
  end
143
230
  end
144
- found.first
231
+
232
+ true
233
+ end
234
+
235
+ def render_opening_tag(tags)
236
+ tags = array_wrap(tags)
237
+
238
+ return nil if tags.empty?
239
+
240
+ tags.map do |tag|
241
+ if tag.is_a? String
242
+ "<#{tag}>"
243
+ else
244
+ tag = OpenStruct.new(tag) unless tag.is_a?(OpenStruct)
245
+
246
+ attrs = ''
247
+ if tag&.attrs
248
+ tag.attrs.each_pair do |attr, value|
249
+ attrs << " #{attr}=\"#{value}\""
250
+ end
251
+ end
252
+
253
+ "<#{tag.tag}#{attrs}>"
254
+ end
255
+ end.join
256
+ end
257
+
258
+ def render_closing_tag(tags)
259
+ tags = array_wrap(tags).reverse
260
+
261
+ return nil if tags.empty?
262
+
263
+ tags.map do |tag|
264
+ if tag.is_a? String
265
+ "</#{tag}>"
266
+ else
267
+ tag = OpenStruct.new(tag) unless tag.is_a?(OpenStruct)
268
+
269
+ "</#{tag.tag}>"
270
+ end
271
+ end.join
272
+ end
273
+
274
+ # From https://github.com/rails/rails/blob/5f3ff60084ab5d5921ca3499814e4697f8350ee7/activesupport/lib/active_support/core_ext/array/wrap.rb
275
+ def array_wrap(object)
276
+ if object.nil?
277
+ []
278
+ elsif object.respond_to?(:to_ary)
279
+ object.to_ary || [object]
280
+ else
281
+ [object]
282
+ end
145
283
  end
146
-
147
284
  end
148
285
  end
@@ -6,15 +6,15 @@ require "prosemirror_to_html/version"
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "prosemirror_to_html"
8
8
  spec.version = ProsemirrorToHtml::VERSION
9
- spec.authors = ["Brian Kimball"]
10
- spec.email = ["bvkimball@gmail.com"]
11
-
9
+ spec.authors = ["Hans Lemuet", "Brian Kimball"]
10
+ spec.email = ["hans@etamin.studio", "bvkimball@gmail.com"]
11
+
12
12
  spec.summary = %q{Takes ProseMirror compatible JSON and outputs HTML.}
13
13
  spec.description = %q{Takes ProseMirror compatible JSON and outputs HTML.}
14
- spec.homepage = "https://github.com/inputhq/prosemirror_to_html"
14
+ spec.homepage = "https://github.com/etaminstudio/prosemirror_to_html"
15
15
  spec.license = "MIT"
16
16
 
17
-
17
+
18
18
  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
19
19
  # to allow pushing to a single host or delete this section to allow pushing to any host.
20
20
  # if spec.respond_to?(:metadata)
@@ -37,8 +37,8 @@ Gem::Specification.new do |spec|
37
37
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
38
38
  spec.require_paths = ["lib"]
39
39
 
40
- spec.add_development_dependency "bundler", "~> 2.0.1"
41
- spec.add_development_dependency "rake", "~> 10.0"
40
+ spec.add_development_dependency "bundler", "~> 2.1.4"
41
+ spec.add_development_dependency "rake", "~> 13.0"
42
42
  spec.add_development_dependency "rspec", "~> 3.0"
43
43
  spec.add_development_dependency "yard"
44
44
  spec.add_dependency "nokogiri"
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prosemirror_to_html
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
+ - Hans Lemuet
7
8
  - Brian Kimball
8
- autorequire:
9
+ autorequire:
9
10
  bindir: exe
10
11
  cert_chain: []
11
- date: 2019-04-20 00:00:00.000000000 Z
12
+ date: 2023-07-03 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: bundler
@@ -16,28 +17,28 @@ dependencies:
16
17
  requirements:
17
18
  - - "~>"
18
19
  - !ruby/object:Gem::Version
19
- version: 2.0.1
20
+ version: 2.1.4
20
21
  type: :development
21
22
  prerelease: false
22
23
  version_requirements: !ruby/object:Gem::Requirement
23
24
  requirements:
24
25
  - - "~>"
25
26
  - !ruby/object:Gem::Version
26
- version: 2.0.1
27
+ version: 2.1.4
27
28
  - !ruby/object:Gem::Dependency
28
29
  name: rake
29
30
  requirement: !ruby/object:Gem::Requirement
30
31
  requirements:
31
32
  - - "~>"
32
33
  - !ruby/object:Gem::Version
33
- version: '10.0'
34
+ version: '13.0'
34
35
  type: :development
35
36
  prerelease: false
36
37
  version_requirements: !ruby/object:Gem::Requirement
37
38
  requirements:
38
39
  - - "~>"
39
40
  - !ruby/object:Gem::Version
40
- version: '10.0'
41
+ version: '13.0'
41
42
  - !ruby/object:Gem::Dependency
42
43
  name: rspec
43
44
  requirement: !ruby/object:Gem::Requirement
@@ -82,6 +83,7 @@ dependencies:
82
83
  version: '0'
83
84
  description: Takes ProseMirror compatible JSON and outputs HTML.
84
85
  email:
86
+ - hans@etamin.studio
85
87
  - bvkimball@gmail.com
86
88
  executables: []
87
89
  extensions: []
@@ -91,6 +93,7 @@ files:
91
93
  - ".gitignore"
92
94
  - ".rspec"
93
95
  - ".travis.yml"
96
+ - CHANGELOG.md
94
97
  - CODE_OF_CONDUCT.md
95
98
  - Gemfile
96
99
  - Gemfile.lock
@@ -105,27 +108,34 @@ files:
105
108
  - lib/prosemirror_to_html/marks/italic.rb
106
109
  - lib/prosemirror_to_html/marks/link.rb
107
110
  - lib/prosemirror_to_html/marks/mark.rb
111
+ - lib/prosemirror_to_html/marks/strike.rb
112
+ - lib/prosemirror_to_html/marks/subscript.rb
113
+ - lib/prosemirror_to_html/marks/superscript.rb
114
+ - lib/prosemirror_to_html/marks/underline.rb
115
+ - lib/prosemirror_to_html/nodes/blockquote.rb
108
116
  - lib/prosemirror_to_html/nodes/bullet_list.rb
109
117
  - lib/prosemirror_to_html/nodes/code_block.rb
110
- - lib/prosemirror_to_html/nodes/code_block_wrapper.rb
111
118
  - lib/prosemirror_to_html/nodes/hard_break.rb
112
119
  - lib/prosemirror_to_html/nodes/heading.rb
120
+ - lib/prosemirror_to_html/nodes/horizontal_rule.rb
113
121
  - lib/prosemirror_to_html/nodes/image.rb
114
122
  - lib/prosemirror_to_html/nodes/list_item.rb
115
123
  - lib/prosemirror_to_html/nodes/node.rb
116
124
  - lib/prosemirror_to_html/nodes/ordered_list.rb
117
125
  - lib/prosemirror_to_html/nodes/paragraph.rb
118
- - lib/prosemirror_to_html/nodes/text.rb
119
- - lib/prosemirror_to_html/nodes/user.rb
126
+ - lib/prosemirror_to_html/nodes/table.rb
127
+ - lib/prosemirror_to_html/nodes/table_cell.rb
128
+ - lib/prosemirror_to_html/nodes/table_header.rb
129
+ - lib/prosemirror_to_html/nodes/table_row.rb
120
130
  - lib/prosemirror_to_html/version.rb
121
131
  - prosemirror_to_html.gemspec
122
132
  - scripts/package
123
133
  - scripts/release
124
- homepage: https://github.com/inputhq/prosemirror_to_html
134
+ homepage: https://github.com/etaminstudio/prosemirror_to_html
125
135
  licenses:
126
136
  - MIT
127
137
  metadata: {}
128
- post_install_message:
138
+ post_install_message:
129
139
  rdoc_options: []
130
140
  require_paths:
131
141
  - lib
@@ -140,9 +150,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
140
150
  - !ruby/object:Gem::Version
141
151
  version: '0'
142
152
  requirements: []
143
- rubyforge_project:
144
- rubygems_version: 2.7.6
145
- signing_key:
153
+ rubygems_version: 3.3.26
154
+ signing_key:
146
155
  specification_version: 4
147
156
  summary: Takes ProseMirror compatible JSON and outputs HTML.
148
157
  test_files: []
@@ -1,13 +0,0 @@
1
- module ProsemirrorToHtml
2
- module Nodes
3
- class CodeBlockWrapper < Node
4
- def matching
5
- @node.name === 'pre'
6
- end
7
-
8
- def data
9
- nil
10
- end
11
- end
12
- end
13
- end
@@ -1,14 +0,0 @@
1
- module ProsemirrorToHtml
2
- module Nodes
3
- class Text < Node
4
-
5
- def matching
6
- @node.type === 'text'
7
- end
8
-
9
- def tag
10
- @node.text
11
- end
12
- end
13
- end
14
- end
@@ -1,14 +0,0 @@
1
- module ProsemirrorToHtml
2
- module Nodes
3
- class User < Node
4
-
5
- def matching
6
- @node.natypeme === 'user'
7
- end
8
-
9
- def tag
10
- nil
11
- end
12
- end
13
- end
14
- end