From 6b1b9aabc9f16ddef944766b8a6f8b389e68f4fa Mon Sep 17 00:00:00 2001 From: Vinicius Stock Date: Sat, 12 Jul 2025 10:56:19 -0400 Subject: [PATCH 1/3] Create Markup::Element base class --- lib/rdoc/markup.rb | 1 + lib/rdoc/markup/element.rb | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 lib/rdoc/markup/element.rb diff --git a/lib/rdoc/markup.rb b/lib/rdoc/markup.rb index fc9f4a1b2a..8307874461 100644 --- a/lib/rdoc/markup.rb +++ b/lib/rdoc/markup.rb @@ -210,6 +210,7 @@ def convert(input, formatter) autoload :BlankLine, "#{__dir__}/markup/blank_line" autoload :BlockQuote, "#{__dir__}/markup/block_quote" autoload :Document, "#{__dir__}/markup/document" + autoload :Element, "#{__dir__}/markup/element" autoload :HardBreak, "#{__dir__}/markup/hard_break" autoload :Heading, "#{__dir__}/markup/heading" autoload :Include, "#{__dir__}/markup/include" diff --git a/lib/rdoc/markup/element.rb b/lib/rdoc/markup/element.rb new file mode 100644 index 0000000000..996cc6b1a1 --- /dev/null +++ b/lib/rdoc/markup/element.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module RDoc + class Markup + # Base class defining the interface for all markup elements found in documentation + # @abstract + class Element + # @abstract + #: (untyped) -> void + def accept(visitor) + raise NotImplementedError, "#{self.class} must implement the accept method" + end + + # @abstract + #: (PP) -> void + def pretty_print(q) + raise NotImplementedError, "#{self.class} must implement the pretty_print method" + end + end + end +end From 82450bdc72fa5d518c831a7145bc58d4c4f84705 Mon Sep 17 00:00:00 2001 From: Vinicius Stock Date: Sat, 12 Jul 2025 10:56:32 -0400 Subject: [PATCH 2/3] Standardize Markup::Heading --- lib/rdoc/markup/heading.rb | 174 ++++++++++++++++++++----------------- 1 file changed, 95 insertions(+), 79 deletions(-) diff --git a/lib/rdoc/markup/heading.rb b/lib/rdoc/markup/heading.rb index d4994845c8..70eb4be720 100644 --- a/lib/rdoc/markup/heading.rb +++ b/lib/rdoc/markup/heading.rb @@ -1,84 +1,100 @@ # frozen_string_literal: true -## -# A heading with a level (1-6) and text -RDoc::Markup::Heading = - Struct.new :level, :text do - - @to_html = nil - @to_label = nil - - ## - # A singleton RDoc::Markup::ToLabel formatter for headings. - - def self.to_label - @to_label ||= RDoc::Markup::ToLabel.new - end - - ## - # A singleton plain HTML formatter for headings. Used for creating labels - # for the Table of Contents - - def self.to_html - return @to_html if @to_html - - markup = RDoc::Markup.new - markup.add_regexp_handling RDoc::CrossReference::CROSSREF_REGEXP, :CROSSREF - - @to_html = RDoc::Markup::ToHtml.new nil - - def @to_html.handle_regexp_CROSSREF(target) - target.text.sub(/^\\/, '') +module RDoc + class Markup + # A heading with a level (1-6) and text + # + # RDoc syntax: + # = Heading 1 + # == Heading 2 + # === Heading 3 + # + # Markdown syntax: + # # Heading 1 + # ## Heading 2 + # ### Heading 3 + class Heading < Element + #: String + attr_reader :text + + #: Integer + attr_accessor :level + + # A singleton RDoc::Markup::ToLabel formatter for headings. + #: () -> RDoc::Markup::ToLabel + def self.to_label + @to_label ||= Markup::ToLabel.new + end + + # A singleton plain HTML formatter for headings. Used for creating labels for the Table of Contents + #: () -> RDoc::Markup::ToHtml + def self.to_html + @to_html ||= begin + markup = Markup.new + markup.add_regexp_handling CrossReference::CROSSREF_REGEXP, :CROSSREF + + @to_html = Markup::ToHtml.new nil + + def @to_html.handle_regexp_CROSSREF(target) + target.text.sub(/^\\/, '') + end + + @to_html + end + end + + #: (Integer, String) -> void + def initialize(level, text) + @level = level + @text = text + super() + end + + #: (Object) -> bool + def ==(other) + other.is_a?(Heading) && other.level == @level && other.text == @text + end + + # @override + #: (untyped) -> void + def accept(visitor) + visitor.accept_heading(self) + end + + # An HTML-safe anchor reference for this header. + #: () -> String + def aref + "label-#{self.class.to_label.convert text.dup}" + end + + # Creates a fully-qualified label which will include the label from +context+. This helps keep ids unique in HTML. + #: (RDoc::Context?) -> String + def label(context = nil) + label = +"" + label << "#{context.aref}-" if context&.respond_to?(:aref) + label << aref + label + end + + # HTML markup of the text of this label without the surrounding header element. + #: () -> String + def plain_html + text = self.text.dup + + if matched = text.match(/rdoc-image:[^:]+:(.*)/) + text = matched[1] + end + + self.class.to_html.to_html(text) + end + + # @override + #: (PP) -> void + def pretty_print(q) + q.group 2, "[head: #{level} ", ']' do + q.pp text + end + end end - - @to_html - end - - ## - # Calls #accept_heading on +visitor+ - - def accept(visitor) - visitor.accept_heading self - end - - ## - # An HTML-safe anchor reference for this header. - - def aref - "label-#{self.class.to_label.convert text.dup}" end - - ## - # Creates a fully-qualified label which will include the label from - # +context+. This helps keep ids unique in HTML. - - def label(context = nil) - label = aref - - label = [context.aref, label].compact.join '-' if - context and context.respond_to? :aref - - label - end - - ## - # HTML markup of the text of this label without the surrounding header - # element. - - def plain_html - text = self.text.dup - - if matched = text.match(/rdoc-image:[^:]+:(.*)/) - text = matched[1] - end - - self.class.to_html.to_html(text) - end - - def pretty_print(q) # :nodoc: - q.group 2, "[head: #{level} ", ']' do - q.pp text - end - end - end From e077b2b023fafa0158e147e7f0c7fe273075cad0 Mon Sep 17 00:00:00 2001 From: Vinicius Stock Date: Sat, 12 Jul 2025 10:56:41 -0400 Subject: [PATCH 3/3] Standardize Markup::Table --- lib/rdoc/markup/table.rb | 88 ++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 40 deletions(-) diff --git a/lib/rdoc/markup/table.rb b/lib/rdoc/markup/table.rb index 9105fe2141..7aaa657901 100644 --- a/lib/rdoc/markup/table.rb +++ b/lib/rdoc/markup/table.rb @@ -1,52 +1,60 @@ # frozen_string_literal: true -## -# A section of table -class RDoc::Markup::Table - # headers of each column - attr_accessor :header +module RDoc + class Markup + # A section of table + class Table < Element + # Headers of each column + #: Array[String] + attr_accessor :header - # alignments of each column - attr_accessor :align + # Alignments of each column + #: Array[Symbol?] + attr_accessor :align - # body texts of each column - attr_accessor :body + # Body texts of each column + #: Array[String] + attr_accessor :body - # Creates new instance - def initialize(header, align, body) - @header, @align, @body = header, align, body - end - - # :stopdoc: - def ==(other) - self.class == other.class and - @header == other.header and - @align == other.align and - @body == other.body - end + #: (Array[String], Array[Symbol?], Array[String]) -> void + def initialize(header, align, body) + @header, @align, @body = header, align, body + end - def accept(visitor) - visitor.accept_table @header, @body, @align - end + #: (Object) -> bool + def ==(other) + self.class == other.class && @header == other.header && + @align == other.align && @body == other.body + end - def pretty_print(q) - q.group 2, '[Table: ', ']' do - q.group 2, '[Head: ', ']' do - q.seplist @header.zip(@align) do |text, align| - q.pp text - if align - q.text ":" - q.breakable - q.text align.to_s - end - end + # @override + #: (untyped) -> void + def accept(visitor) + visitor.accept_table(@header, @body, @align) end - q.breakable - q.group 2, '[Body: ', ']' do - q.seplist @body do |body| - q.group 2, '[', ']' do - q.seplist body do |text| + + # @override + #: (untyped) -> String + def pretty_print(q) + q.group 2, '[Table: ', ']' do + q.group 2, '[Head: ', ']' do + q.seplist @header.zip(@align) do |text, align| q.pp text + if align + q.text ":" + q.breakable + q.text align.to_s + end + end + end + q.breakable + q.group 2, '[Body: ', ']' do + q.seplist @body do |body| + q.group 2, '[', ']' do + q.seplist body do |text| + q.pp text + end + end end end end