jazzy 0.14.4 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/Tests.yml +6 -5
  3. data/.rubocop.yml +13 -0
  4. data/CHANGELOG.md +40 -0
  5. data/CONTRIBUTING.md +1 -1
  6. data/Gemfile.lock +62 -47
  7. data/README.md +115 -5
  8. data/bin/sourcekitten +0 -0
  9. data/js/package-lock.json +6 -6
  10. data/lib/jazzy/config.rb +156 -24
  11. data/lib/jazzy/doc.rb +2 -2
  12. data/lib/jazzy/doc_builder.rb +55 -29
  13. data/lib/jazzy/doc_index.rb +185 -0
  14. data/lib/jazzy/docset_builder/info_plist.mustache +1 -1
  15. data/lib/jazzy/docset_builder.rb +44 -13
  16. data/lib/jazzy/extensions/katex/css/katex.min.css +1 -1
  17. data/lib/jazzy/extensions/katex/js/katex.min.js +1 -1
  18. data/lib/jazzy/gem_version.rb +1 -1
  19. data/lib/jazzy/grouper.rb +130 -0
  20. data/lib/jazzy/podspec_documenter.rb +1 -1
  21. data/lib/jazzy/source_declaration/type.rb +10 -2
  22. data/lib/jazzy/source_declaration.rb +69 -8
  23. data/lib/jazzy/source_document.rb +5 -1
  24. data/lib/jazzy/source_module.rb +13 -11
  25. data/lib/jazzy/sourcekitten.rb +231 -237
  26. data/lib/jazzy/symbol_graph/ext_key.rb +37 -0
  27. data/lib/jazzy/symbol_graph/ext_node.rb +23 -6
  28. data/lib/jazzy/symbol_graph/graph.rb +31 -19
  29. data/lib/jazzy/symbol_graph/relationship.rb +21 -3
  30. data/lib/jazzy/symbol_graph/sym_node.rb +10 -22
  31. data/lib/jazzy/symbol_graph/symbol.rb +28 -0
  32. data/lib/jazzy/symbol_graph.rb +19 -16
  33. data/lib/jazzy/themes/apple/assets/css/jazzy.css.scss +10 -7
  34. data/lib/jazzy/themes/apple/assets/js/typeahead.jquery.js +3 -2
  35. data/lib/jazzy/themes/apple/templates/doc.mustache +8 -1
  36. data/lib/jazzy/themes/fullwidth/assets/css/jazzy.css.scss +5 -5
  37. data/lib/jazzy/themes/fullwidth/assets/js/typeahead.jquery.js +3 -2
  38. data/lib/jazzy/themes/fullwidth/templates/doc.mustache +8 -1
  39. data/lib/jazzy/themes/jony/assets/css/jazzy.css.scss +6 -5
  40. data/lib/jazzy/themes/jony/templates/doc.mustache +9 -2
  41. data/spec/integration_spec.rb +8 -1
  42. metadata +5 -2
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jazzy
4
+ module SymbolGraph
5
+ # An ExtKey identifies an extension of a type, made up of the USR of
6
+ # the type and the constraints of the extension. With Swift 5.9 extension
7
+ # symbols, the USR is the 'fake' USR invented by symbolgraph to solve the
8
+ # same problem as this type, which means less merging takes place.
9
+ class ExtKey
10
+ attr_accessor :usr
11
+ attr_accessor :constraints_text
12
+
13
+ def initialize(usr, constraints)
14
+ self.usr = usr
15
+ self.constraints_text = constraints.map(&:to_swift).join
16
+ end
17
+
18
+ def hash_key
19
+ usr + constraints_text
20
+ end
21
+
22
+ def eql?(other)
23
+ hash_key == other.hash_key
24
+ end
25
+
26
+ def hash
27
+ hash_key.hash
28
+ end
29
+ end
30
+
31
+ class ExtSymNode
32
+ def ext_key
33
+ ExtKey.new(usr, all_constraints.ext)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -23,6 +23,7 @@ module Jazzy
23
23
  # an extension that we fabricate to resolve certain relationships.
24
24
  class ExtNode < BaseNode
25
25
  attr_accessor :usr
26
+ attr_accessor :real_usr
26
27
  attr_accessor :name
27
28
  attr_accessor :all_constraints # ExtConstraints
28
29
  attr_accessor :conformances # array, can be empty
@@ -75,15 +76,15 @@ module Jazzy
75
76
  decl + all_constraints.ext.to_where_clause
76
77
  end
77
78
 
78
- def to_sourcekit(module_name)
79
+ def to_sourcekit(module_name, ext_module_name)
79
80
  declaration = full_declaration
80
81
  xml_declaration = "<swift>#{CGI.escapeHTML(declaration)}</swift>"
81
82
 
82
83
  hash = {
83
84
  'key.kind' => 'source.lang.swift.decl.extension',
84
- 'key.usr' => usr,
85
+ 'key.usr' => real_usr || usr,
85
86
  'key.name' => name,
86
- 'key.modulename' => module_name,
87
+ 'key.modulename' => ext_module_name,
87
88
  'key.parsed_declaration' => declaration,
88
89
  'key.annotated_decl' => xml_declaration,
89
90
  }
@@ -94,9 +95,7 @@ module Jazzy
94
95
  end
95
96
  end
96
97
 
97
- unless children.empty?
98
- hash['key.substructure'] = children_to_sourcekit
99
- end
98
+ add_children_to_sourcekit(hash, module_name)
100
99
 
101
100
  hash
102
101
  end
@@ -112,5 +111,23 @@ module Jazzy
112
111
  sort_key <=> other.sort_key
113
112
  end
114
113
  end
114
+
115
+ # An ExtSymNode is an extension generated from a Swift 5.9 extension
116
+ # symbol, for extensions of types from other modules only.
117
+ class ExtSymNode < ExtNode
118
+ attr_accessor :symbol
119
+
120
+ def initialize(symbol)
121
+ self.symbol = symbol
122
+ super(symbol.usr, symbol.full_name,
123
+ # sadly can't tell what constraints are inherited vs added
124
+ ExtConstraints.new([], symbol.constraints))
125
+ end
126
+
127
+ def to_sourcekit(module_name, ext_module_name)
128
+ hash = super
129
+ symbol.add_to_sourcekit(hash)
130
+ end
131
+ end
115
132
  end
116
133
  end
@@ -7,37 +7,40 @@ module Jazzy
7
7
  # Deserialize it to Symbols and Relationships, then rebuild
8
8
  # the AST shape using SymNodes and ExtNodes and extract SourceKit json.
9
9
  class Graph
10
- attr_accessor :module_name
10
+ attr_accessor :module_name # Our module
11
+ attr_accessor :ext_module_name # Module being extended
11
12
  attr_accessor :symbol_nodes # usr -> SymNode
12
13
  attr_accessor :relationships # [Relationship]
13
14
  attr_accessor :ext_nodes # (usr, constraints) -> ExtNode
14
15
 
15
16
  # Parse the JSON into flat tables of data
16
- def initialize(json, module_name)
17
+ def initialize(json, module_name, ext_module_name)
17
18
  self.module_name = module_name
19
+ self.ext_module_name = ext_module_name
18
20
  graph = JSON.parse(json, symbolize_names: true)
19
21
 
20
22
  self.symbol_nodes = {}
23
+ self.ext_nodes = {}
24
+
21
25
  graph[:symbols].each do |hash|
22
26
  symbol = Symbol.new(hash)
23
- symbol_nodes[symbol.usr] = SymNode.new(symbol)
27
+ if symbol.extension?
28
+ node = ExtSymNode.new(symbol)
29
+ ext_nodes[node.ext_key] = node
30
+ else
31
+ symbol_nodes[symbol.usr] = SymNode.new(symbol)
32
+ end
24
33
  end
25
34
 
26
35
  self.relationships =
27
36
  graph[:relationships].map { |hash| Relationship.new(hash) }
28
-
29
- self.ext_nodes = {}
30
37
  end
31
38
 
32
- # ExtNode index. (type USR, extension constraints) -> ExtNode.
39
+ # ExtNode index. ExtKey (type USR, extension constraints) -> ExtNode.
33
40
  # This minimizes the number of extensions
34
41
 
35
- def ext_key(usr, constraints)
36
- usr + constraints.map(&:to_swift).join
37
- end
38
-
39
42
  def add_ext_member(type_usr, member_node, constraints)
40
- key = ext_key(type_usr, constraints.ext)
43
+ key = ExtKey.new(type_usr, constraints.ext)
41
44
  if ext_node = ext_nodes[key]
42
45
  ext_node.add_child(member_node)
43
46
  else
@@ -50,7 +53,7 @@ module Jazzy
50
53
  type_name,
51
54
  protocol,
52
55
  constraints)
53
- key = ext_key(type_usr, constraints.ext)
56
+ key = ExtKey.new(type_usr, constraints.ext)
54
57
  if ext_node = ext_nodes[key]
55
58
  ext_node.add_conformance(protocol)
56
59
  else
@@ -149,6 +152,15 @@ module Jazzy
149
152
  end
150
153
  end
151
154
 
155
+ # "References to fake_usr should be real_usr"
156
+ def unalias_extensions(fake_usr, real_usr)
157
+ ext_nodes.each_pair do |key, ext|
158
+ if key.usr == fake_usr
159
+ ext.real_usr = real_usr
160
+ end
161
+ end
162
+ end
163
+
152
164
  # Process a structural relationship to link nodes
153
165
  def rebuild_rel(rel)
154
166
  source = symbol_nodes[rel.source_usr]
@@ -166,29 +178,29 @@ module Jazzy
166
178
 
167
179
  when :inheritsFrom
168
180
  rebuild_inherits(rel, source, target)
181
+
182
+ when :extensionTo
183
+ unalias_extensions(rel.source_usr, rel.target_usr)
169
184
  end
185
+
170
186
  # don't seem to care about:
171
187
  # - overrides: not bothered, also unimplemented for protocols
172
188
  end
173
189
 
174
190
  # Rebuild the AST structure and convert to SourceKit
175
191
  def to_sourcekit
176
- # Do default impls after the others so we can find protocol
177
- # type nodes from protocol requirements.
178
- default_impls, other_rels =
179
- relationships.partition(&:default_implementation?)
180
- (other_rels + default_impls).each { |r| rebuild_rel(r) }
192
+ relationships.sort.each { |r| rebuild_rel(r) }
181
193
 
182
194
  root_symbol_nodes =
183
195
  symbol_nodes.values
184
196
  .select(&:top_level_decl?)
185
197
  .sort
186
- .map(&:to_sourcekit)
198
+ .map { |n| n.to_sourcekit(module_name) }
187
199
 
188
200
  root_ext_nodes =
189
201
  ext_nodes.values
190
202
  .sort
191
- .map { |n| n.to_sourcekit(module_name) }
203
+ .map { |n| n.to_sourcekit(module_name, ext_module_name) }
192
204
  {
193
205
  'key.diagnostic_stage' => 'parse',
194
206
  'key.substructure' => root_symbol_nodes + root_ext_nodes,
@@ -10,9 +10,14 @@ module Jazzy
10
10
  attr_accessor :target_fallback # can be nil
11
11
  attr_accessor :constraints # array, can be empty
12
12
 
13
- KINDS = %w[memberOf conformsTo defaultImplementationOf
14
- overrides inheritsFrom requirementOf
15
- optionalRequirementOf].freeze
13
+ # Order matters: defaultImplementationOf after the protocols
14
+ # have been defined; extensionTo after all the extensions have
15
+ # been discovered.
16
+ KINDS = %w[memberOf conformsTo overrides inheritsFrom
17
+ requirementOf optionalRequirementOf
18
+ defaultImplementationOf extensionTo].freeze
19
+
20
+ KINDS_INDEX = KINDS.to_h { |i| [i.to_sym, KINDS.index(i)] }.freeze
16
21
 
17
22
  def protocol_requirement?
18
23
  %i[requirementOf optionalRequirementOf].include? kind
@@ -22,6 +27,10 @@ module Jazzy
22
27
  kind == :defaultImplementationOf
23
28
  end
24
29
 
30
+ def extension_to?
31
+ kind == :extensionTo
32
+ end
33
+
25
34
  # Protocol conformances added by compiler to actor decls that
26
35
  # users aren't interested in.
27
36
  def actor_protocol?
@@ -43,6 +52,15 @@ module Jazzy
43
52
  end
44
53
  self.constraints = Constraint.new_list(hash[:swiftConstraints] || [])
45
54
  end
55
+
56
+ # Sort order
57
+ include Comparable
58
+
59
+ def <=>(other)
60
+ return 0 if kind == other.kind
61
+
62
+ KINDS_INDEX[kind] <=> KINDS_INDEX[other.kind]
63
+ end
46
64
  end
47
65
  end
48
66
  end
@@ -18,14 +18,16 @@ module Jazzy
18
18
  children.append(child)
19
19
  end
20
20
 
21
- def children_to_sourcekit
22
- children.sort.map(&:to_sourcekit)
21
+ def add_children_to_sourcekit(hash, module_name)
22
+ unless children.empty?
23
+ hash['key.substructure'] =
24
+ children.sort.map { |c| c.to_sourcekit(module_name) }
25
+ end
23
26
  end
24
27
  end
25
28
 
26
29
  # A SymNode is a node of the reconstructed syntax tree holding a symbol.
27
30
  # It can turn itself into SourceKit and helps decode extensions.
28
- # rubocop:disable Metrics/ClassLength
29
31
  class SymNode < BaseNode
30
32
  attr_accessor :symbol
31
33
  attr_writer :override
@@ -128,8 +130,7 @@ module Jazzy
128
130
  .join("\n")
129
131
  end
130
132
 
131
- # rubocop:disable Metrics/MethodLength
132
- def to_sourcekit
133
+ def to_sourcekit(module_name)
133
134
  declaration = full_declaration
134
135
  xml_declaration = "<swift>#{CGI.escapeHTML(declaration)}</swift>"
135
136
 
@@ -137,32 +138,20 @@ module Jazzy
137
138
  'key.kind' => symbol.kind,
138
139
  'key.usr' => symbol.usr,
139
140
  'key.name' => symbol.name,
140
- 'key.accessibility' => symbol.acl,
141
- 'key.parsed_decl' => declaration,
141
+ 'key.modulename' => module_name,
142
+ 'key.parsed_declaration' => declaration,
142
143
  'key.annotated_decl' => xml_declaration,
143
144
  'key.symgraph_async' => async?,
144
145
  }
145
- if docs = symbol.doc_comments
146
- hash['key.doc.comment'] = docs
147
- hash['key.doc.full_as_xml'] = ''
148
- end
149
146
  if params = symbol.parameter_names
150
147
  hash['key.doc.parameters'] =
151
148
  params.map { |name| { 'name' => name } }
152
149
  end
153
- if location = symbol.location
154
- hash['key.filepath'] = location[:filename]
155
- hash['key.doc.line'] = location[:line] + 1
156
- hash['key.doc.column'] = location[:character] + 1
157
- end
158
- unless children.empty?
159
- hash['key.substructure'] = children_to_sourcekit
160
- end
161
150
  hash['key.symgraph_spi'] = true if symbol.spi
162
151
 
163
- hash
152
+ add_children_to_sourcekit(hash, module_name)
153
+ symbol.add_to_sourcekit(hash)
164
154
  end
165
- # rubocop:enable Metrics/MethodLength
166
155
 
167
156
  # Sort order - by symbol
168
157
  include Comparable
@@ -171,6 +160,5 @@ module Jazzy
171
160
  symbol <=> other.symbol
172
161
  end
173
162
  end
174
- # rubocop:enable Metrics/ClassLength
175
163
  end
176
164
  end
@@ -22,6 +22,10 @@ module Jazzy
22
22
  path_components[-1] || '??'
23
23
  end
24
24
 
25
+ def full_name
26
+ path_components.join('.')
27
+ end
28
+
25
29
  def initialize(hash)
26
30
  self.usr = hash[:identifier][:precise]
27
31
  self.path_components = hash[:pathComponents]
@@ -101,6 +105,7 @@ module Jazzy
101
105
  'associatedtype' => 'associatedtype',
102
106
  'actor' => 'actor',
103
107
  'macro' => 'macro',
108
+ 'extension' => 'extension',
104
109
  }.freeze
105
110
 
106
111
  # We treat 'static var' differently to 'class var'
@@ -122,6 +127,10 @@ module Jazzy
122
127
  self.kind = "source.lang.swift.decl.#{sourcekit_kind}"
123
128
  end
124
129
 
130
+ def extension?
131
+ kind.end_with?('extension')
132
+ end
133
+
125
134
  # Mapping SymbolGraph's ACL to SourceKit
126
135
 
127
136
  def init_acl(acl)
@@ -217,6 +226,25 @@ module Jazzy
217
226
  availability_attributes(avail_hash_list) + spi_attributes
218
227
  end
219
228
 
229
+ # SourceKit common fields, shared by extension and regular symbols.
230
+ # Things we do not know for fabricated extensions.
231
+ def add_to_sourcekit(hash)
232
+ unless doc_comments.nil?
233
+ hash['key.doc.comment'] = doc_comments
234
+ hash['key.doc.full_as_xml'] = ''
235
+ end
236
+
237
+ hash['key.accessibility'] = acl
238
+
239
+ unless location.nil?
240
+ hash['key.filepath'] = location[:filename]
241
+ hash['key.doc.line'] = location[:line] + 1
242
+ hash['key.doc.column'] = location[:character] + 1
243
+ end
244
+
245
+ hash
246
+ end
247
+
220
248
  # Sort order
221
249
  include Comparable
222
250
 
@@ -7,6 +7,7 @@ require 'jazzy/symbol_graph/symbol'
7
7
  require 'jazzy/symbol_graph/relationship'
8
8
  require 'jazzy/symbol_graph/sym_node'
9
9
  require 'jazzy/symbol_graph/ext_node'
10
+ require 'jazzy/symbol_graph/ext_key'
10
11
 
11
12
  # This is the top-level symbolgraph driver that deals with
12
13
  # figuring out arguments, running the tool, and loading the
@@ -19,10 +20,10 @@ module Jazzy
19
20
  # with configured args.
20
21
  # Then parse the results, and return as JSON in SourceKit[ten]
21
22
  # format.
22
- def self.build(config)
23
- if config.symbolgraph_directory.nil?
23
+ def self.build(module_config)
24
+ if module_config.symbolgraph_directory.nil?
24
25
  Dir.mktmpdir do |tmp_dir|
25
- args = arguments(config, tmp_dir)
26
+ args = arguments(module_config, tmp_dir)
26
27
 
27
28
  Executable.execute_command('swift',
28
29
  args.unshift('symbolgraph-extract'),
@@ -31,17 +32,17 @@ module Jazzy
31
32
  parse_symbols(tmp_dir)
32
33
  end
33
34
  else
34
- parse_symbols(config.symbolgraph_directory.to_s)
35
+ parse_symbols(module_config.symbolgraph_directory.to_s)
35
36
  end
36
37
  end
37
38
 
38
39
  # Figure out the args to pass to symbolgraph-extract
39
- def self.arguments(config, output_path)
40
- if config.module_name.empty?
40
+ def self.arguments(module_config, output_path)
41
+ if module_config.module_name.empty?
41
42
  raise 'error: `--swift-build-tool symbolgraph` requires `--module`.'
42
43
  end
43
44
 
44
- user_args = config.build_tool_arguments.join
45
+ user_args = module_config.build_tool_arguments.join
45
46
 
46
47
  if user_args =~ /-(?:module-name|minimum-access-level|output-dir)/
47
48
  raise 'error: `--build-tool-arguments` for ' \
@@ -51,19 +52,19 @@ module Jazzy
51
52
 
52
53
  # Default set
53
54
  args = [
54
- '-module-name', config.module_name,
55
+ '-module-name', module_config.module_name,
55
56
  '-minimum-access-level', 'private',
56
57
  '-output-dir', output_path,
57
58
  '-skip-synthesized-members'
58
59
  ]
59
60
 
60
61
  # Things user can override
61
- args += ['-sdk', sdk(config)] unless user_args =~ /-sdk/
62
+ args += ['-sdk', sdk(module_config)] unless user_args =~ /-sdk/
62
63
  args += ['-target', target] unless user_args =~ /-target/
63
- args += ['-F', config.source_directory.to_s] unless user_args =~ /-F(?!s)/
64
- args += ['-I', config.source_directory.to_s] unless user_args =~ /-I/
64
+ args += ['-F', module_config.source_directory.to_s] unless user_args =~ /-F(?!s)/
65
+ args += ['-I', module_config.source_directory.to_s] unless user_args =~ /-I/
65
66
 
66
- args + config.build_tool_arguments
67
+ args + module_config.build_tool_arguments
67
68
  end
68
69
 
69
70
  # Parse the symbol files in the given directory
@@ -72,17 +73,19 @@ module Jazzy
72
73
  # The @ part is for extensions in our module (before the @)
73
74
  # of types in another module (after the @).
74
75
  File.basename(filename) =~ /(.*?)(@(.*?))?\.symbols/
75
- module_name = Regexp.last_match[3] || Regexp.last_match[1]
76
+ module_name = Regexp.last_match[1]
77
+ ext_module_name = Regexp.last_match[3] || module_name
78
+ json = File.read(filename)
76
79
  {
77
80
  filename =>
78
- Graph.new(File.read(filename), module_name).to_sourcekit,
81
+ Graph.new(json, module_name, ext_module_name).to_sourcekit,
79
82
  }
80
83
  end.to_json
81
84
  end
82
85
 
83
86
  # Get the SDK path. On !darwin this just isn't needed.
84
- def self.sdk(config)
85
- `xcrun --show-sdk-path --sdk #{config.sdk}`.chomp
87
+ def self.sdk(module_config)
88
+ `xcrun --show-sdk-path --sdk #{module_config.sdk}`.chomp
86
89
  end
87
90
 
88
91
  # Guess a default LLVM target. Feels like the tool should figure this
@@ -23,7 +23,7 @@ $content_top_offset: 70px;
23
23
  $content_body_margin: 16px;
24
24
  $content_body_left_offset: $sidebar_width + $content_body_margin;
25
25
  $header_height: 32px;
26
- $breadcrumb_padding_top: 17px;
26
+ $breadcrumb_padding_top: 12px;
27
27
 
28
28
  $code_font: 0.95em Menlo, monospace;
29
29
 
@@ -206,9 +206,11 @@ header {
206
206
  height: $content_top_offset - $header_height - $breadcrumb_padding_top;
207
207
  padding-top: $breadcrumb_padding_top;
208
208
  position: fixed;
209
- width: 100%;
209
+ width: inherit;
210
210
  z-index: 2;
211
211
  margin-top: $header_height;
212
+ white-space: nowrap;
213
+ overflow-x: scroll;
212
214
  #carat {
213
215
  height: 10px;
214
216
  margin: 0 5px;
@@ -412,11 +414,12 @@ header {
412
414
  .discouraged {
413
415
  text-decoration: line-through;
414
416
  }
415
- .declaration-note {
416
- font-size: .85em;
417
- color: rgba(128,128,128,1);
418
- font-style: italic;
419
- }
417
+ }
418
+
419
+ .declaration-note {
420
+ font-size: .85em;
421
+ color: rgba(128,128,128,1);
422
+ font-style: italic;
420
423
  }
421
424
 
422
425
  .pointer-container {
@@ -1,7 +1,7 @@
1
1
  /*!
2
- * typeahead.js 1.3.1
2
+ * typeahead.js 1.3.3
3
3
  * https://github.com/corejavascript/typeahead.js
4
- * Copyright 2013-2020 Twitter, Inc. and other contributors; Licensed MIT
4
+ * Copyright 2013-2024 Twitter, Inc. and other contributors; Licensed MIT
5
5
  */
6
6
 
7
7
 
@@ -499,6 +499,7 @@
499
499
  });
500
500
  this.$input.attr({
501
501
  "aria-owns": id + "_listbox",
502
+ "aria-controls": id + "_listbox",
502
503
  role: "combobox",
503
504
  "aria-autocomplete": "list",
504
505
  "aria-expanded": false
@@ -28,9 +28,16 @@
28
28
  {{> header}}
29
29
  <div class="content-wrapper">
30
30
  <p id="breadcrumbs">
31
- <a href="{{path_to_root}}index.html">{{module_name}} Reference</a>
31
+ <a href="{{path_to_root}}index.html">{{readme_title}}</a>
32
+ {{#breadcrumbs}}
32
33
  <img id="carat" src="{{path_to_root}}img/carat.png" alt=""/>
34
+ {{#last}}
33
35
  {{name}} {{kind}} Reference
36
+ {{/last}}
37
+ {{^last}}
38
+ <a href="{{path_to_root}}{{url}}">{{name}}</a>
39
+ {{/last}}
40
+ {{/breadcrumbs}}
34
41
  </p>
35
42
  </div>
36
43
  <div class="content-wrapper">
@@ -454,12 +454,12 @@ pre code {
454
454
  margin-left: 20px;
455
455
  font-size: 1rem;
456
456
  }
457
+ }
457
458
 
458
- .declaration-note {
459
- font-size: .85em;
460
- color: #808080;
461
- font-style: italic;
462
- }
459
+ .declaration-note {
460
+ font-size: .85em;
461
+ color: #808080;
462
+ font-style: italic;
463
463
  }
464
464
 
465
465
  .pointer-container {
@@ -1,7 +1,7 @@
1
1
  /*!
2
- * typeahead.js 1.3.1
2
+ * typeahead.js 1.3.3
3
3
  * https://github.com/corejavascript/typeahead.js
4
- * Copyright 2013-2020 Twitter, Inc. and other contributors; Licensed MIT
4
+ * Copyright 2013-2024 Twitter, Inc. and other contributors; Licensed MIT
5
5
  */
6
6
 
7
7
 
@@ -499,6 +499,7 @@
499
499
  });
500
500
  this.$input.attr({
501
501
  "aria-owns": id + "_listbox",
502
+ "aria-controls": id + "_listbox",
502
503
  role: "combobox",
503
504
  "aria-autocomplete": "list",
504
505
  "aria-expanded": false
@@ -31,9 +31,16 @@
31
31
  {{> header}}
32
32
 
33
33
  <p class="breadcrumbs">
34
- <a class="breadcrumb" href="{{path_to_root}}index.html">{{module_name}} Reference</a>
34
+ <a class="breadcrumb" href="{{path_to_root}}index.html">{{readme_title}}</a>
35
+ {{#breadcrumbs}}
35
36
  <img class="carat" src="{{path_to_root}}img/carat.png" alt=""/>
37
+ {{#last}}
36
38
  {{name}} {{kind}} Reference
39
+ {{/last}}
40
+ {{^last}}
41
+ <a class="breadcrumb" href="{{path_to_root}}{{url}}">{{name}}</a>
42
+ {{/last}}
43
+ {{/breadcrumbs}}
37
44
  </p>
38
45
 
39
46
  <div class="content-wrapper">
@@ -450,11 +450,12 @@ header {
450
450
  .token-open {
451
451
  margin-left: 45px;
452
452
  }
453
- .declaration-note {
454
- font-size: .85em;
455
- color: rgba(128,128,128,1);
456
- font-style: italic;
457
- }
453
+ }
454
+
455
+ .declaration-note {
456
+ font-size: .85em;
457
+ color: rgba(128,128,128,1);
458
+ font-style: italic;
458
459
  }
459
460
 
460
461
  .pointer-container {
@@ -26,10 +26,17 @@
26
26
  <div class="content-wrapper">
27
27
  <p id="breadcrumbs">
28
28
  <span class="no-mobile">
29
- <a href="{{path_to_root}}index.html">{{module_name}} Reference</a>
29
+ <a href="{{path_to_root}}index.html">{{readme_title}}</a>
30
+ {{#breadcrumbs}}
30
31
  <img id="carat" src="{{path_to_root}}img/carat.png" alt=""/>
32
+ {{#last}}
33
+ {{name}} {{kind}} Reference
34
+ {{/last}}
35
+ {{^last}}
36
+ <a href="{{path_to_root}}{{url}}">{{name}}</a>
37
+ {{/last}}
38
+ {{/breadcrumbs}}
31
39
  </span>
32
- {{name}} {{kind}} Reference
33
40
  </p>
34
41
  </div>
35
42
  </div>
@@ -121,6 +121,8 @@ describe_cli 'jazzy' do
121
121
  s.replace_pattern(%r{/transformed/}, '/')
122
122
  # Xcode 15 workaround
123
123
  s.replace_pattern(/objc\[.....\]: Class _?DTX\w+ is implemented in both.*?\n/, '')
124
+ # arm vs. intel workaround
125
+ s.replace_pattern(%r{(?<=build/)(arm64|x86_64)(?=-apple)}, '')
124
126
  end
125
127
 
126
128
  require 'shellwords'
@@ -246,7 +248,12 @@ describe_cli 'jazzy' do
246
248
  module_path = `swift build --scratch-path #{build_path} --show-bin-path`
247
249
  behaves_like cli_spec 'misc_jazzy_symgraph_features',
248
250
  '--swift-build-tool symbolgraph ' \
249
- "--build-tool-arguments -I,#{module_path} "
251
+ '--build-tool-arguments ' \
252
+ "-emit-extension-block-symbols,-I,#{module_path}"
253
+ end
254
+
255
+ describe 'Creates docs for a multiple-module project' do
256
+ behaves_like cli_spec 'jazzy_multi_modules'
250
257
  end
251
258
  end if !spec_subset || spec_subset == 'swift'
252
259