Module: Coradoc::AsciiDoc::Transformer::ListRules

Defined in:
lib/coradoc/asciidoc/transformer/list_rules.rb

Overview

Module containing list transformation rules

Class Method Summary collapse

Class Method Details

.apply(transformer_class) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/coradoc/asciidoc/transformer/list_rules.rb', line 8

def self.apply(transformer_class)
  transformer_class.class_eval do
    # List item
    rule(list_item: subtree(:list_item)) do
      marker = list_item[:marker]
      id = list_item[:id]
      text = list_item[:text]
      text = list_item[:text].to_s if list_item[:text].instance_of?(Parslet::Slice)
      attached = list_item[:attached]
      nested = list_item[:nested]
      line_break = list_item[:line_break]

      # Convert nested array to proper List object if needed
      if nested.is_a?(Array) && nested.any?
        nested = if nested.all?(Model::List::Core)
                   nested.first
                 elsif nested.all?(Model::List::Item)
                   first_marker = nested.first.marker
                   if first_marker.to_s.lstrip.start_with?('.', '1', 'a', 'A', 'i', 'I')
                     Model::List::Ordered.new(items: nested)
                   else
                     Model::List::Unordered.new(items: nested)
                   end
                 else
                   nested
                 end
      end

      Model::List::Item.new(
        content: text, id:, marker:, attached:, nested:, line_break:
      )
    end

    # List passthrough
    rule(list: simple(:list)) do
      list
    end

    # Unordered list
    rule(unordered: sequence(:list_items)) do
      Model::List::Unordered.new(items: list_items)
    end

    rule(
      attribute_list: simple(:attribute_list),
      unordered: sequence(:list_items)
    ) do
      Model::List::Unordered.new(items: list_items, attrs: attribute_list)
    end

    # Ordered list
    rule(ordered: sequence(:list_items)) do
      Model::List::Ordered.new(items: list_items)
    end

    rule(
      attribute_list: simple(:attribute_list),
      ordered: sequence(:list_items)
    ) do
      Model::List::Ordered.new(items: list_items, attrs: attribute_list)
    end

    # Definition list term (with optional anchor)
    rule(dlist_term: subtree(:term_data), delimiter: simple(:_delim)) do
      case term_data
      when Hash
        text = term_data[:text]
        text = text.to_s if text.is_a?(Parslet::Slice) || text.is_a?(String)
        text = text.content.to_s if text.is_a?(Model::TextElement)
        id = term_data[:id]
        id = id.to_s if id.is_a?(Parslet::Slice)
        { text: text.to_s, id: id }
      when Model::TextElement
        { text: term_data.content.to_s, id: term_data.id }
      else
        { text: term_data.to_s, id: nil }
      end
    end

    # Definition list item
    rule(
      definition_list_item: {
        terms: sequence(:terms),
        definition: simple(:contents)
      }
    ) do
      term_strings = terms.map do |t|
        t.is_a?(Hash) ? t[:text].to_s : t.to_s
      end
      item_id = nil
      terms.each do |t|
        next unless t.is_a?(Hash) && t[:id]

        item_id = t[:id].to_s
        break
      end
      Model::List::DefinitionItem.new(terms: term_strings, contents: contents, id: item_id)
    end

    # Definition list item with hash terms (single term case)
    rule(
      definition_list_item: subtree(:item_data)
    ) do
      terms_data = item_data[:terms]
      definition = item_data[:definition]

      # Extract terms and optional id from structured dlist_term output
      item_id = nil
      terms = if terms_data.is_a?(Array)
                terms_data.map do |t|
                  if t.is_a?(Hash)
                    item_id ||= t[:id].to_s if t[:id]
                    t[:text].to_s
                  else
                    t.to_s
                  end
                end
              else
                [terms_data.to_s]
              end

      # Extract definition
      contents = definition.to_s

      Model::List::DefinitionItem.new(terms: terms, contents: contents, id: item_id)
    end

    rule(definition_list: sequence(:list_items)) do
      Model::List::Definition.new(items: list_items)
    end

    # Definition list with attribute_list (e.g., [%key])
    rule(
      attribute_list: simple(:attribute_list),
      definition_list: sequence(:list_items)
    ) do
      Model::List::Definition.new(items: list_items, attrs: attribute_list)
    end
  end
end