prosereflect 0.1.1 → 0.3.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 (158) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/docs.yml +63 -0
  3. data/.github/workflows/links.yml +97 -0
  4. data/.github/workflows/rake.yml +4 -0
  5. data/.github/workflows/release.yml +5 -0
  6. data/.gitignore +4 -0
  7. data/.rubocop.yml +19 -1
  8. data/.rubocop_todo.yml +119 -183
  9. data/CLAUDE.md +78 -0
  10. data/Gemfile +8 -4
  11. data/README.adoc +2 -0
  12. data/Rakefile +3 -3
  13. data/docs/Gemfile +10 -0
  14. data/docs/INDEX.adoc +45 -0
  15. data/docs/_advanced/index.adoc +15 -0
  16. data/docs/_advanced/schema.adoc +112 -0
  17. data/docs/_advanced/step-map.adoc +66 -0
  18. data/docs/_advanced/steps.adoc +88 -0
  19. data/docs/_advanced/test-builder.adoc +61 -0
  20. data/docs/_advanced/transform.adoc +92 -0
  21. data/docs/_config.yml +174 -0
  22. data/docs/_features/html-input.adoc +69 -0
  23. data/docs/_features/html-output.adoc +45 -0
  24. data/docs/_features/index.adoc +15 -0
  25. data/docs/_features/marks.adoc +86 -0
  26. data/docs/_features/node-types.adoc +124 -0
  27. data/docs/_features/user-mentions.adoc +47 -0
  28. data/docs/_guides/custom-nodes.adoc +107 -0
  29. data/docs/_guides/index.adoc +13 -0
  30. data/docs/_guides/round-trip-html.adoc +91 -0
  31. data/docs/_guides/serialization.adoc +109 -0
  32. data/docs/_pages/index.adoc +67 -0
  33. data/docs/_reference/document-api.adoc +49 -0
  34. data/docs/_reference/index.adoc +14 -0
  35. data/docs/_reference/node-api.adoc +79 -0
  36. data/docs/_reference/schema-api.adoc +95 -0
  37. data/docs/_reference/transform-api.adoc +77 -0
  38. data/docs/_understanding/document-model.adoc +65 -0
  39. data/docs/_understanding/fragment.adoc +52 -0
  40. data/docs/_understanding/index.adoc +14 -0
  41. data/docs/_understanding/resolved-position.adoc +53 -0
  42. data/docs/_understanding/slice.adoc +54 -0
  43. data/docs/lychee.toml +63 -0
  44. data/lib/prosereflect/attribute/base.rb +4 -6
  45. data/lib/prosereflect/attribute/bold.rb +2 -4
  46. data/lib/prosereflect/attribute/href.rb +1 -3
  47. data/lib/prosereflect/attribute/id.rb +7 -7
  48. data/lib/prosereflect/attribute.rb +4 -7
  49. data/lib/prosereflect/blockquote.rb +19 -11
  50. data/lib/prosereflect/bullet_list.rb +36 -29
  51. data/lib/prosereflect/code_block.rb +23 -27
  52. data/lib/prosereflect/code_block_wrapper.rb +12 -13
  53. data/lib/prosereflect/document.rb +14 -22
  54. data/lib/prosereflect/fragment.rb +249 -0
  55. data/lib/prosereflect/hard_break.rb +6 -6
  56. data/lib/prosereflect/heading.rb +14 -15
  57. data/lib/prosereflect/horizontal_rule.rb +23 -14
  58. data/lib/prosereflect/image.rb +32 -23
  59. data/lib/prosereflect/input/html.rb +179 -104
  60. data/lib/prosereflect/input.rb +7 -0
  61. data/lib/prosereflect/list_item.rb +11 -12
  62. data/lib/prosereflect/mark/base.rb +9 -11
  63. data/lib/prosereflect/mark/bold.rb +1 -3
  64. data/lib/prosereflect/mark/code.rb +1 -3
  65. data/lib/prosereflect/mark/italic.rb +1 -3
  66. data/lib/prosereflect/mark/link.rb +1 -3
  67. data/lib/prosereflect/mark/strike.rb +1 -3
  68. data/lib/prosereflect/mark/subscript.rb +1 -3
  69. data/lib/prosereflect/mark/superscript.rb +1 -3
  70. data/lib/prosereflect/mark/underline.rb +1 -3
  71. data/lib/prosereflect/mark.rb +9 -5
  72. data/lib/prosereflect/node.rb +171 -33
  73. data/lib/prosereflect/ordered_list.rb +17 -14
  74. data/lib/prosereflect/output/html.rb +279 -50
  75. data/lib/prosereflect/output.rb +7 -0
  76. data/lib/prosereflect/paragraph.rb +11 -13
  77. data/lib/prosereflect/parser.rb +56 -66
  78. data/lib/prosereflect/resolved_pos.rb +256 -0
  79. data/lib/prosereflect/schema/attribute.rb +57 -0
  80. data/lib/prosereflect/schema/content_match.rb +656 -0
  81. data/lib/prosereflect/schema/fragment.rb +166 -0
  82. data/lib/prosereflect/schema/mark.rb +121 -0
  83. data/lib/prosereflect/schema/mark_type.rb +130 -0
  84. data/lib/prosereflect/schema/node.rb +236 -0
  85. data/lib/prosereflect/schema/node_type.rb +274 -0
  86. data/lib/prosereflect/schema/schema_main.rb +190 -0
  87. data/lib/prosereflect/schema/spec.rb +92 -0
  88. data/lib/prosereflect/schema.rb +39 -0
  89. data/lib/prosereflect/table.rb +12 -13
  90. data/lib/prosereflect/table_cell.rb +13 -13
  91. data/lib/prosereflect/table_header.rb +17 -17
  92. data/lib/prosereflect/table_row.rb +12 -12
  93. data/lib/prosereflect/text.rb +35 -11
  94. data/lib/prosereflect/transform/attr_step.rb +157 -0
  95. data/lib/prosereflect/transform/insert_step.rb +115 -0
  96. data/lib/prosereflect/transform/mapping.rb +82 -0
  97. data/lib/prosereflect/transform/mark_step.rb +269 -0
  98. data/lib/prosereflect/transform/replace_around_step.rb +181 -0
  99. data/lib/prosereflect/transform/replace_step.rb +157 -0
  100. data/lib/prosereflect/transform/slice.rb +91 -0
  101. data/lib/prosereflect/transform/step.rb +89 -0
  102. data/lib/prosereflect/transform/step_map.rb +126 -0
  103. data/lib/prosereflect/transform/structure.rb +120 -0
  104. data/lib/prosereflect/transform/transform.rb +341 -0
  105. data/lib/prosereflect/transform.rb +26 -0
  106. data/lib/prosereflect/user.rb +15 -15
  107. data/lib/prosereflect/version.rb +1 -1
  108. data/lib/prosereflect.rb +30 -17
  109. data/prosereflect.gemspec +17 -16
  110. data/spec/fixtures/documents/formatted_text.yaml +14 -0
  111. data/spec/fixtures/documents/heading_paragraph.yaml +16 -0
  112. data/spec/fixtures/documents/lists_doc.yaml +32 -0
  113. data/spec/fixtures/documents/mixed_content.yaml +40 -0
  114. data/spec/fixtures/documents/nested_doc.yaml +20 -0
  115. data/spec/fixtures/documents/simple_doc.yaml +6 -0
  116. data/spec/fixtures/documents/table_doc.yaml +32 -0
  117. data/spec/fixtures/documents/transform_test.yaml +14 -0
  118. data/spec/fixtures/schema/custom_schema.rb +37 -0
  119. data/spec/fixtures/schema/test_schema.rb +46 -0
  120. data/spec/fixtures/test_builder/helpers.rb +212 -0
  121. data/spec/prosereflect/document_spec.rb +332 -330
  122. data/spec/prosereflect/fragment_spec.rb +273 -0
  123. data/spec/prosereflect/hard_break_spec.rb +125 -125
  124. data/spec/prosereflect/input/html_spec.rb +718 -522
  125. data/spec/prosereflect/node_spec.rb +311 -182
  126. data/spec/prosereflect/output/html_spec.rb +105 -105
  127. data/spec/prosereflect/output/whitespace_spec.rb +248 -0
  128. data/spec/prosereflect/paragraph_spec.rb +275 -274
  129. data/spec/prosereflect/parser/round_trip_spec.rb +472 -0
  130. data/spec/prosereflect/parser_spec.rb +185 -180
  131. data/spec/prosereflect/resolved_pos_spec.rb +74 -0
  132. data/spec/prosereflect/schema/conftest.rb +68 -0
  133. data/spec/prosereflect/schema/content_match_spec.rb +237 -0
  134. data/spec/prosereflect/schema/mark_spec.rb +274 -0
  135. data/spec/prosereflect/schema/mark_type_spec.rb +86 -0
  136. data/spec/prosereflect/schema/node_type_spec.rb +142 -0
  137. data/spec/prosereflect/schema/schema_spec.rb +194 -0
  138. data/spec/prosereflect/table_cell_spec.rb +183 -183
  139. data/spec/prosereflect/table_row_spec.rb +149 -149
  140. data/spec/prosereflect/table_spec.rb +320 -318
  141. data/spec/prosereflect/test_builder/marks_spec.rb +127 -0
  142. data/spec/prosereflect/text_spec.rb +133 -132
  143. data/spec/prosereflect/transform/equivalence_spec.rb +487 -0
  144. data/spec/prosereflect/transform/mapping_spec.rb +226 -0
  145. data/spec/prosereflect/transform/replace_spec.rb +832 -0
  146. data/spec/prosereflect/transform/replace_step_spec.rb +157 -0
  147. data/spec/prosereflect/transform/slice_spec.rb +48 -0
  148. data/spec/prosereflect/transform/step_map_spec.rb +70 -0
  149. data/spec/prosereflect/transform/step_spec.rb +211 -0
  150. data/spec/prosereflect/transform/structure_spec.rb +98 -0
  151. data/spec/prosereflect/transform/transform_spec.rb +238 -0
  152. data/spec/prosereflect/user_spec.rb +31 -28
  153. data/spec/prosereflect_spec.rb +28 -26
  154. data/spec/spec_helper.rb +7 -6
  155. data/spec/support/matchers.rb +6 -6
  156. data/spec/support/shared_examples.rb +49 -49
  157. metadata +96 -5
  158. data/spec/prosereflect/version_spec.rb +0 -11
@@ -1,243 +1,243 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
3
+ require "spec_helper"
4
4
 
5
5
  RSpec.describe Prosereflect::TableRow do
6
- describe 'initialization' do
7
- it 'initializes as a table_row node' do
8
- row = described_class.new({ 'type' => 'table_row' })
9
- expect(row.type).to eq('table_row')
6
+ describe "initialization" do
7
+ it "initializes as a table_row node" do
8
+ row = described_class.new({ "type" => "table_row" })
9
+ expect(row.type).to eq("table_row")
10
10
  end
11
11
  end
12
12
 
13
- describe '.create' do
14
- it 'creates an empty table row' do
13
+ describe ".create" do
14
+ it "creates an empty table row" do
15
15
  row = described_class.create
16
16
 
17
17
  expected = {
18
- 'type' => 'table_row',
19
- 'content' => []
18
+ "type" => "table_row",
19
+ "content" => [],
20
20
  }
21
21
 
22
22
  expect(row.to_h).to eq(expected)
23
23
  end
24
24
 
25
- it 'creates a table row with attributes' do
25
+ it "creates a table row with attributes" do
26
26
  row = described_class.create(attrs: {
27
- 'background' => '#f5f5f5',
28
- 'height' => '40px',
29
- 'alignment' => 'center'
27
+ "background" => "#f5f5f5",
28
+ "height" => "40px",
29
+ "alignment" => "center",
30
30
  })
31
31
 
32
32
  expected = {
33
- 'type' => 'table_row',
34
- 'attrs' => {
35
- 'background' => '#f5f5f5',
36
- 'height' => '40px',
37
- 'alignment' => 'center'
33
+ "type" => "table_row",
34
+ "attrs" => {
35
+ "background" => "#f5f5f5",
36
+ "height" => "40px",
37
+ "alignment" => "center",
38
38
  },
39
- 'content' => []
39
+ "content" => [],
40
40
  }
41
41
 
42
42
  expect(row.to_h).to eq(expected)
43
43
  end
44
44
  end
45
45
 
46
- describe 'row structure' do
47
- it 'creates a row with simple text cells' do
46
+ describe "row structure" do
47
+ it "creates a row with simple text cells" do
48
48
  row = described_class.create
49
- row.add_cell('First')
50
- row.add_cell('Second')
51
- row.add_cell('Third')
49
+ row.add_cell("First")
50
+ row.add_cell("Second")
51
+ row.add_cell("Third")
52
52
 
53
53
  expected = {
54
- 'type' => 'table_row',
55
- 'content' => [{
56
- 'type' => 'table_cell',
57
- 'content' => [{
58
- 'type' => 'paragraph',
59
- 'content' => [{
60
- 'type' => 'text',
61
- 'text' => 'First'
62
- }]
63
- }]
54
+ "type" => "table_row",
55
+ "content" => [{
56
+ "type" => "table_cell",
57
+ "content" => [{
58
+ "type" => "paragraph",
59
+ "content" => [{
60
+ "type" => "text",
61
+ "text" => "First",
62
+ }],
63
+ }],
64
64
  }, {
65
- 'type' => 'table_cell',
66
- 'content' => [{
67
- 'type' => 'paragraph',
68
- 'content' => [{
69
- 'type' => 'text',
70
- 'text' => 'Second'
71
- }]
72
- }]
65
+ "type" => "table_cell",
66
+ "content" => [{
67
+ "type" => "paragraph",
68
+ "content" => [{
69
+ "type" => "text",
70
+ "text" => "Second",
71
+ }],
72
+ }],
73
73
  }, {
74
- 'type' => 'table_cell',
75
- 'content' => [{
76
- 'type' => 'paragraph',
77
- 'content' => [{
78
- 'type' => 'text',
79
- 'text' => 'Third'
80
- }]
81
- }]
82
- }]
74
+ "type" => "table_cell",
75
+ "content" => [{
76
+ "type" => "paragraph",
77
+ "content" => [{
78
+ "type" => "text",
79
+ "text" => "Third",
80
+ }],
81
+ }],
82
+ }],
83
83
  }
84
84
 
85
85
  expect(row.to_h).to eq(expected)
86
86
  end
87
87
 
88
- it 'creates a row with complex cell content' do
88
+ it "creates a row with complex cell content" do
89
89
  row = described_class.create
90
90
 
91
91
  # First cell with multiple paragraphs
92
92
  cell = row.add_cell
93
- para = cell.add_paragraph('Main point:')
93
+ para = cell.add_paragraph("Main point:")
94
94
  para.add_hard_break
95
- para.add_text('Important', [Prosereflect::Mark::Bold.new])
96
- cell.add_paragraph('(details below)')
95
+ para.add_text("Important", [Prosereflect::Mark::Bold.new])
96
+ cell.add_paragraph("(details below)")
97
97
 
98
98
  # Second cell with mixed formatting
99
99
  cell = row.add_cell
100
100
  para = cell.add_paragraph
101
- para.add_text('Status: ', [Prosereflect::Mark::Bold.new])
102
- para.add_text('In Progress', [Prosereflect::Mark::Italic.new])
101
+ para.add_text("Status: ", [Prosereflect::Mark::Bold.new])
102
+ para.add_text("In Progress", [Prosereflect::Mark::Italic.new])
103
103
  para.add_hard_break
104
- para.add_text('Updated', [Prosereflect::Mark::Strike.new])
104
+ para.add_text("Updated", [Prosereflect::Mark::Strike.new])
105
105
 
106
106
  expected = {
107
- 'type' => 'table_row',
108
- 'content' => [{
109
- 'type' => 'table_cell',
110
- 'content' => [{
111
- 'type' => 'paragraph',
112
- 'content' => [{
113
- 'type' => 'text',
114
- 'text' => 'Main point:'
107
+ "type" => "table_row",
108
+ "content" => [{
109
+ "type" => "table_cell",
110
+ "content" => [{
111
+ "type" => "paragraph",
112
+ "content" => [{
113
+ "type" => "text",
114
+ "text" => "Main point:",
115
115
  }, {
116
- 'type' => 'hard_break'
116
+ "type" => "hard_break",
117
117
  }, {
118
- 'type' => 'text',
119
- 'text' => 'Important',
120
- 'marks' => [{
121
- 'type' => 'bold'
122
- }]
123
- }]
118
+ "type" => "text",
119
+ "text" => "Important",
120
+ "marks" => [{
121
+ "type" => "bold",
122
+ }],
123
+ }],
124
124
  }, {
125
- 'type' => 'paragraph',
126
- 'content' => [{
127
- 'type' => 'text',
128
- 'text' => '(details below)'
129
- }]
130
- }]
125
+ "type" => "paragraph",
126
+ "content" => [{
127
+ "type" => "text",
128
+ "text" => "(details below)",
129
+ }],
130
+ }],
131
131
  }, {
132
- 'type' => 'table_cell',
133
- 'content' => [{
134
- 'type' => 'paragraph',
135
- 'content' => [{
136
- 'type' => 'text',
137
- 'text' => 'Status: ',
138
- 'marks' => [{
139
- 'type' => 'bold'
140
- }]
132
+ "type" => "table_cell",
133
+ "content" => [{
134
+ "type" => "paragraph",
135
+ "content" => [{
136
+ "type" => "text",
137
+ "text" => "Status: ",
138
+ "marks" => [{
139
+ "type" => "bold",
140
+ }],
141
141
  }, {
142
- 'type' => 'text',
143
- 'text' => 'In Progress',
144
- 'marks' => [{
145
- 'type' => 'italic'
146
- }]
142
+ "type" => "text",
143
+ "text" => "In Progress",
144
+ "marks" => [{
145
+ "type" => "italic",
146
+ }],
147
147
  }, {
148
- 'type' => 'hard_break'
148
+ "type" => "hard_break",
149
149
  }, {
150
- 'type' => 'text',
151
- 'text' => 'Updated',
152
- 'marks' => [{
153
- 'type' => 'strike'
154
- }]
155
- }]
156
- }]
157
- }]
150
+ "type" => "text",
151
+ "text" => "Updated",
152
+ "marks" => [{
153
+ "type" => "strike",
154
+ }],
155
+ }],
156
+ }],
157
+ }],
158
158
  }
159
159
 
160
160
  expect(row.to_h).to eq(expected)
161
161
  end
162
162
  end
163
163
 
164
- describe 'row operations' do
164
+ describe "row operations" do
165
165
  let(:row) do
166
166
  r = described_class.create
167
- r.add_cell('First')
168
- r.add_cell('Second')
169
- r.add_cell('Third')
167
+ r.add_cell("First")
168
+ r.add_cell("Second")
169
+ r.add_cell("Third")
170
170
  r
171
171
  end
172
172
 
173
- describe '#cells' do
174
- it 'returns all cells in the row' do
173
+ describe "#cells" do
174
+ it "returns all cells in the row" do
175
175
  expect(row.cells.size).to eq(3)
176
176
  expect(row.cells).to all(be_a(Prosereflect::TableCell))
177
177
  expect(row.cells.map(&:text_content)).to eq(%w[First Second Third])
178
178
  end
179
179
 
180
- it 'returns empty array for row with no cells' do
180
+ it "returns empty array for row with no cells" do
181
181
  empty_row = described_class.create
182
182
  expect(empty_row.cells).to eq([])
183
183
  end
184
184
  end
185
185
 
186
- describe '#add_cell' do
187
- it 'adds a cell with text content and attributes' do
188
- cell = row.add_cell('Test', attrs: {
189
- 'colspan' => 2,
190
- 'rowspan' => 1,
191
- 'background' => '#eee'
186
+ describe "#add_cell" do
187
+ it "adds a cell with text content and attributes" do
188
+ cell = row.add_cell("Test", attrs: {
189
+ "colspan" => 2,
190
+ "rowspan" => 1,
191
+ "background" => "#eee",
192
192
  })
193
193
 
194
194
  expected = {
195
- 'type' => 'table_cell',
196
- 'attrs' => {
197
- 'colspan' => 2,
198
- 'rowspan' => 1,
199
- 'background' => '#eee'
195
+ "type" => "table_cell",
196
+ "attrs" => {
197
+ "colspan" => 2,
198
+ "rowspan" => 1,
199
+ "background" => "#eee",
200
200
  },
201
- 'content' => [{
202
- 'type' => 'paragraph',
203
- 'content' => [{
204
- 'type' => 'text',
205
- 'text' => 'Test'
206
- }]
207
- }]
201
+ "content" => [{
202
+ "type" => "paragraph",
203
+ "content" => [{
204
+ "type" => "text",
205
+ "text" => "Test",
206
+ }],
207
+ }],
208
208
  }
209
209
 
210
210
  expect(cell.to_h).to eq(expected)
211
211
  end
212
212
 
213
- it 'adds a cell with formatted content' do
213
+ it "adds a cell with formatted content" do
214
214
  cell = row.add_cell
215
215
  para = cell.add_paragraph
216
- para.add_text('Bold', [Prosereflect::Mark::Bold.new])
217
- para.add_text(' and ')
218
- para.add_text('italic', [Prosereflect::Mark::Italic.new])
216
+ para.add_text("Bold", [Prosereflect::Mark::Bold.new])
217
+ para.add_text(" and ")
218
+ para.add_text("italic", [Prosereflect::Mark::Italic.new])
219
219
 
220
220
  expected = {
221
- 'type' => 'table_cell',
222
- 'content' => [{
223
- 'type' => 'paragraph',
224
- 'content' => [{
225
- 'type' => 'text',
226
- 'text' => 'Bold',
227
- 'marks' => [{
228
- 'type' => 'bold'
229
- }]
221
+ "type" => "table_cell",
222
+ "content" => [{
223
+ "type" => "paragraph",
224
+ "content" => [{
225
+ "type" => "text",
226
+ "text" => "Bold",
227
+ "marks" => [{
228
+ "type" => "bold",
229
+ }],
230
230
  }, {
231
- 'type' => 'text',
232
- 'text' => ' and '
231
+ "type" => "text",
232
+ "text" => " and ",
233
233
  }, {
234
- 'type' => 'text',
235
- 'text' => 'italic',
236
- 'marks' => [{
237
- 'type' => 'italic'
238
- }]
239
- }]
240
- }]
234
+ "type" => "text",
235
+ "text" => "italic",
236
+ "marks" => [{
237
+ "type" => "italic",
238
+ }],
239
+ }],
240
+ }],
241
241
  }
242
242
 
243
243
  expect(cell.to_h).to eq(expected)