Module: ReverseMarkdown

Defined in:
lib/solargraph/converters/dd.rb,
lib/solargraph/converters/dl.rb,
lib/solargraph/converters/dt.rb,
lib/solargraph/pin/documenting.rb

Defined Under Namespace

Modules: Converters

Class Method Summary collapse

Class Method Details

.convert(input, options = {}) ⇒ String

Parameters:

  • input (String)
  • options (Hash) (defaults to: {})

Returns:

  • (String)


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
# File 'lib/solargraph/pin/documenting.rb', line 28

module Solargraph
  module Pin
    # A module to add the Pin::Base#documentation method.
    #
    module Documenting
      # A documentation formatter that either performs Markdown conversion for
      # text, or applies backticks for code blocks.
      #
      class DocSection
        # @return [String]
        attr_reader :plaintext

        # @param code [Boolean] True if this section is a code block
        def initialize code
          @plaintext = String.new('')
          @code = code
        end

        def code?
          @code
        end

        # @param text [String]
        # @return [String]
        def concat text
          @plaintext.concat text
        end

        def to_s
          return to_code if code?
          to_markdown
        end

        private

        # @return [String]
        def to_code
          "\n```ruby\n#{Documenting.normalize_indentation(@plaintext)}#{"\n" unless @plaintext.end_with?("\n")}```\n\n"
        end

        # @return [String]
        def to_markdown
          ReverseMarkdown.convert Kramdown::Document.new(@plaintext, input: 'GFM').to_html
        end
      end

      # @return [String]
      def documentation
        @documentation ||= begin
          # Using DocSections allows for code blocks that start with an empty
          # line and at least two spaces of indentation. This is a common
          # convention in Ruby core documentation, e.g., String#split.
          sections = [DocSection.new(false)]
          Documenting.normalize_indentation(Documenting.strip_html_comments(docstring.to_s.gsub("\t",
                                                                                                '  '))).lines.each do |l|
            if l.start_with?('  ')
              # Code block
              sections.push DocSection.new(true) unless sections.last.code?
            elsif sections.last.code?
              # Regular documentation
              sections.push DocSection.new(false)
            end
            sections.last.concat l
          end
          sections.map(&:to_s).join.strip
        end
      end

      # @param text [String]
      # @return [String]
      def self.strip_html_comments text
        text.gsub(/<!--([\s\S]*?)-->/, '').strip
      end

      # @param text [String]
      # @return [String]
      def self.normalize_indentation text
        left = text.lines.map do |line|
          match = line.match(/^ +/)
          next 0 unless match
          # @sg-ignore Need to add nil check here
          match[0].length
        end.min
        return text if left.nil? || left.zero?
        text.lines.map { |line| line[left..] }.join
      end
    end
  end
end