jazzy 0.12.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
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