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
@@ -11,41 +11,237 @@ RSpec.describe Prosereflect::HardBreak do
|
|
11
11
|
end
|
12
12
|
|
13
13
|
describe '.create' do
|
14
|
-
it 'creates a hard break' do
|
14
|
+
it 'creates a simple hard break' do
|
15
15
|
break_node = described_class.create
|
16
|
-
|
17
|
-
|
16
|
+
|
17
|
+
expected = {
|
18
|
+
'type' => 'hard_break'
|
19
|
+
}
|
20
|
+
|
21
|
+
expect(break_node.to_h).to eq(expected)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'creates a hard break with a single mark' do
|
25
|
+
break_node = described_class.create
|
26
|
+
break_node.marks = [{ 'type' => 'bold' }]
|
27
|
+
|
28
|
+
expected = {
|
29
|
+
'type' => 'hard_break',
|
30
|
+
'marks' => [{
|
31
|
+
'type' => 'bold'
|
32
|
+
}]
|
33
|
+
}
|
34
|
+
|
35
|
+
expect(break_node.to_h).to eq(expected)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'creates a hard break with multiple marks' do
|
39
|
+
break_node = described_class.create
|
40
|
+
break_node.marks = [
|
41
|
+
{ 'type' => 'bold' },
|
42
|
+
{ 'type' => 'italic' },
|
43
|
+
{ 'type' => 'strike' }
|
44
|
+
]
|
45
|
+
|
46
|
+
expected = {
|
47
|
+
'type' => 'hard_break',
|
48
|
+
'marks' => [{
|
49
|
+
'type' => 'bold'
|
50
|
+
}, {
|
51
|
+
'type' => 'italic'
|
52
|
+
}, {
|
53
|
+
'type' => 'strike'
|
54
|
+
}]
|
55
|
+
}
|
56
|
+
|
57
|
+
expect(break_node.to_h).to eq(expected)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe 'in document context' do
|
62
|
+
it 'works in a paragraph with mixed content' do
|
63
|
+
paragraph = Prosereflect::Paragraph.new
|
64
|
+
paragraph.add_text('First line')
|
65
|
+
paragraph.add_hard_break
|
66
|
+
paragraph.add_text('Second line with ')
|
67
|
+
paragraph.add_text('bold', [Prosereflect::Mark::Bold.new])
|
68
|
+
paragraph.add_hard_break
|
69
|
+
paragraph.add_text('Third line')
|
70
|
+
|
71
|
+
expected = {
|
72
|
+
'type' => 'paragraph',
|
73
|
+
'content' => [{
|
74
|
+
'type' => 'text',
|
75
|
+
'text' => 'First line'
|
76
|
+
}, {
|
77
|
+
'type' => 'hard_break'
|
78
|
+
}, {
|
79
|
+
'type' => 'text',
|
80
|
+
'text' => 'Second line with '
|
81
|
+
}, {
|
82
|
+
'type' => 'text',
|
83
|
+
'text' => 'bold',
|
84
|
+
'marks' => [{
|
85
|
+
'type' => 'bold'
|
86
|
+
}]
|
87
|
+
}, {
|
88
|
+
'type' => 'hard_break'
|
89
|
+
}, {
|
90
|
+
'type' => 'text',
|
91
|
+
'text' => 'Third line'
|
92
|
+
}]
|
93
|
+
}
|
94
|
+
|
95
|
+
expect(paragraph.to_h).to eq(expected)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'works in a list item with multiple breaks' do
|
99
|
+
list = Prosereflect::BulletList.new
|
100
|
+
item = list.add_item('First part')
|
101
|
+
item.add_hard_break([{ 'type' => 'strike' }])
|
102
|
+
item.add_text('Second part')
|
103
|
+
item.add_hard_break
|
104
|
+
item.add_text('Third part')
|
105
|
+
|
106
|
+
expected = {
|
107
|
+
'type' => 'bullet_list',
|
108
|
+
'attrs' => {
|
109
|
+
'bullet_style' => nil
|
110
|
+
},
|
111
|
+
'content' => [{
|
112
|
+
'type' => 'list_item',
|
113
|
+
'content' => [{
|
114
|
+
'type' => 'paragraph',
|
115
|
+
'content' => [{
|
116
|
+
'type' => 'text',
|
117
|
+
'text' => 'First part'
|
118
|
+
}, {
|
119
|
+
'type' => 'hard_break',
|
120
|
+
'marks' => [{
|
121
|
+
'type' => 'strike'
|
122
|
+
}]
|
123
|
+
}, {
|
124
|
+
'type' => 'text',
|
125
|
+
'text' => 'Second part'
|
126
|
+
}, {
|
127
|
+
'type' => 'hard_break'
|
128
|
+
}, {
|
129
|
+
'type' => 'text',
|
130
|
+
'text' => 'Third part'
|
131
|
+
}]
|
132
|
+
}]
|
133
|
+
}]
|
134
|
+
}
|
135
|
+
|
136
|
+
expect(list.to_h).to eq(expected)
|
18
137
|
end
|
19
138
|
|
20
|
-
it '
|
21
|
-
|
22
|
-
|
23
|
-
|
139
|
+
it 'works in a table cell with multiple paragraphs' do
|
140
|
+
cell = Prosereflect::TableCell.new
|
141
|
+
para1 = cell.add_paragraph('First paragraph')
|
142
|
+
para1.add_hard_break
|
143
|
+
para1.add_text('continues here')
|
144
|
+
|
145
|
+
para2 = cell.add_paragraph('Second paragraph')
|
146
|
+
para2.add_hard_break([Prosereflect::Mark::Italic.new])
|
147
|
+
para2.add_text('with style')
|
148
|
+
|
149
|
+
expected = {
|
150
|
+
'type' => 'table_cell',
|
151
|
+
'content' => [{
|
152
|
+
'type' => 'paragraph',
|
153
|
+
'content' => [{
|
154
|
+
'type' => 'text',
|
155
|
+
'text' => 'First paragraph'
|
156
|
+
}, {
|
157
|
+
'type' => 'hard_break'
|
158
|
+
}, {
|
159
|
+
'type' => 'text',
|
160
|
+
'text' => 'continues here'
|
161
|
+
}]
|
162
|
+
}, {
|
163
|
+
'type' => 'paragraph',
|
164
|
+
'content' => [{
|
165
|
+
'type' => 'text',
|
166
|
+
'text' => 'Second paragraph'
|
167
|
+
}, {
|
168
|
+
'type' => 'hard_break',
|
169
|
+
'marks' => [{
|
170
|
+
'type' => 'italic'
|
171
|
+
}]
|
172
|
+
}, {
|
173
|
+
'type' => 'text',
|
174
|
+
'text' => 'with style'
|
175
|
+
}]
|
176
|
+
}]
|
177
|
+
}
|
178
|
+
|
179
|
+
expect(cell.to_h).to eq(expected)
|
24
180
|
end
|
25
181
|
end
|
26
182
|
|
27
183
|
describe '#text_content' do
|
28
184
|
it 'returns a newline character' do
|
29
|
-
break_node = described_class.
|
185
|
+
break_node = described_class.new
|
30
186
|
expect(break_node.text_content).to eq("\n")
|
31
187
|
end
|
188
|
+
|
189
|
+
it 'returns a newline character regardless of marks' do
|
190
|
+
break_node = described_class.create(marks: [
|
191
|
+
Prosereflect::Mark::Bold.new,
|
192
|
+
Prosereflect::Mark::Italic.new
|
193
|
+
])
|
194
|
+
expect(break_node.text_content).to eq("\n")
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'properly formats text in a paragraph with multiple breaks' do
|
198
|
+
paragraph = Prosereflect::Paragraph.new
|
199
|
+
paragraph.add_text('Line 1')
|
200
|
+
paragraph.add_hard_break
|
201
|
+
paragraph.add_text('Line 2')
|
202
|
+
paragraph.add_hard_break
|
203
|
+
paragraph.add_text('Line 3')
|
204
|
+
|
205
|
+
expect(paragraph.text_content).to eq("Line 1\nLine 2\nLine 3")
|
206
|
+
end
|
32
207
|
end
|
33
208
|
|
34
|
-
describe '
|
35
|
-
it '
|
209
|
+
describe 'serialization' do
|
210
|
+
it 'preserves mark order in serialization' do
|
211
|
+
break_node = described_class.create
|
212
|
+
break_node.marks = [
|
213
|
+
{ 'type' => 'bold' },
|
214
|
+
{ 'type' => 'italic' },
|
215
|
+
{ 'type' => 'strike' },
|
216
|
+
{ 'type' => 'underline' }
|
217
|
+
]
|
218
|
+
|
219
|
+
expected = {
|
220
|
+
'type' => 'hard_break',
|
221
|
+
'marks' => [{
|
222
|
+
'type' => 'bold'
|
223
|
+
}, {
|
224
|
+
'type' => 'italic'
|
225
|
+
}, {
|
226
|
+
'type' => 'strike'
|
227
|
+
}, {
|
228
|
+
'type' => 'underline'
|
229
|
+
}]
|
230
|
+
}
|
231
|
+
|
232
|
+
expect(break_node.to_h).to eq(expected)
|
233
|
+
end
|
234
|
+
|
235
|
+
it 'handles empty marks array' do
|
236
|
+
break_node = described_class.create
|
237
|
+
break_node.marks = []
|
238
|
+
expect(break_node.to_h).to eq({ 'type' => 'hard_break' })
|
239
|
+
end
|
240
|
+
|
241
|
+
it 'excludes marks when nil' do
|
36
242
|
break_node = described_class.create
|
37
|
-
|
38
|
-
expect(
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'includes marks in hash representation' do
|
42
|
-
marks = [{ 'type' => 'italic' }]
|
43
|
-
break_node = described_class.create(marks)
|
44
|
-
hash = break_node.to_h
|
45
|
-
expect(hash).to eq({
|
46
|
-
'type' => 'hard_break',
|
47
|
-
'marks' => marks
|
48
|
-
})
|
243
|
+
break_node.marks = nil
|
244
|
+
expect(break_node.to_h).to eq({ 'type' => 'hard_break' })
|
49
245
|
end
|
50
246
|
end
|
51
247
|
end
|