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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +4 -0
  3. data/.github/workflows/release.yml +5 -0
  4. data/.rubocop.yml +19 -1
  5. data/.rubocop_todo.yml +141 -191
  6. data/CLAUDE.md +78 -0
  7. data/Gemfile +8 -4
  8. data/Rakefile +3 -3
  9. data/lib/prosereflect/attribute/base.rb +4 -6
  10. data/lib/prosereflect/attribute/bold.rb +2 -4
  11. data/lib/prosereflect/attribute/href.rb +1 -3
  12. data/lib/prosereflect/attribute/id.rb +7 -7
  13. data/lib/prosereflect/attribute.rb +4 -7
  14. data/lib/prosereflect/blockquote.rb +10 -11
  15. data/lib/prosereflect/bullet_list.rb +16 -15
  16. data/lib/prosereflect/code_block.rb +26 -26
  17. data/lib/prosereflect/code_block_wrapper.rb +12 -13
  18. data/lib/prosereflect/document.rb +14 -22
  19. data/lib/prosereflect/hard_break.rb +6 -6
  20. data/lib/prosereflect/heading.rb +14 -15
  21. data/lib/prosereflect/horizontal_rule.rb +14 -14
  22. data/lib/prosereflect/image.rb +23 -23
  23. data/lib/prosereflect/input/html.rb +83 -104
  24. data/lib/prosereflect/input.rb +7 -0
  25. data/lib/prosereflect/list_item.rb +11 -12
  26. data/lib/prosereflect/mark/base.rb +9 -11
  27. data/lib/prosereflect/mark/bold.rb +1 -3
  28. data/lib/prosereflect/mark/code.rb +1 -3
  29. data/lib/prosereflect/mark/italic.rb +1 -3
  30. data/lib/prosereflect/mark/link.rb +1 -3
  31. data/lib/prosereflect/mark/strike.rb +1 -3
  32. data/lib/prosereflect/mark/subscript.rb +1 -3
  33. data/lib/prosereflect/mark/superscript.rb +1 -3
  34. data/lib/prosereflect/mark/underline.rb +1 -3
  35. data/lib/prosereflect/mark.rb +9 -5
  36. data/lib/prosereflect/node.rb +31 -31
  37. data/lib/prosereflect/ordered_list.rb +15 -14
  38. data/lib/prosereflect/output/html.rb +52 -50
  39. data/lib/prosereflect/output.rb +7 -0
  40. data/lib/prosereflect/paragraph.rb +11 -13
  41. data/lib/prosereflect/parser.rb +47 -66
  42. data/lib/prosereflect/table.rb +12 -13
  43. data/lib/prosereflect/table_cell.rb +13 -13
  44. data/lib/prosereflect/table_header.rb +17 -17
  45. data/lib/prosereflect/table_row.rb +12 -12
  46. data/lib/prosereflect/text.rb +11 -11
  47. data/lib/prosereflect/user.rb +15 -15
  48. data/lib/prosereflect/version.rb +1 -1
  49. data/lib/prosereflect.rb +27 -17
  50. data/prosereflect.gemspec +17 -16
  51. data/spec/prosereflect/document_spec.rb +332 -330
  52. data/spec/prosereflect/hard_break_spec.rb +125 -125
  53. data/spec/prosereflect/input/html_spec.rb +522 -522
  54. data/spec/prosereflect/node_spec.rb +183 -182
  55. data/spec/prosereflect/output/html_spec.rb +105 -105
  56. data/spec/prosereflect/paragraph_spec.rb +275 -274
  57. data/spec/prosereflect/parser_spec.rb +185 -180
  58. data/spec/prosereflect/table_cell_spec.rb +183 -183
  59. data/spec/prosereflect/table_row_spec.rb +149 -149
  60. data/spec/prosereflect/table_spec.rb +320 -318
  61. data/spec/prosereflect/text_spec.rb +133 -132
  62. data/spec/prosereflect/user_spec.rb +31 -28
  63. data/spec/prosereflect_spec.rb +28 -26
  64. data/spec/spec_helper.rb +6 -6
  65. data/spec/support/matchers.rb +6 -6
  66. data/spec/support/shared_examples.rb +49 -49
  67. metadata +8 -5
  68. data/spec/prosereflect/version_spec.rb +0 -11
@@ -1,247 +1,247 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
3
+ require "spec_helper"
4
4
 
5
5
  RSpec.describe Prosereflect::HardBreak do
6
- describe 'initialization' do
7
- it 'initializes as a hard_break node' do
8
- break_node = described_class.new({ 'type' => 'hard_break' })
9
- expect(break_node.type).to eq('hard_break')
6
+ describe "initialization" do
7
+ it "initializes as a hard_break node" do
8
+ break_node = described_class.new({ "type" => "hard_break" })
9
+ expect(break_node.type).to eq("hard_break")
10
10
  end
11
11
  end
12
12
 
13
- describe '.create' do
14
- it 'creates a simple hard break' do
13
+ describe ".create" do
14
+ it "creates a simple hard break" do
15
15
  break_node = described_class.create
16
16
 
17
17
  expected = {
18
- 'type' => 'hard_break'
18
+ "type" => "hard_break",
19
19
  }
20
20
 
21
21
  expect(break_node.to_h).to eq(expected)
22
22
  end
23
23
 
24
- it 'creates a hard break with a single mark' do
24
+ it "creates a hard break with a single mark" do
25
25
  break_node = described_class.create
26
- break_node.marks = [{ 'type' => 'bold' }]
26
+ break_node.marks = [{ "type" => "bold" }]
27
27
 
28
28
  expected = {
29
- 'type' => 'hard_break',
30
- 'marks' => [{
31
- 'type' => 'bold'
32
- }]
29
+ "type" => "hard_break",
30
+ "marks" => [{
31
+ "type" => "bold",
32
+ }],
33
33
  }
34
34
 
35
35
  expect(break_node.to_h).to eq(expected)
36
36
  end
37
37
 
38
- it 'creates a hard break with multiple marks' do
38
+ it "creates a hard break with multiple marks" do
39
39
  break_node = described_class.create
40
40
  break_node.marks = [
41
- { 'type' => 'bold' },
42
- { 'type' => 'italic' },
43
- { 'type' => 'strike' }
41
+ { "type" => "bold" },
42
+ { "type" => "italic" },
43
+ { "type" => "strike" },
44
44
  ]
45
45
 
46
46
  expected = {
47
- 'type' => 'hard_break',
48
- 'marks' => [{
49
- 'type' => 'bold'
47
+ "type" => "hard_break",
48
+ "marks" => [{
49
+ "type" => "bold",
50
50
  }, {
51
- 'type' => 'italic'
51
+ "type" => "italic",
52
52
  }, {
53
- 'type' => 'strike'
54
- }]
53
+ "type" => "strike",
54
+ }],
55
55
  }
56
56
 
57
57
  expect(break_node.to_h).to eq(expected)
58
58
  end
59
59
  end
60
60
 
61
- describe 'in document context' do
62
- it 'works in a paragraph with mixed content' do
61
+ describe "in document context" do
62
+ it "works in a paragraph with mixed content" do
63
63
  paragraph = Prosereflect::Paragraph.new
64
- paragraph.add_text('First line')
64
+ paragraph.add_text("First line")
65
65
  paragraph.add_hard_break
66
- paragraph.add_text('Second line with ')
67
- paragraph.add_text('bold', [Prosereflect::Mark::Bold.new])
66
+ paragraph.add_text("Second line with ")
67
+ paragraph.add_text("bold", [Prosereflect::Mark::Bold.new])
68
68
  paragraph.add_hard_break
69
- paragraph.add_text('Third line')
69
+ paragraph.add_text("Third line")
70
70
 
71
71
  expected = {
72
- 'type' => 'paragraph',
73
- 'content' => [{
74
- 'type' => 'text',
75
- 'text' => 'First line'
72
+ "type" => "paragraph",
73
+ "content" => [{
74
+ "type" => "text",
75
+ "text" => "First line",
76
76
  }, {
77
- 'type' => 'hard_break'
77
+ "type" => "hard_break",
78
78
  }, {
79
- 'type' => 'text',
80
- 'text' => 'Second line with '
79
+ "type" => "text",
80
+ "text" => "Second line with ",
81
81
  }, {
82
- 'type' => 'text',
83
- 'text' => 'bold',
84
- 'marks' => [{
85
- 'type' => 'bold'
86
- }]
82
+ "type" => "text",
83
+ "text" => "bold",
84
+ "marks" => [{
85
+ "type" => "bold",
86
+ }],
87
87
  }, {
88
- 'type' => 'hard_break'
88
+ "type" => "hard_break",
89
89
  }, {
90
- 'type' => 'text',
91
- 'text' => 'Third line'
92
- }]
90
+ "type" => "text",
91
+ "text" => "Third line",
92
+ }],
93
93
  }
94
94
 
95
95
  expect(paragraph.to_h).to eq(expected)
96
96
  end
97
97
 
98
- it 'works in a list item with multiple breaks' do
98
+ it "works in a list item with multiple breaks" do
99
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')
100
+ item = list.add_item("First part")
101
+ item.add_hard_break([{ "type" => "strike" }])
102
+ item.add_text("Second part")
103
103
  item.add_hard_break
104
- item.add_text('Third part')
104
+ item.add_text("Third part")
105
105
 
106
106
  expected = {
107
- 'type' => 'bullet_list',
108
- 'attrs' => {
109
- 'bullet_style' => nil
107
+ "type" => "bullet_list",
108
+ "attrs" => {
109
+ "bullet_style" => nil,
110
110
  },
111
- 'content' => [{
112
- 'type' => 'list_item',
113
- 'content' => [{
114
- 'type' => 'paragraph',
115
- 'content' => [{
116
- 'type' => 'text',
117
- 'text' => 'First part'
111
+ "content" => [{
112
+ "type" => "list_item",
113
+ "content" => [{
114
+ "type" => "paragraph",
115
+ "content" => [{
116
+ "type" => "text",
117
+ "text" => "First part",
118
118
  }, {
119
- 'type' => 'hard_break',
120
- 'marks' => [{
121
- 'type' => 'strike'
122
- }]
119
+ "type" => "hard_break",
120
+ "marks" => [{
121
+ "type" => "strike",
122
+ }],
123
123
  }, {
124
- 'type' => 'text',
125
- 'text' => 'Second part'
124
+ "type" => "text",
125
+ "text" => "Second part",
126
126
  }, {
127
- 'type' => 'hard_break'
127
+ "type" => "hard_break",
128
128
  }, {
129
- 'type' => 'text',
130
- 'text' => 'Third part'
131
- }]
132
- }]
133
- }]
129
+ "type" => "text",
130
+ "text" => "Third part",
131
+ }],
132
+ }],
133
+ }],
134
134
  }
135
135
 
136
136
  expect(list.to_h).to eq(expected)
137
137
  end
138
138
 
139
- it 'works in a table cell with multiple paragraphs' do
139
+ it "works in a table cell with multiple paragraphs" do
140
140
  cell = Prosereflect::TableCell.new
141
- para1 = cell.add_paragraph('First paragraph')
141
+ para1 = cell.add_paragraph("First paragraph")
142
142
  para1.add_hard_break
143
- para1.add_text('continues here')
143
+ para1.add_text("continues here")
144
144
 
145
- para2 = cell.add_paragraph('Second paragraph')
145
+ para2 = cell.add_paragraph("Second paragraph")
146
146
  para2.add_hard_break([Prosereflect::Mark::Italic.new])
147
- para2.add_text('with style')
147
+ para2.add_text("with style")
148
148
 
149
149
  expected = {
150
- 'type' => 'table_cell',
151
- 'content' => [{
152
- 'type' => 'paragraph',
153
- 'content' => [{
154
- 'type' => 'text',
155
- 'text' => 'First paragraph'
150
+ "type" => "table_cell",
151
+ "content" => [{
152
+ "type" => "paragraph",
153
+ "content" => [{
154
+ "type" => "text",
155
+ "text" => "First paragraph",
156
156
  }, {
157
- 'type' => 'hard_break'
157
+ "type" => "hard_break",
158
158
  }, {
159
- 'type' => 'text',
160
- 'text' => 'continues here'
161
- }]
159
+ "type" => "text",
160
+ "text" => "continues here",
161
+ }],
162
162
  }, {
163
- 'type' => 'paragraph',
164
- 'content' => [{
165
- 'type' => 'text',
166
- 'text' => 'Second paragraph'
163
+ "type" => "paragraph",
164
+ "content" => [{
165
+ "type" => "text",
166
+ "text" => "Second paragraph",
167
167
  }, {
168
- 'type' => 'hard_break',
169
- 'marks' => [{
170
- 'type' => 'italic'
171
- }]
168
+ "type" => "hard_break",
169
+ "marks" => [{
170
+ "type" => "italic",
171
+ }],
172
172
  }, {
173
- 'type' => 'text',
174
- 'text' => 'with style'
175
- }]
176
- }]
173
+ "type" => "text",
174
+ "text" => "with style",
175
+ }],
176
+ }],
177
177
  }
178
178
 
179
179
  expect(cell.to_h).to eq(expected)
180
180
  end
181
181
  end
182
182
 
183
- describe '#text_content' do
184
- it 'returns a newline character' do
183
+ describe "#text_content" do
184
+ it "returns a newline character" do
185
185
  break_node = described_class.new
186
186
  expect(break_node.text_content).to eq("\n")
187
187
  end
188
188
 
189
- it 'returns a newline character regardless of marks' do
189
+ it "returns a newline character regardless of marks" do
190
190
  break_node = described_class.create(marks: [
191
191
  Prosereflect::Mark::Bold.new,
192
- Prosereflect::Mark::Italic.new
192
+ Prosereflect::Mark::Italic.new,
193
193
  ])
194
194
  expect(break_node.text_content).to eq("\n")
195
195
  end
196
196
 
197
- it 'properly formats text in a paragraph with multiple breaks' do
197
+ it "properly formats text in a paragraph with multiple breaks" do
198
198
  paragraph = Prosereflect::Paragraph.new
199
- paragraph.add_text('Line 1')
199
+ paragraph.add_text("Line 1")
200
200
  paragraph.add_hard_break
201
- paragraph.add_text('Line 2')
201
+ paragraph.add_text("Line 2")
202
202
  paragraph.add_hard_break
203
- paragraph.add_text('Line 3')
203
+ paragraph.add_text("Line 3")
204
204
 
205
205
  expect(paragraph.text_content).to eq("Line 1\nLine 2\nLine 3")
206
206
  end
207
207
  end
208
208
 
209
- describe 'serialization' do
210
- it 'preserves mark order in serialization' do
209
+ describe "serialization" do
210
+ it "preserves mark order in serialization" do
211
211
  break_node = described_class.create
212
212
  break_node.marks = [
213
- { 'type' => 'bold' },
214
- { 'type' => 'italic' },
215
- { 'type' => 'strike' },
216
- { 'type' => 'underline' }
213
+ { "type" => "bold" },
214
+ { "type" => "italic" },
215
+ { "type" => "strike" },
216
+ { "type" => "underline" },
217
217
  ]
218
218
 
219
219
  expected = {
220
- 'type' => 'hard_break',
221
- 'marks' => [{
222
- 'type' => 'bold'
220
+ "type" => "hard_break",
221
+ "marks" => [{
222
+ "type" => "bold",
223
223
  }, {
224
- 'type' => 'italic'
224
+ "type" => "italic",
225
225
  }, {
226
- 'type' => 'strike'
226
+ "type" => "strike",
227
227
  }, {
228
- 'type' => 'underline'
229
- }]
228
+ "type" => "underline",
229
+ }],
230
230
  }
231
231
 
232
232
  expect(break_node.to_h).to eq(expected)
233
233
  end
234
234
 
235
- it 'handles empty marks array' do
235
+ it "handles empty marks array" do
236
236
  break_node = described_class.create
237
237
  break_node.marks = []
238
- expect(break_node.to_h).to eq({ 'type' => 'hard_break' })
238
+ expect(break_node.to_h).to eq({ "type" => "hard_break" })
239
239
  end
240
240
 
241
- it 'excludes marks when nil' do
241
+ it "excludes marks when nil" do
242
242
  break_node = described_class.create
243
243
  break_node.marks = nil
244
- expect(break_node.to_h).to eq({ 'type' => 'hard_break' })
244
+ expect(break_node.to_h).to eq({ "type" => "hard_break" })
245
245
  end
246
246
  end
247
247
  end