Class: Coradoc::AsciiDoc::Transformer
- Inherits:
-
Parslet::Transform
- Object
- Parslet::Transform
- Coradoc::AsciiDoc::Transformer
- Defined in:
- lib/coradoc/asciidoc/transformer.rb,
lib/coradoc/asciidoc/transformer/list_rules.rb,
lib/coradoc/asciidoc/transformer/misc_rules.rb,
lib/coradoc/asciidoc/transformer/text_rules.rb,
lib/coradoc/asciidoc/transformer/block_rules.rb,
lib/coradoc/asciidoc/transformer/header_rules.rb,
lib/coradoc/asciidoc/transformer/inline_rules.rb,
lib/coradoc/asciidoc/transformer/table_layout.rb,
lib/coradoc/asciidoc/transformer/structural_rules.rb,
lib/coradoc/asciidoc/transformer/table_cell_builder.rb,
lib/coradoc/asciidoc/transformer/block_type_classifier.rb,
lib/coradoc/asciidoc/transformer/source_line_extractor.rb,
lib/coradoc/asciidoc/transformer/attribute_list_normalizer.rb
Overview
Parslet::Transform subclass that converts AST to AsciiDoc model objects.
This transformer uses a modular rule system where each group of rules is defined in a separate file for maintainability.
Rule modules (each autoloaded):
- HeaderRules: Document header, author, revision
- InlineRules: Inline formatting (bold, italic, etc.)
- TextRules: Text elements and paragraphs
- BlockRules: Block elements (example, admonition, etc.)
- ListRules: List items and list types
- StructuralRules: Sections, tables, documents
- MiscRules: Comments, attributes, media elements
Defined Under Namespace
Modules: AttributeListNormalizer, BlockRules, BlockTypeClassifier, HeaderRules, InlineRules, ListRules, MiscRules, SourceLineExtractor, StructuralRules, TableCellBuilder, TableLayout, TextRules
Class Method Summary collapse
- .build_table_cell(format, content) ⇒ Object
-
.extract_inline_content(data) ⇒ Object
Helper method for extracting inline content (used by InlineRules).
-
.extract_simple_inline_content(data) ⇒ Object
Helper method for extracting simple inline content.
- .group_cells_into_rows(cells, explicit_col_count = nil) ⇒ Object
- .infer_column_count(cells) ⇒ Object
-
.legacy_transform(syntax_tree) ⇒ Object
deprecated
Deprecated.
Use Transformer.transform instead
-
.lines_to_text_elements(lines) ⇒ Object
Convert parser-output "lines" into an array of TextElement model objects.
- .parse_block_content(text) ⇒ Object
- .parse_cols_attribute(attrs) ⇒ Object
-
.parse_inline_content(text, style = nil) ⇒ Object
Helper method for parsing inline content from raw text.
- .regroup_table_rows(rows, attrs = nil) ⇒ Object
-
.split_lines_on_hard_break(lines) ⇒ Object
Split
:linesentries that span multiple source lines (via text_any greedy-matching across hard_line_break). -
.transform(syntax_tree) ⇒ Object
Transform a syntax tree using this transformer's rules.
Instance Method Summary collapse
-
#call_on_match(bindings, block) ⇒ Object
Single deepening seam for source_line propagation.
Class Method Details
.build_table_cell(format, content) ⇒ Object
95 96 97 |
# File 'lib/coradoc/asciidoc/transformer.rb', line 95 def self.build_table_cell(format, content) TableCellBuilder.build(format, content) end |
.extract_inline_content(data) ⇒ Object
Helper method for extracting inline content (used by InlineRules)
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/coradoc/asciidoc/transformer.rb', line 48 def self.extract_inline_content(data) if data.is_a?(Hash) && data.key?(:content) data[:content] elsif data.is_a?(Array) data.map do |item| if item.is_a?(Hash) && item.key?(:text) text = item[:text] if text.is_a?(Model::Base) && text.class.attributes.key?(:content) text.content elsif text.is_a?(Model::Base) text else text.to_s end else item end end else data end end |
.extract_simple_inline_content(data) ⇒ Object
Helper method for extracting simple inline content
72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/coradoc/asciidoc/transformer.rb', line 72 def self.extract_simple_inline_content(data) if data.is_a?(Hash) && data.key?(:content) data[:content] elsif data.is_a?(Array) data.map do |item| item.is_a?(Hash) && item.key?(:text) ? item[:text].to_s : item end.join else data end end |
.group_cells_into_rows(cells, explicit_col_count = nil) ⇒ Object
103 104 105 |
# File 'lib/coradoc/asciidoc/transformer.rb', line 103 def self.group_cells_into_rows(cells, explicit_col_count = nil) TableLayout.group_cells_into_rows(cells, explicit_col_count) end |
.infer_column_count(cells) ⇒ Object
107 108 109 |
# File 'lib/coradoc/asciidoc/transformer.rb', line 107 def self.infer_column_count(cells) TableLayout.infer_column_count(cells) end |
.legacy_transform(syntax_tree) ⇒ Object
Use transform instead
Legacy transform method (deprecated)
217 218 219 |
# File 'lib/coradoc/asciidoc/transformer.rb', line 217 def self.legacy_transform(syntax_tree) new.apply(syntax_tree) end |
.lines_to_text_elements(lines) ⇒ Object
Convert parser-output "lines" into an array of TextElement model objects. Each line is one of:
- { text: <Array or scalar>, line_break: <str> }
- any other shape (passed through unchanged)
Used by the paragraph and reviewer_note rules to share the same line-shape handling (DRY).
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/coradoc/asciidoc/transformer.rb', line 130 def self.lines_to_text_elements(lines) # Parslet may deliver `lines` as a single Hash (one line captured) # or an Array of Hashes (multiple lines). `Array(hash)` converts # to nested pairs, which we don't want — normalize explicitly. normalized = case lines when nil then [] when Array then lines when Hash then [lines] else Array(lines) end normalized.map do |line| next line unless line.is_a?(Hash) && line.key?(:text) text_content = line[:text] # `text_content` may be a single Hash (one inline), an Array # of Hashes (multiple inlines), or a String. Normalize to an # Array of Hashes for uniform processing. text_array = case text_content when Array then text_content when Hash then [text_content] when String then [{ text: text_content }] else [{ text: text_content.to_s }] end transformed = text_array.map do |item| item.is_a?(Hash) ? new.apply(item) : item end Model::TextElement.new( content: transformed, line_break: line[:line_break] ) end end |
.parse_block_content(text) ⇒ Object
91 92 93 |
# File 'lib/coradoc/asciidoc/transformer.rb', line 91 def self.parse_block_content(text) TableCellBuilder.parse_block_content(text) end |
.parse_cols_attribute(attrs) ⇒ Object
99 100 101 |
# File 'lib/coradoc/asciidoc/transformer.rb', line 99 def self.parse_cols_attribute(attrs) TableLayout.parse_cols_attribute(attrs) end |
.parse_inline_content(text, style = nil) ⇒ Object
Helper method for parsing inline content from raw text. Kept as a thin delegator for backwards compatibility; implementation lives in TableCellBuilder (table cells are the primary consumer).
87 88 89 |
# File 'lib/coradoc/asciidoc/transformer.rb', line 87 def self.parse_inline_content(text, style = nil) TableCellBuilder.parse_inline_content(text, style) end |
.regroup_table_rows(rows, attrs = nil) ⇒ Object
111 112 113 |
# File 'lib/coradoc/asciidoc/transformer.rb', line 111 def self.regroup_table_rows(rows, attrs = nil) TableLayout.regroup_table_rows(rows, attrs) end |
.split_lines_on_hard_break(lines) ⇒ Object
Split :lines entries that span multiple source lines (via
text_any greedy-matching across hard_line_break). Each call
returns one entry per logical source line: when a line entry's
:text array contains a hard_line_break, the entry is split
at each hard_break, producing N+1 entries for N hard breaks.
The hard_break is preserved as the :line_break of its segment.
Without this, a dd source like:
`term::` First line. +
+
attached
produces a single :lines entry whose text contains
["First line.", hard_line_break(" +\n"), "+", "attached..."],
which the renderer joins into "First line. + attached" — the
+ continuation marker ends up inside the dd's text instead
of triggering the attached-block path.
Used by the dlist transformer before lines_to_text_elements.
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/coradoc/asciidoc/transformer.rb', line 182 def self.split_lines_on_hard_break(lines) normalized = case lines when nil then [] when Array then lines when Hash then [lines] else Array(lines) end normalized.flat_map do |line| next [line] unless line.is_a?(Hash) && line[:text].is_a?(Array) next [line] unless line[:text].any? { |p| p.is_a?(Hash) && p.key?(:hard_line_break) } segments = [] current_text = [] current_break = nil line[:text].each do |part| if part.is_a?(Hash) && part.key?(:hard_line_break) segments << { text: current_text, line_break: part[:hard_line_break] } current_text = [] current_break = :had_hard_break else current_text << part end end # Final segment gets the original line's line_break (or empty # if it ended with a hard break). final_break = current_break == :had_hard_break ? "\n" : line[:line_break] segments << { text: current_text, line_break: final_break } # Drop leading empty segment if the line started with a hard break # (shouldn't happen in practice but be defensive). segments.reject { |s| s[:text].empty? && s != segments.last } end end |
.transform(syntax_tree) ⇒ Object
Transform a syntax tree using this transformer's rules
119 120 121 |
# File 'lib/coradoc/asciidoc/transformer.rb', line 119 def self.transform(syntax_tree) new.apply(syntax_tree) end |
Instance Method Details
#call_on_match(bindings, block) ⇒ Object
Single deepening seam for source_line propagation. Parslet's
transform pipeline funnels every rule block through
call_on_match(bindings, block); overriding it lets us post-
process the block's result and inject source_line from the
matched bindings, so individual rules no longer need to call
SourceLineExtractor.extract themselves (DRY — was 47 call
sites across 7 rule files).
Safety:
* Only Model::Base results get an injection — Strings, Arrays,
and intermediate hashes pass through unchanged.
* Existing explicit source_line values are preserved — the
injection is fill-in-the-blank, never overwrite.
* No Slice in the bindings → SourceLineExtractor returns nil,
no injection (synthetic transformations stay clean).
236 237 238 239 240 241 242 243 244 |
# File 'lib/coradoc/asciidoc/transformer.rb', line 236 def call_on_match(bindings, block) result = super return result unless result.is_a?(Model::Base) return result if result.source_line line = self.class::SourceLineExtractor.extract(bindings) result.source_line = line if line result end |