jazzy 0.12.0 → 0.13.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b8b0a6f32e8d7182725eafedb4ec488e382de192af903fb42ee9d7cd3c7396c3
4
- data.tar.gz: 1b2dbf01dae14692d0a04a1912f71d98cc44d2397fe81280df0d072089b3ad4b
3
+ metadata.gz: d55202d57dfdb0b3aad10b90f122d34e10a529bf73dde92ce2d0063473c011fe
4
+ data.tar.gz: 221dd32f5dac077431fe1d449b857966b2b9dcfc8a5f4cd0cefd61e1862558c9
5
5
  SHA512:
6
- metadata.gz: 04ef74edf753cb424bfe2b9f8bdc7860b3d9072e91a5be60a7db38981d705cc595286a33d805482129746b4ee6626ef5852cbbf13e428d0e0f7fcd99310adf14
7
- data.tar.gz: 8b038aaabd0516983b87d80841e1dc490b35e6493cae241193d07b09c946f8f47dd0b7b84bd20300fd382d522ad6ca3104fb2478c9eb6ab764afb5a6840014b4
6
+ metadata.gz: cf1b7616ead246ea0e45a0c1e3148fc8cf3a04600c295c5bec0c7b5cff530296b9deb50f6b9c429940c1bf12dce036d4863038e55b3f892e748e5e99e7f3fc65
7
+ data.tar.gz: e7725d323d9550f97f27a6bd2e0c89d674cda5d4199dc6433e38f7b78e01f58388d8af8842c28293abb9ce4434068e24fbf1483941e2ab771787db7220dd788a
@@ -1,3 +1,36 @@
1
+ ## 0.13.0
2
+
3
+ ##### Breaking
4
+
5
+ * None.
6
+
7
+ ##### Enhancements
8
+
9
+ * Add section headings for members added by Swift conditional conformances.
10
+ [John Fairhurst](https://github.com/johnfairh)
11
+ [#717](https://github.com/realm/jazzy/issues/717)
12
+
13
+ * Parse markdown in MARK comments, make the html available to themes via
14
+ `name_html` mustache tag key for section headings.
15
+ [John Fairhurst](https://github.com/johnfairh)
16
+
17
+ * Include protocol conformances added by extensions in Swift docs.
18
+ [John Fairhurst](https://github.com/johnfairh)
19
+
20
+ ##### Bug Fixes
21
+
22
+ * Render bullet lists correctly when followed by a callout.
23
+ [John Fairhurst](https://github.com/johnfairh)
24
+ [#785](https://github.com/realm/jazzy/issues/785)
25
+
26
+ * Render markup of text inside double quotes.
27
+ [John Fairhurst](https://github.com/johnfairh)
28
+ [#992](https://github.com/realm/jazzy/issues/992)
29
+
30
+ * Fix `sourcekitten_sourcefile` used from config file.
31
+ [John Fairhurst](https://github.com/johnfairh)
32
+ [#1137](https://github.com/realm/jazzy/issues/1137)
33
+
1
34
  ## 0.12.0
2
35
 
3
36
  ##### Breaking
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- jazzy (0.12.0)
4
+ jazzy (0.13.0)
5
5
  cocoapods (~> 1.5)
6
6
  mustache (~> 1.1)
7
7
  open4
@@ -14,7 +14,7 @@ PATH
14
14
  GEM
15
15
  remote: https://rubygems.org/
16
16
  specs:
17
- CFPropertyList (3.0.1)
17
+ CFPropertyList (3.0.2)
18
18
  activesupport (4.2.11.1)
19
19
  i18n (~> 0.7)
20
20
  minitest (~> 5.1)
@@ -62,7 +62,7 @@ GEM
62
62
  fuzzy_match (~> 2.0.4)
63
63
  nap (~> 1.0)
64
64
  cocoapods-deintegrate (1.0.4)
65
- cocoapods-downloader (1.2.2)
65
+ cocoapods-downloader (1.3.0)
66
66
  cocoapods-plugins (1.0.0)
67
67
  nap
68
68
  cocoapods-search (1.0.0)
@@ -93,11 +93,11 @@ GEM
93
93
  terminal-table (~> 1)
94
94
  diffy (3.3.0)
95
95
  escape (0.0.4)
96
- faraday (0.17.0)
96
+ faraday (0.17.1)
97
97
  multipart-post (>= 1.2, < 3)
98
98
  faraday-http-cache (2.0.0)
99
99
  faraday (~> 0.8)
100
- ffi (1.11.1)
100
+ ffi (1.11.3)
101
101
  fourflusher (2.3.1)
102
102
  fuzzy_match (2.0.4)
103
103
  gh_inspector (1.1.3)
@@ -111,15 +111,13 @@ GEM
111
111
  kramdown-parser-gfm (1.1.0)
112
112
  kramdown (~> 2.0)
113
113
  liferaft (0.0.6)
114
- metaclass (0.0.4)
115
114
  minitest (5.13.0)
116
- mocha (1.9.0)
117
- metaclass (~> 0.0.1)
115
+ mocha (1.10.1)
118
116
  mocha-on-bacon (0.2.3)
119
117
  mocha (>= 0.13.0)
120
118
  molinillo (0.6.6)
121
119
  multipart-post (2.1.1)
122
- mustache (1.1.0)
120
+ mustache (1.1.1)
123
121
  nanaimo (0.2.6)
124
122
  nap (1.1.0)
125
123
  netrc (0.11.0)
@@ -127,7 +125,7 @@ GEM
127
125
  octokit (4.14.0)
128
126
  sawyer (~> 0.8.0, >= 0.5.3)
129
127
  open4 (1.3.4)
130
- parallel (1.18.0)
128
+ parallel (1.19.1)
131
129
  parser (2.6.5.0)
132
130
  ast (~> 2.4.0)
133
131
  powerpack (0.1.2)
@@ -138,7 +136,7 @@ GEM
138
136
  rake
139
137
  rake (10.5.0)
140
138
  redcarpet (3.5.0)
141
- rouge (3.12.0)
139
+ rouge (3.13.0)
142
140
  rubocop (0.49.0)
143
141
  parallel (~> 1.10)
144
142
  parser (>= 2.3.3.1, < 3.0)
@@ -176,7 +176,7 @@ module Jazzy
176
176
  command_line: ['-s', '--sourcekitten-sourcefile filepath1,…filepathN',
177
177
  Array],
178
178
  description: 'File(s) generated from sourcekitten output to parse',
179
- parse: ->(paths) { paths.map { |path| expand_path(path) } }
179
+ parse: ->(paths) { [paths].flatten.map { |path| expand_path(path) } }
180
180
 
181
181
  config_attr :source_directory,
182
182
  command_line: '--source-directory DIRPATH',
@@ -350,9 +350,10 @@ module Jazzy
350
350
  end
351
351
  # rubocop:enable Metrics/MethodLength
352
352
 
353
- def self.make_task(mark, uid, items)
353
+ def self.make_task(mark, uid, items, doc_model)
354
354
  {
355
355
  name: mark.name,
356
+ name_html: (render(doc_model, mark.name) if mark.name),
356
357
  uid: URI.encode(uid),
357
358
  items: items,
358
359
  pre_separator: mark.has_start_dash,
@@ -376,7 +377,7 @@ module Jazzy
376
377
  else
377
378
  mark_names_counts[uid] = 1
378
379
  end
379
- make_task(mark, uid, items)
380
+ make_task(mark, uid, items, mark_children.first)
380
381
  end
381
382
  end
382
383
 
@@ -1,3 +1,3 @@
1
1
  module Jazzy
2
- VERSION = '0.12.0'.freeze unless defined? Jazzy::VERSION
2
+ VERSION = '0.13.0'.freeze unless defined? Jazzy::VERSION
3
3
  end
@@ -82,21 +82,21 @@ module Jazzy
82
82
 
83
83
  def render_aside(type, text)
84
84
  <<-HTML
85
- <div class="aside aside-#{type.underscore.tr('_', '-')}">
85
+ </ul><div class="aside aside-#{type.underscore.tr('_', '-')}">
86
86
  <p class="aside-title">#{type.underscore.humanize}</p>
87
87
  #{text}
88
- </div>
88
+ </div><ul>
89
89
  HTML
90
90
  end
91
91
 
92
92
  def list(text, list_type)
93
93
  elided = text.gsub!(ELIDED_LI_TOKEN, '')
94
94
  return if text =~ /\A\s*\Z/ && elided
95
- return text if text =~ /class="aside-title"/
96
95
  str = "\n"
97
96
  str << (list_type == :ordered ? "<ol>\n" : "<ul>\n")
98
97
  str << text
99
98
  str << (list_type == :ordered ? "</ol>\n" : "</ul>\n")
99
+ str.gsub(%r{\n?<ul>\n<\/ul>}, '')
100
100
  end
101
101
 
102
102
  def block_code(code, language)
@@ -112,7 +112,6 @@ module Jazzy
112
112
  autolink: true,
113
113
  fenced_code_blocks: true,
114
114
  no_intra_emphasis: true,
115
- quote: true,
116
115
  strikethrough: true,
117
116
  space_after_headers: false,
118
117
  tables: true,
@@ -130,6 +130,8 @@ module Jazzy
130
130
  attr_accessor :deprecation_message
131
131
  attr_accessor :unavailable
132
132
  attr_accessor :unavailable_message
133
+ attr_accessor :generic_requirements
134
+ attr_accessor :inherited_types
133
135
 
134
136
  def usage_discouraged?
135
137
  unavailable || deprecated
@@ -139,6 +141,36 @@ module Jazzy
139
141
  CGI.unescape(url)
140
142
  end
141
143
 
144
+ def constrained_extension?
145
+ type.swift_extension? &&
146
+ generic_requirements
147
+ end
148
+
149
+ def mark_for_children
150
+ if constrained_extension?
151
+ SourceMark.new_generic_requirements(generic_requirements)
152
+ else
153
+ SourceMark.new
154
+ end
155
+ end
156
+
157
+ def inherited_types?
158
+ inherited_types &&
159
+ !inherited_types.empty?
160
+ end
161
+
162
+ # Is there at least one inherited type that is not in the given list?
163
+ def other_inherited_types?(unwanted)
164
+ return false unless inherited_types?
165
+ inherited_types.any? { |t| !unwanted.include?(t) }
166
+ end
167
+
168
+ # SourceKit only sets modulename for imported modules
169
+ def type_from_doc_module?
170
+ !type.extension? ||
171
+ (swift? && usr && modulename.nil?)
172
+ end
173
+
142
174
  def alternative_abstract
143
175
  if file = alternative_abstract_file
144
176
  Pathname(file).read
@@ -114,6 +114,10 @@ module Jazzy
114
114
  kind == 'source.lang.swift.decl.protocol'
115
115
  end
116
116
 
117
+ def swift_typealias?
118
+ kind == 'source.lang.swift.decl.typealias'
119
+ end
120
+
117
121
  def param?
118
122
  # SourceKit strangely categorizes initializer parameters as local
119
123
  # variables, so both kinds represent a parameter in jazzy.
@@ -28,6 +28,12 @@ module Jazzy
28
28
  self.name = mark_string[start_index..end_index]
29
29
  end
30
30
 
31
+ def self.new_generic_requirements(requirements)
32
+ marked_up = requirements.gsub(/\b([^=:]\S*)\b/, '`\1`')
33
+ text = "Available where #{marked_up}"
34
+ new(text)
35
+ end
36
+
31
37
  def empty?
32
38
  !name && !has_start_dash && !has_end_dash
33
39
  end
@@ -37,5 +43,10 @@ module Jazzy
37
43
  self.has_start_dash = other.has_start_dash
38
44
  self.has_end_dash = other.has_end_dash
39
45
  end
46
+
47
+ # Can we merge the contents of another mark into our own?
48
+ def can_merge?(other)
49
+ other.empty? || other.name == name
50
+ end
40
51
  end
41
52
  end
@@ -124,6 +124,18 @@ module Jazzy
124
124
  end
125
125
  end
126
126
 
127
+ # Merge consecutive sections with the same mark into one section
128
+ def self.merge_consecutive_marks(docs)
129
+ prev_mark = nil
130
+ docs.each do |doc|
131
+ if prev_mark && prev_mark.can_merge?(doc.mark)
132
+ doc.mark = prev_mark
133
+ end
134
+ prev_mark = doc.mark
135
+ merge_consecutive_marks(doc.children)
136
+ end
137
+ end
138
+
127
139
  def self.sanitize_filename(doc)
128
140
  unsafe_filename = doc.url_name || doc.name
129
141
  sanitzation_enabled = Config.instance.use_safe_filenames
@@ -289,21 +301,29 @@ module Jazzy
289
301
  return false
290
302
  end
291
303
 
292
- # Document extensions & enum elements, since we can't tell their ACL.
304
+ # Document enum elements, since we can't tell their ACL.
293
305
  return true if type.swift_enum_element?
294
- if type.swift_extension?
295
- return Array(doc['key.substructure']).any? do |subdoc|
296
- subtype = SourceDeclaration::Type.new(subdoc['key.kind'])
297
- !subtype.mark? && should_document?(subdoc)
298
- end
299
- end
306
+ # Document extensions if they might have parts covered by the ACL.
307
+ return should_document_swift_extension?(doc) if type.swift_extension?
300
308
 
301
309
  acl_ok = SourceDeclaration::AccessControlLevel.from_doc(doc) >= @min_acl
302
- acl_ok.tap { @stats.add_acl_skipped unless acl_ok }
310
+ unless acl_ok
311
+ @stats.add_acl_skipped
312
+ @inaccessible_protocols.append(doc['key.name']) if type.swift_protocol?
313
+ end
314
+ acl_ok
303
315
  end
304
316
  # rubocop:enable Metrics/CyclomaticComplexity
305
317
  # rubocop:enable Metrics/PerceivedComplexity
306
318
 
319
+ def self.should_document_swift_extension?(doc)
320
+ doc['key.inheritedtypes'] ||
321
+ Array(doc['key.substructure']).any? do |subdoc|
322
+ subtype = SourceDeclaration::Type.new(subdoc['key.kind'])
323
+ !subtype.mark? && should_document?(subdoc)
324
+ end
325
+ end
326
+
307
327
  def self.should_mark_undocumented(filepath)
308
328
  source_directory = Config.instance.source_directory.to_s
309
329
  (filepath || '').start_with?(source_directory)
@@ -467,14 +487,10 @@ module Jazzy
467
487
  end
468
488
 
469
489
  def self.make_substructure(doc, declaration)
470
- declaration.children = if doc['key.substructure']
471
- make_source_declarations(
472
- doc['key.substructure'],
473
- declaration,
474
- )
475
- else
476
- []
477
- end
490
+ return [] unless subdocs = doc['key.substructure']
491
+ make_source_declarations(subdocs,
492
+ declaration,
493
+ declaration.mark_for_children)
478
494
  end
479
495
 
480
496
  # rubocop:disable Metrics/MethodLength
@@ -531,10 +547,17 @@ module Jazzy
531
547
  declaration.end_line = doc['key.parsed_scope.end']
532
548
  declaration.deprecated = doc['key.always_deprecated']
533
549
  declaration.unavailable = doc['key.always_unavailable']
550
+ declaration.generic_requirements =
551
+ find_generic_requirements(doc['key.parsed_declaration'])
552
+ inherited_types = doc['key.inheritedtypes'] || []
553
+ declaration.inherited_types =
554
+ inherited_types.map { |type| type['key.name'] }.compact
534
555
 
535
556
  next unless make_doc_info(doc, declaration)
536
- make_substructure(doc, declaration)
537
- next if declaration.type.extension? && declaration.children.empty?
557
+ declaration.children = make_substructure(doc, declaration)
558
+ next if declaration.type.extension? &&
559
+ declaration.children.empty? &&
560
+ !declaration.inherited_types?
538
561
  declarations << declaration
539
562
  end
540
563
  declarations
@@ -543,6 +566,12 @@ module Jazzy
543
566
  # rubocop:enable Metrics/CyclomaticComplexity
544
567
  # rubocop:enable Metrics/MethodLength
545
568
 
569
+ def self.find_generic_requirements(parsed_declaration)
570
+ parsed_declaration =~ /\bwhere\s+(.*)$/m
571
+ return nil unless Regexp.last_match
572
+ Regexp.last_match[1].gsub(/\s+/, ' ')
573
+ end
574
+
546
575
  # Expands extensions of nested types declared at the top level into
547
576
  # a tree so they can be deduplicated properly
548
577
  def self.expand_extensions(decls)
@@ -566,6 +595,7 @@ module Jazzy
566
595
  SourceDeclaration.new.tap do |decl|
567
596
  make_default_doc_info(decl)
568
597
  decl.name = name
598
+ decl.modulename = extension.modulename
569
599
  decl.type = extension.type
570
600
  decl.mark = extension.mark
571
601
  decl.usr = candidates.first.usr unless candidates.empty?
@@ -588,10 +618,10 @@ module Jazzy
588
618
  .group_by { |d| deduplication_key(d, declarations) }
589
619
  .values
590
620
 
591
- duplicate_groups.map do |group|
621
+ duplicate_groups.flat_map do |group|
592
622
  # Put extended type (if present) before extensions
593
623
  merge_declarations(group)
594
- end
624
+ end.compact
595
625
  end
596
626
 
597
627
  # Returns true if an Objective-C declaration is mergeable.
@@ -601,13 +631,21 @@ module Jazzy
601
631
  && name_match(decl.objc_category_name[0], root_decls))
602
632
  end
603
633
 
634
+ # Returns if a Swift declaration is mergeable.
635
+ # Start off merging in typealiases to help understand extensions.
636
+ def self.mergeable_swift?(decl)
637
+ decl.type.swift_extensible? ||
638
+ decl.type.swift_extension? ||
639
+ decl.type.swift_typealias?
640
+ end
641
+
604
642
  # Two declarations get merged if they have the same deduplication key.
605
643
  def self.deduplication_key(decl, root_decls)
606
644
  # Swift extension of objc class
607
645
  if decl.swift_objc_extension?
608
646
  [decl.swift_extension_objc_name, :objc_class_and_categories]
609
647
  # Swift type or Swift extension of Swift type
610
- elsif decl.type.swift_extensible? || decl.type.swift_extension?
648
+ elsif mergeable_swift?(decl)
611
649
  [decl.usr, decl.name]
612
650
  # Objc categories and classes
613
651
  elsif mergeable_objc?(decl, root_decls)
@@ -633,17 +671,36 @@ module Jazzy
633
671
  end
634
672
  typedecl = typedecls.first
635
673
 
674
+ extensions = reject_inaccessible_extensions(typedecl, extensions)
675
+
636
676
  if typedecl
637
677
  if typedecl.type.swift_protocol?
638
- merge_default_implementations_into_protocol(typedecl, extensions)
639
- mark_members_from_protocol_extension(extensions)
678
+ mark_and_merge_protocol_extensions(typedecl, extensions)
640
679
  extensions.reject! { |ext| ext.children.empty? }
641
680
  end
642
681
 
643
- merge_declaration_marks(typedecl, extensions)
682
+ merge_objc_declaration_marks(typedecl, extensions)
644
683
  end
645
684
 
646
- decls = typedecls + extensions
685
+ # Keep type-aliases separate from any extensions
686
+ if typedecl && typedecl.type.swift_typealias?
687
+ [merge_type_and_extensions(typedecls, []),
688
+ merge_type_and_extensions([], extensions)]
689
+ else
690
+ merge_type_and_extensions(typedecls, extensions)
691
+ end
692
+ end
693
+ # rubocop:enable Metrics/MethodLength
694
+
695
+ def self.merge_type_and_extensions(typedecls, extensions)
696
+ # Constrained extensions at the end
697
+ constrained, regular_exts = extensions.partition(&:constrained_extension?)
698
+ decls = typedecls + regular_exts + constrained
699
+ return nil if decls.empty?
700
+
701
+ move_merged_extension_marks(decls)
702
+ merge_code_declaration(decls)
703
+
647
704
  decls.first.tap do |merged|
648
705
  merged.children = deduplicate_declarations(
649
706
  decls.flat_map(&:children).uniq,
@@ -653,58 +710,112 @@ module Jazzy
653
710
  end
654
711
  end
655
712
  end
656
- # rubocop:enable Metrics/MethodLength
657
713
 
714
+ # Now we know all the public types and all the private protocols,
715
+ # reject extensions that add public protocols to private types
716
+ # or add private protocols to public types.
717
+ def self.reject_inaccessible_extensions(typedecl, extensions)
718
+ swift_exts, objc_exts = extensions.partition(&:swift?)
719
+
720
+ # Reject extensions that are just conformances to private protocols
721
+ unwanted_exts, wanted_exts = swift_exts.partition do |ext|
722
+ ext.children.empty? &&
723
+ !ext.other_inherited_types?(@inaccessible_protocols)
724
+ end
725
+
726
+ # Given extensions of a type from this module, without the
727
+ # type itself, the type must be private and the extensions
728
+ # should be rejected.
729
+ if !typedecl &&
730
+ wanted_exts.first &&
731
+ wanted_exts.first.type_from_doc_module?
732
+ unwanted_exts += wanted_exts
733
+ wanted_exts = []
734
+ end
735
+
736
+ # Don't tell the user to document them
737
+ unwanted_exts.each { |e| @stats.remove_undocumented(e) }
738
+
739
+ objc_exts + wanted_exts
740
+ end
741
+
742
+ # Protocol extensions.
743
+ #
658
744
  # If any of the extensions provide default implementations for methods in
659
745
  # the given protocol, merge those members into the protocol doc instead of
660
746
  # keeping them on the extension. These get a “Default implementation”
661
- # annotation in the generated docs.
662
- def self.merge_default_implementations_into_protocol(protocol, extensions)
663
- protocol.children.each do |proto_method|
664
- extensions.each do |ext|
665
- defaults, ext.children = ext.children.partition do |ext_member|
666
- ext_member.name == proto_method.name
747
+ # annotation in the generated docs. Default implementations added by
748
+ # conditional extensions are annotated but listed separately.
749
+ #
750
+ # Protocol methods provided only in an extension and not in the protocol
751
+ # itself are a special beast: they do not use dynamic dispatch. These get an
752
+ # “Extension method” annotation in the generated docs.
753
+ def self.mark_and_merge_protocol_extensions(protocol, extensions)
754
+ extensions.each do |ext|
755
+ ext.children = ext.children.select do |ext_member|
756
+ proto_member = protocol.children.find do |p|
757
+ p.name == ext_member.name && p.type == ext_member.type
758
+ end
759
+
760
+ # Extension-only method, keep.
761
+ unless proto_member
762
+ ext_member.from_protocol_extension = true
763
+ next true
667
764
  end
668
- unless defaults.empty?
669
- proto_method.default_impl_abstract =
670
- defaults.flat_map { |d| [d.abstract, d.discussion] }.join
765
+
766
+ # Default impl but constrained, mark and keep.
767
+ if ext.constrained_extension?
768
+ ext_member.default_impl_abstract = ext_member.abstract
769
+ ext_member.abstract = nil
770
+ next true
671
771
  end
772
+
773
+ # Default impl for all users, merge.
774
+ proto_member.default_impl_abstract = ext_member.abstract
775
+ next false
672
776
  end
673
777
  end
674
778
  end
675
779
 
676
- # Protocol methods provided only in an extension and not in the protocol
677
- # itself are a special beast: they do not use dynamic dispatch. These get an
678
- # “Extension method” annotation in the generated docs.
679
- def self.mark_members_from_protocol_extension(extensions)
780
+ # Mark children merged from categories with the name of category
781
+ # (unless they already have a mark)
782
+ def self.merge_objc_declaration_marks(typedecl, extensions)
783
+ return unless typedecl.type.objc_class?
680
784
  extensions.each do |ext|
681
- ext.children.each do |ext_member|
682
- ext_member.from_protocol_extension = true
683
- end
785
+ _, category_name = ext.objc_category_name
786
+ ext.children.each { |c| c.mark.name ||= category_name }
684
787
  end
685
788
  end
686
789
 
687
- # Customize marks associated with to-be-merged declarations
688
- def self.merge_declaration_marks(typedecl, extensions)
689
- if typedecl.type.objc_class?
690
- # Mark children merged from categories with the name of category
691
- # (unless they already have a mark)
692
- extensions.each do |ext|
693
- _, category_name = ext.objc_category_name
694
- ext.children.each { |c| c.mark.name ||= category_name }
695
- end
696
- else
697
- # If the Swift extension has a mark and the first child doesn't
698
- # then copy the mark contents down so it still shows up.
699
- extensions.each do |ext|
700
- child = ext.children.first
701
- if child && child.mark.empty?
702
- child.mark.copy(ext.mark)
703
- end
790
+ # For each extension to be merged, move any MARK from the extension
791
+ # declaration down to the extension contents so it still shows up.
792
+ def self.move_merged_extension_marks(decls)
793
+ return unless to_be_merged = decls[1..-1]
794
+ to_be_merged.each do |ext|
795
+ child = ext.children.first
796
+ if child && child.mark.empty?
797
+ child.mark.copy(ext.mark)
704
798
  end
705
799
  end
706
800
  end
707
801
 
802
+ # Merge useful information added by extensions into the main
803
+ # declaration: public protocol conformances and, for top-level extensions,
804
+ # further conditional extensions of the same type.
805
+ def self.merge_code_declaration(decls)
806
+ first = decls.first
807
+
808
+ declarations = decls[1..-1].select do |decl|
809
+ decl.type.swift_extension? &&
810
+ (decl.other_inherited_types?(@inaccessible_protocols) ||
811
+ (first.type.swift_extension? && decl.constrained_extension?))
812
+ end.map(&:declaration)
813
+
814
+ unless declarations.empty?
815
+ first.declaration = declarations.prepend(first.declaration).uniq.join
816
+ end
817
+ end
818
+
708
819
  # Apply filtering based on the "included" and "excluded" flags.
709
820
  def self.filter_files(json)
710
821
  json = filter_included_files(json) if Config.instance.included_files.any?
@@ -860,6 +971,7 @@ module Jazzy
860
971
  @min_acl = min_acl
861
972
  @skip_undocumented = skip_undocumented
862
973
  @stats = Stats.new
974
+ @inaccessible_protocols = []
863
975
  sourcekitten_json = filter_files(JSON.parse(sourcekitten_output).flatten)
864
976
  docs = make_source_declarations(sourcekitten_json).concat inject_docs
865
977
  docs = expand_extensions(docs)
@@ -870,6 +982,7 @@ module Jazzy
870
982
  docs = docs.reject { |doc| doc.type.swift_enum_element? }
871
983
  ungrouped_docs = docs
872
984
  docs = group_docs(docs)
985
+ merge_consecutive_marks(docs)
873
986
  make_doc_urls(docs)
874
987
  autolink(docs, ungrouped_docs)
875
988
  [docs, @stats]
@@ -18,6 +18,10 @@ module Jazzy
18
18
  @undocumented_decls << decl
19
19
  end
20
20
 
21
+ def remove_undocumented(decl)
22
+ @undocumented_decls.delete(decl)
23
+ end
24
+
21
25
  def acl_included
22
26
  documented + undocumented
23
27
  end
@@ -152,7 +152,7 @@ header {
152
152
  background-color: $bg_color;
153
153
  position: fixed;
154
154
  width: 100%;
155
- z-index: 1;
155
+ z-index: 2;
156
156
  img {
157
157
  padding-right: 6px;
158
158
  vertical-align: -4px;
@@ -177,7 +177,7 @@ header {
177
177
  padding-top: $breadcrumb_padding_top;
178
178
  position: fixed;
179
179
  width: 100%;
180
- z-index: 1;
180
+ z-index: 2;
181
181
  margin-top: $header_height;
182
182
  #carat {
183
183
  height: 10px;
@@ -270,6 +270,17 @@ header {
270
270
  margin: -$content_top_offset 0 0;
271
271
  }
272
272
  }
273
+ .section-name {
274
+ p {
275
+ margin-bottom: inherit;
276
+ line-height: inherit;
277
+ }
278
+ code {
279
+ background-color: inherit;
280
+ padding: inherit;
281
+ color: inherit;
282
+ }
283
+ }
273
284
  }
274
285
 
275
286
  .section {
@@ -317,6 +328,29 @@ header {
317
328
  }
318
329
  }
319
330
 
331
+ .section-name-container {
332
+ position: relative;
333
+ display: inline-block;
334
+
335
+ .section-name-link {
336
+ position: absolute;
337
+ top: 0;
338
+ left: 0;
339
+ bottom: 0;
340
+ right: 0;
341
+ margin-bottom: 0;
342
+ }
343
+
344
+ .section-name {
345
+ position: relative;
346
+ pointer-events: none;
347
+ z-index: 1;
348
+ a {
349
+ pointer-events: auto;
350
+ }
351
+ }
352
+ }
353
+
320
354
  .item {
321
355
  padding-top: 8px;
322
356
  width: 100%;
@@ -3,9 +3,10 @@
3
3
  <div class="task-name-container">
4
4
  <a name="/{{uid}}"></a>
5
5
  <a name="//apple_ref/{{language_stub}}/Section/{{name}}" class="dashAnchor"></a>
6
- <a href="#/{{uid}}">
7
- <h3 class="section-name">{{name}}</h3>
8
- </a>
6
+ <div class="section-name-container">
7
+ <a class="section-name-link" href="#/{{uid}}"></a>
8
+ <h3 class="section-name">{{{name_html}}}</h3>
9
+ </div>
9
10
  </div>
10
11
  {{/name}}
11
12
  <ul>
@@ -201,13 +201,15 @@ code {
201
201
  font-family: $code_font;
202
202
  }
203
203
 
204
- p, li {
205
- > code {
206
- background: $code_bg_color;
207
- padding: .2em;
208
- &:before, &:after {
209
- letter-spacing: -.2em;
210
- content: "\00a0";
204
+ .item-container, .top-matter {
205
+ p, li {
206
+ > code {
207
+ background: $code_bg_color;
208
+ padding: .2em;
209
+ &:before, &:after {
210
+ letter-spacing: -.2em;
211
+ content: "\00a0";
212
+ }
211
213
  }
212
214
  }
213
215
  }
@@ -367,6 +369,10 @@ pre code {
367
369
  .section-name {
368
370
  color: #666;
369
371
  display: block;
372
+
373
+ p {
374
+ margin-bottom: inherit;
375
+ }
370
376
  }
371
377
 
372
378
  .declaration .highlight {
@@ -394,6 +400,28 @@ pre code {
394
400
  }
395
401
  }
396
402
 
403
+ .section-name-container {
404
+ position: relative;
405
+
406
+ .section-name-link {
407
+ position: absolute;
408
+ top: 0;
409
+ left: 0;
410
+ bottom: 0;
411
+ right: 0;
412
+ margin-bottom: 0;
413
+ }
414
+
415
+ .section-name {
416
+ position: relative;
417
+ pointer-events: none;
418
+ z-index: 1;
419
+ a {
420
+ pointer-events: auto;
421
+ }
422
+ }
423
+ }
424
+
397
425
  .item-container {
398
426
  padding: 0;
399
427
  }
@@ -35,7 +35,7 @@
35
35
  <article class="main-content">
36
36
 
37
37
  <section class="section">
38
- <div class="section-content">
38
+ <div class="section-content top-matter">
39
39
  {{^hide_name}}<h1>{{name}}</h1>{{/hide_name}}
40
40
  {{> deprecation}}
41
41
  {{#declaration}}
@@ -3,9 +3,10 @@
3
3
  <div class="task-name-container">
4
4
  <a name="/{{uid}}"></a>
5
5
  <a name="//apple_ref/{{language_stub}}/Section/{{name}}" class="dashAnchor"></a>
6
- <a href="#/{{uid}}">
7
- <h3 class="section-name">{{name}}</h3>
8
- </a>
6
+ <div class="section-name-container">
7
+ <a class="section-name-link" href="#/{{uid}}"></a>
8
+ <h3 class="section-name">{{{name_html}}}</h3>
9
+ </div>
9
10
  </div>
10
11
  {{/name}}
11
12
  <ul class="item-container">
@@ -182,7 +182,7 @@ header {
182
182
  background-color: $bg_color;
183
183
  position: fixed;
184
184
  width: 100%;
185
- z-index: 2;
185
+ z-index: 3;
186
186
  img {
187
187
  padding-right: 6px;
188
188
  vertical-align: -4px;
@@ -204,7 +204,7 @@ header {
204
204
  #breadcrumbs-container {
205
205
  background-color: $bg_color;
206
206
  position: fixed;
207
- z-index: 1;
207
+ z-index: 2;
208
208
  width: 100%;
209
209
  }
210
210
 
@@ -310,6 +310,16 @@ header {
310
310
  margin: -$content_top_offset 0 0;
311
311
  }
312
312
  }
313
+
314
+ .section-name {
315
+ p {
316
+ margin-bottom: inherit;
317
+ line-height: inherit;
318
+ }
319
+ code {
320
+ color: inherit;
321
+ }
322
+ }
313
323
  }
314
324
 
315
325
  .highlight {
@@ -356,6 +366,29 @@ header {
356
366
  }
357
367
  }
358
368
 
369
+ .section-name-container {
370
+ position: relative;
371
+ display: inline-block;
372
+
373
+ .section-name-link {
374
+ position: absolute;
375
+ top: 0;
376
+ left: 0;
377
+ bottom: 0;
378
+ right: 0;
379
+ margin-bottom: 0;
380
+ }
381
+
382
+ .section-name {
383
+ position: relative;
384
+ pointer-events: none;
385
+ z-index: 1;
386
+ a {
387
+ pointer-events: auto;
388
+ }
389
+ }
390
+ }
391
+
359
392
  .item {
360
393
  padding-top: 8px;
361
394
  width: 100%;
@@ -3,9 +3,10 @@
3
3
  <div class="task-name-container">
4
4
  <a name="/{{uid}}"></a>
5
5
  <a name="//apple_ref/{{language_stub}}/Section/{{name}}" class="dashAnchor"></a>
6
- <a href="#/{{uid}}">
7
- <h3 class="section-name">{{name}}</h3>
8
- </a>
6
+ <div class="section-name-container">
7
+ <a class="section-name-link" href="#/{{uid}}"></a>
8
+ <h3 class="section-name">{{{name_html}}}</h3>
9
+ </div>
9
10
  </div>
10
11
  {{/name}}
11
12
  <ul>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jazzy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - JP Simard
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2019-11-11 00:00:00.000000000 Z
13
+ date: 2019-12-09 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: cocoapods