Module: YARD::Aggredator::Helper

Defined in:
lib/yard/aggredator/plugin.rb

Overview

Модуль с манкипатчами, который инклюдися в шаблонизатор YARD

Constant Summary collapse

REDCARPET_OPTS =
%i[autolink fenced_code gh_blockcode
lax_spacing tables with_toc_data no_intraemphasis
strikethrough]

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.find_static_file(file, root: nil) ⇒ Object



134
135
136
137
138
139
140
141
142
143
# File 'lib/yard/aggredator/plugin.rb', line 134

def self.find_static_file(file, root: nil)
  files = [file]
  files << File.relative_path(Dir.pwd, File.expand_path(file))
  if root.to_s['.yardoc']
    files << root.to_s.sub('.yardoc', file)
    files << files.last.sub('/doc/', '/gems/')
  end

  files.find { |f| File.file?(f) }
end

Instance Method Details

#extract_reftags(object) ⇒ Object

Контент директив надо искать рекурсивно во всех children



179
180
181
182
# File 'lib/yard/aggredator/plugin.rb', line 179

def extract_reftags(object)
  nested = object.respond_to?(:children) ? object.children.map { |o| extract_reftags(o) }.flatten : []
  nested + (object&.tags || []).select { |t| t.tag_name == REFERENCED_TAG_NAME }
end

#format_constant(value) ⇒ Object



169
170
171
# File 'lib/yard/aggredator/plugin.rb', line 169

def format_constant(value)
  "<pre class=\"code ruby highlight\"><code class=\"ruby\">#{super}</code></pre>"
end

#html_markup_markdown(text) ⇒ Object



44
45
46
47
48
49
50
51
52
# File 'lib/yard/aggredator/plugin.rb', line 44

def html_markup_markdown(text)
  provider = markup_class(:markdown)
  case provider.to_s
  when 'RedcarpetCompat'
    provider.new(text, *REDCARPET_OPTS).to_html
  else
    super
  end
end

#html_syntax_highlight_mermaid(source) ⇒ Object



69
70
71
72
73
74
75
76
77
78
# File 'lib/yard/aggredator/plugin.rb', line 69

def html_syntax_highlight_mermaid(source)
  # html="
  #   <script type=\"module\">
  #     import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
  #     mermaid.initialize({ startOnLoad: false });
  #     window.onload = function(){mermaid.init()};
  #   </script><pre class=\"mermaid\">#{source}</pre>
  #   "
  "<pre class=\"mermaid\">#{source}</pre>"
end

#htmlify(text, markup = options.markup) ⇒ Object



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
# File 'lib/yard/aggredator/plugin.rb', line 14

def htmlify(text, markup = options.markup)
  detected_markup = plain_detect_markup(@current_linking_file || @file&.filename, markup)

  # отложенные директивы @!include и @!embed могли оставить ссылки-заглушки, и теперь можно их заменить на реальный контент
  render_referenced_directives(text, owner)

  # Выкусываю <div _render="...">...</div> чтоб зарендерить текст внутри
  text = text.gsub(%r{<div(?<attrs>(?:\s+\w+="(?:.+?)")*)\s*>(?:\s*)?(?<content>.+?)(?:\s*)?</div>}m) do |*_args|
    md = ::Regexp.last_match
    if md[:attrs]['_render']
      "<div #{md[:attrs]}>" + htmlify(md[:content], markup) + '</div>'
    else
      md[0]
    end
  end

  return super if detected_markup == :markdown

  if (detected_markup || %i[plain text
                            mermaid].include?(markup)) && text && respond_to?(:plain_pretty_include)
    return plain_pretty_include(text, detected_markup, markup)
  end

  super
end


127
128
129
130
131
132
# File 'lib/yard/aggredator/plugin.rb', line 127

def link_include_file(file)
  @current_linking_file = file
  super
ensure
  @current_linking_file = nil
end

#linkify(*args) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/yard/aggredator/plugin.rb', line 145

def linkify(*args)
  if args.first.is_a?(String) && /^link:file:(\S+)/.match(args.first)
    file = ::Regexp.last_match(1)
    relpath = File.relative_path(Dir.pwd, File.expand_path(file))
    if serializer.class == YARD::Serializers::FileSystemSerializer
      # Это генерация статики. Например `yardoc` или `yard doc`
      link_url(url_for(relpath), args[1])
    else
      # Это генерация динамики. Например `yard server`
      link_file(relpath, args[1])
    end
  elsif args.first.is_a?(String) && /^include:file:(\S+)/.match(args.first)
    file = ::Regexp.last_match(1)
    root = YARD::Registry.send(:thread_local_store).file.to_s
    if (finded = Aggredator::Helper.find_static_file(file, root: root))
      return link_include_file(finded)
    end

    super
  else
    super
  end
end

#parse_codeblocks(html) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/yard/aggredator/plugin.rb', line 103

def parse_codeblocks(html)
  html.gsub(%r{<pre((?:\s+\w+="(?:.+?)")*)\s*>(?:\s*<code((?:\s+\w+="(?:.+?)")*)\s*>)?(.+?)(?:</code>\s*)?</pre>}m) do
    md = ::Regexp.last_match
    string = md[3]

    next md[0] if string.start_with?('<span') && string['background-color']

    # handle !!!LANG prefix to send to html_syntax_highlight_LANG
    language, = parse_lang_for_codeblock(string)
    language ||= detect_lang_in_codeblock_attributes(::Regexp.last_match(1), ::Regexp.last_match(2))
    language ||= object.source_type

    string = html_syntax_highlight(CGI.unescapeHTML(string), language) if options.highlight

    if language == 'mermaid'
      string
    else

      classes = ['code', language].compact.join(' ')
      %(<pre class="#{classes} highlight"><code class="#{language}">#{string}</code></pre>)
    end
  end
end

#plain_detect_markup(file, markup) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/yard/aggredator/plugin.rb', line 54

def plain_detect_markup(file, markup)
  return nil unless file

  case File.extname(file).downcase
  when '.json'
    :json
  when '.txt', '.text', '.csv'
    :text
  when '.mermaid'
    :mermaid
  else
    markup.to_sym
  end
end

#plain_pretty_include(text, detected_markup, markup) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/yard/aggredator/plugin.rb', line 80

def plain_pretty_include(text, detected_markup, markup)
  markup = detected_markup || markup

  pretty = case markup
           when :json
             begin
               JSON.pretty_generate(JSON.parse(text))
             rescue StandardError
               text
             end
           else
             text
           end

  html = "<pre>\t!!!#{markup}\n#{pretty}</pre>"
  if @file
    # we are inside server layout rendering
    parse_codeblocks(html)
  else
    html
  end
end

#render_referenced_directives(text, object) ⇒ Object

заменить все ссылки-заглушки в тексте на реальный контент директив.



174
175
176
# File 'lib/yard/aggredator/plugin.rb', line 174

def render_referenced_directives(text, object)
  extract_reftags(object).each { |reftag| text.gsub!(reftag.directive.uuid, reftag.directive.expand) }
end