prosereflect 0.1.0 → 0.1.1
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/.rubocop_todo.yml +23 -4
- data/README.adoc +193 -12
- data/lib/prosereflect/attribute/base.rb +34 -0
- data/lib/prosereflect/attribute/bold.rb +20 -0
- data/lib/prosereflect/attribute/href.rb +24 -0
- data/lib/prosereflect/attribute/id.rb +24 -0
- data/lib/prosereflect/attribute.rb +13 -0
- data/lib/prosereflect/blockquote.rb +85 -0
- data/lib/prosereflect/bullet_list.rb +83 -0
- data/lib/prosereflect/code_block.rb +135 -0
- data/lib/prosereflect/code_block_wrapper.rb +66 -0
- data/lib/prosereflect/document.rb +99 -24
- data/lib/prosereflect/hard_break.rb +11 -9
- data/lib/prosereflect/heading.rb +64 -0
- data/lib/prosereflect/horizontal_rule.rb +70 -0
- data/lib/prosereflect/image.rb +126 -0
- data/lib/prosereflect/input/html.rb +505 -0
- data/lib/prosereflect/list_item.rb +65 -0
- data/lib/prosereflect/mark/base.rb +49 -0
- data/lib/prosereflect/mark/bold.rb +15 -0
- data/lib/prosereflect/mark/code.rb +14 -0
- data/lib/prosereflect/mark/italic.rb +15 -0
- data/lib/prosereflect/mark/link.rb +18 -0
- data/lib/prosereflect/mark/strike.rb +15 -0
- data/lib/prosereflect/mark/subscript.rb +15 -0
- data/lib/prosereflect/mark/superscript.rb +15 -0
- data/lib/prosereflect/mark/underline.rb +15 -0
- data/lib/prosereflect/mark.rb +11 -0
- data/lib/prosereflect/node.rb +181 -32
- data/lib/prosereflect/ordered_list.rb +85 -0
- data/lib/prosereflect/output/html.rb +374 -0
- data/lib/prosereflect/paragraph.rb +26 -15
- data/lib/prosereflect/parser.rb +111 -24
- data/lib/prosereflect/table.rb +40 -9
- data/lib/prosereflect/table_cell.rb +33 -8
- data/lib/prosereflect/table_header.rb +92 -0
- data/lib/prosereflect/table_row.rb +31 -8
- data/lib/prosereflect/text.rb +13 -17
- data/lib/prosereflect/user.rb +63 -0
- data/lib/prosereflect/version.rb +1 -1
- data/lib/prosereflect.rb +6 -0
- data/prosereflect.gemspec +1 -0
- data/spec/prosereflect/document_spec.rb +436 -36
- data/spec/prosereflect/hard_break_spec.rb +218 -22
- data/spec/prosereflect/input/html_spec.rb +797 -0
- data/spec/prosereflect/node_spec.rb +258 -89
- data/spec/prosereflect/output/html_spec.rb +369 -0
- data/spec/prosereflect/paragraph_spec.rb +424 -49
- data/spec/prosereflect/parser_spec.rb +304 -91
- data/spec/prosereflect/table_cell_spec.rb +268 -57
- data/spec/prosereflect/table_row_spec.rb +210 -40
- data/spec/prosereflect/table_spec.rb +392 -61
- data/spec/prosereflect/text_spec.rb +206 -48
- data/spec/prosereflect/user_spec.rb +73 -0
- data/spec/prosereflect_spec.rb +5 -0
- data/spec/support/shared_examples.rb +44 -15
- metadata +47 -3
- data/debug_loading.rb +0 -34
@@ -5,8 +5,29 @@ require_relative 'paragraph'
|
|
5
5
|
|
6
6
|
module Prosereflect
|
7
7
|
class TableCell < Node
|
8
|
+
PM_TYPE = 'table_cell'
|
9
|
+
|
10
|
+
attribute :type, :string, default: -> { send('const_get', 'PM_TYPE') }
|
11
|
+
|
12
|
+
key_value do
|
13
|
+
map 'type', to: :type, render_default: true
|
14
|
+
map 'content', to: :content
|
15
|
+
map 'attrs', to: :attrs
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(attributes = {})
|
19
|
+
attributes[:content] ||= []
|
20
|
+
super
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.create(attrs = nil)
|
24
|
+
new(type: PM_TYPE, attrs: attrs, content: [])
|
25
|
+
end
|
26
|
+
|
8
27
|
def paragraphs
|
9
|
-
|
28
|
+
return [] unless content
|
29
|
+
|
30
|
+
content.select { |node| node.is_a?(Paragraph) }
|
10
31
|
end
|
11
32
|
|
12
33
|
def text_content
|
@@ -17,13 +38,6 @@ module Prosereflect
|
|
17
38
|
text_content.split("\n").map(&:strip).reject(&:empty?)
|
18
39
|
end
|
19
40
|
|
20
|
-
# Create a new table cell
|
21
|
-
def self.create(attrs = nil)
|
22
|
-
cell = new({ 'type' => 'table_cell', 'content' => [] })
|
23
|
-
cell.instance_variable_set(:@attrs, attrs) if attrs
|
24
|
-
cell
|
25
|
-
end
|
26
|
-
|
27
41
|
# Add a paragraph to the cell
|
28
42
|
def add_paragraph(text = nil)
|
29
43
|
paragraph = Paragraph.create
|
@@ -33,5 +47,16 @@ module Prosereflect
|
|
33
47
|
add_child(paragraph)
|
34
48
|
paragraph
|
35
49
|
end
|
50
|
+
|
51
|
+
# Override to_h to handle empty content and attributes properly
|
52
|
+
def to_h
|
53
|
+
result = super
|
54
|
+
result['content'] ||= []
|
55
|
+
if result['attrs']
|
56
|
+
result['attrs'] = result['attrs'].is_a?(Hash) && result['attrs'][:attrs] ? result['attrs'][:attrs] : result['attrs']
|
57
|
+
result.delete('attrs') if result['attrs'].empty?
|
58
|
+
end
|
59
|
+
result
|
60
|
+
end
|
36
61
|
end
|
37
62
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'table_cell'
|
4
|
+
|
5
|
+
module Prosereflect
|
6
|
+
# TableHeader class represents a header cell in a table (<th> tag).
|
7
|
+
# It inherits from TableCell but adds header-specific attributes.
|
8
|
+
class TableHeader < TableCell
|
9
|
+
PM_TYPE = 'table_header'
|
10
|
+
|
11
|
+
attribute :type, :string, default: -> { send('const_get', 'PM_TYPE') }
|
12
|
+
attribute :scope, :string # row, col, rowgroup, or colgroup
|
13
|
+
attribute :abbr, :string # abbreviated version of content
|
14
|
+
attribute :colspan, :integer # number of columns this header spans
|
15
|
+
|
16
|
+
key_value do
|
17
|
+
map 'type', to: :type, render_default: true
|
18
|
+
map 'content', to: :content
|
19
|
+
map 'attrs', to: :attrs
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(attributes = {})
|
23
|
+
attributes[:content] ||= []
|
24
|
+
super
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.create(attrs = nil)
|
28
|
+
new(type: PM_TYPE, attrs: attrs, content: [])
|
29
|
+
end
|
30
|
+
|
31
|
+
# Add text to the last paragraph, or create a new one if none exists
|
32
|
+
def add_text(text, marks = nil)
|
33
|
+
last_paragraph = content&.last
|
34
|
+
last_paragraph = add_paragraph if !last_paragraph || !last_paragraph.is_a?(Paragraph)
|
35
|
+
last_paragraph.add_text(text, marks)
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
# Set the scope of the header (row, col, rowgroup, or colgroup)
|
40
|
+
def scope=(scope_value)
|
41
|
+
return unless %w[row col rowgroup colgroup].include?(scope_value)
|
42
|
+
|
43
|
+
self.attrs ||= {}
|
44
|
+
attrs['scope'] = scope_value
|
45
|
+
end
|
46
|
+
|
47
|
+
def scope
|
48
|
+
attrs&.[]('scope')
|
49
|
+
end
|
50
|
+
|
51
|
+
# Set abbreviated version of the header content
|
52
|
+
def abbr=(abbr_text)
|
53
|
+
self.attrs ||= {}
|
54
|
+
attrs['abbr'] = abbr_text
|
55
|
+
end
|
56
|
+
|
57
|
+
def abbr
|
58
|
+
attrs&.[]('abbr')
|
59
|
+
end
|
60
|
+
|
61
|
+
# Set the number of columns this header spans
|
62
|
+
def colspan=(span)
|
63
|
+
return unless span.to_i.positive?
|
64
|
+
|
65
|
+
self.attrs ||= {}
|
66
|
+
attrs['colspan'] = span.to_i
|
67
|
+
end
|
68
|
+
|
69
|
+
def colspan
|
70
|
+
attrs&.[]('colspan')
|
71
|
+
end
|
72
|
+
|
73
|
+
# Get header attributes as a hash
|
74
|
+
def header_attributes
|
75
|
+
{
|
76
|
+
scope: scope,
|
77
|
+
abbr: abbr,
|
78
|
+
colspan: colspan
|
79
|
+
}.compact
|
80
|
+
end
|
81
|
+
|
82
|
+
# Override to_h to exclude nil attributes
|
83
|
+
def to_h
|
84
|
+
result = super
|
85
|
+
if result['attrs']
|
86
|
+
result['attrs'].reject! { |_, v| v.nil? }
|
87
|
+
result.delete('attrs') if result['attrs'].empty?
|
88
|
+
end
|
89
|
+
result
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -5,20 +5,32 @@ require_relative 'table_cell'
|
|
5
5
|
|
6
6
|
module Prosereflect
|
7
7
|
class TableRow < Node
|
8
|
-
|
9
|
-
|
8
|
+
PM_TYPE = 'table_row'
|
9
|
+
|
10
|
+
attribute :type, :string, default: -> { send('const_get', 'PM_TYPE') }
|
11
|
+
|
12
|
+
key_value do
|
13
|
+
map 'type', to: :type, render_default: true
|
14
|
+
map 'content', to: :content
|
15
|
+
map 'attrs', to: :attrs
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(opts = {})
|
19
|
+
opts[:content] ||= []
|
20
|
+
super
|
10
21
|
end
|
11
22
|
|
12
|
-
# Create a new table row
|
13
23
|
def self.create(attrs = nil)
|
14
|
-
|
15
|
-
|
16
|
-
|
24
|
+
new(type: PM_TYPE, attrs: attrs, content: [])
|
25
|
+
end
|
26
|
+
|
27
|
+
def cells
|
28
|
+
content || []
|
17
29
|
end
|
18
30
|
|
19
31
|
# Add a cell to the row
|
20
|
-
def add_cell(content_text = nil)
|
21
|
-
cell = TableCell.create
|
32
|
+
def add_cell(content_text = nil, attrs: nil)
|
33
|
+
cell = TableCell.create(attrs)
|
22
34
|
|
23
35
|
if content_text
|
24
36
|
paragraph = cell.add_paragraph
|
@@ -28,5 +40,16 @@ module Prosereflect
|
|
28
40
|
add_child(cell)
|
29
41
|
cell
|
30
42
|
end
|
43
|
+
|
44
|
+
# Override to_h to handle empty content and attributes properly
|
45
|
+
def to_h
|
46
|
+
result = super
|
47
|
+
result['content'] ||= []
|
48
|
+
if result['attrs']
|
49
|
+
result['attrs'] = result['attrs'].is_a?(Hash) && result['attrs'][:attrs] ? result['attrs'][:attrs] : result['attrs']
|
50
|
+
result.delete('attrs') if result['attrs'].empty?
|
51
|
+
end
|
52
|
+
result
|
53
|
+
end
|
31
54
|
end
|
32
55
|
end
|
data/lib/prosereflect/text.rb
CHANGED
@@ -4,33 +4,29 @@ require_relative 'node'
|
|
4
4
|
|
5
5
|
module Prosereflect
|
6
6
|
class Text < Node
|
7
|
-
|
8
|
-
attr_accessor :marks
|
7
|
+
PM_TYPE = 'text'
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
@text = data['text'] || ''
|
13
|
-
end
|
9
|
+
attribute :type, :string, default: -> { send('const_get', 'PM_TYPE') }
|
10
|
+
attribute :text, :string, default: ''
|
14
11
|
|
15
|
-
|
16
|
-
|
12
|
+
key_value do
|
13
|
+
map 'type', to: :type, render_default: true
|
14
|
+
map 'text', to: :text
|
15
|
+
map 'marks', to: :marks
|
17
16
|
end
|
18
17
|
|
19
|
-
def
|
20
|
-
|
18
|
+
def self.create(text = '', marks = nil)
|
19
|
+
new(text: text, marks: marks)
|
21
20
|
end
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
node = new({ 'type' => 'text', 'text' => text })
|
26
|
-
node.instance_variable_set(:@marks, marks) if marks
|
27
|
-
node
|
22
|
+
def text_content
|
23
|
+
text || ''
|
28
24
|
end
|
29
25
|
|
30
|
-
#
|
26
|
+
# Override the to_h method to include the text attribute
|
31
27
|
def to_h
|
32
28
|
result = super
|
33
|
-
result['text'] =
|
29
|
+
result['text'] = text
|
34
30
|
result
|
35
31
|
end
|
36
32
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'node'
|
4
|
+
|
5
|
+
module Prosereflect
|
6
|
+
# User class represents a user mention in ProseMirror.
|
7
|
+
class User < Node
|
8
|
+
PM_TYPE = 'user'
|
9
|
+
|
10
|
+
attribute :type, :string, default: -> { send('const_get', 'PM_TYPE') }
|
11
|
+
attribute :id, :string
|
12
|
+
attribute :attrs, :hash
|
13
|
+
|
14
|
+
key_value do
|
15
|
+
map 'type', to: :type, render_default: true
|
16
|
+
map 'attrs', to: :attrs
|
17
|
+
map 'content', to: :content
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(attributes = {})
|
21
|
+
attributes[:content] = []
|
22
|
+
super
|
23
|
+
|
24
|
+
return unless attributes[:attrs]
|
25
|
+
|
26
|
+
@id = attributes[:attrs]['id']
|
27
|
+
self.attrs = { 'id' => @id }
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.create(attrs = nil)
|
31
|
+
new(attrs: attrs)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Update the user ID
|
35
|
+
def id=(user_id)
|
36
|
+
@id = user_id
|
37
|
+
self.attrs ||= {}
|
38
|
+
attrs['id'] = user_id
|
39
|
+
end
|
40
|
+
|
41
|
+
def id
|
42
|
+
@id || attrs&.[]('id')
|
43
|
+
end
|
44
|
+
|
45
|
+
# Override content-related methods since user mentions don't have content
|
46
|
+
def add_child(*)
|
47
|
+
raise NotImplementedError, 'User mention nodes cannot have children'
|
48
|
+
end
|
49
|
+
|
50
|
+
def content
|
51
|
+
[]
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_h
|
55
|
+
hash = super
|
56
|
+
hash['attrs'] = {
|
57
|
+
'id' => id
|
58
|
+
}
|
59
|
+
hash['content'] = []
|
60
|
+
hash
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/prosereflect/version.rb
CHANGED
data/lib/prosereflect.rb
CHANGED
@@ -2,14 +2,20 @@
|
|
2
2
|
|
3
3
|
require_relative 'prosereflect/version'
|
4
4
|
require_relative 'prosereflect/node'
|
5
|
+
require_relative 'prosereflect/mark'
|
6
|
+
require_relative 'prosereflect/attribute'
|
5
7
|
require_relative 'prosereflect/text'
|
6
8
|
require_relative 'prosereflect/paragraph'
|
7
9
|
require_relative 'prosereflect/hard_break'
|
8
10
|
require_relative 'prosereflect/table'
|
9
11
|
require_relative 'prosereflect/table_row'
|
10
12
|
require_relative 'prosereflect/table_cell'
|
13
|
+
require_relative 'prosereflect/heading'
|
11
14
|
require_relative 'prosereflect/document'
|
12
15
|
require_relative 'prosereflect/parser'
|
16
|
+
require_relative 'prosereflect/input/html'
|
17
|
+
require_relative 'prosereflect/output/html'
|
18
|
+
require_relative 'prosereflect/user'
|
13
19
|
|
14
20
|
module Prosereflect
|
15
21
|
class Error < StandardError; end
|