jazzy 0.13.7 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/Tests.yml +2 -2
  3. data/.rubocop.yml +123 -24
  4. data/CHANGELOG.md +34 -0
  5. data/Dangerfile +11 -8
  6. data/Gemfile +3 -1
  7. data/Gemfile.lock +49 -34
  8. data/README.md +23 -11
  9. data/Rakefile +13 -12
  10. data/bin/jazzy +3 -2
  11. data/jazzy.gemspec +8 -6
  12. data/lib/jazzy.rb +2 -0
  13. data/lib/jazzy/config.rb +116 -69
  14. data/lib/jazzy/doc.rb +3 -1
  15. data/lib/jazzy/doc_builder.rb +63 -81
  16. data/lib/jazzy/docset_builder.rb +3 -1
  17. data/lib/jazzy/documentation_generator.rb +6 -2
  18. data/lib/jazzy/executable.rb +3 -0
  19. data/lib/jazzy/extensions/bitbucket/img/bitbucket.svg +11 -0
  20. data/lib/jazzy/{themes/apple/assets → extensions/github}/img/gh.png +0 -0
  21. data/lib/jazzy/extensions/gitlab/img/gitlab.svg +23 -0
  22. data/lib/jazzy/gem_version.rb +3 -1
  23. data/lib/jazzy/highlighter.rb +5 -3
  24. data/lib/jazzy/jazzy_markdown.rb +63 -30
  25. data/lib/jazzy/podspec_documenter.rb +14 -16
  26. data/lib/jazzy/search_builder.rb +4 -3
  27. data/lib/jazzy/source_declaration.rb +9 -3
  28. data/lib/jazzy/source_declaration/access_control_level.rb +7 -5
  29. data/lib/jazzy/source_declaration/type.rb +3 -1
  30. data/lib/jazzy/source_document.rb +8 -5
  31. data/lib/jazzy/source_host.rb +111 -0
  32. data/lib/jazzy/source_mark.rb +8 -6
  33. data/lib/jazzy/source_module.rb +6 -6
  34. data/lib/jazzy/sourcekitten.rb +98 -72
  35. data/lib/jazzy/stats.rb +4 -2
  36. data/lib/jazzy/symbol_graph.rb +15 -15
  37. data/lib/jazzy/symbol_graph/constraint.rb +5 -1
  38. data/lib/jazzy/symbol_graph/ext_node.rb +3 -1
  39. data/lib/jazzy/symbol_graph/graph.rb +13 -11
  40. data/lib/jazzy/symbol_graph/relationship.rb +3 -0
  41. data/lib/jazzy/symbol_graph/sym_node.rb +11 -6
  42. data/lib/jazzy/symbol_graph/symbol.rb +18 -15
  43. data/lib/jazzy/themes/apple/assets/css/highlight.css.scss +63 -59
  44. data/lib/jazzy/themes/apple/assets/css/jazzy.css.scss +5 -1
  45. data/lib/jazzy/themes/apple/assets/js/jazzy.js +4 -0
  46. data/lib/jazzy/themes/apple/assets/js/jazzy.search.js +4 -0
  47. data/lib/jazzy/themes/apple/templates/doc.mustache +3 -3
  48. data/lib/jazzy/themes/apple/templates/footer.mustache +1 -1
  49. data/lib/jazzy/themes/apple/templates/header.mustache +3 -3
  50. data/lib/jazzy/themes/apple/templates/task.mustache +3 -3
  51. data/lib/jazzy/themes/fullwidth/assets/css/highlight.css.scss +63 -59
  52. data/lib/jazzy/themes/fullwidth/assets/css/jazzy.css.scss +6 -2
  53. data/lib/jazzy/themes/fullwidth/assets/js/jazzy.js +4 -0
  54. data/lib/jazzy/themes/fullwidth/assets/js/jazzy.search.js +4 -0
  55. data/lib/jazzy/themes/fullwidth/templates/doc.mustache +3 -3
  56. data/lib/jazzy/themes/fullwidth/templates/footer.mustache +1 -1
  57. data/lib/jazzy/themes/fullwidth/templates/header.mustache +5 -5
  58. data/lib/jazzy/themes/fullwidth/templates/task.mustache +3 -3
  59. data/lib/jazzy/themes/jony/assets/css/highlight.css.scss +63 -59
  60. data/lib/jazzy/themes/jony/assets/css/jazzy.css.scss +5 -1
  61. data/lib/jazzy/themes/jony/assets/js/jazzy.js +4 -0
  62. data/lib/jazzy/themes/jony/templates/doc.mustache +3 -3
  63. data/lib/jazzy/themes/jony/templates/footer.mustache +1 -1
  64. data/lib/jazzy/themes/jony/templates/header.mustache +5 -5
  65. data/lib/jazzy/themes/jony/templates/task.mustache +3 -3
  66. data/spec/integration_spec.rb +39 -36
  67. data/spec/spec_helper.rb +3 -1
  68. data/spec/spec_helper/pre_flight.rb +2 -0
  69. metadata +27 -13
  70. data/lib/jazzy/themes/fullwidth/assets/img/gh.png +0 -0
  71. data/lib/jazzy/themes/jony/assets/img/gh.png +0 -0
  72. data/spec/sourcekitten_spec.rb +0 -6
data/README.md CHANGED
@@ -13,7 +13,7 @@ Instead of parsing your source files, `jazzy` hooks into [Clang][clang] and
13
13
  its comments for more accurate results. The output matches the look and feel
14
14
  of Apple’s official reference documentation, post WWDC 2014.
15
15
 
16
- Jazzy can also generate documentation from compiled swift modules [using their
16
+ Jazzy can also generate documentation from compiled Swift modules [using their
17
17
  symbol graph](#docs-from-swiftmodules-or-frameworks) instead of source code.
18
18
 
19
19
  ![Screenshot](images/screenshot.jpg)
@@ -60,8 +60,11 @@ all available options, run `jazzy --help config`.
60
60
  ### Supported documentation keywords
61
61
 
62
62
  Swift documentation is written in markdown and supports a number of special keywords.
63
- For a complete list and examples, see Erica Sadun's post on [*Swift header documentation in Xcode 7*](https://ericasadun.com/2015/06/14/swift-header-documentation-in-xcode-7/),
64
- her [book on Swift Documentation Markup](https://itunes.apple.com/us/book/swift-documentation-markup/id1049010423), and the [Xcode Markup Formatting Reference](https://developer.apple.com/library/content/documentation/Xcode/Reference/xcode_markup_formatting_ref/).
63
+ Here are some resources with tutorials and examples, starting with the most modern:
64
+ * Apple's [Writing Symbol Documentation in Your Source Files](https://developer.apple.com/documentation/xcode/writing-symbol-documentation-in-your-source-files) article.
65
+ * Apple's [Formatting Your Documentation Content](https://developer.apple.com/documentation/xcode/formatting-your-documentation-content) article.
66
+ * Apple's [Xcode Markup Formatting Reference](https://developer.apple.com/library/content/documentation/Xcode/Reference/xcode_markup_formatting_ref/).
67
+ * Erica Sadun's [Swift header documentation in Xcode 7](https://ericasadun.com/2015/06/14/swift-header-documentation-in-xcode-7/) post and her [book on Swift Documentation Markup](https://itunes.apple.com/us/book/swift-documentation-markup/id1049010423).
65
68
 
66
69
  For Objective-C documentation the same keywords are supported, but note that the format
67
70
  is slightly different. In Swift you would write `- returns:`, but in Objective-C you write `@return`. See Apple's [*HeaderDoc User Guide*](https://developer.apple.com/legacy/library/documentation/DeveloperTools/Conceptual/HeaderDoc/tags/tags.html) for more details. **Note: `jazzy` currently does not support _all_ Objective-C keywords listed in this document, only @param, @return, @warning, @see, and @note.**
@@ -76,6 +79,12 @@ backticks generates a link, for example:
76
79
  * \`[MyClass method1]\` - a link to an Objective-C method.
77
80
  * \`-[MyClass method2:param1]\` - a link to another Objective-C method.
78
81
 
82
+ Jazzy understands Apple's DocC-style links too, for example:
83
+ * \`\`MyClass/method(param1:)\`\` - a link to the documentation for that method
84
+ that appears as just `method(param1:)` in the rendered page.
85
+ * \`\`\<doc:method(_:)-e873\>\`\` - a link to a specific overload of `method(_:)`.
86
+ Jazzy can't tell which overload you intend and links to the first one.
87
+
79
88
  ### Math
80
89
 
81
90
  Jazzy can render math equations written in LaTeX embedded in your markdown:
@@ -108,8 +117,9 @@ jazzy \
108
117
  --clean \
109
118
  --author Realm \
110
119
  --author_url https://realm.io \
111
- --github_url https://github.com/realm/realm-cocoa \
112
- --github-file-prefix https://github.com/realm/realm-cocoa/tree/v0.96.2 \
120
+ --source-host github \
121
+ --source-host-url https://github.com/realm/realm-cocoa \
122
+ --source-host-files-url https://github.com/realm/realm-cocoa/tree/v0.96.2 \
113
123
  --module-version 0.96.2 \
114
124
  --build-tool-arguments -scheme,RealmSwift \
115
125
  --module RealmSwift \
@@ -150,8 +160,9 @@ jazzy \
150
160
  --clean \
151
161
  --author Realm \
152
162
  --author_url https://realm.io \
153
- --github_url https://github.com/realm/realm-cocoa \
154
- --github-file-prefix https://github.com/realm/realm-cocoa/tree/v2.2.0 \
163
+ --source-host github \
164
+ --source-host-url https://github.com/realm/realm-cocoa \
165
+ --source-host-files-url https://github.com/realm/realm-cocoa/tree/v2.2.0 \
155
166
  --module-version 2.2.0 \
156
167
  --build-tool-arguments --objc,Realm/Realm.h,--,-x,objective-c,-isysroot,$(xcrun --show-sdk-path),-I,$(pwd) \
157
168
  --module Realm \
@@ -167,8 +178,9 @@ jazzy \
167
178
  --objc \
168
179
  --author AFNetworking \
169
180
  --author_url http://afnetworking.com \
170
- --github_url https://github.com/AFNetworking/AFNetworking \
171
- --github-file-prefix https://github.com/AFNetworking/AFNetworking/tree/2.6.2 \
181
+ --source-host github \
182
+ --source-host-url https://github.com/AFNetworking/AFNetworking \
183
+ --source-host-files-url https://github.com/AFNetworking/AFNetworking/tree/2.6.2 \
172
184
  --module-version 2.6.2 \
173
185
  --umbrella-header AFNetworking/AFNetworking.h \
174
186
  --framework-root . \
@@ -227,7 +239,7 @@ Some examples:
227
239
  ```shell
228
240
  jazzy --module Combine --swift-build-tool symbolgraph
229
241
  --sdk iphoneos
230
- --build-tool-arguments --target,arm64-apple-ios14.1
242
+ --build-tool-arguments -target,arm64-apple-ios14.1
231
243
  ```
232
244
  The `target` is the LLVM target triple and needs to match the SDK. The
233
245
  default here is the target of the host system that Jazzy is running on,
@@ -249,7 +261,7 @@ Some examples:
249
261
  a `.swiftmodule`. Again the `--source-directory` is searched by default
250
262
  if `-F` is not passed in.
251
263
 
252
- See `swift symbolgraph-extract --help` for all the things you can pass via
264
+ See `swift symbolgraph-extract -help` for all the things you can pass via
253
265
  `--build-tool-arguments`: if your module has dependencies then you may need
254
266
  to add various search path options to let Swift load it.
255
267
 
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #-- Bootstrap --------------------------------------------------------------#
2
4
 
3
5
  desc 'Initializes your working copy to run the specs'
@@ -9,7 +11,7 @@ task :bootstrap do
9
11
  title 'Updating submodules'
10
12
  sh 'git submodule update --init --recursive'
11
13
  else
12
- $stderr.puts "\033[0;31m" \
14
+ warn "\033[0;31m" \
13
15
  "[!] Please install the bundler gem manually:\n" \
14
16
  ' $ [sudo] gem install bundler' \
15
17
  "\e[0m"
@@ -95,7 +97,7 @@ begin
95
97
 
96
98
  desc 'Runs RuboCop linter on Ruby files'
97
99
  task :rubocop do
98
- sh 'bundle exec rubocop lib spec'
100
+ sh 'bundle exec rubocop'
99
101
  end
100
102
 
101
103
  #-- SourceKitten -----------------------------------------------------------#
@@ -115,20 +117,20 @@ begin
115
117
  'jquery/dist/jquery.min.js' => [
116
118
  'themes/apple/assets/js',
117
119
  'themes/fullwidth/assets/js',
118
- 'themes/jony/assets/js'
120
+ 'themes/jony/assets/js',
119
121
  ],
120
122
  'lunr/lunr.min.js' => [
121
123
  'themes/apple/assets/js',
122
- 'themes/fullwidth/assets/js'
124
+ 'themes/fullwidth/assets/js',
123
125
  ],
124
126
  'corejs-typeahead/dist/typeahead.jquery.js' => [
125
127
  'themes/apple/assets/js',
126
- 'themes/fullwidth/assets/js'
128
+ 'themes/fullwidth/assets/js',
127
129
  ],
128
130
  'katex/dist/katex.min.css' => ['extensions/katex/css'],
129
131
  'katex/dist/fonts' => ['extensions/katex/css'],
130
- 'katex/dist/katex.min.js' => ['extensions/katex/js']
131
- }
132
+ 'katex/dist/katex.min.js' => ['extensions/katex/js'],
133
+ }.freeze
132
134
 
133
135
  desc 'Copies theme dependencies (`npm update/install` by hand first)'
134
136
  task :theme_deps do
@@ -138,15 +140,14 @@ begin
138
140
  end
139
141
  end
140
142
  end
141
-
142
143
  rescue LoadError, NameError => e
143
- $stderr.puts "\033[0;31m" \
144
+ warn "\033[0;31m" \
144
145
  '[!] Some Rake tasks haven been disabled because the environment' \
145
146
  ' couldn’t be loaded. Be sure to run `rake bootstrap` first.' \
146
147
  "\e[0m"
147
- $stderr.puts e.message
148
- $stderr.puts e.backtrace
149
- $stderr.puts
148
+ warn e.message
149
+ warn e.backtrace
150
+ warn ''
150
151
  end
151
152
 
152
153
  #-- Helpers ------------------------------------------------------------------#
data/bin/jazzy CHANGED
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  if $PROGRAM_NAME == __FILE__ && !ENV['JAZZY_NO_BUNDLER']
4
- ENV['BUNDLE_GEMFILE'] = File.expand_path('../../Gemfile', __FILE__)
5
+ ENV['BUNDLE_GEMFILE'] = File.expand_path('../Gemfile', __dir__)
5
6
  require 'rubygems'
6
7
  require 'bundler/setup'
7
- $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
8
+ $LOAD_PATH.unshift File.expand_path('../lib', __dir__)
8
9
  elsif ENV['JAZZY_NO_BUNDLER']
9
10
  require 'rubygems'
10
11
  gem 'jazzy'
data/jazzy.gemspec CHANGED
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  require File.expand_path('lib/jazzy/gem_version.rb', File.dirname(__FILE__))
4
5
 
@@ -9,25 +10,26 @@ Gem::Specification.new do |spec|
9
10
  spec.email = ['jp@jpsim.com']
10
11
  spec.summary = 'Soulful docs for Swift & Objective-C.'
11
12
  spec.description = 'Soulful docs for Swift & Objective-C. ' \
12
- "Run in your Xcode project's root directory for " \
13
- 'instant HTML docs.'
13
+ "Run in your Xcode project's root directory for " \
14
+ 'instant HTML docs.'
14
15
  spec.homepage = 'https://github.com/realm/jazzy'
15
16
  spec.license = 'MIT'
16
17
 
17
18
  spec.files = `git ls-files`.split($/)
18
- spec.executables << 'jazzy'
19
+ spec.executables << 'jazzy'
19
20
 
20
21
  spec.add_runtime_dependency 'cocoapods', '~> 1.5'
21
22
  spec.add_runtime_dependency 'mustache', '~> 1.1'
22
- spec.add_runtime_dependency 'open4'
23
+ spec.add_runtime_dependency 'open4', '~> 1.3'
23
24
  spec.add_runtime_dependency 'redcarpet', '~> 3.4'
25
+ spec.add_runtime_dependency 'rexml', '~> 3.2'
24
26
  spec.add_runtime_dependency 'rouge', ['>= 2.0.6', '< 4.0']
25
27
  spec.add_runtime_dependency 'sassc', '~> 2.1'
26
28
  spec.add_runtime_dependency 'sqlite3', '~> 1.3'
27
29
  spec.add_runtime_dependency 'xcinvoke', '~> 0.3.0'
28
30
 
29
- spec.add_development_dependency 'bundler', '~> 1.7'
31
+ spec.add_development_dependency 'bundler', '~> 2.1'
30
32
  spec.add_development_dependency 'rake', '~> 13.0'
31
33
 
32
- spec.required_ruby_version = '>= 2.0.0'
34
+ spec.required_ruby_version = '>= 2.6.3'
33
35
  end
data/lib/jazzy.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'jazzy/config'
2
4
  require 'jazzy/doc_builder'
3
5
 
data/lib/jazzy/config.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'optparse'
2
4
  require 'pathname'
3
5
  require 'uri'
@@ -8,7 +10,7 @@ require 'jazzy/source_declaration/access_control_level'
8
10
  module Jazzy
9
11
  # rubocop:disable Metrics/ClassLength
10
12
  class Config
11
- # rubocop:disable Style/AccessorMethodName
13
+ # rubocop:disable Naming/AccessorMethodName
12
14
  class Attribute
13
15
  attr_reader :name, :description, :command_line, :config_file_key,
14
16
  :default, :parse
@@ -50,6 +52,7 @@ module Jazzy
50
52
 
51
53
  def attach_to_option_parser(config, opt)
52
54
  return if command_line.empty?
55
+
53
56
  opt.on(*command_line, *description) do |val|
54
57
  set(config, val)
55
58
  end
@@ -70,11 +73,12 @@ module Jazzy
70
73
  end
71
74
  end
72
75
  end
73
- # rubocop:enable Style/AccessorMethodName
76
+ # rubocop:enable Naming/AccessorMethodName
74
77
 
75
78
  def self.config_attr(name, **opts)
76
79
  attr_accessor name
77
80
  attr_accessor "#{name}_configured"
81
+
78
82
  @all_config_attrs ||= []
79
83
  @all_config_attrs << Attribute.new(name, **opts)
80
84
  end
@@ -112,7 +116,7 @@ module Jazzy
112
116
 
113
117
  # ──────── Build ────────
114
118
 
115
- # rubocop:disable Layout/AlignParameters
119
+ # rubocop:disable Layout/ArgumentAlignment
116
120
 
117
121
  config_attr :output,
118
122
  description: 'Folder to output the HTML docs to',
@@ -124,7 +128,7 @@ module Jazzy
124
128
  command_line: ['-c', '--[no-]clean'],
125
129
  description: ['Delete contents of output directory before running. ',
126
130
  'WARNING: If --output is set to ~/Desktop, this will '\
127
- 'delete the ~/Desktop directory.'],
131
+ 'delete the ~/Desktop directory.'],
128
132
  default: false
129
133
 
130
134
  config_attr :objc_mode,
@@ -150,10 +154,10 @@ module Jazzy
150
154
  config_attr :hide_declarations,
151
155
  command_line: '--hide-declarations [objc|swift] ',
152
156
  description: 'Hide declarations in the specified language. Given that ' \
153
- 'generating Swift docs only generates Swift declarations, ' \
154
- 'this is useful for hiding a specific interface for ' \
155
- 'either Objective-C or mixed Objective-C and Swift ' \
156
- 'projects.',
157
+ 'generating Swift docs only generates Swift declarations, ' \
158
+ 'this is useful for hiding a specific interface for ' \
159
+ 'either Objective-C or mixed Objective-C and Swift ' \
160
+ 'projects.',
157
161
  default: ''
158
162
 
159
163
  config_attr :keep_property_attributes,
@@ -170,7 +174,7 @@ module Jazzy
170
174
  config_attr :build_tool_arguments,
171
175
  command_line: ['-b', '--build-tool-arguments arg1,arg2,…argN', Array],
172
176
  description: 'Arguments to forward to xcodebuild, swift build, or ' \
173
- 'sourcekitten.',
177
+ 'sourcekitten.',
174
178
  default: []
175
179
 
176
180
  alias_config_attr :xcodebuild_arguments, :build_tool_arguments,
@@ -192,7 +196,7 @@ module Jazzy
192
196
  config_attr :excluded_files,
193
197
  command_line: ['-e', '--exclude filepath1,filepath2,…filepathN', Array],
194
198
  description: 'Source file pathnames to be excluded from documentation. '\
195
- 'Supports wildcards.',
199
+ 'Supports wildcards.',
196
200
  default: [],
197
201
  parse: ->(files) do
198
202
  Array(files).map { |f| expand_glob_path(f).to_s }
@@ -201,7 +205,7 @@ module Jazzy
201
205
  config_attr :included_files,
202
206
  command_line: ['-i', '--include filepath1,filepath2,…filepathN', Array],
203
207
  description: 'Source file pathnames to be included in documentation. '\
204
- 'Supports wildcards.',
208
+ 'Supports wildcards.',
205
209
  default: [],
206
210
  parse: ->(files) do
207
211
  Array(files).map { |f| expand_glob_path(f).to_s }
@@ -213,8 +217,9 @@ module Jazzy
213
217
  parse: ->(v) do
214
218
  if v.to_s.empty?
215
219
  nil
220
+ elsif v.to_f < 2
221
+ raise 'jazzy only supports Swift 2.0 or later.'
216
222
  else
217
- raise 'jazzy only supports Swift 2.0 or later.' if v.to_f < 2
218
223
  v
219
224
  end
220
225
  end
@@ -224,13 +229,14 @@ module Jazzy
224
229
  config_attr :swift_build_tool,
225
230
  command_line: "--swift-build-tool #{SWIFT_BUILD_TOOLS.join(' | ')}",
226
231
  description: 'Control whether Jazzy uses Swift Package Manager, '\
227
- 'xcodebuild, or swift-symbolgraph to build the module '\
228
- 'to be documented. By default it uses xcodebuild if '\
229
- 'there is a .xcodeproj file in the source directory.',
232
+ 'xcodebuild, or swift-symbolgraph to build the module '\
233
+ 'to be documented. By default it uses xcodebuild if '\
234
+ 'there is a .xcodeproj file in the source directory.',
230
235
  parse: ->(tool) do
231
236
  return tool.to_sym if SWIFT_BUILD_TOOLS.include?(tool)
237
+
232
238
  raise "Unsupported swift_build_tool #{tool}, "\
233
- "supported values: #{SWIFT_BUILD_TOOLS.join(', ')}"
239
+ "supported values: #{SWIFT_BUILD_TOOLS.join(', ')}"
234
240
  end
235
241
 
236
242
  # ──────── Metadata ────────
@@ -254,13 +260,13 @@ module Jazzy
254
260
  config_attr :version,
255
261
  command_line: '--module-version VERSION',
256
262
  description: 'Version string to use as part of the default docs '\
257
- 'title and inside the docset.',
263
+ 'title and inside the docset.',
258
264
  default: '1.0'
259
265
 
260
266
  config_attr :title,
261
267
  command_line: '--title TITLE',
262
268
  description: 'Title to display at the top of each page, overriding the '\
263
- 'default generated from module name and version.',
269
+ 'default generated from module name and version.',
264
270
  default: ''
265
271
 
266
272
  config_attr :copyright,
@@ -285,16 +291,16 @@ module Jazzy
285
291
  config_attr :podspec,
286
292
  command_line: '--podspec FILEPATH',
287
293
  description: 'A CocoaPods Podspec that describes the Swift library to '\
288
- 'document',
294
+ 'document',
289
295
  parse: ->(ps) { PodspecDocumenter.create_podspec(Pathname(ps)) if ps },
290
296
  default: Dir['*.podspec{,.json}'].first
291
297
 
292
298
  config_attr :pod_sources,
293
299
  command_line: ['--pod-sources url1,url2,…urlN', Array],
294
300
  description: 'A list of sources to find pod dependencies. Used only '\
295
- 'with --podspec when the podspec contains references to '\
296
- 'privately hosted pods. You must include the default pod '\
297
- 'source if public pods are also used.',
301
+ 'with --podspec when the podspec contains references to '\
302
+ 'privately hosted pods. You must include the default pod '\
303
+ 'source if public pods are also used.',
298
304
  default: []
299
305
 
300
306
  config_attr :docset_icon,
@@ -316,30 +322,56 @@ module Jazzy
316
322
  config_attr :dash_url,
317
323
  command_line: ['-d', '--dash_url URL'],
318
324
  description: 'Location of the dash XML feed '\
319
- 'e.g. https://realm.io/docsets/realm.xml)',
325
+ 'e.g. https://realm.io/docsets/realm.xml)',
320
326
  parse: ->(d) { URI(d) }
321
327
 
322
- config_attr :github_url,
323
- command_line: ['-g', '--github_url URL'],
324
- description: 'GitHub URL of this project (e.g. '\
325
- 'https://github.com/realm/realm-cocoa)',
328
+ SOURCE_HOSTS = %w[github gitlab bitbucket].freeze
329
+
330
+ config_attr :source_host,
331
+ command_line: "--source-host #{SOURCE_HOSTS.join(' | ')}",
332
+ description: ['The source-code hosting site to be linked from documentation.',
333
+ 'This setting affects the logo image and link format.',
334
+ "Default: 'github'"],
335
+ default: 'github',
336
+ parse: ->(host) do
337
+ return host.to_sym if SOURCE_HOSTS.include?(host)
338
+
339
+ raise "Unsupported source_host '#{host}', "\
340
+ "supported values: #{SOURCE_HOSTS.join(', ')}"
341
+ end
342
+
343
+ config_attr :source_host_url,
344
+ command_line: ['--source-host-url URL'],
345
+ description: ["URL to link from the source host's logo.",
346
+ 'For example https://github.com/realm/realm-cocoa'],
326
347
  parse: ->(g) { URI(g) }
327
348
 
328
- config_attr :github_file_prefix,
349
+ alias_config_attr :github_url, :source_host_url,
350
+ command_line: ['-g', '--github_url URL'],
351
+ description: 'Back-compatibility alias for source_host_url.'
352
+
353
+ config_attr :source_host_files_url,
354
+ command_line: '--source-host-files-url PREFIX',
355
+ description: [
356
+ "The base URL on the source host of the project's files, to link "\
357
+ 'from individual declarations.',
358
+ 'For example https://github.com/realm/realm-cocoa/tree/v0.87.1',
359
+ ]
360
+
361
+ alias_config_attr :github_file_prefix, :source_host_files_url,
329
362
  command_line: '--github-file-prefix PREFIX',
330
- description: 'GitHub URL file prefix of this project (e.g. '\
331
- 'https://github.com/realm/realm-cocoa/tree/v0.87.1)'
363
+ description: 'Back-compatibility alias for source_host_files_url'
332
364
 
333
365
  config_attr :docset_playground_url,
334
366
  command_line: '--docset-playground-url URL',
335
367
  description: 'URL of an interactive playground to demonstrate the '\
336
- 'framework, linked to from the docset.'
368
+ 'framework, linked to from the docset.'
337
369
 
338
370
  # ──────── Doc generation options ────────
339
371
  config_attr :disable_search,
340
372
  command_line: '--disable-search',
341
- description: ['Avoid generating a search index. '\
342
- 'Search is available in some themes.'],
373
+ description: 'Avoid generating a search index. '\
374
+ 'Search is available in some themes.',
343
375
  default: false
344
376
 
345
377
  config_attr :skip_documentation,
@@ -359,7 +391,7 @@ module Jazzy
359
391
  config_attr :skip_undocumented,
360
392
  command_line: '--[no-]skip-undocumented',
361
393
  description: "Don't document declarations that have no documentation "\
362
- 'comments.',
394
+ 'comments.',
363
395
  default: false
364
396
 
365
397
  config_attr :hide_documentation_coverage,
@@ -368,22 +400,22 @@ module Jazzy
368
400
  default: false
369
401
 
370
402
  config_attr :custom_categories,
371
- description: ['Custom navigation categories to replace the standard '\
372
- 'Classes, Protocols, etc.”', 'Types not explicitly named '\
373
- 'in a custom category appear in generic groups at the end.',
374
- 'Example: https://git.io/v4Bcp'],
403
+ description: 'Custom navigation categories to replace the standard '\
404
+ "'Classes', 'Protocols', etc. Types not explicitly named "\
405
+ 'in a custom category appear in generic groups at the '\
406
+ 'end. Example: https://git.io/v4Bcp',
375
407
  default: []
376
408
 
377
409
  config_attr :custom_categories_unlisted_prefix,
378
410
  description: "Prefix for navigation section names that aren't "\
379
- 'explicitly listed in `custom_categories`.',
411
+ 'explicitly listed in `custom_categories`.',
380
412
  default: 'Other '
381
413
 
382
414
  config_attr :hide_unlisted_documentation,
383
415
  command_line: '--[no-]hide-unlisted-documentation',
384
416
  description: "Don't include documentation in the sidebar from the "\
385
- "`documentation` config value that aren't explicitly "\
386
- 'listed in `custom_categories`.',
417
+ "`documentation` config value that aren't explicitly "\
418
+ 'listed in `custom_categories`.',
387
419
  default: false
388
420
 
389
421
  config_attr :custom_head,
@@ -391,15 +423,15 @@ module Jazzy
391
423
  description: 'Custom HTML to inject into <head></head>.',
392
424
  default: ''
393
425
 
394
- BUILTIN_THEME_DIR = Pathname(__FILE__).parent + 'themes'
426
+ BUILTIN_THEME_DIR = Pathname(__dir__) + 'themes'
395
427
  BUILTIN_THEMES = BUILTIN_THEME_DIR.children(false).map(&:to_s)
396
428
 
397
429
  config_attr :theme_directory,
398
430
  command_line: "--theme [#{BUILTIN_THEMES.join(' | ')} | DIRPATH]",
399
431
  description: "Which theme to use. Specify either 'apple' (default), "\
400
- 'one of the other built-in theme names, or the path to '\
401
- 'your mustache templates and other assets for a custom '\
402
- 'theme.',
432
+ 'one of the other built-in theme names, or the path to '\
433
+ 'your mustache templates and other assets for a custom '\
434
+ 'theme.',
403
435
  default: 'apple',
404
436
  parse: ->(t) do
405
437
  if BUILTIN_THEMES.include?(t)
@@ -412,9 +444,9 @@ module Jazzy
412
444
  config_attr :use_safe_filenames,
413
445
  command_line: '--use-safe-filenames',
414
446
  description: 'Replace unsafe characters in filenames with an encoded '\
415
- 'representation. This will reduce human readability of '\
416
- 'some URLs, but may be necessary for projects that '\
417
- 'expose filename-unfriendly functions such as /(_:_:)',
447
+ 'representation. This will reduce human readability of '\
448
+ 'some URLs, but may be necessary for projects that '\
449
+ 'expose filename-unfriendly functions such as /(_:_:)',
418
450
  default: false
419
451
 
420
452
  config_attr :template_directory,
@@ -434,17 +466,17 @@ module Jazzy
434
466
  config_attr :undocumented_text,
435
467
  command_line: '--undocumented-text UNDOCUMENTED_TEXT',
436
468
  description: 'Default text for undocumented symbols. The default '\
437
- 'is "Undocumented", put "" if no text is required',
469
+ 'is "Undocumented", put "" if no text is required',
438
470
  default: 'Undocumented'
439
471
 
440
472
  config_attr :separate_global_declarations,
441
473
  command_line: '--[no-]separate-global-declarations',
442
474
  description: 'Create separate pages for all global declarations '\
443
- "(classes, structures, enums etc.) even if they don't "\
444
- 'have children.',
475
+ "(classes, structures, enums etc.) even if they don't "\
476
+ 'have children.',
445
477
  default: false
446
478
 
447
- # rubocop:enable Style/AlignParameter
479
+ # rubocop:enable Layout/ArgumentAlignment
448
480
 
449
481
  def initialize
450
482
  self.class.all_config_attrs.each do |attr|
@@ -457,7 +489,6 @@ module Jazzy
457
489
  Doc.template_path = theme_directory + 'templates'
458
490
  end
459
491
 
460
- # rubocop:disable Metrics/MethodLength
461
492
  def self.parse!
462
493
  config = new
463
494
  config.parse_command_line
@@ -471,9 +502,16 @@ module Jazzy
471
502
  )
472
503
  end
473
504
 
505
+ config.validate
506
+
474
507
  config
475
508
  end
476
509
 
510
+ def warning(message)
511
+ warn "WARNING: #{message}"
512
+ end
513
+
514
+ # rubocop:disable Metrics/MethodLength
477
515
  def parse_command_line
478
516
  OptionParser.new do |opt|
479
517
  opt.banner = 'Usage: jazzy'
@@ -485,7 +523,7 @@ module Jazzy
485
523
  end
486
524
 
487
525
  opt.on('-v', '--version', 'Print version number') do
488
- puts 'jazzy version: ' + Jazzy::VERSION
526
+ puts "jazzy version: #{Jazzy::VERSION}"
489
527
  exit
490
528
  end
491
529
 
@@ -504,6 +542,10 @@ module Jazzy
504
542
  exit
505
543
  end
506
544
  end.parse!
545
+
546
+ unless ARGV.empty?
547
+ warning "Leftover unused command-line text: #{ARGV}"
548
+ end
507
549
  end
508
550
 
509
551
  def parse_config_file
@@ -521,13 +563,12 @@ module Jazzy
521
563
 
522
564
  config_file.each do |key, value|
523
565
  unless attr = attrs_by_conf_key[key]
524
- message = "WARNING: Unknown config file attribute #{key.inspect}"
566
+ message = "Unknown config file attribute #{key.inspect}"
525
567
  if matching_name = attrs_by_name[key]
526
- message << ' (Did you mean '
527
- message << matching_name.first.config_file_key.inspect
528
- message << '?)'
568
+ message +=
569
+ " (Did you mean #{matching_name.first.config_file_key.inspect}?)"
529
570
  end
530
- warn message
571
+ warning message
531
572
  next
532
573
  end
533
574
 
@@ -537,6 +578,17 @@ module Jazzy
537
578
  self.base_path = nil
538
579
  end
539
580
 
581
+ def validate
582
+ if source_host_configured &&
583
+ source_host_url.nil? &&
584
+ source_host_files_url.nil?
585
+ warning 'Option `source_host` is set but has no effect without either '\
586
+ '`source_host_url` or `source_host_files_url`.'
587
+ end
588
+ end
589
+
590
+ # rubocop:enable Metrics/MethodLength
591
+
540
592
  def locate_config_file
541
593
  return config_file if config_file
542
594
 
@@ -550,15 +602,10 @@ module Jazzy
550
602
 
551
603
  def read_config_file(file)
552
604
  case File.extname(file)
553
- when '.json' then JSON.parse(File.read(file))
554
- when '.yaml', '.yml' then
555
- if YAML.respond_to?('safe_load') # ruby >= 2.1.0
556
- YAML.safe_load(File.read(file))
557
- else
558
- # rubocop:disable Security/YAMLLoad
559
- YAML.load(File.read(file))
560
- # rubocop:enable Security/YAMLLoad
561
- end
605
+ when '.json'
606
+ JSON.parse(File.read(file))
607
+ when '.yaml', '.yml'
608
+ YAML.safe_load(File.read(file))
562
609
  else raise "Config file must be .yaml or .json, but got #{file.inspect}"
563
610
  end
564
611
  end
@@ -575,7 +622,7 @@ module Jazzy
575
622
 
576
623
  The config file can be in YAML or JSON format. Available options are:
577
624
 
578
- _EOS_
625
+ _EOS_
579
626
  .gsub(/^ +/, '')
580
627
 
581
628
  print_option_help