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,14 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'node'
4
-
5
3
  module Prosereflect
6
4
  # Image class represents a ProseMirror image node.
7
5
  # It handles image attributes like src, alt, title, dimensions, etc.
8
6
  class Image < Node
9
- PM_TYPE = 'image'
7
+ PM_TYPE = "image"
10
8
 
11
- attribute :type, :string, default: -> { send('const_get', 'PM_TYPE') }
9
+ attribute :type, :string, default: -> {
10
+ self.class.send(:const_get, "PM_TYPE")
11
+ }
12
12
  attribute :src, :string
13
13
  attribute :alt, :string
14
14
  attribute :title, :string
@@ -17,8 +17,8 @@ module Prosereflect
17
17
  attribute :attrs, :hash
18
18
 
19
19
  key_value do
20
- map 'type', to: :type, render_default: true
21
- map 'attrs', to: :attrs
20
+ map "type", to: :type, render_default: true
21
+ map "attrs", to: :attrs
22
22
  end
23
23
 
24
24
  def initialize(attributes = {})
@@ -27,11 +27,11 @@ module Prosereflect
27
27
 
28
28
  # Extract attributes from the attrs hash if provided
29
29
  if attributes[:attrs]
30
- @src = attributes[:attrs]['src']
31
- @alt = attributes[:attrs]['alt']
32
- @title = attributes[:attrs]['title']
33
- @width = attributes[:attrs]['width']
34
- @height = attributes[:attrs]['height']
30
+ @src = attributes[:attrs]["src"]
31
+ @alt = attributes[:attrs]["alt"]
32
+ @title = attributes[:attrs]["title"]
33
+ @width = attributes[:attrs]["width"]
34
+ @height = attributes[:attrs]["height"]
35
35
  end
36
36
 
37
37
  super
@@ -45,35 +45,35 @@ module Prosereflect
45
45
  def src=(src_url)
46
46
  @src = src_url
47
47
  self.attrs ||= {}
48
- attrs['src'] = src_url
48
+ attrs["src"] = src_url
49
49
  end
50
50
 
51
51
  # Update the alt text
52
52
  def alt=(alt_text)
53
53
  @alt = alt_text
54
54
  self.attrs ||= {}
55
- attrs['alt'] = alt_text
55
+ attrs["alt"] = alt_text
56
56
  end
57
57
 
58
58
  # Update the title (tooltip)
59
59
  def title=(title_text)
60
60
  @title = title_text
61
61
  self.attrs ||= {}
62
- attrs['title'] = title_text
62
+ attrs["title"] = title_text
63
63
  end
64
64
 
65
65
  # Update the width
66
66
  def width=(value)
67
67
  @width = value
68
68
  self.attrs ||= {}
69
- attrs['width'] = value
69
+ attrs["width"] = value
70
70
  end
71
71
 
72
72
  # Update the height
73
73
  def height=(value)
74
74
  @height = value
75
75
  self.attrs ||= {}
76
- attrs['height'] = value
76
+ attrs["height"] = value
77
77
  end
78
78
 
79
79
  # Update dimensions (width and height)
@@ -90,13 +90,13 @@ module Prosereflect
90
90
  alt: alt,
91
91
  title: title,
92
92
  width: width,
93
- height: height
93
+ height: height,
94
94
  }.compact
95
95
  end
96
96
 
97
97
  # Override content-related methods since images don't have content
98
98
  def add_child(*)
99
- raise NotImplementedError, 'Image nodes cannot have children'
99
+ raise NotImplementedError, "Image nodes cannot have children"
100
100
  end
101
101
 
102
102
  def content
@@ -104,23 +104,23 @@ module Prosereflect
104
104
  end
105
105
 
106
106
  def src
107
- @src || attrs&.[]('src')
107
+ @src || attrs&.[]("src")
108
108
  end
109
109
 
110
110
  def alt
111
- @alt || attrs&.[]('alt')
111
+ @alt || attrs&.[]("alt")
112
112
  end
113
113
 
114
114
  def title
115
- @title || attrs&.[]('title')
115
+ @title || attrs&.[]("title")
116
116
  end
117
117
 
118
118
  def width
119
- @width || attrs&.[]('width')
119
+ @width || attrs&.[]("width")
120
120
  end
121
121
 
122
122
  def height
123
- @height || attrs&.[]('height')
123
+ @height || attrs&.[]("height")
124
124
  end
125
125
  end
126
126
  end
@@ -1,33 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'nokogiri'
4
- require_relative '../document'
5
- require_relative '../paragraph'
6
- require_relative '../text'
7
- require_relative '../table'
8
- require_relative '../table_row'
9
- require_relative '../table_cell'
10
- require_relative '../table_header'
11
- require_relative '../hard_break'
12
- require_relative '../mark/bold'
13
- require_relative '../mark/italic'
14
- require_relative '../mark/code'
15
- require_relative '../mark/link'
16
- require_relative '../mark/strike'
17
- require_relative '../mark/subscript'
18
- require_relative '../mark/superscript'
19
- require_relative '../mark/underline'
20
- require_relative '../attribute/href'
21
- require_relative '../ordered_list'
22
- require_relative '../bullet_list'
23
- require_relative '../list_item'
24
- require_relative '../blockquote'
25
- require_relative '../horizontal_rule'
26
- require_relative '../image'
27
- require_relative '../code_block_wrapper'
28
- require_relative '../code_block'
29
- require_relative '../heading'
30
- require_relative '../user'
3
+ require "nokogiri"
31
4
 
32
5
  module Prosereflect
33
6
  module Input
@@ -38,7 +11,7 @@ module Prosereflect
38
11
  html_doc = Nokogiri::HTML(html)
39
12
  document = Document.create # Use create instead of new to initialize content array
40
13
 
41
- content_node = html_doc.at_css('body') || html_doc.root
14
+ content_node = html_doc.at_css("body") || html_doc.root
42
15
 
43
16
  # Process all child nodes
44
17
  process_node_children(content_node, document)
@@ -65,43 +38,43 @@ module Prosereflect
65
38
 
66
39
  # Convert an HTML node to a ProseMirror node
67
40
  def convert_node(html_node)
68
- return nil if html_node.comment? || html_node.text? && html_node.text.strip.empty?
41
+ return nil if html_node.comment? || (html_node.text? && html_node.text.strip.empty?)
69
42
 
70
43
  case html_node.name
71
- when 'text', '#text'
44
+ when "text", "#text"
72
45
  create_text_node(html_node)
73
- when 'p'
46
+ when "p"
74
47
  create_paragraph_node(html_node)
75
48
  when /^h([1-6])$/
76
49
  create_heading_node(html_node, Regexp.last_match(1).to_i)
77
- when 'br'
50
+ when "br"
78
51
  HardBreak.new
79
- when 'table'
52
+ when "table"
80
53
  create_table_node(html_node)
81
- when 'tr'
54
+ when "tr"
82
55
  create_table_row_node(html_node)
83
- when 'th', 'td'
56
+ when "th", "td"
84
57
  create_table_cell_node(html_node)
85
- when 'ol'
58
+ when "ol"
86
59
  create_ordered_list_node(html_node)
87
- when 'ul'
60
+ when "ul"
88
61
  create_bullet_list_node(html_node)
89
- when 'li'
62
+ when "li"
90
63
  create_list_item_node(html_node)
91
- when 'blockquote'
64
+ when "blockquote"
92
65
  create_blockquote_node(html_node)
93
- when 'hr'
66
+ when "hr"
94
67
  create_horizontal_rule_node(html_node)
95
- when 'img'
68
+ when "img"
96
69
  create_image_node(html_node)
97
- when 'user-mention'
70
+ when "user-mention"
98
71
  create_user_node(html_node)
99
- when 'div', 'span'
72
+ when "div", "span"
100
73
  # For containers, we process their children
101
74
  handle_container_node(html_node)
102
- when 'pre'
75
+ when "pre"
103
76
  create_code_block_wrapper(html_node)
104
- when 'strong', 'b', 'em', 'i', 'code', 'a', 'strike', 's', 'del', 'sub', 'sup', 'u'
77
+ when "strong", "b", "em", "i", "code", "a", "strike", "s", "del", "sub", "sup", "u"
105
78
  # For inline elements with text styling, we handle differently
106
79
  handle_styled_text(html_node)
107
80
  else
@@ -126,13 +99,13 @@ module Prosereflect
126
99
  def create_table_node(html_node)
127
100
  table = Table.new
128
101
 
129
- thead = html_node.at_css('thead')
130
- thead&.css('tr')&.each do |tr|
102
+ thead = html_node.at_css("thead")
103
+ thead&.css("tr")&.each do |tr|
131
104
  process_table_row(tr, table, true)
132
105
  end
133
106
 
134
- tbody = html_node.at_css('tbody') || html_node
135
- tbody.css('tr').each do |tr|
107
+ tbody = html_node.at_css("tbody") || html_node
108
+ tbody.css("tr").each do |tr|
136
109
  process_table_row(tr, table, false)
137
110
  end
138
111
 
@@ -142,7 +115,7 @@ module Prosereflect
142
115
  # Process a table row
143
116
  def create_table_row_node(html_node)
144
117
  row = TableRow.new
145
- html_node.css('th, td').each do |cell|
118
+ html_node.css("th, td").each do |cell|
146
119
  row.add_child(create_table_cell_node(cell))
147
120
  end
148
121
  row
@@ -157,13 +130,13 @@ module Prosereflect
157
130
  # Create a table cell node from HTML cell
158
131
  def create_table_cell_node(html_node)
159
132
  # Create either a TableHeader or TableCell based on the tag name
160
- cell = if html_node.name == 'th'
133
+ cell = if html_node.name == "th"
161
134
  header = TableHeader.create
162
135
 
163
136
  # Handle header-specific attributes
164
- header.scope = html_node['scope'] if html_node['scope']
165
- header.abbr = html_node['abbr'] if html_node['abbr']
166
- header.colspan = html_node['colspan'] if html_node['colspan']
137
+ header.scope = html_node["scope"] if html_node["scope"]
138
+ header.abbr = html_node["abbr"] if html_node["abbr"]
139
+ header.colspan = html_node["colspan"] if html_node["colspan"]
167
140
 
168
141
  header
169
142
  else
@@ -184,7 +157,7 @@ module Prosereflect
184
157
  # Handle a container-like node (div, span, etc.)
185
158
  def handle_container_node(html_node)
186
159
  # For top-level divs, process children directly
187
- if html_node.name == 'div'
160
+ if html_node.name == "div"
188
161
  results = []
189
162
  html_node.children.each do |child|
190
163
  next if child.text? && child.text.strip.empty?
@@ -224,38 +197,38 @@ module Prosereflect
224
197
  def handle_styled_text(html_node)
225
198
  # Create mark based on the current node
226
199
  mark = case html_node.name
227
- when 'strong', 'b'
200
+ when "strong", "b"
228
201
  mark = Mark::Bold.new
229
- mark.type = 'bold'
202
+ mark.type = "bold"
230
203
  mark
231
- when 'em', 'i'
204
+ when "em", "i"
232
205
  mark = Mark::Italic.new
233
- mark.type = 'italic'
206
+ mark.type = "italic"
234
207
  mark
235
- when 'code'
208
+ when "code"
236
209
  mark = Mark::Code.new
237
- mark.type = 'code'
210
+ mark.type = "code"
238
211
  mark
239
- when 'a'
212
+ when "a"
240
213
  mark = Mark::Link.new
241
- mark.type = 'link'
242
- mark.attrs = { 'href' => html_node['href'] } if html_node['href']
214
+ mark.type = "link"
215
+ mark.attrs = { "href" => html_node["href"] } if html_node["href"]
243
216
  mark
244
- when 'strike', 's', 'del'
217
+ when "strike", "s", "del"
245
218
  mark = Mark::Strike.new
246
- mark.type = 'strike'
219
+ mark.type = "strike"
247
220
  mark
248
- when 'sub'
221
+ when "sub"
249
222
  mark = Mark::Subscript.new
250
- mark.type = 'subscript'
223
+ mark.type = "subscript"
251
224
  mark
252
- when 'sup'
225
+ when "sup"
253
226
  mark = Mark::Superscript.new
254
- mark.type = 'superscript'
227
+ mark.type = "superscript"
255
228
  mark
256
- when 'u'
229
+ when "u"
257
230
  mark = Mark::Underline.new
258
- mark.type = 'underline'
231
+ mark.type = "underline"
259
232
  mark
260
233
  end
261
234
 
@@ -292,7 +265,8 @@ module Prosereflect
292
265
  def contains_only_text_or_inline(node)
293
266
  node.children.all? do |child|
294
267
  child.text? ||
295
- %w[strong b em i code a br span strike s del sub sup u].include?(child.name) ||
268
+ %w[strong b em i code a br span strike s del sub sup
269
+ u].include?(child.name) ||
296
270
  (child.element? && contains_only_text_or_inline(child))
297
271
  end
298
272
  end
@@ -302,11 +276,11 @@ module Prosereflect
302
276
  list = OrderedList.new
303
277
 
304
278
  # Handle start attribute
305
- start_val = (html_node['start'] || '1').to_i
279
+ start_val = (html_node["start"] || "1").to_i
306
280
  list.start = start_val
307
281
 
308
282
  # Process list items
309
- html_node.css('> li').each do |li|
283
+ html_node.css("> li").each do |li|
310
284
  list.add_child(create_list_item_node(li))
311
285
  end
312
286
 
@@ -319,11 +293,11 @@ module Prosereflect
319
293
  list.bullet_style = nil
320
294
 
321
295
  # Handle style attribute if present
322
- if html_node['style']&.include?('list-style-type')
323
- style = case html_node['style']
324
- when /disc/ then 'disc'
325
- when /circle/ then 'circle'
326
- when /square/ then 'square'
296
+ if html_node["style"]&.include?("list-style-type")
297
+ style = case html_node["style"]
298
+ when /disc/ then "disc"
299
+ when /circle/ then "circle"
300
+ when /square/ then "square"
327
301
  end
328
302
  list.bullet_style = style
329
303
  end
@@ -337,7 +311,9 @@ module Prosereflect
337
311
  item = ListItem.new
338
312
 
339
313
  # Handle text content first
340
- text_content = html_node.children.select { |child| child.text? || inline_element?(child) }
314
+ text_content = html_node.children.select do |child|
315
+ child.text? || inline_element?(child)
316
+ end
341
317
  if text_content.any?
342
318
  paragraph = Paragraph.new
343
319
  text_content.each do |child|
@@ -348,7 +324,9 @@ module Prosereflect
348
324
  end
349
325
 
350
326
  # Handle nested content
351
- html_node.children.reject { |child| child.text? || inline_element?(child) }.each do |child|
327
+ html_node.children.reject do |child|
328
+ child.text? || inline_element?(child)
329
+ end.each do |child|
352
330
  node = convert_node(child)
353
331
  if node.is_a?(Array)
354
332
  node.each { |n| item.add_content(n) }
@@ -364,7 +342,8 @@ module Prosereflect
364
342
  def inline_element?(node)
365
343
  return false unless node.element?
366
344
 
367
- %w[strong b em i code a br span strike s del sub sup u].include?(node.name)
345
+ %w[strong b em i code a br span strike s del sub sup
346
+ u].include?(node.name)
368
347
  end
369
348
 
370
349
  # Create a blockquote node from HTML blockquote
@@ -372,7 +351,7 @@ module Prosereflect
372
351
  quote = Blockquote.new
373
352
 
374
353
  # Handle cite attribute if present
375
- quote.citation = html_node['cite'] if html_node['cite']
354
+ quote.citation = html_node["cite"] if html_node["cite"]
376
355
 
377
356
  # Process each child separately to maintain block structure
378
357
  html_node.children.each do |child|
@@ -401,8 +380,8 @@ module Prosereflect
401
380
  hr = HorizontalRule.new
402
381
 
403
382
  # Handle style attributes if present
404
- if html_node['style']
405
- style = html_node['style']
383
+ if html_node["style"]
384
+ style = html_node["style"]
406
385
 
407
386
  # Parse border-style
408
387
  hr.style = Regexp.last_match(1) if style =~ /border-style:\s*(solid|dashed|dotted)/
@@ -420,20 +399,20 @@ module Prosereflect
420
399
  # Create an image node from HTML img
421
400
  def create_image_node(html_node)
422
401
  # Skip images without src
423
- return nil unless html_node['src']
402
+ return nil unless html_node["src"]
424
403
 
425
404
  image = Image.new
426
405
 
427
406
  # Handle required src attribute
428
- image.src = html_node['src']
407
+ image.src = html_node["src"]
429
408
 
430
409
  # Handle optional attributes
431
- image.alt = html_node['alt'] if html_node['alt']
432
- image.title = html_node['title'] if html_node['title']
410
+ image.alt = html_node["alt"] if html_node["alt"]
411
+ image.title = html_node["title"] if html_node["title"]
433
412
 
434
413
  # Handle dimensions
435
- width = html_node['width']&.to_i
436
- height = html_node['height']&.to_i
414
+ width = html_node["width"]&.to_i
415
+ height = html_node["height"]&.to_i
437
416
  image.dimensions = [width, height] if width || height
438
417
 
439
418
  image
@@ -443,17 +422,17 @@ module Prosereflect
443
422
  def create_code_block_wrapper(html_node)
444
423
  wrapper = CodeBlockWrapper.new
445
424
  wrapper.attrs = {
446
- 'line_numbers' => false
425
+ "line_numbers" => false,
447
426
  }
448
427
 
449
- code_node = html_node.at_css('code')
428
+ code_node = html_node.at_css("code")
450
429
  if code_node
451
430
  block = create_code_block(code_node)
452
431
  wrapper.add_child(block)
453
432
  end
454
433
 
455
- wrapper.to_h['attrs'] = {
456
- 'line_numbers' => false
434
+ wrapper.to_h["attrs"] = {
435
+ "line_numbers" => false,
457
436
  }
458
437
  wrapper
459
438
  end
@@ -465,9 +444,9 @@ module Prosereflect
465
444
  language = extract_language(html_node)
466
445
 
467
446
  block.attrs = {
468
- 'content' => content,
469
- 'language' => language,
470
- 'line_numbers' => nil
447
+ "content" => content,
448
+ "language" => language,
449
+ "line_numbers" => nil,
471
450
  }
472
451
  block.content = content
473
452
 
@@ -475,9 +454,9 @@ module Prosereflect
475
454
  end
476
455
 
477
456
  def extract_language(html_node)
478
- return nil unless html_node['class']
457
+ return nil unless html_node["class"]
479
458
 
480
- return unless html_node['class'] =~ /language-(\w+)/
459
+ return unless html_node["class"] =~ /language-(\w+)/
481
460
 
482
461
  Regexp.last_match(1)
483
462
  end
@@ -493,10 +472,10 @@ module Prosereflect
493
472
  # Create a user mention node from HTML user-mention element
494
473
  def create_user_node(html_node)
495
474
  # Skip user mentions without data-id
496
- return nil unless html_node['data-id']
475
+ return nil unless html_node["data-id"]
497
476
 
498
477
  user = User.new
499
- user.id = html_node['data-id']
478
+ user.id = html_node["data-id"]
500
479
  user
501
480
  end
502
481
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Prosereflect
4
+ module Input
5
+ autoload :Html, "#{__dir__}/input/html"
6
+ end
7
+ end
@@ -1,22 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'node'
4
- require_relative 'paragraph'
5
- require_relative 'text'
6
- require_relative 'hard_break'
7
-
8
3
  module Prosereflect
9
4
  # ListItem class represents a list item in ProseMirror.
10
5
  class ListItem < Node
11
- PM_TYPE = 'list_item'
6
+ PM_TYPE = "list_item"
12
7
 
13
- attribute :type, :string, default: -> { send('const_get', 'PM_TYPE') }
8
+ attribute :type, :string, default: -> {
9
+ self.class.send(:const_get, "PM_TYPE")
10
+ }
14
11
  attribute :attrs, :hash
15
12
 
16
13
  key_value do
17
- map 'type', to: :type, render_default: true
18
- map 'attrs', to: :attrs
19
- map 'content', to: :content
14
+ map "type", to: :type, render_default: true
15
+ map "attrs", to: :attrs
16
+ map "content", to: :content
20
17
  end
21
18
 
22
19
  def initialize(attributes = {})
@@ -57,9 +54,11 @@ module Prosereflect
57
54
 
58
55
  # Get plain text content from all nodes
59
56
  def text_content
60
- return '' unless content
57
+ return "" unless content
61
58
 
62
- content.map { |node| node.respond_to?(:text_content) ? node.text_content : '' }.join("\n").strip
59
+ content.map do |node|
60
+ node.respond_to?(:text_content) ? node.text_content : ""
61
+ end.join("\n").strip
63
62
  end
64
63
  end
65
64
  end
@@ -1,47 +1,45 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'lutaml/model'
4
-
5
3
  module Prosereflect
6
4
  module Mark
7
5
  class Base < Lutaml::Model::Serializable
8
- PM_TYPE = 'mark'
6
+ PM_TYPE = "mark"
9
7
 
10
8
  attribute :type, :string, default: lambda {
11
9
  begin
12
10
  self.class.const_get(:PM_TYPE)
13
11
  rescue StandardError
14
- 'mark'
12
+ "mark"
15
13
  end
16
14
  }
17
15
  attribute :attrs, :hash
18
16
 
19
17
  key_value do
20
- map 'type', to: :type, render_default: true
21
- map 'attrs', to: :attrs
18
+ map "type", to: :type, render_default: true
19
+ map "attrs", to: :attrs
22
20
  end
23
21
 
24
22
  def self.create(attrs = nil)
25
23
  new(type: const_get(:PM_TYPE), attrs: attrs)
26
24
  rescue NameError
27
- new(type: 'mark', attrs: attrs)
25
+ new(type: "mark", attrs: attrs)
28
26
  end
29
27
 
30
28
  # Convert to hash for serialization
31
29
  def to_h
32
- result = { 'type' => type }
33
- result['attrs'] = attrs if attrs && !attrs.empty?
30
+ result = { "type" => type }
31
+ result["attrs"] = attrs if attrs && !attrs.empty?
34
32
  result
35
33
  end
36
34
 
37
35
  # Override initialize to ensure the type is set correctly
38
36
  def initialize(options = {})
39
- super(options)
37
+ super
40
38
  # Only set the type to PM_TYPE if no type was provided in options
41
39
  self.type = begin
42
40
  options[:type] || self.class.const_get(:PM_TYPE)
43
41
  rescue StandardError
44
- 'mark'
42
+ "mark"
45
43
  end
46
44
  end
47
45
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'base'
4
-
5
3
  # {
6
4
  # type: "bold"
7
5
  # }
@@ -9,7 +7,7 @@ require_relative 'base'
9
7
  module Prosereflect
10
8
  module Mark
11
9
  class Bold < Base
12
- PM_TYPE = 'bold'
10
+ PM_TYPE = "bold"
13
11
  end
14
12
  end
15
13
  end
@@ -1,14 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'base'
4
-
5
3
  # {
6
4
  # type: "code"
7
5
  # }
8
6
  module Prosereflect
9
7
  module Mark
10
8
  class Code < Base
11
- PM_TYPE = 'code'
9
+ PM_TYPE = "code"
12
10
  end
13
11
  end
14
12
  end