Class: TreeHaver::Backends::Markly::Node

Inherits:
Object
  • Object
show all
Includes:
Comparable, Enumerable
Defined in:
lib/tree_haver/backends/markly.rb

Overview

Markly node wrapper

Wraps Markly::Node to provide TreeHaver::Node-compatible interface.

Note: Markly uses different type names than Commonmarker:

  • :header instead of :heading

  • :hrule instead of :thematic_break

  • :blockquote instead of :block_quote

  • :html instead of :html_block

Constant Summary collapse

TYPE_MAP =

Type normalization map (Markly → canonical)

{
  header: "heading",
  hrule: "thematic_break",
  html: "html_block",
  # blockquote is the same
  # Most types are the same between Markly and Commonmarker
}.freeze
DEFAULT_SOURCE_POSITION =

Default source position for nodes that don’t have position info

{
  start_line: 1,
  start_column: 1,
  end_line: 1,
  end_column: 1,
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(node, source, lines = nil) ⇒ Node

Returns a new instance of Node.



248
249
250
251
252
# File 'lib/tree_haver/backends/markly.rb', line 248

def initialize(node, source, lines = nil)
  @inner_node = node
  @source = source
  @lines = lines || source.lines
end

Instance Attribute Details

#inner_nodeObject (readonly)

Returns the value of attribute inner_node.



246
247
248
# File 'lib/tree_haver/backends/markly.rb', line 246

def inner_node
  @inner_node
end

#sourceObject (readonly)

Returns the value of attribute source.



246
247
248
# File 'lib/tree_haver/backends/markly.rb', line 246

def source
  @source
end

Instance Method Details

#<=>(other) ⇒ Object



431
432
433
434
435
436
# File 'lib/tree_haver/backends/markly.rb', line 431

def <=>(other)
  return unless other.respond_to?(:start_byte)
  cmp = start_byte <=> other.start_byte
  return cmp unless cmp&.zero?
  end_byte <=> other.end_byte
end

#child(index) ⇒ Object



344
345
346
# File 'lib/tree_haver/backends/markly.rb', line 344

def child(index)
  children[index]
end

#child_countObject



340
341
342
# File 'lib/tree_haver/backends/markly.rb', line 340

def child_count
  children.size
end

#childrenArray<Node>

Get child nodes

Markly uses first_child/next pattern

Returns:

  • (Array<Node>)

    Child nodes



317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
# File 'lib/tree_haver/backends/markly.rb', line 317

def children
  result = []
  child = begin
    @inner_node.first_child
  rescue
    nil
  end
  while child
    result << Node.new(child, @source, @lines)
    child = begin
      child.next
    rescue
      nil
    end
  end
  result
end

#each(&block) ⇒ Object



335
336
337
338
# File 'lib/tree_haver/backends/markly.rb', line 335

def each(&block)
  return to_enum(__method__) unless block
  children.each(&block)
end

#end_byteObject



358
359
360
361
362
363
# File 'lib/tree_haver/backends/markly.rb', line 358

def end_byte
  pos = inner_source_position
  line = pos[:end_line] - 1
  col = pos[:end_column] - 1
  calculate_byte_offset(line, col)
end

#end_lineInteger

Get the 1-based line number where this node ends

Returns:

  • (Integer)

    1-based line number



391
392
393
# File 'lib/tree_haver/backends/markly.rb', line 391

def end_line
  inner_source_position[:end_line]
end

#end_pointObject



372
373
374
375
376
377
# File 'lib/tree_haver/backends/markly.rb', line 372

def end_point
  pos = inner_source_position
  line = pos[:end_line] - 1
  col = pos[:end_column] - 1
  Point.new(line, col)
end

#fence_infoString?

Get fence info for code blocks

Returns:

  • (String, nil)


493
494
495
496
497
498
499
500
# File 'lib/tree_haver/backends/markly.rb', line 493

def fence_info
  return unless type == "code_block"
  begin
    @inner_node.fence_info
  rescue
    nil
  end
end

#first_childNode?

Get the first child node

Returns:

  • (Node, nil)

    First child or nil



413
414
415
# File 'lib/tree_haver/backends/markly.rb', line 413

def first_child
  children.first
end

#has_error?Boolean

Returns:

  • (Boolean)


423
424
425
# File 'lib/tree_haver/backends/markly.rb', line 423

def has_error?
  false
end

#header_levelInteger?

Get heading level (1-6)

Returns:

  • (Integer, nil)


482
483
484
485
486
487
488
489
# File 'lib/tree_haver/backends/markly.rb', line 482

def header_level
  return unless raw_type == "header"
  begin
    @inner_node.header_level
  rescue
    nil
  end
end

#inner_source_positionHash{Symbol => Integer}

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Get source position from the inner Markly node

Markly provides source_position as a hash with :start_line, :start_column, :end_line, :end_column (all 1-based).

Returns:

  • (Hash{Symbol => Integer})

    Source position from Markly



261
262
263
264
265
266
267
# File 'lib/tree_haver/backends/markly.rb', line 261

def inner_source_position
  @inner_source_position ||= if @inner_node.respond_to?(:source_position)
    @inner_node.source_position || DEFAULT_SOURCE_POSITION
  else
    DEFAULT_SOURCE_POSITION
  end
end

#inspectObject



438
439
440
# File 'lib/tree_haver/backends/markly.rb', line 438

def inspect
  "#<TreeHaver::Backends::Markly::Node type=#{type} raw_type=#{raw_type}>"
end

#missing?Boolean

Returns:

  • (Boolean)


427
428
429
# File 'lib/tree_haver/backends/markly.rb', line 427

def missing?
  false
end

#named?Boolean Also known as: structural?

Returns:

  • (Boolean)


417
418
419
# File 'lib/tree_haver/backends/markly.rb', line 417

def named?
  true
end

#next_siblingNode?

Get the next sibling (Markly uses .next)

Returns:



520
521
522
523
524
525
526
527
# File 'lib/tree_haver/backends/markly.rb', line 520

def next_sibling
  sibling = begin
    @inner_node.next
  rescue
    nil
  end
  sibling ? Node.new(sibling, @source, @lines) : nil
end

#parentNode?

Get the parent node

Returns:



542
543
544
545
546
547
548
549
# File 'lib/tree_haver/backends/markly.rb', line 542

def parent
  p = begin
    @inner_node.parent
  rescue
    nil
  end
  p ? Node.new(p, @source, @lines) : nil
end

#prev_siblingNode?

Get the previous sibling

Returns:



531
532
533
534
535
536
537
538
# File 'lib/tree_haver/backends/markly.rb', line 531

def prev_sibling
  sibling = begin
    @inner_node.previous
  rescue
    nil
  end
  sibling ? Node.new(sibling, @source, @lines) : nil
end

#raw_typeString

Get the raw (non-normalized) type

Returns:

  • (String)


283
284
285
# File 'lib/tree_haver/backends/markly.rb', line 283

def raw_type
  @inner_node.type.to_s
end

#source_positionHash{Symbol => Integer}

Get position information as a hash

Returns a hash with 1-based line numbers and 0-based columns. Compatible with *-merge gems’ FileAnalysisBase.

Returns:

  • (Hash{Symbol => Integer})

    Position hash



401
402
403
404
405
406
407
408
# File 'lib/tree_haver/backends/markly.rb', line 401

def source_position
  {
    start_line: start_line,
    end_line: end_line,
    start_column: start_point.column,
    end_column: end_point.column,
  }
end

#start_byteObject

Position information Markly provides source_position as a hash with :start_line, :start_column, :end_line, :end_column (1-based)



351
352
353
354
355
356
# File 'lib/tree_haver/backends/markly.rb', line 351

def start_byte
  pos = inner_source_position
  line = pos[:start_line] - 1
  col = pos[:start_column] - 1
  calculate_byte_offset(line, col)
end

#start_lineInteger

Get the 1-based line number where this node starts

Markly provides 1-based line numbers via source_position hash.

Returns:

  • (Integer)

    1-based line number



384
385
386
# File 'lib/tree_haver/backends/markly.rb', line 384

def start_line
  inner_source_position[:start_line]
end

#start_pointObject



365
366
367
368
369
370
# File 'lib/tree_haver/backends/markly.rb', line 365

def start_point
  pos = inner_source_position
  line = pos[:start_line] - 1
  col = pos[:start_column] - 1
  Point.new(line, col)
end

#textString

Get the text content of this node

Returns:

  • (String)

    Node text



290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
# File 'lib/tree_haver/backends/markly.rb', line 290

def text
  # Markly nodes have string_content for leaf nodes (text, code, etc.)
  # Container nodes (heading, paragraph, etc.) have empty string_content
  # and need to use to_plaintext or concatenate children's text.
  if @inner_node.respond_to?(:string_content)
    content = @inner_node.string_content.to_s
    # If string_content is non-empty, use it (leaf node)
    return content unless content.empty?
  end

  # For container nodes, use to_plaintext or concatenate children
  if @inner_node.respond_to?(:to_plaintext)
    begin
      @inner_node.to_plaintext
    rescue
      children.map(&:text).join
    end
  else
    children.map(&:text).join
  end
end

#titleString?

Get title for links/images

Returns:

  • (String, nil)


512
513
514
515
516
# File 'lib/tree_haver/backends/markly.rb', line 512

def title
  @inner_node.title
rescue
  nil
end

#to_commonmarkString

Convert node to CommonMark format

Delegates to the inner Markly node’s to_commonmark method.

Returns:

  • (String)

    CommonMark representation



447
448
449
# File 'lib/tree_haver/backends/markly.rb', line 447

def to_commonmark
  @inner_node.to_commonmark
end

#to_htmlString

Convert node to HTML

Delegates to the inner Markly node’s to_html method.

Returns:

  • (String)

    HTML representation



474
475
476
# File 'lib/tree_haver/backends/markly.rb', line 474

def to_html
  @inner_node.to_html
end

#to_markdownString

Convert node to Markdown format

Delegates to the inner Markly node’s to_markdown method.

Returns:

  • (String)

    Markdown representation



456
457
458
# File 'lib/tree_haver/backends/markly.rb', line 456

def to_markdown
  @inner_node.to_markdown
end

#to_plaintextString

Convert node to plain text

Delegates to the inner Markly node’s to_plaintext method.

Returns:

  • (String)

    Plain text representation



465
466
467
# File 'lib/tree_haver/backends/markly.rb', line 465

def to_plaintext
  @inner_node.to_plaintext
end

#typeString Also known as: kind

Get the node type as a string

Normalizes Markly types to canonical names for consistency.

Returns:

  • (String)

    Node type



274
275
276
277
# File 'lib/tree_haver/backends/markly.rb', line 274

def type
  raw_type = @inner_node.type.to_s
  TYPE_MAP[raw_type.to_sym]&.to_s || raw_type
end

#urlString?

Get URL for links/images

Returns:

  • (String, nil)


504
505
506
507
508
# File 'lib/tree_haver/backends/markly.rb', line 504

def url
  @inner_node.url
rescue
  nil
end