jazzy 0.13.7 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
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/lib/jazzy/doc.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'date'
2
4
  require 'pathname'
3
5
  require 'mustache'
@@ -18,7 +20,7 @@ module Jazzy
18
20
  date = ENV['JAZZY_FAKE_DATE'] || DateTime.now.strftime('%Y-%m-%d')
19
21
  year = date[0..3]
20
22
  "© #{year} [#{config.author_name}](#{config.author_url}). " \
21
- "All rights reserved. (Last updated: #{date})"
23
+ "All rights reserved. (Last updated: #{date})"
22
24
  )
23
25
  Markdown.render_copyright(copyright).chomp
24
26
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'fileutils'
2
4
  require 'mustache'
3
5
  require 'pathname'
@@ -51,8 +53,8 @@ module Jazzy
51
53
 
52
54
  def self.children_for_doc(doc)
53
55
  doc.children
54
- .sort_by { |c| [c.nav_order, c.name, c.usr || ''] }
55
- .flat_map do |child|
56
+ .sort_by { |c| [c.nav_order, c.name, c.usr || ''] }
57
+ .flat_map do |child|
56
58
  # FIXME: include arbitrarily nested extensible types
57
59
  [{ name: child.name, url: child.url }] +
58
60
  Array(child.children.select do |sub_child|
@@ -68,8 +70,7 @@ module Jazzy
68
70
  # @return [SourceModule] the documented source module
69
71
  def self.build(options)
70
72
  if options.sourcekitten_sourcefile_configured
71
- stdout = '[' + options.sourcekitten_sourcefile.map(&:read)
72
- .join(',') + ']'
73
+ stdout = "[#{options.sourcekitten_sourcefile.map(&:read).join(',')}]"
73
74
  elsif options.podspec_configured
74
75
  pod_documenter = PodspecDocumenter.new(options.podspec)
75
76
  stdout = pod_documenter.sourcekitten_output(options)
@@ -104,6 +105,7 @@ module Jazzy
104
105
  def self.each_doc(output_dir, docs, &block)
105
106
  docs.each do |doc|
106
107
  next unless doc.render_as_page?
108
+
107
109
  # Filepath is relative to documentation root:
108
110
  path = output_dir + doc.filepath
109
111
  block.call(doc, path)
@@ -132,8 +134,8 @@ module Jazzy
132
134
  SearchBuilder.build(source_module, output_dir)
133
135
  end
134
136
 
135
- copy_assets(output_dir)
136
- copy_extensions(output_dir)
137
+ copy_extensions(source_module, output_dir)
138
+ copy_theme_assets(output_dir)
137
139
 
138
140
  DocsetBuilder.new(output_dir, source_module).build!
139
141
 
@@ -170,7 +172,7 @@ module Jazzy
170
172
 
171
173
  def self.relative_path_if_inside(path, base_path)
172
174
  relative = path.relative_path_from(base_path)
173
- if relative.to_path =~ %r{/^..(\/|$)/}
175
+ if relative.to_path =~ %r{/^..(/|$)/}
174
176
  path
175
177
  else
176
178
  relative
@@ -206,7 +208,7 @@ module Jazzy
206
208
  end
207
209
  end
208
210
 
209
- def self.copy_assets(destination)
211
+ def self.copy_theme_assets(destination)
210
212
  assets_directory = Config.instance.theme_directory + 'assets'
211
213
  FileUtils.cp_r(assets_directory.children, destination)
212
214
  Pathname.glob(destination + 'css/**/*.scss').each do |scss|
@@ -217,12 +219,15 @@ module Jazzy
217
219
  end
218
220
  end
219
221
 
220
- def self.copy_extensions(destination)
222
+ def self.copy_extensions(source_module, destination)
223
+ if source_host = source_module.host&.extension
224
+ copy_extension(source_host, destination)
225
+ end
221
226
  copy_extension('katex', destination) if Markdown.has_math
222
227
  end
223
228
 
224
229
  def self.copy_extension(name, destination)
225
- ext_directory = Pathname(__FILE__).parent + 'extensions/' + name
230
+ ext_directory = Pathname(__dir__) / 'extensions' / name
226
231
  FileUtils.cp_r(ext_directory.children, destination)
227
232
  end
228
233
 
@@ -231,26 +236,37 @@ module Jazzy
231
236
  SourceKitten.autolink_document(html, doc_model)
232
237
  end
233
238
 
239
+ # Build Mustache document - common fields between page types
240
+ def self.new_document(source_module, doc_model)
241
+ Doc.new.tap do |doc|
242
+ doc[:custom_head] = Config.instance.custom_head
243
+ doc[:disable_search] = Config.instance.disable_search
244
+ doc[:doc_coverage] = source_module.doc_coverage unless
245
+ Config.instance.hide_documentation_coverage
246
+ doc[:structure] = source_module.doc_structure
247
+ doc[:module_name] = source_module.name
248
+ doc[:author_name] = source_module.author_name
249
+ if source_host = source_module.host
250
+ doc[:source_host_name] = source_host.name
251
+ doc[:source_host_url] = source_host.url
252
+ doc[:source_host_image] = source_host.image
253
+ doc[:source_host_item_url] = source_host.item_url(doc_model)
254
+ doc[:github_url] = doc[:source_host_url]
255
+ doc[:github_token_url] = doc[:source_host_item_url]
256
+ end
257
+ doc[:dash_url] = source_module.dash_url
258
+ end
259
+ end
260
+
234
261
  # Build Mustache document from a markdown source file
235
- # @param [Config] options Build options
262
+ # @param [SourceModule] module-wide settings
236
263
  # @param [Hash] doc_model Parsed doc. @see SourceKitten.parse
237
264
  # @param [String] path_to_root
238
- # @param [Array] doc_structure doc structure comprised of section names and
239
- # child names and URLs. @see doc_structure_for_docs
240
265
  def self.document_markdown(source_module, doc_model, path_to_root)
241
- doc = Doc.new # Mustache model instance
266
+ doc = new_document(source_module, doc_model)
242
267
  name = doc_model.name == 'index' ? source_module.name : doc_model.name
243
268
  doc[:name] = name
244
269
  doc[:overview] = render(doc_model, doc_model.content(source_module))
245
- doc[:custom_head] = Config.instance.custom_head
246
- doc[:disable_search] = Config.instance.disable_search
247
- doc[:doc_coverage] = source_module.doc_coverage unless
248
- Config.instance.hide_documentation_coverage
249
- doc[:structure] = source_module.doc_structure
250
- doc[:module_name] = source_module.name
251
- doc[:author_name] = source_module.author_name
252
- doc[:github_url] = source_module.github_url
253
- doc[:dash_url] = source_module.dash_url
254
270
  doc[:path_to_root] = path_to_root
255
271
  doc[:hide_name] = true
256
272
  doc.render.gsub(ELIDED_AUTOLINK_TOKEN, path_to_root)
@@ -324,30 +340,6 @@ module Jazzy
324
340
  end
325
341
  # rubocop:enable Metrics/MethodLength
326
342
 
327
- def self.should_link_to_github(file)
328
- return unless file
329
- file = file.realpath.to_path
330
- source_directory = Config.instance.source_directory.to_path
331
- file.start_with?(source_directory)
332
- end
333
-
334
- # Construct Github token URL
335
- # @param [Hash] item Parsed doc child item
336
- # @param [Config] options Build options
337
- def self.gh_token_url(item, source_module)
338
- return unless github_prefix = source_module.github_file_prefix
339
- return unless should_link_to_github(item.file)
340
- gh_line = if item.start_line && (item.start_line != item.end_line)
341
- "#L#{item.start_line}-L#{item.end_line}"
342
- else
343
- "#L#{item.line}"
344
- end
345
- relative_file_path = item.file.realpath.relative_path_from(
346
- source_module.root_path,
347
- )
348
- "#{github_prefix}/#{relative_file_path}#{gh_line}"
349
- end
350
-
351
343
  # Build mustache item for a top-level doc
352
344
  # @param [Hash] item Parsed doc child item
353
345
  # @param [Config] options Build options
@@ -355,27 +347,29 @@ module Jazzy
355
347
  def self.render_item(item, source_module)
356
348
  # Combine abstract and discussion into abstract
357
349
  abstract = (item.abstract || '') + (item.discussion || '')
350
+ source_host_item_url = source_module.host&.item_url(item)
358
351
  {
359
- name: item.name,
360
- name_html: item.name.gsub(':', ':<wbr>'),
361
- abstract: abstract,
362
- declaration: item.display_declaration,
363
- language: item.display_language,
352
+ name: item.name,
353
+ name_html: item.name.gsub(':', ':<wbr>'),
354
+ abstract: abstract,
355
+ declaration: item.display_declaration,
356
+ language: item.display_language,
364
357
  other_language_declaration: item.display_other_language_declaration,
365
- usr: item.usr,
366
- dash_type: item.type.dash_type,
367
- github_token_url: gh_token_url(item, source_module),
368
- default_impl_abstract: item.default_impl_abstract,
369
- from_protocol_extension: item.from_protocol_extension,
370
- return: item.return,
371
- parameters: (item.parameters if item.parameters.any?),
372
- url: (item.url if item.render_as_page?),
373
- start_line: item.start_line,
374
- end_line: item.end_line,
375
- direct_link: item.omit_content_from_parent?,
376
- deprecation_message: item.deprecation_message,
377
- unavailable_message: item.unavailable_message,
378
- usage_discouraged: item.usage_discouraged?,
358
+ usr: item.usr,
359
+ dash_type: item.type.dash_type,
360
+ source_host_item_url: source_host_item_url,
361
+ github_token_url: source_host_item_url,
362
+ default_impl_abstract: item.default_impl_abstract,
363
+ from_protocol_extension: item.from_protocol_extension,
364
+ return: item.return,
365
+ parameters: (item.parameters if item.parameters.any?),
366
+ url: (item.url if item.render_as_page?),
367
+ start_line: item.start_line,
368
+ end_line: item.end_line,
369
+ direct_link: item.omit_content_from_parent?,
370
+ deprecation_message: item.deprecation_message,
371
+ unavailable_message: item.unavailable_message,
372
+ usage_discouraged: item.usage_discouraged?,
379
373
  }
380
374
  end
381
375
  # rubocop:enable Metrics/MethodLength
@@ -412,12 +406,10 @@ module Jazzy
412
406
  end
413
407
 
414
408
  # rubocop:disable Metrics/MethodLength
415
- # Build Mustache document from single parsed doc
416
- # @param [Config] options Build options
409
+ # Build Mustache document from single parsed decl
410
+ # @param [SourceModule] module-wide settings
417
411
  # @param [Hash] doc_model Parsed doc. @see SourceKitten.parse
418
412
  # @param [String] path_to_root
419
- # @param [Array] doc_structure doc structure comprised of section names and
420
- # child names and URLs. @see doc_structure_for_docs
421
413
  def self.document(source_module, doc_model, path_to_root)
422
414
  if doc_model.type.markdown?
423
415
  return document_markdown(source_module, doc_model, path_to_root)
@@ -429,11 +421,7 @@ module Jazzy
429
421
  overview = render(doc_model, alternative_abstract) + overview
430
422
  end
431
423
 
432
- doc = Doc.new # Mustache model instance
433
- doc[:custom_head] = Config.instance.custom_head
434
- doc[:disable_search] = Config.instance.disable_search
435
- doc[:doc_coverage] = source_module.doc_coverage unless
436
- Config.instance.hide_documentation_coverage
424
+ doc = new_document(source_module, doc_model)
437
425
  doc[:name] = doc_model.name
438
426
  doc[:kind] = doc_model.type.name
439
427
  doc[:dash_type] = doc_model.type.dash_type
@@ -444,13 +432,7 @@ module Jazzy
444
432
  doc[:overview] = overview
445
433
  doc[:parameters] = doc_model.parameters
446
434
  doc[:return] = doc_model.return
447
- doc[:structure] = source_module.doc_structure
448
435
  doc[:tasks] = render_tasks(source_module, doc_model.children)
449
- doc[:module_name] = source_module.name
450
- doc[:author_name] = source_module.author_name
451
- doc[:github_url] = source_module.github_url
452
- doc[:github_token_url] = gh_token_url(doc_model, source_module)
453
- doc[:dash_url] = source_module.dash_url
454
436
  doc[:path_to_root] = path_to_root
455
437
  doc[:deprecation_message] = doc_model.deprecation_message
456
438
  doc[:unavailable_message] = doc_model.unavailable_message
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'mustache'
2
4
  require 'sqlite3'
3
5
 
@@ -89,7 +91,7 @@ module Jazzy
89
91
  (output_dir + "#{source_module.name}.xml").open('w') do |xml|
90
92
  url = URI.join(config.root_url, "docsets/#{source_module.name}.tgz")
91
93
  xml << "<entry><version>#{config.version}</version><url>#{url}" \
92
- "</url></entry>\n"
94
+ "</url></entry>\n"
93
95
  end
94
96
  end
95
97
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'pathname'
2
4
 
3
5
  require 'jazzy/jazzy_markdown'
@@ -12,19 +14,21 @@ module Jazzy
12
14
  SourceDocument.new.tap do |sd|
13
15
  sd.name = File.basename(file_path, '.md')
14
16
  sd.overview = overview Pathname(file_path)
15
- sd.usr = 'documentation.' + sd.name
17
+ sd.usr = "documentation.#{sd.name}"
16
18
  end
17
19
  end
18
20
  end
19
21
 
20
22
  def self.overview(file_path)
21
- return '' unless file_path && file_path.exist?
23
+ return '' unless file_path&.exist?
24
+
22
25
  file_path.read
23
26
  end
24
27
 
25
28
  def self.documentation_entries
26
29
  return [] unless
27
30
  config.documentation_glob_configured && config.documentation_glob
31
+
28
32
  config.documentation_glob.select { |e| File.file? e }
29
33
  end
30
34
  end
@@ -1,7 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Jazzy
2
4
  module Executable
3
5
  class IO < Array
4
6
  def initialize(io = nil)
7
+ super()
5
8
  @io = io
6
9
  end
7
10
 
@@ -0,0 +1,11 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg fill="none" version="1.1" viewBox="0 0 24 21.58" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="m22.95 7.2332h-7.1932l-1.1989 7.0734h-4.9953l-5.8745 6.9934s0.27972 0.2398 0.67935 0.2398h15.665c0.3597 0 0.6794-0.2797 0.7593-0.6394z" fill="url(#paint0_linear)"/>
4
+ <path d="m0.77041 0c-0.47956 0-0.83918 0.43959-0.75926 0.87918l3.237 19.822c0.03996 0.2398 0.15986 0.4796 0.35968 0.6394 0 0 0.27972 0.2398 0.67935 0.2398l6.0743-7.2732h-0.8392l-1.3188-7.0734h14.746l1.039-6.3541c0.08-0.47955-0.2797-0.87918-0.7593-0.87918z" fill="#fff"/>
5
+ <defs>
6
+ <linearGradient id="paint0_linear" x1="27.898" x2="16.618" y1="15.387" y2="23.023" gradientTransform="translate(-4 -5)" gradientUnits="userSpaceOnUse">
7
+ <stop stop-color="#fff" stop-opacity=".4" offset=".071833"/>
8
+ <stop stop-color="#fff" offset="1"/>
9
+ </linearGradient>
10
+ </defs>
11
+ </svg>
@@ -0,0 +1,23 @@
1
+ <svg
2
+ xmlns="http://www.w3.org/2000/svg"
3
+ height="313.44601"
4
+ width="338.96616"
5
+ xml:space="preserve"
6
+ viewBox="0 0 338.96616 313.44601"
7
+ y="0px"
8
+ x="0px"
9
+ version="1.1">
10
+ <style
11
+ id="style10"
12
+ type="text/css">
13
+ .st2{fill:#FFFFFF;}
14
+ </style>
15
+ <g
16
+ transform="translate(-123.54995,-122.776)"
17
+ id="logo_art">
18
+ <path
19
+ id="path12"
20
+ d="m 461.514,298.355 -18.049,-55.587 c 0.008,0.025 0.011,0.051 0.019,0.076 -0.009,-0.029 -0.014,-0.058 -0.022,-0.087 -10e-4,-0.002 -10e-4,-0.003 -10e-4,-0.005 0,-0.001 0,-0.002 0,-0.002 l -35.83,-110.31 c -1.96,-5.811 -7.353,-9.711 -13.536,-9.663 -6.201,0.032 -11.446,3.857 -13.364,9.748 L 346.721,237.23 H 239.408 L 205.334,132.518 c -1.916,-5.886 -7.162,-9.71 -13.362,-9.742 -0.025,0 -0.049,0 -0.075,0 -6.105,0 -11.509,3.876 -13.49,9.752 l -35.732,110.211 -0.005,0.014 c 0,0.001 0,0.002 0,0.003 -0.009,0.028 -0.013,0.056 -0.022,0.084 0.008,-0.025 0.011,-0.051 0.019,-0.076 l -18.115,55.591 c -2.725,8.392 0.232,17.512 7.36,22.697 L 288.328,434.7 c 0.023,0.017 0.049,0.027 0.072,0.044 0.067,0.048 0.132,0.097 0.2,0.142 -0.064,-0.043 -0.124,-0.09 -0.187,-0.134 0,0 0,-0.001 -0.001,-0.001 0.01,0.008 0.022,0.013 0.033,0.02 0.009,0.006 0.018,0.01 0.027,0.016 0.001,0.001 0.002,0.002 0.004,0.003 0.242,0.168 0.493,0.322 0.753,0.463 0.036,0.02 0.068,0.045 0.104,0.064 10e-4,0 10e-4,10e-4 0.002,10e-4 0.022,0.011 0.042,0.025 0.064,0.036 0.017,0.008 0.035,0.013 0.051,0.021 0.012,0.006 0.025,0.01 0.037,0.015 0.029,0.014 0.061,0.023 0.09,0.038 0.136,0.065 0.279,0.118 0.419,0.175 0.131,0.054 0.258,0.117 0.392,0.164 0.006,0.002 0.011,0.005 0.017,0.007 0.022,0.008 0.042,0.019 0.065,0.027 0.028,0.01 0.055,0.021 0.083,0.03 0.011,0.003 0.022,0.005 0.033,0.008 0.035,0.011 0.073,0.016 0.108,0.026 0.013,0.004 0.028,0.006 0.042,0.01 0.188,0.057 0.383,0.098 0.577,0.141 0.076,0.017 0.149,0.041 0.226,0.055 0.011,0.002 0.021,0.006 0.033,0.008 0.025,0.005 0.048,0.014 0.074,0.018 0.041,0.007 0.081,0.02 0.123,0.026 0.033,0.005 0.067,0.003 0.1,0.008 0.006,0.001 0.011,0 0.017,0.001 0.002,0 0.003,0 0.005,0 0.369,0.053 0.743,0.09 1.124,0.09 0.002,0 0.004,0 0.007,0 v 0 c 0.001,0 0.002,0 0.002,0 0,0 10e-4,0 10e-4,0 0.001,0 0.002,0 0.003,0 0.382,0 0.756,-0.037 1.126,-0.09 10e-4,0 0.003,0 0.004,0 0.006,-0.001 0.012,0 0.018,-0.001 0.033,-0.005 0.068,-0.003 0.101,-0.008 0.042,-0.007 0.082,-0.019 0.124,-0.026 0.025,-0.004 0.048,-0.013 0.073,-0.018 0.011,-0.002 0.021,-0.006 0.032,-0.008 0.078,-0.015 0.153,-0.039 0.231,-0.056 0.191,-0.042 0.383,-0.083 0.57,-0.139 0.013,-0.004 0.026,-0.005 0.039,-0.009 0.037,-0.011 0.075,-0.016 0.112,-0.027 0.011,-0.004 0.023,-0.005 0.034,-0.008 0.029,-0.009 0.057,-0.021 0.085,-0.031 0.022,-0.008 0.042,-0.019 0.064,-0.027 0.006,-0.002 0.011,-0.005 0.017,-0.007 0.142,-0.05 0.276,-0.116 0.415,-0.173 0.129,-0.054 0.261,-0.102 0.387,-0.162 0.031,-0.015 0.064,-0.024 0.094,-0.039 0.012,-0.006 0.026,-0.01 0.038,-0.016 0.017,-0.008 0.035,-0.013 0.052,-0.022 0.023,-0.012 0.045,-0.026 0.067,-0.037 0,0 10e-4,0 10e-4,-10e-4 0.037,-0.019 0.07,-0.046 0.107,-0.066 0.258,-0.14 0.508,-0.293 0.749,-0.46 0.019,-0.013 0.041,-0.023 0.061,-0.037 0.005,-0.004 0.011,-0.006 0.016,-0.01 0.023,-0.017 0.05,-0.028 0.073,-0.045 l 156.44,-113.65 c 7.124,-5.182 10.081,-14.302 7.356,-22.694 z m -67.32,-155.581 30.68,94.456 h -61.36 z m 25.307,110.428 -12.519,16.041 -92.334,118.307 43.677,-134.348 z M 285.428,430.707 c 0,0 0,0 0,0 0.008,0.024 0.021,0.046 0.029,0.071 -0.008,-0.025 -0.021,-0.047 -0.029,-0.071 z M 271.42,387.558 166.624,253.202 v 0 h 61.18 z m -79.545,-244.785 30.737,94.457 h -61.36 z m -50.571,165.36 c -1.516,-1.103 -2.144,-3.05 -1.563,-4.838 l 13.466,-41.325 98.67,126.502 z m 146.749,126.356 c -0.031,-0.025 -0.061,-0.052 -0.091,-0.078 -0.006,-0.005 -0.012,-0.012 -0.019,-0.017 -0.06,-0.05 -0.119,-0.101 -0.177,-0.153 -0.114,-0.099 -0.226,-0.2 -0.333,-0.306 0.009,0.008 0.019,0.015 0.028,0.023 0.012,0.011 0.025,0.02 0.037,0.031 0.229,0.219 0.47,0.425 0.722,0.615 0.003,0.002 0.005,0.005 0.008,0.007 0.012,0.009 0.022,0.02 0.034,0.03 -0.069,-0.05 -0.141,-0.098 -0.209,-0.152 z m 4.975,-32.097 -25.665,-79.059 -22.766,-70.131 h 96.933 z m 5.253,31.849 c -0.06,0.052 -0.118,0.104 -0.179,0.154 -0.007,0.006 -0.014,0.013 -0.021,0.019 -0.031,0.025 -0.06,0.052 -0.09,0.077 -0.066,0.053 -0.138,0.101 -0.207,0.152 0.012,-0.009 0.022,-0.021 0.035,-0.029 0.002,-0.002 0.004,-0.004 0.006,-0.006 0.252,-0.19 0.492,-0.394 0.719,-0.613 0.009,-0.009 0.02,-0.016 0.029,-0.024 0.012,-0.011 0.025,-0.02 0.036,-0.031 -0.106,0.103 -0.217,0.203 -0.328,0.301 z M 444.766,308.13 334.209,388.447 432.912,261.98 l 13.412,41.307 c 0.582,1.796 -0.045,3.743 -1.558,4.843 z"
21
+ class="st2" />
22
+ </g>
23
+ </svg>
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Jazzy
2
- VERSION = '0.13.7'.freeze unless defined? Jazzy::VERSION
4
+ VERSION = '0.14.0' unless defined? Jazzy::VERSION
3
5
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rouge'
2
4
 
3
5
  module Jazzy
4
6
  # This module helps highlight code
5
7
  module Highlighter
6
- SWIFT = 'swift'.freeze
7
- OBJC = 'objective_c'.freeze
8
+ SWIFT = 'swift'
9
+ OBJC = 'objective_c'
8
10
 
9
11
  class Formatter < Rouge::Formatters::HTML
10
12
  def initialize(language)
@@ -12,7 +14,7 @@ module Jazzy
12
14
  super()
13
15
  end
14
16
 
15
- def stream(tokens, &b)
17
+ def stream(tokens, &block)
16
18
  yield "<pre class=\"highlight #{@language}\"><code>"
17
19
  super
18
20
  yield "</code></pre>\n"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'redcarpet'
2
4
  require 'rouge'
3
5
  require 'rouge/plugins/redcarpet'
@@ -42,6 +44,7 @@ module Jazzy
42
44
  end
43
45
  end
44
46
 
47
+ # rubocop:disable Metrics/ClassLength
45
48
  class JazzyHTML < Redcarpet::Render::HTML
46
49
  include Redcarpet::Render::SmartyPants
47
50
  include Rouge::Plugins::Redcarpet
@@ -51,24 +54,25 @@ module Jazzy
51
54
 
52
55
  def header(text, header_level)
53
56
  text_slug = text.gsub(/[^[[:word:]]]+/, '-')
54
- .downcase
55
- .sub(/^-/, '')
56
- .sub(/-$/, '')
57
+ .downcase
58
+ .sub(/^-/, '')
59
+ .sub(/-$/, '')
57
60
 
58
61
  "<h#{header_level} id='#{text_slug}' class='heading'>" \
59
62
  "#{text}" \
60
- "</h#{header_level}>\n"
63
+ "</h#{header_level}>\n"
61
64
  end
62
65
 
63
66
  def codespan(text)
64
- if /^\$\$(.*)\$\$$/m =~ text
67
+ case text
68
+ when /^\$\$(.*)\$\$$/m
65
69
  o = ["<div class='math m-block'>", Regexp.last_match[1], '</div>']
66
70
  Markdown.has_math = true
67
- elsif /^\$(.*)\$$/m =~ text
71
+ when /^\$(.*)\$$/m
68
72
  o = ["<span class='math m-inline'>", Regexp.last_match[1], '</span>']
69
73
  Markdown.has_math = true
70
74
  else
71
- o = ['<code>', text, '</code>']
75
+ o = ['<code>', text.to_s, '</code>']
72
76
  end
73
77
 
74
78
  o[0] + CGI.escapeHTML(o[1]) + o[2]
@@ -115,10 +119,10 @@ module Jazzy
115
119
  # any one of our special list types
116
120
  (#{SPECIAL_LIST_TYPES.map(&Regexp.method(:escape)).join('|')})
117
121
  [\s:] # followed by either a space or a colon
118
- }ix
122
+ }ix.freeze
119
123
 
120
124
  ELIDED_LI_TOKEN =
121
- '7wNVzLB0OYPL2eGlPKu8q4vITltqh0Y6DPZf659TPMAeYh49o'.freeze
125
+ '7wNVzLB0OYPL2eGlPKu8q4vITltqh0Y6DPZf659TPMAeYh49o'
122
126
 
123
127
  def list_item(text, _list_type)
124
128
  if text =~ SPECIAL_LIST_TYPE_REGEX
@@ -126,30 +130,58 @@ module Jazzy
126
130
  if UNIQUELY_HANDLED_CALLOUTS.include? type.downcase
127
131
  return ELIDED_LI_TOKEN
128
132
  end
129
- return render_aside(type, text.sub(/#{Regexp.escape(type)}:\s+/, ''))
133
+
134
+ return render_list_aside(type,
135
+ text.sub(/#{Regexp.escape(type)}:\s+/, ''))
130
136
  end
131
- str = '<li>'
132
- str << text.strip
133
- str << "</li>\n"
137
+ "<li>#{text.strip}</li>\n"
138
+ end
139
+
140
+ def render_list_aside(type, text)
141
+ "</ul>#{render_aside(type, text).chomp}<ul>\n"
134
142
  end
135
143
 
136
144
  def render_aside(type, text)
137
145
  <<-HTML
138
- </ul><div class="aside aside-#{type.underscore.tr('_', '-')}">
146
+ <div class="aside aside-#{type.underscore.tr('_', '-')}">
139
147
  <p class="aside-title">#{type.underscore.humanize}</p>
140
148
  #{text}
141
- </div><ul>
149
+ </div>
142
150
  HTML
143
151
  end
144
152
 
145
153
  def list(text, list_type)
146
154
  elided = text.gsub!(ELIDED_LI_TOKEN, '')
147
155
  return if text =~ /\A\s*\Z/ && elided
148
- str = "\n"
149
- str << (list_type == :ordered ? "<ol>\n" : "<ul>\n")
150
- str << text
151
- str << (list_type == :ordered ? "</ol>\n" : "</ul>\n")
152
- str.gsub(%r{\n?<ul>\n<\/ul>}, '')
156
+
157
+ tag = list_type == :ordered ? 'ol' : 'ul'
158
+ "\n<#{tag}>\n#{text}</#{tag}>\n"
159
+ .gsub(%r{\n?<ul>\n?</ul>}, '')
160
+ end
161
+
162
+ # List from
163
+ # https://developer.apple.com/documentation/xcode/formatting-your-documentation-content#Add-Notes-and-Other-Asides
164
+ DOCC_CALLOUTS = %w[note
165
+ important
166
+ warning
167
+ tip
168
+ experiment].freeze
169
+
170
+ DOCC_CALLOUT_REGEX = %r{
171
+ \A\s* # optional leading spaces
172
+ (?:<p>\s*)? # optional opening p tag
173
+ # any one of the callout names
174
+ (#{DOCC_CALLOUTS.map(&Regexp.method(:escape)).join('|')})
175
+ : # followed directly by a colon
176
+ }ix.freeze
177
+
178
+ def block_quote(html)
179
+ if html =~ DOCC_CALLOUT_REGEX
180
+ type = Regexp.last_match[1]
181
+ render_aside(type, html.sub(/#{Regexp.escape(type)}:\s*/, ''))
182
+ else
183
+ "\n<blockquote>\n#{html}</blockquote>\n"
184
+ end
153
185
  end
154
186
 
155
187
  def block_code(code, language)
@@ -160,6 +192,7 @@ module Jazzy
160
192
  Highlighter::Formatter.new(lexer.tag)
161
193
  end
162
194
  end
195
+ # rubocop:enable Metrics/ClassLength
163
196
 
164
197
  REDCARPET_OPTIONS = {
165
198
  autolink: true,
@@ -182,22 +215,22 @@ module Jazzy
182
215
  super
183
216
  end
184
217
 
185
- INTRO_PAT = '\A(?<intro>\s*(<p>\s*)?)'.freeze
186
- OUTRO_PAT = '(?<outro>.*)\z'.freeze
218
+ INTRO_PAT = '\A(?<intro>\s*(<p>\s*)?)'
219
+ OUTRO_PAT = '(?<outro>.*)\z'
187
220
 
188
- RETURNS_REGEX = /#{INTRO_PAT}returns:#{OUTRO_PAT}/im
221
+ RETURNS_REGEX = /#{INTRO_PAT}returns:#{OUTRO_PAT}/im.freeze
189
222
 
190
- IDENT_PAT = '(?<param>\S+)'.freeze
223
+ IDENT_PAT = '(?<param>\S+)'
191
224
 
192
225
  # Param formats: normal swift, objc via sourcekitten, and
193
226
  # possibly inside 'Parameters:'
194
- PARAM_PAT1 = "(parameter +#{IDENT_PAT}\\s*:)".freeze
195
- PARAM_PAT2 = "(parameter:\\s*#{IDENT_PAT}\\s+)".freeze
196
- PARAM_PAT3 = "(#{IDENT_PAT}\\s*:)".freeze
227
+ PARAM_PAT1 = "(parameter +#{IDENT_PAT}\\s*:)"
228
+ PARAM_PAT2 = "(parameter:\\s*#{IDENT_PAT}\\s+)"
229
+ PARAM_PAT3 = "(#{IDENT_PAT}\\s*:)"
197
230
 
198
- PARAM_PAT = "(?:#{PARAM_PAT1}|#{PARAM_PAT2}|#{PARAM_PAT3})".freeze
231
+ PARAM_PAT = "(?:#{PARAM_PAT1}|#{PARAM_PAT2}|#{PARAM_PAT3})"
199
232
 
200
- PARAM_REGEX = /#{INTRO_PAT}#{PARAM_PAT}#{OUTRO_PAT}/im
233
+ PARAM_REGEX = /#{INTRO_PAT}#{PARAM_PAT}#{OUTRO_PAT}/im.freeze
201
234
 
202
235
  def list_item(text, _list_type)
203
236
  if text =~ RETURNS_REGEX
@@ -242,7 +275,7 @@ module Jazzy
242
275
  class JazzyCopyright < Redcarpet::Render::HTML
243
276
  def link(link, _title, content)
244
277
  %(<a class="link" href="#{link}" target="_blank" \
245
- rel="external">#{content}</a>)
278
+ rel="noopener" rel="external">#{content}</a>)
246
279
  end
247
280
  end
248
281