prosereflect 0.1.1 → 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.
- checksums.yaml +4 -4
- data/.github/workflows/rake.yml +4 -0
- data/.github/workflows/release.yml +5 -0
- data/.rubocop.yml +19 -1
- data/.rubocop_todo.yml +141 -191
- data/CLAUDE.md +78 -0
- data/Gemfile +8 -4
- data/Rakefile +3 -3
- data/lib/prosereflect/attribute/base.rb +4 -6
- data/lib/prosereflect/attribute/bold.rb +2 -4
- data/lib/prosereflect/attribute/href.rb +1 -3
- data/lib/prosereflect/attribute/id.rb +7 -7
- data/lib/prosereflect/attribute.rb +4 -7
- data/lib/prosereflect/blockquote.rb +10 -11
- data/lib/prosereflect/bullet_list.rb +16 -15
- data/lib/prosereflect/code_block.rb +26 -26
- data/lib/prosereflect/code_block_wrapper.rb +12 -13
- data/lib/prosereflect/document.rb +14 -22
- data/lib/prosereflect/hard_break.rb +6 -6
- data/lib/prosereflect/heading.rb +14 -15
- data/lib/prosereflect/horizontal_rule.rb +14 -14
- data/lib/prosereflect/image.rb +23 -23
- data/lib/prosereflect/input/html.rb +83 -104
- data/lib/prosereflect/input.rb +7 -0
- data/lib/prosereflect/list_item.rb +11 -12
- data/lib/prosereflect/mark/base.rb +9 -11
- data/lib/prosereflect/mark/bold.rb +1 -3
- data/lib/prosereflect/mark/code.rb +1 -3
- data/lib/prosereflect/mark/italic.rb +1 -3
- data/lib/prosereflect/mark/link.rb +1 -3
- data/lib/prosereflect/mark/strike.rb +1 -3
- data/lib/prosereflect/mark/subscript.rb +1 -3
- data/lib/prosereflect/mark/superscript.rb +1 -3
- data/lib/prosereflect/mark/underline.rb +1 -3
- data/lib/prosereflect/mark.rb +9 -5
- data/lib/prosereflect/node.rb +31 -31
- data/lib/prosereflect/ordered_list.rb +15 -14
- data/lib/prosereflect/output/html.rb +52 -50
- data/lib/prosereflect/output.rb +7 -0
- data/lib/prosereflect/paragraph.rb +11 -13
- data/lib/prosereflect/parser.rb +47 -66
- data/lib/prosereflect/table.rb +12 -13
- data/lib/prosereflect/table_cell.rb +13 -13
- data/lib/prosereflect/table_header.rb +17 -17
- data/lib/prosereflect/table_row.rb +12 -12
- data/lib/prosereflect/text.rb +11 -11
- data/lib/prosereflect/user.rb +15 -15
- data/lib/prosereflect/version.rb +1 -1
- data/lib/prosereflect.rb +27 -17
- data/prosereflect.gemspec +17 -16
- data/spec/prosereflect/document_spec.rb +332 -330
- data/spec/prosereflect/hard_break_spec.rb +125 -125
- data/spec/prosereflect/input/html_spec.rb +522 -522
- data/spec/prosereflect/node_spec.rb +183 -182
- data/spec/prosereflect/output/html_spec.rb +105 -105
- data/spec/prosereflect/paragraph_spec.rb +275 -274
- data/spec/prosereflect/parser_spec.rb +185 -180
- data/spec/prosereflect/table_cell_spec.rb +183 -183
- data/spec/prosereflect/table_row_spec.rb +149 -149
- data/spec/prosereflect/table_spec.rb +320 -318
- data/spec/prosereflect/text_spec.rb +133 -132
- data/spec/prosereflect/user_spec.rb +31 -28
- data/spec/prosereflect_spec.rb +28 -26
- data/spec/spec_helper.rb +6 -6
- data/spec/support/matchers.rb +6 -6
- data/spec/support/shared_examples.rb +49 -49
- metadata +8 -5
- data/spec/prosereflect/version_spec.rb +0 -11
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative 'base'
|
|
4
|
-
|
|
5
3
|
# {
|
|
6
4
|
# type: "italic"
|
|
7
5
|
# }
|
|
@@ -9,7 +7,7 @@ require_relative 'base'
|
|
|
9
7
|
module Prosereflect
|
|
10
8
|
module Mark
|
|
11
9
|
class Italic < Base
|
|
12
|
-
PM_TYPE =
|
|
10
|
+
PM_TYPE = "italic"
|
|
13
11
|
end
|
|
14
12
|
end
|
|
15
13
|
end
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative 'base'
|
|
4
|
-
|
|
5
3
|
# {
|
|
6
4
|
# type: "link",
|
|
7
5
|
# attrs: {
|
|
@@ -12,7 +10,7 @@ require_relative 'base'
|
|
|
12
10
|
module Prosereflect
|
|
13
11
|
module Mark
|
|
14
12
|
class Link < Base
|
|
15
|
-
PM_TYPE =
|
|
13
|
+
PM_TYPE = "link"
|
|
16
14
|
end
|
|
17
15
|
end
|
|
18
16
|
end
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative 'base'
|
|
4
|
-
|
|
5
3
|
# {
|
|
6
4
|
# type: "strike"
|
|
7
5
|
# }
|
|
@@ -9,7 +7,7 @@ require_relative 'base'
|
|
|
9
7
|
module Prosereflect
|
|
10
8
|
module Mark
|
|
11
9
|
class Strike < Base
|
|
12
|
-
PM_TYPE =
|
|
10
|
+
PM_TYPE = "strike"
|
|
13
11
|
end
|
|
14
12
|
end
|
|
15
13
|
end
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative 'base'
|
|
4
|
-
|
|
5
3
|
# {
|
|
6
4
|
# type: "subscript"
|
|
7
5
|
# }
|
|
@@ -9,7 +7,7 @@ require_relative 'base'
|
|
|
9
7
|
module Prosereflect
|
|
10
8
|
module Mark
|
|
11
9
|
class Subscript < Base
|
|
12
|
-
PM_TYPE =
|
|
10
|
+
PM_TYPE = "subscript"
|
|
13
11
|
end
|
|
14
12
|
end
|
|
15
13
|
end
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative 'base'
|
|
4
|
-
|
|
5
3
|
# {
|
|
6
4
|
# type: "superscript"
|
|
7
5
|
# }
|
|
@@ -9,7 +7,7 @@ require_relative 'base'
|
|
|
9
7
|
module Prosereflect
|
|
10
8
|
module Mark
|
|
11
9
|
class Superscript < Base
|
|
12
|
-
PM_TYPE =
|
|
10
|
+
PM_TYPE = "superscript"
|
|
13
11
|
end
|
|
14
12
|
end
|
|
15
13
|
end
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative 'base'
|
|
4
|
-
|
|
5
3
|
# {
|
|
6
4
|
# type: "underline"
|
|
7
5
|
# }
|
|
@@ -9,7 +7,7 @@ require_relative 'base'
|
|
|
9
7
|
module Prosereflect
|
|
10
8
|
module Mark
|
|
11
9
|
class Underline < Base
|
|
12
|
-
PM_TYPE =
|
|
10
|
+
PM_TYPE = "underline"
|
|
13
11
|
end
|
|
14
12
|
end
|
|
15
13
|
end
|
data/lib/prosereflect/mark.rb
CHANGED
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
module Prosereflect
|
|
4
4
|
module Mark
|
|
5
|
+
autoload :Base, "#{__dir__}/mark/base"
|
|
6
|
+
autoload :Bold, "#{__dir__}/mark/bold"
|
|
7
|
+
autoload :Italic, "#{__dir__}/mark/italic"
|
|
8
|
+
autoload :Code, "#{__dir__}/mark/code"
|
|
9
|
+
autoload :Link, "#{__dir__}/mark/link"
|
|
10
|
+
autoload :Strike, "#{__dir__}/mark/strike"
|
|
11
|
+
autoload :Subscript, "#{__dir__}/mark/subscript"
|
|
12
|
+
autoload :Superscript, "#{__dir__}/mark/superscript"
|
|
13
|
+
autoload :Underline, "#{__dir__}/mark/underline"
|
|
5
14
|
end
|
|
6
15
|
end
|
|
7
|
-
|
|
8
|
-
require_relative 'mark/bold'
|
|
9
|
-
require_relative 'mark/italic'
|
|
10
|
-
require_relative 'mark/code'
|
|
11
|
-
require_relative 'mark/link'
|
data/lib/prosereflect/node.rb
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'lutaml/model'
|
|
4
|
-
require_relative 'attribute'
|
|
5
|
-
require_relative 'mark'
|
|
6
|
-
|
|
7
3
|
module Prosereflect
|
|
8
4
|
class Node < Lutaml::Model::Serializable
|
|
9
|
-
PM_TYPE =
|
|
5
|
+
PM_TYPE = "node"
|
|
10
6
|
|
|
11
7
|
attribute :type, :string
|
|
12
8
|
attribute :attrs, :hash
|
|
@@ -14,10 +10,10 @@ module Prosereflect
|
|
|
14
10
|
attribute :content, Node, polymorphic: true, collection: true
|
|
15
11
|
|
|
16
12
|
key_value do
|
|
17
|
-
map
|
|
18
|
-
map
|
|
19
|
-
map
|
|
20
|
-
map
|
|
13
|
+
map "type", to: :type, render_default: true
|
|
14
|
+
map "attrs", to: :attrs
|
|
15
|
+
map "marks", to: :marks
|
|
16
|
+
map "content", to: :content
|
|
21
17
|
end
|
|
22
18
|
|
|
23
19
|
def initialize(data = nil, attrs = nil)
|
|
@@ -25,18 +21,18 @@ module Prosereflect
|
|
|
25
21
|
super(type: data, attrs: attrs, content: [])
|
|
26
22
|
elsif data.is_a?(Hash)
|
|
27
23
|
# Handle marks in a special way to preserve expected behavior in tests
|
|
28
|
-
if data[:marks] || data[
|
|
29
|
-
marks_data = data[:marks] || data[
|
|
24
|
+
if data[:marks] || data["marks"]
|
|
25
|
+
marks_data = data[:marks] || data["marks"]
|
|
30
26
|
data = data.dup
|
|
31
|
-
data.delete(
|
|
27
|
+
data.delete("marks")
|
|
32
28
|
data.delete(:marks)
|
|
33
29
|
super(data)
|
|
34
30
|
self.marks = marks_data
|
|
35
31
|
else
|
|
36
32
|
# Handle attrs properly
|
|
37
|
-
if data[:attrs] || data[
|
|
33
|
+
if data[:attrs] || data["attrs"]
|
|
38
34
|
data = data.dup
|
|
39
|
-
data[:attrs] = process_attrs_data(data[:attrs] || data[
|
|
35
|
+
data[:attrs] = process_attrs_data(data[:attrs] || data["attrs"])
|
|
40
36
|
end
|
|
41
37
|
super(data)
|
|
42
38
|
end
|
|
@@ -56,33 +52,35 @@ module Prosereflect
|
|
|
56
52
|
def self.create(type = nil, attrs = nil)
|
|
57
53
|
new(type || self::PM_TYPE, attrs)
|
|
58
54
|
rescue NameError
|
|
59
|
-
new(type ||
|
|
55
|
+
new(type || "node", attrs)
|
|
60
56
|
end
|
|
61
57
|
|
|
62
58
|
# Convert to hash for serialization
|
|
63
59
|
def to_h
|
|
64
|
-
result = {
|
|
60
|
+
result = { "type" => type }
|
|
65
61
|
|
|
66
62
|
if attrs && !attrs.empty?
|
|
67
63
|
if attrs.is_a?(Hash)
|
|
68
|
-
result[
|
|
69
|
-
elsif attrs.is_a?(Array) && attrs.all?
|
|
64
|
+
result["attrs"] = process_node_attributes(attrs, type)
|
|
65
|
+
elsif attrs.is_a?(Array) && attrs.all? do |attr|
|
|
66
|
+
attr.respond_to?(:to_h)
|
|
67
|
+
end
|
|
70
68
|
# Convert array of attribute objects to a hash
|
|
71
69
|
attrs_array = attrs.map do |attr|
|
|
72
70
|
attr.is_a?(Prosereflect::Attribute::Base) ? attr.to_h : attr
|
|
73
71
|
end
|
|
74
|
-
result[
|
|
72
|
+
result["attrs"] = attrs_array unless attrs_array.empty?
|
|
75
73
|
end
|
|
76
74
|
end
|
|
77
75
|
|
|
78
76
|
if marks && !marks.empty?
|
|
79
|
-
result[
|
|
77
|
+
result["marks"] = marks.map do |mark|
|
|
80
78
|
if mark.is_a?(Hash)
|
|
81
79
|
mark
|
|
82
80
|
elsif mark.respond_to?(:to_h)
|
|
83
81
|
mark.to_h
|
|
84
82
|
elsif mark.respond_to?(:type)
|
|
85
|
-
{
|
|
83
|
+
{ "type" => mark.type.to_s }
|
|
86
84
|
else
|
|
87
85
|
raise ArgumentError, "Invalid mark type: #{mark.class}"
|
|
88
86
|
end
|
|
@@ -90,8 +88,10 @@ module Prosereflect
|
|
|
90
88
|
end
|
|
91
89
|
|
|
92
90
|
if content && !content.empty?
|
|
93
|
-
result[
|
|
94
|
-
content.map
|
|
91
|
+
result["content"] = if content.is_a?(Array)
|
|
92
|
+
content.map do |item|
|
|
93
|
+
item.respond_to?(:to_h) ? item.to_h : item
|
|
94
|
+
end
|
|
95
95
|
else
|
|
96
96
|
[content]
|
|
97
97
|
end
|
|
@@ -112,7 +112,7 @@ module Prosereflect
|
|
|
112
112
|
elsif mark.respond_to?(:to_h)
|
|
113
113
|
mark.to_h
|
|
114
114
|
elsif mark.respond_to?(:type)
|
|
115
|
-
{
|
|
115
|
+
{ "type" => mark.type.to_s }
|
|
116
116
|
else
|
|
117
117
|
raise ArgumentError, "Invalid mark type: #{mark.class}"
|
|
118
118
|
end
|
|
@@ -131,8 +131,8 @@ module Prosereflect
|
|
|
131
131
|
elsif value.is_a?(Array)
|
|
132
132
|
@marks = value.map do |v|
|
|
133
133
|
if v.is_a?(Hash)
|
|
134
|
-
type = v[
|
|
135
|
-
attrs = v[
|
|
134
|
+
type = v["type"] || v[:type]
|
|
135
|
+
attrs = v["attrs"] || v[:attrs]
|
|
136
136
|
begin
|
|
137
137
|
mark_class = Prosereflect::Mark.const_get(type.to_s.capitalize)
|
|
138
138
|
mark_class.new(attrs: attrs)
|
|
@@ -197,11 +197,11 @@ module Prosereflect
|
|
|
197
197
|
def find_children(node_type)
|
|
198
198
|
return [] unless content
|
|
199
199
|
|
|
200
|
-
content.
|
|
200
|
+
content.grep(node_type)
|
|
201
201
|
end
|
|
202
202
|
|
|
203
203
|
def text_content
|
|
204
|
-
return
|
|
204
|
+
return "" unless content
|
|
205
205
|
|
|
206
206
|
content.map(&:text_content).join
|
|
207
207
|
end
|
|
@@ -214,9 +214,9 @@ module Prosereflect
|
|
|
214
214
|
private
|
|
215
215
|
|
|
216
216
|
def process_node_attributes(attrs, node_type)
|
|
217
|
-
if attrs[
|
|
218
|
-
attrs[
|
|
219
|
-
elsif node_type ==
|
|
217
|
+
if attrs["attrs"].is_a?(Hash)
|
|
218
|
+
attrs["attrs"]
|
|
219
|
+
elsif node_type == "bullet_list" && attrs["bullet_style"].nil?
|
|
220
220
|
nil
|
|
221
221
|
else
|
|
222
222
|
attrs
|
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative 'node'
|
|
4
|
-
require_relative 'list_item'
|
|
5
|
-
|
|
6
3
|
module Prosereflect
|
|
7
4
|
# OrderedList class represents a numbered list in ProseMirror.
|
|
8
5
|
class OrderedList < Node
|
|
9
|
-
PM_TYPE =
|
|
6
|
+
PM_TYPE = "ordered_list"
|
|
10
7
|
|
|
11
|
-
attribute :type, :string, default: -> {
|
|
8
|
+
attribute :type, :string, default: -> {
|
|
9
|
+
self.class.send(:const_get, "PM_TYPE")
|
|
10
|
+
}
|
|
12
11
|
attribute :start, :integer
|
|
13
12
|
attribute :attrs, :hash
|
|
14
13
|
|
|
15
14
|
key_value do
|
|
16
|
-
map
|
|
17
|
-
map
|
|
18
|
-
map
|
|
15
|
+
map "type", to: :type, render_default: true
|
|
16
|
+
map "attrs", to: :attrs
|
|
17
|
+
map "content", to: :content
|
|
19
18
|
end
|
|
20
19
|
|
|
21
20
|
def initialize(attributes = {})
|
|
@@ -30,11 +29,11 @@ module Prosereflect
|
|
|
30
29
|
def start=(value)
|
|
31
30
|
@start = value
|
|
32
31
|
self.attrs ||= {}
|
|
33
|
-
attrs[
|
|
32
|
+
attrs["start"] = value
|
|
34
33
|
end
|
|
35
34
|
|
|
36
35
|
def start
|
|
37
|
-
@start || attrs&.[](
|
|
36
|
+
@start || attrs&.[]("start") || 1
|
|
38
37
|
end
|
|
39
38
|
|
|
40
39
|
def add_item(text)
|
|
@@ -67,19 +66,21 @@ module Prosereflect
|
|
|
67
66
|
# Update the order (1 for numerical, 'a' for alphabetical, etc.)
|
|
68
67
|
def order=(order_value)
|
|
69
68
|
self.attrs ||= {}
|
|
70
|
-
attrs[
|
|
69
|
+
attrs["order"] = order_value
|
|
71
70
|
end
|
|
72
71
|
|
|
73
72
|
# Get the order value
|
|
74
73
|
def order
|
|
75
|
-
attrs&.[](
|
|
74
|
+
attrs&.[]("order") || 1
|
|
76
75
|
end
|
|
77
76
|
|
|
78
77
|
# Get text content with proper formatting
|
|
79
78
|
def text_content
|
|
80
|
-
return
|
|
79
|
+
return "" unless content
|
|
81
80
|
|
|
82
|
-
content.map
|
|
81
|
+
content.map do |item|
|
|
82
|
+
item.respond_to?(:text_content) ? item.text_content : ""
|
|
83
|
+
end.join("\n")
|
|
83
84
|
end
|
|
84
85
|
end
|
|
85
86
|
end
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require_relative '../document'
|
|
3
|
+
require "nokogiri"
|
|
5
4
|
|
|
6
5
|
module Prosereflect
|
|
7
6
|
module Output
|
|
@@ -16,7 +15,7 @@ module Prosereflect
|
|
|
16
15
|
end
|
|
17
16
|
|
|
18
17
|
doc = Nokogiri::HTML(builder.to_html)
|
|
19
|
-
html = doc.at_css(
|
|
18
|
+
html = doc.at_css("div").children.to_html
|
|
20
19
|
|
|
21
20
|
code_blocks = {}
|
|
22
21
|
html.scan(%r{<code[^>]*>(.*?)</code>}m).each_with_index do |match, i|
|
|
@@ -27,7 +26,7 @@ module Prosereflect
|
|
|
27
26
|
end
|
|
28
27
|
|
|
29
28
|
# Remove newlines and spaces
|
|
30
|
-
html = html.gsub(/\n\s*/,
|
|
29
|
+
html = html.gsub(/\n\s*/, "")
|
|
31
30
|
|
|
32
31
|
code_blocks.each do |placeholder, content|
|
|
33
32
|
html.sub!(placeholder, content)
|
|
@@ -43,41 +42,41 @@ module Prosereflect
|
|
|
43
42
|
return unless node
|
|
44
43
|
|
|
45
44
|
case node.type
|
|
46
|
-
when
|
|
45
|
+
when "doc"
|
|
47
46
|
process_document(node, builder)
|
|
48
|
-
when
|
|
47
|
+
when "paragraph"
|
|
49
48
|
process_paragraph(node, builder)
|
|
50
|
-
when
|
|
49
|
+
when "heading"
|
|
51
50
|
process_heading(node, builder)
|
|
52
|
-
when
|
|
51
|
+
when "text"
|
|
53
52
|
process_text(node, builder)
|
|
54
|
-
when
|
|
53
|
+
when "table"
|
|
55
54
|
process_table(node, builder)
|
|
56
|
-
when
|
|
55
|
+
when "table_row"
|
|
57
56
|
process_table_row(node, builder)
|
|
58
|
-
when
|
|
57
|
+
when "table_cell"
|
|
59
58
|
process_table_cell(node, builder)
|
|
60
|
-
when
|
|
59
|
+
when "table_header"
|
|
61
60
|
process_table_header(node, builder)
|
|
62
|
-
when
|
|
61
|
+
when "hard_break"
|
|
63
62
|
builder.br
|
|
64
|
-
when
|
|
63
|
+
when "image"
|
|
65
64
|
process_image(node, builder)
|
|
66
|
-
when
|
|
65
|
+
when "user"
|
|
67
66
|
process_user(node, builder)
|
|
68
|
-
when
|
|
67
|
+
when "bullet_list"
|
|
69
68
|
process_bullet_list(node, builder)
|
|
70
|
-
when
|
|
69
|
+
when "ordered_list"
|
|
71
70
|
process_ordered_list(node, builder)
|
|
72
|
-
when
|
|
71
|
+
when "list_item"
|
|
73
72
|
process_list_item(node, builder)
|
|
74
|
-
when
|
|
73
|
+
when "blockquote"
|
|
75
74
|
process_blockquote(node, builder)
|
|
76
|
-
when
|
|
75
|
+
when "horizontal_rule"
|
|
77
76
|
process_horizontal_rule(node, builder)
|
|
78
|
-
when
|
|
77
|
+
when "code_block_wrapper"
|
|
79
78
|
process_code_block_wrapper(node, builder)
|
|
80
|
-
when
|
|
79
|
+
when "code_block"
|
|
81
80
|
process_code_block(node, builder)
|
|
82
81
|
else
|
|
83
82
|
# Default handling for unknown nodes - treat as a container
|
|
@@ -124,27 +123,27 @@ module Prosereflect
|
|
|
124
123
|
remaining_marks = marks[1..]
|
|
125
124
|
|
|
126
125
|
mark_type = if current_mark.is_a?(Hash)
|
|
127
|
-
current_mark[
|
|
126
|
+
current_mark["type"]
|
|
128
127
|
elsif current_mark.respond_to?(:type)
|
|
129
128
|
current_mark.type
|
|
130
129
|
else
|
|
131
|
-
|
|
130
|
+
"unknown"
|
|
132
131
|
end
|
|
133
132
|
|
|
134
133
|
case mark_type
|
|
135
|
-
when
|
|
134
|
+
when "bold"
|
|
136
135
|
builder.strong do
|
|
137
136
|
apply_marks(text, remaining_marks, builder)
|
|
138
137
|
end
|
|
139
|
-
when
|
|
138
|
+
when "italic"
|
|
140
139
|
builder.em do
|
|
141
140
|
apply_marks(text, remaining_marks, builder)
|
|
142
141
|
end
|
|
143
|
-
when
|
|
142
|
+
when "code"
|
|
144
143
|
builder.code do
|
|
145
144
|
apply_marks(text, remaining_marks, builder)
|
|
146
145
|
end
|
|
147
|
-
when
|
|
146
|
+
when "link"
|
|
148
147
|
href = find_href_attribute(current_mark)
|
|
149
148
|
if href
|
|
150
149
|
builder.a(href: href) do
|
|
@@ -153,19 +152,19 @@ module Prosereflect
|
|
|
153
152
|
else
|
|
154
153
|
apply_marks(text, remaining_marks, builder)
|
|
155
154
|
end
|
|
156
|
-
when
|
|
155
|
+
when "strike"
|
|
157
156
|
builder.del do
|
|
158
157
|
apply_marks(text, remaining_marks, builder)
|
|
159
158
|
end
|
|
160
|
-
when
|
|
159
|
+
when "underline"
|
|
161
160
|
builder.u do
|
|
162
161
|
apply_marks(text, remaining_marks, builder)
|
|
163
162
|
end
|
|
164
|
-
when
|
|
163
|
+
when "subscript"
|
|
165
164
|
builder.sub do
|
|
166
165
|
apply_marks(text, remaining_marks, builder)
|
|
167
166
|
end
|
|
168
|
-
when
|
|
167
|
+
when "superscript"
|
|
169
168
|
builder.sup do
|
|
170
169
|
apply_marks(text, remaining_marks, builder)
|
|
171
170
|
end
|
|
@@ -178,23 +177,23 @@ module Prosereflect
|
|
|
178
177
|
# Find href attribute in a link mark
|
|
179
178
|
def find_href_attribute(mark)
|
|
180
179
|
if mark.is_a?(Hash)
|
|
181
|
-
if mark[
|
|
182
|
-
return mark[
|
|
183
|
-
elsif mark[
|
|
184
|
-
href_attr = mark[
|
|
185
|
-
return href_attr[
|
|
180
|
+
if mark["attrs"].is_a?(Hash)
|
|
181
|
+
return mark["attrs"]["href"]
|
|
182
|
+
elsif mark["attrs"].is_a?(Array)
|
|
183
|
+
href_attr = mark["attrs"].find { |a| a.is_a?(Prosereflect::Attribute::Href) || (a.is_a?(Hash) && a["type"] == "href") }
|
|
184
|
+
return href_attr["href"] if href_attr.is_a?(Hash) && href_attr["href"]
|
|
186
185
|
return href_attr.href if href_attr.respond_to?(:href)
|
|
187
186
|
end
|
|
188
187
|
elsif mark.respond_to?(:attrs)
|
|
189
188
|
attrs = mark.attrs
|
|
190
189
|
if attrs.is_a?(Hash)
|
|
191
|
-
return attrs[
|
|
190
|
+
return attrs["href"]
|
|
192
191
|
elsif attrs.is_a?(Array)
|
|
193
192
|
href_attr = attrs.find { |attr| attr.is_a?(Prosereflect::Attribute::Href) }
|
|
194
193
|
return href_attr&.href if href_attr
|
|
195
194
|
|
|
196
|
-
hash_attr = attrs.find { |attr| attr.is_a?(Hash) && attr[
|
|
197
|
-
return hash_attr[
|
|
195
|
+
hash_attr = attrs.find { |attr| attr.is_a?(Hash) && attr["href"] }
|
|
196
|
+
return hash_attr["href"] if hash_attr
|
|
198
197
|
end
|
|
199
198
|
end
|
|
200
199
|
nil
|
|
@@ -206,7 +205,9 @@ module Prosereflect
|
|
|
206
205
|
rows = node.rows || node.content
|
|
207
206
|
return if rows.empty?
|
|
208
207
|
|
|
209
|
-
has_header = rows.first&.content&.any?
|
|
208
|
+
has_header = rows.first&.content&.any? do |cell|
|
|
209
|
+
cell.type == "table_header"
|
|
210
|
+
end
|
|
210
211
|
|
|
211
212
|
if has_header
|
|
212
213
|
builder.thead do
|
|
@@ -233,7 +234,7 @@ module Prosereflect
|
|
|
233
234
|
# Process a table cell
|
|
234
235
|
def process_table_cell(node, builder)
|
|
235
236
|
builder.td do
|
|
236
|
-
if node.content&.size == 1 && node.content.first.type ==
|
|
237
|
+
if node.content&.size == 1 && node.content.first.type == "paragraph"
|
|
237
238
|
node.content.first.content&.each do |child|
|
|
238
239
|
process_node(child, builder)
|
|
239
240
|
end
|
|
@@ -251,7 +252,7 @@ module Prosereflect
|
|
|
251
252
|
attrs[:colspan] = node.colspan if node.colspan
|
|
252
253
|
|
|
253
254
|
builder.th(attrs) do
|
|
254
|
-
if node.content&.size == 1 && node.content.first.type ==
|
|
255
|
+
if node.content&.size == 1 && node.content.first.type == "paragraph"
|
|
255
256
|
node.content.first.content&.each do |child|
|
|
256
257
|
process_node(child, builder)
|
|
257
258
|
end
|
|
@@ -265,7 +266,7 @@ module Prosereflect
|
|
|
265
266
|
def process_image(node, builder)
|
|
266
267
|
attrs = {
|
|
267
268
|
src: node.src,
|
|
268
|
-
alt: node.alt
|
|
269
|
+
alt: node.alt,
|
|
269
270
|
}
|
|
270
271
|
attrs[:title] = node.title if node.title
|
|
271
272
|
attrs[:width] = node.width if node.width
|
|
@@ -283,7 +284,7 @@ module Prosereflect
|
|
|
283
284
|
def process_bullet_list(node, builder)
|
|
284
285
|
builder.ul do
|
|
285
286
|
node.content&.each do |child|
|
|
286
|
-
if child.type ==
|
|
287
|
+
if child.type == "list_item"
|
|
287
288
|
process_node(child, builder)
|
|
288
289
|
else
|
|
289
290
|
builder.li do
|
|
@@ -330,7 +331,7 @@ module Prosereflect
|
|
|
330
331
|
attrs[:style] << "border-style: #{node.style}" if node.style
|
|
331
332
|
attrs[:style] << "width: #{node.width}" if node.width
|
|
332
333
|
attrs[:style] << "border-width: #{node.thickness}px" if node.thickness
|
|
333
|
-
attrs[:style] = attrs[:style].join(
|
|
334
|
+
attrs[:style] = attrs[:style].join("; ") unless attrs[:style].empty?
|
|
334
335
|
|
|
335
336
|
builder.hr(attrs)
|
|
336
337
|
end
|
|
@@ -339,9 +340,10 @@ module Prosereflect
|
|
|
339
340
|
def process_code_block_wrapper(node, builder)
|
|
340
341
|
attrs = {}
|
|
341
342
|
if node.attrs
|
|
342
|
-
attrs[
|
|
343
|
-
if node.attrs[
|
|
344
|
-
attrs[
|
|
343
|
+
attrs["data-line-numbers"] = "true" if node.attrs["line_numbers"]
|
|
344
|
+
if node.attrs["highlight_lines"].is_a?(Array) && !node.attrs["highlight_lines"].empty? && node.attrs["highlight_lines"] != [0]
|
|
345
|
+
attrs["data-highlight-lines"] =
|
|
346
|
+
node.attrs["highlight_lines"].join(",")
|
|
345
347
|
end
|
|
346
348
|
end
|
|
347
349
|
|
|
@@ -353,7 +355,7 @@ module Prosereflect
|
|
|
353
355
|
# Process a code block node
|
|
354
356
|
def process_code_block(node, builder)
|
|
355
357
|
attrs = {}
|
|
356
|
-
attrs[
|
|
358
|
+
attrs["class"] = "language-#{node.language}" if node.language
|
|
357
359
|
|
|
358
360
|
builder.code(attrs) do
|
|
359
361
|
builder.text node.content
|
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative 'node'
|
|
4
|
-
require_relative 'text'
|
|
5
|
-
require_relative 'hard_break'
|
|
6
|
-
|
|
7
3
|
module Prosereflect
|
|
8
4
|
class Paragraph < Node
|
|
9
|
-
PM_TYPE =
|
|
5
|
+
PM_TYPE = "paragraph"
|
|
10
6
|
|
|
11
|
-
attribute :type, :string, default: -> {
|
|
7
|
+
attribute :type, :string, default: -> {
|
|
8
|
+
self.class.send(:const_get, "PM_TYPE")
|
|
9
|
+
}
|
|
12
10
|
|
|
13
11
|
key_value do
|
|
14
|
-
map
|
|
15
|
-
map
|
|
16
|
-
map
|
|
17
|
-
map
|
|
12
|
+
map "type", to: :type, render_default: true
|
|
13
|
+
map "content", to: :content
|
|
14
|
+
map "attrs", to: :attrs
|
|
15
|
+
map "marks", to: :marks
|
|
18
16
|
end
|
|
19
17
|
|
|
20
18
|
def initialize(params = {})
|
|
@@ -29,13 +27,13 @@ module Prosereflect
|
|
|
29
27
|
def text_nodes
|
|
30
28
|
return [] unless content
|
|
31
29
|
|
|
32
|
-
content.
|
|
30
|
+
content.grep(Text)
|
|
33
31
|
end
|
|
34
32
|
|
|
35
33
|
def text_content
|
|
36
|
-
return
|
|
34
|
+
return "" unless content
|
|
37
35
|
|
|
38
|
-
result =
|
|
36
|
+
result = ""
|
|
39
37
|
content.each do |node|
|
|
40
38
|
result += node.text_content
|
|
41
39
|
end
|