jazzy 0.13.4 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/Tests.yml +52 -0
  3. data/.rubocop.yml +123 -24
  4. data/CHANGELOG.md +103 -0
  5. data/CONTRIBUTING.md +5 -5
  6. data/Dangerfile +11 -8
  7. data/Gemfile +3 -1
  8. data/Gemfile.lock +91 -69
  9. data/README.md +85 -13
  10. data/Rakefile +19 -13
  11. data/bin/jazzy +3 -2
  12. data/bin/sourcekitten +0 -0
  13. data/jazzy.gemspec +8 -6
  14. data/js/package-lock.json +30 -25
  15. data/js/package.json +3 -3
  16. data/lib/jazzy.rb +2 -0
  17. data/lib/jazzy/config.rb +124 -70
  18. data/lib/jazzy/doc.rb +3 -1
  19. data/lib/jazzy/doc_builder.rb +75 -81
  20. data/lib/jazzy/docset_builder.rb +3 -1
  21. data/lib/jazzy/documentation_generator.rb +6 -2
  22. data/lib/jazzy/executable.rb +3 -0
  23. data/lib/jazzy/extensions/bitbucket/img/bitbucket.svg +11 -0
  24. data/lib/jazzy/{themes/apple/assets → extensions/github}/img/gh.png +0 -0
  25. data/lib/jazzy/extensions/gitlab/img/gitlab.svg +23 -0
  26. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_AMS-Regular.ttf +0 -0
  27. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_AMS-Regular.woff +0 -0
  28. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  29. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
  30. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
  31. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  32. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
  33. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
  34. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  35. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
  36. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Fraktur-Bold.woff +0 -0
  37. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  38. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
  39. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Fraktur-Regular.woff +0 -0
  40. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  41. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-Bold.ttf +0 -0
  42. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-Bold.woff +0 -0
  43. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-Bold.woff2 +0 -0
  44. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
  45. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-BoldItalic.woff +0 -0
  46. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  47. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-Italic.ttf +0 -0
  48. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-Italic.woff +0 -0
  49. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-Italic.woff2 +0 -0
  50. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-Regular.ttf +0 -0
  51. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-Regular.woff +0 -0
  52. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Main-Regular.woff2 +0 -0
  53. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
  54. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Math-BoldItalic.woff +0 -0
  55. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  56. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Math-Italic.ttf +0 -0
  57. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Math-Italic.woff +0 -0
  58. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Math-Italic.woff2 +0 -0
  59. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
  60. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_SansSerif-Bold.woff +0 -0
  61. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  62. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
  63. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_SansSerif-Italic.woff +0 -0
  64. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  65. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
  66. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_SansSerif-Regular.woff +0 -0
  67. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  68. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Script-Regular.ttf +0 -0
  69. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Script-Regular.woff +0 -0
  70. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Script-Regular.woff2 +0 -0
  71. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size1-Regular.ttf +0 -0
  72. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size1-Regular.woff +0 -0
  73. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  74. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size2-Regular.ttf +0 -0
  75. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size2-Regular.woff +0 -0
  76. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  77. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size3-Regular.ttf +0 -0
  78. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size3-Regular.woff +0 -0
  79. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  80. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size4-Regular.ttf +0 -0
  81. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size4-Regular.woff +0 -0
  82. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  83. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
  84. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Typewriter-Regular.woff +0 -0
  85. data/lib/jazzy/extensions/katex/css/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  86. data/lib/jazzy/extensions/katex/css/katex.min.css +1 -1
  87. data/lib/jazzy/extensions/katex/js/katex.min.js +1 -1
  88. data/lib/jazzy/gem_version.rb +3 -1
  89. data/lib/jazzy/highlighter.rb +5 -3
  90. data/lib/jazzy/jazzy_markdown.rb +101 -30
  91. data/lib/jazzy/podspec_documenter.rb +14 -16
  92. data/lib/jazzy/search_builder.rb +4 -3
  93. data/lib/jazzy/source_declaration.rb +24 -5
  94. data/lib/jazzy/source_declaration/access_control_level.rb +7 -5
  95. data/lib/jazzy/source_declaration/type.rb +33 -1
  96. data/lib/jazzy/source_document.rb +8 -5
  97. data/lib/jazzy/source_host.rb +111 -0
  98. data/lib/jazzy/source_mark.rb +8 -6
  99. data/lib/jazzy/source_module.rb +6 -6
  100. data/lib/jazzy/sourcekitten.rb +105 -79
  101. data/lib/jazzy/stats.rb +4 -2
  102. data/lib/jazzy/symbol_graph.rb +95 -0
  103. data/lib/jazzy/symbol_graph/constraint.rb +98 -0
  104. data/lib/jazzy/symbol_graph/ext_node.rb +116 -0
  105. data/lib/jazzy/symbol_graph/graph.rb +195 -0
  106. data/lib/jazzy/symbol_graph/relationship.rb +42 -0
  107. data/lib/jazzy/symbol_graph/sym_node.rb +163 -0
  108. data/lib/jazzy/symbol_graph/symbol.rb +222 -0
  109. data/lib/jazzy/themes/apple/assets/css/highlight.css.scss +63 -59
  110. data/lib/jazzy/themes/apple/assets/css/jazzy.css.scss +101 -4
  111. data/lib/jazzy/themes/apple/assets/img/spinner.gif +0 -0
  112. data/lib/jazzy/themes/apple/assets/js/jazzy.js +4 -0
  113. data/lib/jazzy/themes/apple/assets/js/jazzy.search.js +74 -0
  114. data/lib/jazzy/themes/apple/assets/js/jquery.min.js +2 -2
  115. data/lib/jazzy/themes/apple/assets/js/lunr.min.js +6 -0
  116. data/lib/jazzy/themes/apple/assets/js/typeahead.jquery.js +1694 -0
  117. data/lib/jazzy/themes/apple/templates/doc.mustache +35 -0
  118. data/lib/jazzy/themes/apple/templates/footer.mustache +1 -1
  119. data/lib/jazzy/themes/apple/templates/header.mustache +10 -3
  120. data/lib/jazzy/themes/apple/templates/task.mustache +4 -4
  121. data/lib/jazzy/themes/fullwidth/assets/css/highlight.css.scss +63 -59
  122. data/lib/jazzy/themes/fullwidth/assets/css/jazzy.css.scss +11 -2
  123. data/lib/jazzy/themes/fullwidth/assets/js/jazzy.js +4 -0
  124. data/lib/jazzy/themes/fullwidth/assets/js/jazzy.search.js +4 -0
  125. data/lib/jazzy/themes/fullwidth/assets/js/jquery.min.js +2 -2
  126. data/lib/jazzy/themes/fullwidth/assets/js/lunr.min.js +3 -3
  127. data/lib/jazzy/themes/fullwidth/templates/doc.mustache +30 -0
  128. data/lib/jazzy/themes/fullwidth/templates/footer.mustache +1 -1
  129. data/lib/jazzy/themes/fullwidth/templates/header.mustache +5 -5
  130. data/lib/jazzy/themes/fullwidth/templates/task.mustache +4 -4
  131. data/lib/jazzy/themes/jony/assets/css/highlight.css.scss +63 -59
  132. data/lib/jazzy/themes/jony/assets/css/jazzy.css.scss +34 -2
  133. data/lib/jazzy/themes/jony/assets/js/jazzy.js +4 -0
  134. data/lib/jazzy/themes/jony/assets/js/jquery.min.js +2 -2
  135. data/lib/jazzy/themes/jony/templates/doc.mustache +30 -0
  136. data/lib/jazzy/themes/jony/templates/footer.mustache +1 -1
  137. data/lib/jazzy/themes/jony/templates/header.mustache +5 -5
  138. data/lib/jazzy/themes/jony/templates/task.mustache +4 -4
  139. data/spec/integration_spec.rb +54 -42
  140. data/spec/spec_helper.rb +3 -1
  141. data/spec/spec_helper/pre_flight.rb +2 -0
  142. metadata +43 -19
  143. data/.circleci/config.yml +0 -83
  144. data/lib/jazzy/themes/fullwidth/assets/img/gh.png +0 -0
  145. data/lib/jazzy/themes/jony/assets/img/gh.png +0 -0
  146. data/spec/sourcekitten_spec.rb +0 -6
@@ -1,32 +1,32 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'uri'
2
4
 
3
5
  require 'jazzy/config'
4
6
  require 'jazzy/source_declaration'
7
+ require 'jazzy/source_host'
5
8
 
6
9
  module Jazzy
7
10
  class SourceModule
8
11
  attr_accessor :name
9
- attr_accessor :root_path
10
12
  attr_accessor :docs
11
13
  attr_accessor :doc_coverage
12
14
  attr_accessor :doc_structure
13
15
  attr_accessor :author_name
14
- attr_accessor :github_url
15
- attr_accessor :github_file_prefix
16
16
  attr_accessor :author_url
17
17
  attr_accessor :dash_url
18
+ attr_accessor :host
18
19
 
19
20
  def initialize(options, docs, doc_structure, doc_coverage)
20
21
  self.docs = docs
21
- self.root_path = options.source_directory
22
22
  self.doc_structure = doc_structure
23
23
  self.doc_coverage = doc_coverage
24
24
  self.name = options.module_name
25
25
  self.author_name = options.author_name
26
- self.github_url = options.github_url
27
- self.github_file_prefix = options.github_file_prefix
28
26
  self.author_url = options.author_url
27
+ self.host = SourceHost.create(options)
29
28
  return unless options.dash_url
29
+
30
30
  self.dash_url =
31
31
  "dash-feed://#{ERB::Util.url_encode(options.dash_url.to_s)}"
32
32
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
  require 'pathname'
3
5
  require 'shellwords'
@@ -12,7 +14,7 @@ require 'jazzy/source_declaration'
12
14
  require 'jazzy/source_mark'
13
15
  require 'jazzy/stats'
14
16
 
15
- ELIDED_AUTOLINK_TOKEN = '36f8f5912051ae747ef441d6511ca4cb'.freeze
17
+ ELIDED_AUTOLINK_TOKEN = '36f8f5912051ae747ef441d6511ca4cb'
16
18
 
17
19
  def autolink_regex(middle_regex, after_highlight)
18
20
  start_tag_re, end_tag_re =
@@ -29,16 +31,15 @@ class String
29
31
  gsub(autolink_regex(middle_regex, after_highlight)) do
30
32
  original = Regexp.last_match(0)
31
33
  start_tag, raw_name, end_tag = Regexp.last_match.captures
32
- link_target = yield(CGI.unescape_html(raw_name))
34
+ link_target, display_name = yield(CGI.unescape_html(raw_name))
33
35
 
34
36
  if link_target &&
35
37
  !link_target.type.extension? &&
36
38
  link_target.url &&
37
39
  link_target.url != doc_url.split('#').first && # Don't link to parent
38
40
  link_target.url != doc_url # Don't link to self
39
- start_tag +
40
- "<a href=\"#{ELIDED_AUTOLINK_TOKEN}#{link_target.url}\">" +
41
- raw_name + '</a>' + end_tag
41
+ "#{start_tag}<a href=\"#{ELIDED_AUTOLINK_TOKEN}#{link_target.url}\">" \
42
+ "#{CGI.escape_html(display_name)}</a>#{end_tag}"
42
43
  else
43
44
  original
44
45
  end
@@ -74,8 +75,8 @@ module Jazzy
74
75
  children = category['children'].flat_map do |name|
75
76
  docs_with_name, docs = docs.partition { |doc| doc.name == name }
76
77
  if docs_with_name.empty?
77
- STDERR.puts 'WARNING: No documented top-level declarations match ' \
78
- "name \"#{name}\" specified in categories file"
78
+ warn 'WARNING: No documented top-level declarations match ' \
79
+ "name \"#{name}\" specified in categories file"
79
80
  end
80
81
  docs_with_name
81
82
  end
@@ -129,7 +130,7 @@ module Jazzy
129
130
  def self.merge_consecutive_marks(docs)
130
131
  prev_mark = nil
131
132
  docs.each do |doc|
132
- if prev_mark && prev_mark.can_merge?(doc.mark)
133
+ if prev_mark&.can_merge?(doc.mark)
133
134
  doc.mark = prev_mark
134
135
  end
135
136
  prev_mark = doc.mark
@@ -138,12 +139,12 @@ module Jazzy
138
139
  end
139
140
 
140
141
  def self.sanitize_filename(doc)
141
- unsafe_filename = doc.url_name || doc.name
142
+ unsafe_filename = doc.docs_filename
142
143
  sanitzation_enabled = Config.instance.use_safe_filenames
143
144
  if sanitzation_enabled && !doc.type.name_controlled_manually?
144
- return CGI.escape(unsafe_filename).gsub('_', '%5F').tr('%', '_')
145
+ CGI.escape(unsafe_filename).gsub('_', '%5F').tr('%', '_')
145
146
  else
146
- return unsafe_filename
147
+ unsafe_filename
147
148
  end
148
149
  end
149
150
 
@@ -162,11 +163,11 @@ module Jazzy
162
163
  # Don't create HTML page for this doc if it doesn't have children
163
164
  # Instead, make its link a hash-link on its parent's page
164
165
  if doc.typename == '<<error type>>'
165
- warn 'A compile error prevented ' + doc.fully_qualified_name +
166
- ' from receiving a unique USR. Documentation may be ' \
167
- 'incomplete. Please check for compile errors by running ' \
168
- '`xcodebuild` or `swift build` with arguments ' \
169
- "`#{Config.instance.build_tool_arguments.shelljoin}`."
166
+ warn "A compile error prevented #{doc.fully_qualified_name} " \
167
+ 'from receiving a unique USR. Documentation may be ' \
168
+ 'incomplete. Please check for compile errors by running ' \
169
+ '`xcodebuild` or `swift build` with arguments ' \
170
+ "`#{Config.instance.build_tool_arguments.shelljoin}`."
170
171
  end
171
172
  id = doc.usr
172
173
  unless id
@@ -174,11 +175,11 @@ module Jazzy
174
175
  warn "`#{id}` has no USR. First make sure all modules used in " \
175
176
  'your project have been imported. If all used modules are ' \
176
177
  'imported, please report this problem by filing an issue at ' \
177
- 'https://github.com/realm/jazzy/issues along with your Xcode ' \
178
- 'project. If this token is declared in an `#if` block, please ' \
179
- 'ignore this message.'
178
+ 'https://github.com/realm/jazzy/issues along with your ' \
179
+ 'Xcode project. If this token is declared in an `#if` block, ' \
180
+ 'please ignore this message.'
180
181
  end
181
- doc.url = doc.parent_in_docs.url + '#/' + id
182
+ doc.url = "#{doc.parent_in_docs.url}#/#{id}"
182
183
  end
183
184
  end
184
185
  end
@@ -189,6 +190,7 @@ module Jazzy
189
190
  # Declarations under outer namespace type (Structures, Classes, etc.)
190
191
  def self.subdir_for_doc(doc)
191
192
  return [] if doc.type.markdown?
193
+
192
194
  top_level_decl = doc.namespace_path.first
193
195
  if top_level_decl.type.name
194
196
  [top_level_decl.type.plural_url_name] +
@@ -258,6 +260,7 @@ module Jazzy
258
260
  unless xcode = XCInvoke::Xcode.find_swift_version(swift_version)
259
261
  raise "Unable to find an Xcode with swift version #{swift_version}."
260
262
  end
263
+
261
264
  env = xcode.as_env
262
265
  else
263
266
  env = ENV
@@ -269,8 +272,6 @@ module Jazzy
269
272
 
270
273
  def self.make_default_doc_info(declaration)
271
274
  # @todo: Fix these
272
- declaration.line = nil
273
- declaration.column = nil
274
275
  declaration.abstract = ''
275
276
  declaration.parameters = []
276
277
  declaration.children = []
@@ -278,13 +279,12 @@ module Jazzy
278
279
 
279
280
  def self.availability_attribute?(doc)
280
281
  return false unless doc['key.attributes']
282
+
281
283
  !doc['key.attributes'].select do |attribute|
282
284
  attribute.values.first == 'source.decl.attribute.available'
283
285
  end.empty?
284
286
  end
285
287
 
286
- # rubocop:disable Metrics/CyclomaticComplexity
287
- # rubocop:disable Metrics/PerceivedComplexity
288
288
  def self.should_document?(doc)
289
289
  return false if doc['key.doc.comment'].to_s.include?(':nodoc:')
290
290
 
@@ -314,8 +314,6 @@ module Jazzy
314
314
  end
315
315
  acl_ok
316
316
  end
317
- # rubocop:enable Metrics/CyclomaticComplexity
318
- # rubocop:enable Metrics/PerceivedComplexity
319
317
 
320
318
  def self.should_document_swift_extension?(doc)
321
319
  doc['key.inheritedtypes'] ||
@@ -325,19 +323,19 @@ module Jazzy
325
323
  end
326
324
  end
327
325
 
328
- def self.should_mark_undocumented(filepath)
329
- source_directory = Config.instance.source_directory.to_s
330
- (filepath || '').start_with?(source_directory)
326
+ # Call things undocumented if they were compiled properly
327
+ # and came from our module.
328
+ def self.should_mark_undocumented(declaration)
329
+ declaration.usr && !declaration.modulename
331
330
  end
332
331
 
333
332
  def self.process_undocumented_token(doc, declaration)
334
333
  make_default_doc_info(declaration)
335
334
 
336
- filepath = doc['key.filepath']
337
-
338
- if !declaration.swift? || should_mark_undocumented(filepath)
335
+ if !declaration.swift? || should_mark_undocumented(declaration)
339
336
  @stats.add_undocumented(declaration)
340
337
  return nil if @skip_undocumented
338
+
341
339
  declaration.abstract = undocumented_abstract
342
340
  else
343
341
  declaration.abstract = Markdown.render(doc['key.doc.comment'] || '',
@@ -405,7 +403,7 @@ module Jazzy
405
403
  def self.xml_to_text(xml)
406
404
  document = REXML::Document.new(xml)
407
405
  REXML::XPath.match(document.root, '//text()').map(&:value).join
408
- rescue
406
+ rescue StandardError
409
407
  ''
410
408
  end
411
409
 
@@ -491,11 +489,10 @@ module Jazzy
491
489
  end
492
490
 
493
491
  # @available attrs only in compiler 'interface' style
494
- available_attrs = extract_availability(doc['key.doc.declaration'] || '')
495
-
496
- available_attrs.concat(extract_attributes(annotated_decl_attrs))
497
- .push(decl)
498
- .join("\n")
492
+ extract_availability(doc['key.doc.declaration'] || '')
493
+ .concat(extract_attributes(annotated_decl_attrs))
494
+ .push(decl)
495
+ .join("\n")
499
496
  end
500
497
 
501
498
  # Strip default property attributes because libclang
@@ -511,12 +508,14 @@ module Jazzy
511
508
  attrs = Regexp.last_match[1].split(',').map(&:strip) - DEFAULT_ATTRIBUTES
512
509
  attrs_text = attrs.empty? ? '' : " (#{attrs.join(', ')})"
513
510
 
514
- declaration.sub(/(?<=@property)\s+\(.*?\)/, attrs_text)
515
- .gsub(/\s+/, ' ')
511
+ declaration
512
+ .sub(/(?<=@property)\s+\(.*?\)/, attrs_text)
513
+ .gsub(/\s+/, ' ')
516
514
  end
517
515
 
518
516
  def self.make_substructure(doc, declaration)
519
517
  return [] unless subdocs = doc['key.substructure']
518
+
520
519
  make_source_declarations(subdocs,
521
520
  declaration,
522
521
  declaration.mark_for_children)
@@ -559,19 +558,20 @@ module Jazzy
559
558
 
560
559
  unless declaration.type.name
561
560
  raise 'Please file an issue at ' \
562
- 'https://github.com/realm/jazzy/issues about adding support ' \
563
- "for `#{declaration.type.kind}`."
561
+ 'https://github.com/realm/jazzy/issues about adding support ' \
562
+ "for `#{declaration.type.kind}`."
564
563
  end
565
564
 
566
565
  declaration.file = Pathname(doc['key.filepath']) if doc['key.filepath']
567
566
  declaration.usr = doc['key.usr']
567
+ declaration.type_usr = doc['key.typeusr']
568
568
  declaration.modulename = doc['key.modulename']
569
569
  declaration.name = documented_name
570
570
  declaration.mark = current_mark
571
571
  declaration.access_control_level =
572
572
  SourceDeclaration::AccessControlLevel.from_doc(doc)
573
- declaration.line = doc['key.doc.line']
574
- declaration.column = doc['key.doc.column']
573
+ declaration.line = doc['key.doc.line'] || doc['key.line']
574
+ declaration.column = doc['key.doc.column'] || doc['key.column']
575
575
  declaration.start_line = doc['key.parsed_scope.start']
576
576
  declaration.end_line = doc['key.parsed_scope.end']
577
577
  declaration.deprecated = doc['key.always_deprecated']
@@ -583,10 +583,12 @@ module Jazzy
583
583
  inherited_types.map { |type| type['key.name'] }.compact
584
584
 
585
585
  next unless make_doc_info(doc, declaration)
586
+
586
587
  declaration.children = make_substructure(doc, declaration)
587
588
  next if declaration.type.extension? &&
588
589
  declaration.children.empty? &&
589
590
  !declaration.inherited_types?
591
+
590
592
  declarations << declaration
591
593
  end
592
594
  declarations
@@ -598,6 +600,7 @@ module Jazzy
598
600
  def self.find_generic_requirements(parsed_declaration)
599
601
  parsed_declaration =~ /\bwhere\s+(.*)$/m
600
602
  return nil unless Regexp.last_match
603
+
601
604
  Regexp.last_match[1].gsub(/\s+/, ' ')
602
605
  end
603
606
 
@@ -619,6 +622,7 @@ module Jazzy
619
622
 
620
623
  def self.expand_extension(extension, name_parts, decls)
621
624
  return extension if name_parts.empty?
625
+
622
626
  name = name_parts.shift
623
627
  candidates = decls.select { |decl| decl.name == name }
624
628
  SourceDeclaration.new.tap do |decl|
@@ -644,8 +648,8 @@ module Jazzy
644
648
  # Merges redundant declarations when documenting podspecs.
645
649
  def self.deduplicate_declarations(declarations)
646
650
  duplicate_groups = declarations
647
- .group_by { |d| deduplication_key(d, declarations) }
648
- .values
651
+ .group_by { |d| deduplication_key(d, declarations) }
652
+ .values
649
653
 
650
654
  duplicate_groups.flat_map do |group|
651
655
  # Put extended type (if present) before extensions
@@ -688,15 +692,17 @@ module Jazzy
688
692
  end
689
693
 
690
694
  # rubocop:disable Metrics/MethodLength
695
+ # rubocop:disable Metrics/PerceivedComplexity
691
696
  # Merges all of the given types and extensions into a single document.
692
697
  def self.merge_declarations(decls)
693
698
  extensions, typedecls = decls.partition { |d| d.type.extension? }
694
699
 
695
700
  if typedecls.size > 1
701
+ info = typedecls
702
+ .map { |t| "#{t.type.name.downcase} #{t.name}" }
703
+ .join(', ')
696
704
  warn 'Found conflicting type declarations with the same name, which ' \
697
- 'may indicate a build issue or a bug in Jazzy: ' +
698
- typedecls.map { |t| "#{t.type.name.downcase} #{t.name}" }
699
- .join(', ')
705
+ "may indicate a build issue or a bug in Jazzy: #{info}"
700
706
  end
701
707
  typedecl = typedecls.first
702
708
 
@@ -712,13 +718,14 @@ module Jazzy
712
718
  end
713
719
 
714
720
  # Keep type-aliases separate from any extensions
715
- if typedecl && typedecl.type.swift_typealias?
721
+ if typedecl&.type&.swift_typealias?
716
722
  [merge_type_and_extensions(typedecls, []),
717
723
  merge_type_and_extensions([], extensions)]
718
724
  else
719
725
  merge_type_and_extensions(typedecls, extensions)
720
726
  end
721
727
  end
728
+ # rubocop:enable Metrics/PerceivedComplexity
722
729
  # rubocop:enable Metrics/MethodLength
723
730
 
724
731
  def self.merge_type_and_extensions(typedecls, extensions)
@@ -810,6 +817,7 @@ module Jazzy
810
817
  # (unless they already have a mark)
811
818
  def self.merge_objc_declaration_marks(typedecl, extensions)
812
819
  return unless typedecl.type.objc_class?
820
+
813
821
  extensions.each do |ext|
814
822
  _, category_name = ext.objc_category_name
815
823
  ext.children.each { |c| c.mark.name ||= category_name }
@@ -819,7 +827,8 @@ module Jazzy
819
827
  # For each extension to be merged, move any MARK from the extension
820
828
  # declaration down to the extension contents so it still shows up.
821
829
  def self.move_merged_extension_marks(decls)
822
- return unless to_be_merged = decls[1..-1]
830
+ return unless to_be_merged = decls[1..]
831
+
823
832
  to_be_merged.each do |ext|
824
833
  child = ext.children.first
825
834
  if child && child.mark.empty?
@@ -834,7 +843,7 @@ module Jazzy
834
843
  def self.merge_code_declaration(decls)
835
844
  first = decls.first
836
845
 
837
- declarations = decls[1..-1].select do |decl|
846
+ declarations = decls[1..].select do |decl|
838
847
  decl.type.swift_extension? &&
839
848
  (decl.other_inherited_types?(@inaccessible_protocols) ||
840
849
  (first.type.swift_extension? && decl.constrained_extension?))
@@ -879,9 +888,11 @@ module Jazzy
879
888
 
880
889
  def self.name_match(name_part, docs)
881
890
  return nil unless name_part
891
+
882
892
  wildcard_expansion = Regexp.escape(name_part)
883
- .gsub('\.\.\.', '[^)]*')
884
- .gsub(/<.*>/, '')
893
+ .gsub('\.\.\.', '[^)]*')
894
+ .gsub(/<.*>/, '')
895
+
885
896
  whole_name_pat = /\A#{wildcard_expansion}\Z/
886
897
  docs.find do |doc|
887
898
  whole_name_pat =~ doc.name
@@ -911,19 +922,26 @@ module Jazzy
911
922
  # - method signatures after they've been processed by the highlighter
912
923
  #
913
924
  # The `after_highlight` flag is used to differentiate between the two modes.
914
- def self.autolink_text(text, doc, root_decls, after_highlight = false)
925
+ #
926
+ # DocC link format - follow Xcode and don't display slash-separated parts.
927
+ # rubocop:disable Metrics/MethodLength
928
+ def self.autolink_text(text, doc, root_decls, after_highlight: false)
915
929
  text.autolink_block(doc.url, '[^\s]+', after_highlight) do |raw_name|
916
- parts = raw_name.sub(/^@/, '') # ignore for custom attribute ref
917
- .split(/(?<!\.)\.(?!\.)/) # dot with no neighboring dots
918
- .reject(&:empty?)
930
+ sym_name =
931
+ (raw_name[/^<doc:(.*)>$/, 1] || raw_name).sub(/(?<!^)-.+$/, '')
932
+
933
+ parts = sym_name
934
+ .sub(/^@/, '') # ignore for custom attribute ref
935
+ .split(%r{(?<!\.)[/.](?!\.)}) # dot or slash, but not '...'
936
+ .reject(&:empty?)
919
937
 
920
938
  # First dot-separated component can match any ancestor or top-level doc
921
939
  first_part = parts.shift
922
940
  name_root = ancestor_name_match(first_part, doc) ||
923
941
  name_match(first_part, root_decls)
924
942
 
925
- # Traverse children via subsequence components, if any
926
- name_traversal(parts, name_root)
943
+ # Traverse children via subsequent components, if any
944
+ [name_traversal(parts, name_root), sym_name.sub(%r{^.*/}, '')]
927
945
  end.autolink_block(doc.url, '[+-]\[\w+(?: ?\(\w+\))? [\w:]+\]',
928
946
  after_highlight) do |raw_name|
929
947
  match = raw_name.match(/([+-])\[(\w+(?: ?\(\w+\))?) ([\w:]+)\]/)
@@ -935,42 +953,50 @@ module Jazzy
935
953
 
936
954
  if name_root
937
955
  # Look up the verb in the subject’s children
938
- name_match(match[1] + match[3], name_root.children)
956
+ [name_match(match[1] + match[3], name_root.children), raw_name]
939
957
  end
940
958
  end.autolink_block(doc.url, '[+-]\w[\w:]*', after_highlight) do |raw_name|
941
- name_match(raw_name, doc.children)
959
+ [name_match(raw_name, doc.children), raw_name]
942
960
  end
943
961
  end
962
+ # rubocop:enable Metrics/MethodLength
944
963
 
945
964
  AUTOLINK_TEXT_FIELDS = %w[return
946
965
  abstract
947
966
  unavailable_message
948
967
  deprecation_message].freeze
949
968
 
969
+ def self.autolink_text_fields(doc, root_decls)
970
+ AUTOLINK_TEXT_FIELDS.each do |field|
971
+ if text = doc.send(field)
972
+ doc.send(field + '=', autolink_text(text, doc, root_decls))
973
+ end
974
+ end
975
+
976
+ (doc.parameters || []).each do |param|
977
+ param[:discussion] =
978
+ autolink_text(param[:discussion], doc, root_decls)
979
+ end
980
+ end
981
+
950
982
  AUTOLINK_HIGHLIGHT_FIELDS = %w[declaration
951
983
  other_language_declaration].freeze
952
984
 
985
+ def self.autolink_highlight_fields(doc, root_decls)
986
+ AUTOLINK_HIGHLIGHT_FIELDS.each do |field|
987
+ if text = doc.send(field)
988
+ doc.send(field + '=',
989
+ autolink_text(text, doc, root_decls, after_highlight: true))
990
+ end
991
+ end
992
+ end
993
+
953
994
  def self.autolink(docs, root_decls)
954
995
  @autolink_root_decls = root_decls
955
996
  docs.each do |doc|
956
997
  doc.children = autolink(doc.children, root_decls)
957
-
958
- AUTOLINK_TEXT_FIELDS.each do |field|
959
- if text = doc.send(field)
960
- doc.send(field + '=', autolink_text(text, doc, root_decls))
961
- end
962
- end
963
-
964
- AUTOLINK_HIGHLIGHT_FIELDS.each do |field|
965
- if text = doc.send(field)
966
- doc.send(field + '=', autolink_text(text, doc, root_decls, true))
967
- end
968
- end
969
-
970
- (doc.parameters || []).each do |param|
971
- param[:discussion] =
972
- autolink_text(param[:discussion], doc, root_decls)
973
- end
998
+ autolink_text_fields(doc, root_decls)
999
+ autolink_highlight_fields(doc, root_decls)
974
1000
  end
975
1001
  end
976
1002