Module: Uniword::Builder::RunUtils

Defined in:
lib/uniword/builder/run_utils.rb

Overview

Shared run utilities used by both ParagraphBuilder (build-time) and Reconciler::Helpers (reconcile-time).

Provides canonical implementations of run classification and merging. Both modules delegate here to ensure identical behavior.

Class Method Summary collapse

Class Method Details

.empty_run?(run) ⇒ Boolean

Whether a run contains no renderable content.

A run is empty only if it has no text content and no structural elements (breaks, tabs, drawings, field chars, etc.).

Returns:

  • (Boolean)


17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/uniword/builder/run_utils.rb', line 17

def empty_run?(run)
  return false if Array(run.break).any?
  return false if run.tab
  return false if run.drawings&.any?
  return false if run.pictures&.any?
  return false if run.alternate_content
  return false if run.footnote_reference
  return false if run.endnote_reference
  return false if run.field_char
  return false if run.instr_text
  return false if run.position_tab
  return false if run.del_text
  return false if run.no_break_hyphen
  return false if run.sym
  return false if run.last_rendered_page_break
  return false if run.separator_char
  return false if run.continuation_separator_char

  run.text_string.empty?
end

.merge_text(target, source) ⇒ Object

Merge source run's text into target run.

Handles xml:space="preserve" for whitespace-sensitive content.



83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/uniword/builder/run_utils.rb', line 83

def merge_text(target, source)
  if Array(source.text).any?
    existing = target.text_string
    appended = source.text_string
    combined = existing + appended
    new_text = Wordprocessingml::Text.new(content: combined)
    if Wordprocessingml::Text.preserve_whitespace?(combined)
      new_text.xml_space = "preserve"
    end
    target.text = new_text
  end
end

.mergeable?(existing, incoming) ⇒ Boolean

Whether two text-only runs can be merged.

Runs can be merged if both are text-only with identical formatting.

Returns:

  • (Boolean)


73
74
75
76
77
78
# File 'lib/uniword/builder/run_utils.rb', line 73

def mergeable?(existing, incoming)
  return false unless text_only_run?(existing) && text_only_run?(incoming)
  return false if incoming.text_string.empty?

  properties_match?(existing, incoming)
end

.properties_match?(a, b) ⇒ Boolean

Whether two runs have identical formatting (RunProperties).

Returns:

  • (Boolean)


61
62
63
64
65
66
67
68
# File 'lib/uniword/builder/run_utils.rb', line 61

def properties_match?(a, b)
  rpr_a = a.properties
  rpr_b = b.properties
  return true if rpr_a.nil? && rpr_b.nil?
  return false if rpr_a.nil? || rpr_b.nil?

  rpr_a.to_xml == rpr_b.to_xml
end

.text_only_run?(run) ⇒ Boolean

Whether a run contains only text (no structural elements).

Runs with drawings, breaks, tabs, field chars, etc. are NOT text-only and should never be merged with other runs.

Returns:

  • (Boolean)


42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/uniword/builder/run_utils.rb', line 42

def text_only_run?(run)
  return false if run.drawings&.any?
  return false if run.pictures&.any?
  return false if run.alternate_content
  return false if run.footnote_reference
  return false if run.endnote_reference
  return false if run.field_char
  return false if run.instr_text
  return false if run.sym
  return false if Array(run.break).any?
  return false if run.tab
  return false if run.position_tab
  return false if run.no_break_hyphen
  return false if run.del_text

  true
end