jazzy 0.0.13 → 0.0.14

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/.rubocop.yml +4 -3
  3. data/Gemfile.lock +5 -3
  4. data/Rakefile +4 -2
  5. data/bin/sourcekitten +0 -0
  6. data/jazzy.gemspec +1 -0
  7. data/lib/jazzy/assets/css/{jazzy.css → jazzy.css.scss} +199 -231
  8. data/lib/jazzy/config.rb +27 -13
  9. data/lib/jazzy/doc.mustache +2 -2
  10. data/lib/jazzy/doc.rb +2 -1
  11. data/lib/jazzy/doc_builder.rb +124 -70
  12. data/lib/jazzy/gem_version.rb +1 -1
  13. data/lib/jazzy/source_module.rb +28 -0
  14. data/lib/jazzy/sourcekitten.rb +95 -70
  15. data/lib/jazzy/xml_helper.rb +2 -1
  16. data/spec/integration_specs/document_alamofire/after/docs/Classes.html +2 -2
  17. data/spec/integration_specs/document_alamofire/after/docs/Classes/Manager.html +2 -2
  18. data/spec/integration_specs/document_alamofire/after/docs/Classes/Manager/init(configuration:).html +2 -2
  19. data/spec/integration_specs/document_alamofire/after/docs/Classes/Request.html +2 -2
  20. data/spec/integration_specs/document_alamofire/after/docs/Enums.html +2 -2
  21. data/spec/integration_specs/document_alamofire/after/docs/Enums/ParameterEncoding.html +2 -2
  22. data/spec/integration_specs/document_alamofire/after/docs/Extensions.html +2 -2
  23. data/spec/integration_specs/document_alamofire/after/docs/Extensions/Manager.html +2 -2
  24. data/spec/integration_specs/document_alamofire/after/docs/Extensions/Request.html +2 -2
  25. data/spec/integration_specs/document_alamofire/after/docs/Functions.html +2 -2
  26. data/spec/integration_specs/document_alamofire/after/docs/Global Variables.html +2 -2
  27. data/spec/integration_specs/document_alamofire/after/docs/Protocols.html +2 -2
  28. data/spec/integration_specs/document_alamofire/after/docs/Protocols/URLRequestConvertible.html +2 -2
  29. data/spec/integration_specs/document_alamofire/after/docs/Protocols/URLStringConvertible.html +2 -2
  30. data/spec/integration_specs/document_alamofire/after/docs/css/jazzy.css +140 -257
  31. data/spec/integration_specs/document_alamofire/after/docs/index.html +2 -2
  32. data/spec/integration_specs/document_alamofire/after/execution_output.txt +2 -1
  33. data/spec/integration_specs/misc_jazzy_features/after/docs/Classes.html +2 -2
  34. data/spec/integration_specs/misc_jazzy_features/after/docs/Classes/ImplicitlyInternalTopLevelClass.html +2 -2
  35. data/spec/integration_specs/misc_jazzy_features/after/docs/Enums.html +2 -2
  36. data/spec/integration_specs/misc_jazzy_features/after/docs/Enums/DocumentedEnum.html +2 -2
  37. data/spec/integration_specs/misc_jazzy_features/after/docs/Global Variables.html +2 -2
  38. data/spec/integration_specs/misc_jazzy_features/after/docs/css/jazzy.css +140 -257
  39. data/spec/integration_specs/misc_jazzy_features/after/docs/index.html +2 -2
  40. data/spec/integration_specs/misc_jazzy_features/after/execution_output.txt +2 -1
  41. metadata +18 -4
  42. data/.rubocop_todo.yml +0 -24
data/lib/jazzy/config.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'optparse'
2
+ require 'pathname'
2
3
 
3
4
  module Jazzy
4
5
  class Config
@@ -14,7 +15,7 @@ module Jazzy
14
15
  attr_accessor :clean
15
16
 
16
17
  def initialize
17
- self.output = File.expand_path('docs')
18
+ self.output = Pathname('docs')
18
19
  self.xcodebuild_arguments = []
19
20
  self.author_name = ''
20
21
  self.module_name = ''
@@ -26,6 +27,7 @@ module Jazzy
26
27
  self.clean = false
27
28
  end
28
29
 
30
+ # rubocop:disable Metrics/MethodLength
29
31
  def self.parse!
30
32
  config = new
31
33
  OptionParser.new do |opt|
@@ -33,46 +35,58 @@ module Jazzy
33
35
  opt.separator ''
34
36
  opt.separator 'Options'
35
37
 
36
- opt.on('-o', '--output FOLDER', 'Folder to output the HTML docs to') do |output|
37
- config.output = File.expand_path(output)
38
+ opt.on('-o', '--output FOLDER',
39
+ 'Folder to output the HTML docs to') do |output|
40
+ config.output = Pathname(output)
38
41
  end
39
42
 
40
43
  opt.on('-c', '--[no-]clean',
41
44
  'Delete contents of output directory before running.',
42
- 'WARNING: If --output is set to ~/Desktop, this will delete the ~/Desktop directory.') do |clean|
45
+ 'WARNING: If --output is set to ~/Desktop, this will delete the \
46
+ ~/Desktop directory.') do |clean|
43
47
  config.clean = clean
44
48
  end
45
49
 
46
- opt.on('-x', '--xcodebuild-arguments arg1,arg2,…argN', Array, 'Arguments to forward to xcodebuild') do |args|
50
+ opt.on('-x', '--xcodebuild-arguments arg1,arg2,…argN', Array,
51
+ 'Arguments to forward to xcodebuild') do |args|
47
52
  config.xcodebuild_arguments = args
48
53
  end
49
54
 
50
- opt.on('-a', '--author AUTHOR_NAME', 'Name of author to attribute in docs (i.e. Realm)') do |a|
55
+ opt.on('-a', '--author AUTHOR_NAME',
56
+ 'Name of author to attribute in docs (i.e. Realm)') do |a|
51
57
  config.author_name = a
52
58
  end
53
59
 
54
- opt.on('-u', '--author_url URL', 'Author URL of this project (i.e. http://realm.io)') do |u|
60
+ opt.on('-u', '--author_url URL',
61
+ 'Author URL of this project (i.e. http://realm.io)') do |u|
55
62
  config.author_url = u
56
63
  end
57
64
 
58
- opt.on('-m', '--module MODULE_NAME', 'Name of module being documented. (i.e. RealmSwift)') do |m|
65
+ opt.on('-m', '--module MODULE_NAME',
66
+ 'Name of module being documented. (i.e. RealmSwift)') do |m|
59
67
  config.module_name = m
60
68
  end
61
69
 
62
- opt.on('-d', '--dash_url URL', 'URL to install docs in Dash (i.e. dash-feed://http%3A%2F%2Fcocoadocs.org%2Fdocsets%2FRealm%2FRealm.xml') do |d|
70
+ opt.on('-d', '--dash_url URL',
71
+ 'URL to install docs in Dash (i.e. dash-feed://...') do |d|
63
72
  config.dash_url = d
64
73
  end
65
74
 
66
- opt.on('-g', '--github_url URL', 'GitHub URL of this project (i.e. https://github.com/realm/realm-cocoa)') do |g|
75
+ opt.on('-g', '--github_url URL',
76
+ 'GitHub URL of this project (i.e. \
77
+ https://github.com/realm/realm-cocoa)') do |g|
67
78
  config.github_url = g
68
79
  end
69
80
 
70
- opt.on('--github-file-prefix PREFIX', 'GitHub URL file prefix of this project (i.e. https://github.com/realm/realm-cocoa/tree/v0.87.1)') do |g|
81
+ opt.on('--github-file-prefix PREFIX',
82
+ 'GitHub URL file prefix of this project (i.e. \
83
+ https://github.com/realm/realm-cocoa/tree/v0.87.1)') do |g|
71
84
  config.github_file_prefix = g
72
85
  end
73
86
 
74
- opt.on('-s', '--sourcekitten-sourcefile FILEPATH', 'XML doc file generated from sourcekitten to parse') do |s|
75
- config.sourcekitten_sourcefile = s
87
+ opt.on('-s', '--sourcekitten-sourcefile FILEPATH',
88
+ 'XML doc file generated from sourcekitten to parse') do |s|
89
+ config.sourcekitten_sourcefile = Pathname(s)
76
90
  end
77
91
 
78
92
  opt.on('-v', '--version', 'Print version number') do
@@ -11,7 +11,7 @@
11
11
  <a title="{{name}} {{kind}} Reference"></a>
12
12
  <header>
13
13
  <div class="content-wrapper">
14
- <p class="header-text"><a href="#">{{module_name}} Docs</a></p>
14
+ <p class="header-text"><a href="{{path_to_root}}index.html">{{module_name}} Docs</a> ({{doc_coverage}}% documented)</p>
15
15
  {{#github_url}}
16
16
  <p id="header-links"><a href="{{github_url}}"><img id="header-icon" src="{{path_to_root}}img/gh.png" height="16px" width="16px" />View on GitHub</a></p>
17
17
  {{/github_url}}
@@ -23,7 +23,7 @@
23
23
  <section id="valence">
24
24
  <div class="content-wrapper">
25
25
  <p id="hierarchial_navigation">
26
- <a href="#" id="design_resources_link">{{module_name}} Reference</a>
26
+ <a href="{{path_to_root}}index.html" id="design_resources_link">{{module_name}} Reference</a>
27
27
  <img id="carat" src="{{path_to_root}}img/carat.png" height="10px" width="6px" />
28
28
  {{name}} {{kind}} Reference
29
29
  </p>
data/lib/jazzy/doc.rb CHANGED
@@ -1,10 +1,11 @@
1
1
  require 'date'
2
+ require 'pathname'
2
3
 
3
4
  require 'jazzy/gem_version'
4
5
 
5
6
  module Jazzy
6
7
  class Doc < Mustache
7
- self.template_path = File.dirname(__FILE__) + '/..'
8
+ self.template_path = Pathname(__FILE__).parent.parent
8
9
 
9
10
  def date
10
11
  # Fake date is used to keep integration tests consistent
@@ -1,11 +1,14 @@
1
1
  require 'fileutils'
2
2
  require 'mustache'
3
3
  require 'uri'
4
+ require 'pathname'
5
+ require 'sass'
4
6
 
5
7
  require 'jazzy/config'
6
8
  require 'jazzy/doc'
7
9
  require 'jazzy/jazzy_markdown'
8
10
  require 'jazzy/source_declaration'
11
+ require 'jazzy/source_module'
9
12
  require 'jazzy/sourcekitten'
10
13
 
11
14
  module Jazzy
@@ -14,18 +17,21 @@ module Jazzy
14
17
  module DocBuilder
15
18
  # mkdir -p output directory and clean if option is set
16
19
  def self.prepare_output_dir(output_dir, clean)
17
- FileUtils.rm_r output_dir if clean && File.directory?(output_dir)
20
+ FileUtils.rm_r output_dir if clean && output_dir.directory?
18
21
  FileUtils.mkdir_p output_dir
19
22
  end
20
23
 
21
24
  # Generate doc structure to be used in sidebar navigation
22
- # @return [Array] doc structure comprised of section names and child names and URLs
25
+ # @return [Array] doc structure comprised of
26
+ # section names & child names & URLs
23
27
  def self.doc_structure_for_docs(docs)
24
28
  structure = []
25
29
  docs.each do |doc|
26
30
  structure << {
27
31
  section: doc.name,
28
- children: doc.children.map { |child| { name: child.name, url: child.url } },
32
+ children: doc.children.map do |child|
33
+ { name: child.name, url: child.url }
34
+ end,
29
35
  }
30
36
  end
31
37
  structure
@@ -35,9 +41,7 @@ module Jazzy
35
41
  # @param [Config] options
36
42
  def self.build(options)
37
43
  if options.sourcekitten_sourcefile
38
- file = File.open(options.sourcekitten_sourcefile)
39
- file_contents = file.read
40
- file.close
44
+ file_contents = options.sourcekitten_sourcefile.read
41
45
  build_docs_for_sourcekitten_output(file_contents, options)
42
46
  else
43
47
  stdout = SourceKitten.run_sourcekitten(options.xcodebuild_arguments)
@@ -61,16 +65,22 @@ module Jazzy
61
65
  # @param [Integer] depth Number of parents. Used to calculate path_to_root
62
66
  # for web.
63
67
  # @param [Array] doc_structure @see #doc_structure_for_docs
64
- def self.build_docs(output_dir, docs, options, depth, doc_structure)
68
+ def self.build_docs(output_dir, docs, source_module, depth)
65
69
  docs.each do |doc|
66
70
  next if doc.name != 'index' && doc.children.count == 0
67
71
  prepare_output_dir(output_dir, false)
68
- path = File.join(output_dir, "#{doc.name}.html")
72
+ path = output_dir + "#{doc.name}.html"
69
73
  path_to_root = ['../'].cycle(depth).to_a.join('')
70
- File.open(path, 'w') { |file| file.write(DocBuilder.document(options, doc, path_to_root, doc_structure)) }
71
- if doc.name != 'index'
72
- DocBuilder.build_docs(File.join(output_dir, doc.name), doc.children, options, depth + 1, doc_structure)
74
+ path.open('w') do |file|
75
+ file.write(document(source_module, doc, path_to_root))
73
76
  end
77
+ next if doc.name == 'index'
78
+ build_docs(
79
+ output_dir + doc.name,
80
+ doc.children,
81
+ source_module,
82
+ depth + 1,
83
+ )
74
84
  end
75
85
  end
76
86
 
@@ -80,88 +90,132 @@ module Jazzy
80
90
  def self.build_docs_for_sourcekitten_output(sourcekitten_output, options)
81
91
  output_dir = options.output
82
92
  prepare_output_dir(output_dir, options.clean)
83
- docs = SourceKitten.parse(sourcekitten_output)
84
- doc_structure = doc_structure_for_docs(docs)
93
+
94
+ (docs, coverage) = SourceKitten.parse(sourcekitten_output)
95
+
96
+ structure = doc_structure_for_docs(docs)
97
+
85
98
  docs << SourceDeclaration.new.tap { |sd| sd.name = 'index' }
86
- DocBuilder.build_docs(output_dir, docs, options, 0, doc_structure)
87
99
 
88
- # Copy assets into output directory
89
- assets_dir = File.expand_path(File.dirname(__FILE__) + '/../../lib/jazzy/assets/') + '/.'
90
- FileUtils.cp_r(assets_dir, output_dir)
100
+ source_module = SourceModule.new(options, docs, structure, coverage)
101
+ build_docs(output_dir, source_module.docs, source_module, 0)
102
+
103
+ copy_assets(output_dir)
91
104
 
92
- puts 'jam out ♪♫ to your fresh new docs at ' + output_dir
105
+ puts "jam out ♪♫ to your fresh new docs in `#{output_dir}`"
93
106
  end
94
107
 
95
- # Build Mustache document from single parsed doc
108
+ def self.copy_assets(destination)
109
+ origin = Pathname(__FILE__).parent + '../../lib/jazzy/assets/.'
110
+ FileUtils.cp_r(origin, destination)
111
+ Pathname.glob(destination + 'css/**/*.scss').each do |scss|
112
+ contents = scss.read
113
+ css = Sass::Engine.new(contents, syntax: :scss).render
114
+ css_filename = scss.sub(/\.scss$/, '')
115
+ css_filename.open('w') { |f| f.write(css) }
116
+ FileUtils.rm scss
117
+ end
118
+ end
119
+
120
+ # Build index Mustache document
96
121
  # @param [Config] options Build options
97
- # @param [Hash] doc_model Parsed doc. @see SourceKitten.parse
98
122
  # @param [String] path_to_root
99
123
  # @param [Array] doc_structure doc structure comprised of section names and
100
124
  # child names and URLs. @see doc_structure_for_docs
101
- def self.document(options, doc_model, path_to_root, doc_structure)
125
+ def self.document_index(source_module, path_to_root)
102
126
  doc = Doc.new # Mustache model instance
103
- # Do something special for index.
104
- # @todo render README here
105
- if doc_model.name == 'index'
106
- doc[:name] = options.module_name
107
- doc[:overview] = Jazzy.markdown.render(
108
- "This is the index page for #{options.module_name} docs. " \
109
- 'Navigate using the links on the left.',
110
- )
111
- doc[:structure] = doc_structure
112
- doc[:module_name] = options.module_name
113
- doc[:author_name] = options.author_name
114
- doc[:author_website] = options.author_url
115
- doc[:github_url] = options.github_url
116
- doc[:dash_url] = options.dash_url
117
- doc[:path_to_root] = path_to_root
118
- return doc.render
127
+ doc[:name] = source_module.name
128
+ doc[:overview] = Jazzy.markdown.render(
129
+ "This is the index page for #{source_module.name} docs. " \
130
+ 'Navigate using the links on the left.',
131
+ )
132
+ doc[:doc_coverage] = source_module.doc_coverage
133
+ doc[:structure] = source_module.doc_structure
134
+ doc[:module_name] = source_module.name
135
+ doc[:author_name] = source_module.author_name
136
+ doc[:author_website] = source_module.author_url
137
+ doc[:github_url] = source_module.github_url
138
+ doc[:dash_url] = source_module.dash_url
139
+ doc[:path_to_root] = path_to_root
140
+ doc.render
141
+ end
142
+
143
+ # Construct Github token URL
144
+ # @param [Hash] item Parsed doc child item
145
+ # @param [Config] options Build options
146
+ def self.gh_token_url(item, source_module)
147
+ if source_module.github_file_prefix && item.file
148
+ gh_prefix = source_module.github_file_prefix
149
+ relative_file_path = item.file.gsub(`pwd`.strip, '')
150
+ gh_line = "#L#{item.line}"
151
+ gh_prefix + relative_file_path + gh_line
119
152
  end
153
+ end
120
154
 
121
- ########################################################
122
- # Map doc_model values to mustache model values
123
- ########################################################
155
+ # Build mustache item for a top-level doc
156
+ # @param [Hash] item Parsed doc child item
157
+ # @param [Config] options Build options
158
+ def self.render_item(item, source_module)
159
+ # Combine abstract and discussion into abstract
160
+ abstract = (item.abstract || '') + (item.discussion || '')
161
+ item_render = {
162
+ name: item.name,
163
+ abstract: Jazzy.markdown.render(abstract),
164
+ declaration: item.declaration,
165
+ usr: item.usr,
166
+ }
167
+ gh_token_url = gh_token_url(item, source_module)
168
+ item_render[:github_token_url] = gh_token_url if gh_token_url
169
+ item_render[:return] = Jazzy.markdown.render(item.return) if item.return
170
+ item_render[:parameters] = item.parameters if item.parameters.length > 0
171
+ item_render
172
+ end
124
173
 
125
- doc[:name] = doc_model.name
126
- doc[:kind] = doc_model.kindName
127
- doc[:overview] = Jazzy.markdown.render(doc_model.abstract || '')
128
- doc[:tasks] = []
129
- doc[:structure] = doc_structure
174
+ # Render tasks for Mustache document
175
+ # @param [Config] options Build options
176
+ # @param [Hash] doc_model Parsed doc. @see SourceKitten.parse
177
+ def self.render_tasks(source_module, doc_model)
178
+ tasks = []
130
179
  # @todo parse mark-style comments and use as task names
131
180
  tasknames = ['Children']
132
181
  tasknames.each do |taskname|
133
182
  items = []
134
- doc_model.children.each do |sub_item|
135
- # Combine abstract and discussion into abstract
136
- abstract = (sub_item.abstract || '') + (sub_item.discussion || '')
137
- item = {
138
- name: sub_item.name,
139
- abstract: Jazzy.markdown.render(abstract),
140
- declaration: sub_item.declaration,
141
- usr: sub_item.usr,
142
- }
143
- if options.github_file_prefix && sub_item.file
144
- gh_prefix = options.github_file_prefix
145
- relative_file_path = sub_item.file.gsub(`pwd`.strip, '')
146
- gh_line = "#L#{sub_item.line}"
147
- item[:github_token_url] = gh_prefix + relative_file_path + gh_line
148
- end
149
- item[:return] = Jazzy.markdown.render(sub_item.return) if sub_item.return
150
- parameters = sub_item.parameters
151
- item[:parameters] = parameters if parameters.length > 0
152
- items << item
183
+ doc_model.children.each do |item|
184
+ items << render_item(item, source_module)
153
185
  end
154
- doc[:tasks] << {
186
+ tasks << {
155
187
  name: '',
156
188
  uid: URI.encode(taskname),
157
189
  items: items,
158
190
  }
159
191
  end
160
- doc[:module_name] = options.module_name
161
- doc[:author_name] = options.author_name
162
- doc[:author_website] = options.author_url
163
- doc[:github_url] = options.github_url
164
- doc[:dash_url] = options.dash_url
192
+ tasks
193
+ end
194
+
195
+ # Build Mustache document from single parsed doc
196
+ # @param [Config] options Build options
197
+ # @param [Hash] doc_model Parsed doc. @see SourceKitten.parse
198
+ # @param [String] path_to_root
199
+ # @param [Array] doc_structure doc structure comprised of section names and
200
+ # child names and URLs. @see doc_structure_for_docs
201
+ def self.document(source_module, doc_model, path_to_root)
202
+ # @todo render README here
203
+ if doc_model.name == 'index'
204
+ return document_index(source_module, path_to_root)
205
+ end
206
+
207
+ doc = Doc.new # Mustache model instance
208
+ doc[:doc_coverage] = source_module.doc_coverage
209
+ doc[:name] = doc_model.name
210
+ doc[:kind] = doc_model.kindName
211
+ doc[:overview] = Jazzy.markdown.render(doc_model.abstract || '')
212
+ doc[:structure] = source_module.doc_structure
213
+ doc[:tasks] = render_tasks(source_module, doc_model)
214
+ doc[:module_name] = source_module.name
215
+ doc[:author_name] = source_module.author_name
216
+ doc[:author_website] = source_module.author_url
217
+ doc[:github_url] = source_module.github_url
218
+ doc[:dash_url] = source_module.dash_url
165
219
  doc[:path_to_root] = path_to_root
166
220
  doc.render
167
221
  end
@@ -1,3 +1,3 @@
1
1
  module Jazzy
2
- VERSION = '0.0.13' unless defined? Jazzy::VERSION
2
+ VERSION = '0.0.14' unless defined? Jazzy::VERSION
3
3
  end
@@ -0,0 +1,28 @@
1
+ require 'jazzy/config'
2
+ require 'jazzy/source_declaration'
3
+
4
+ module Jazzy
5
+ class SourceModule
6
+ attr_accessor :name
7
+ attr_accessor :docs
8
+ attr_accessor :doc_coverage
9
+ attr_accessor :doc_structure
10
+ attr_accessor :author_name
11
+ attr_accessor :github_url
12
+ attr_accessor :github_file_prefix
13
+ attr_accessor :author_url
14
+ attr_accessor :dash_url
15
+
16
+ def initialize(options, docs, doc_structure, doc_coverage)
17
+ self.docs = docs
18
+ self.doc_structure = doc_structure
19
+ self.doc_coverage = doc_coverage
20
+ self.name = options.module_name
21
+ self.author_name = options.author_name
22
+ self.github_url = options.github_url
23
+ self.github_file_prefix = options.github_file_prefix
24
+ self.author_url = options.author_url
25
+ self.dash_url = options.dash_url
26
+ end
27
+ end
28
+ end
@@ -1,5 +1,6 @@
1
1
  require 'active_support/inflector'
2
2
  require 'json'
3
+ require 'pathname'
3
4
 
4
5
  require 'jazzy/config'
5
6
  require 'jazzy/source_declaration'
@@ -8,42 +9,40 @@ require 'jazzy/xml_helper'
8
9
  module Jazzy
9
10
  # This module interacts with the sourcekitten command-line executable
10
11
  module SourceKitten
11
- # SourceKit-provided token kinds along with their human-readable descriptions
12
+ # SourceKit-provided token kinds along with their names
12
13
  # @todo Make sure this list is exhaustive for source.lang.swift.decl.*
13
- def self.kinds
14
- {
15
- 'source.lang.swift.decl.function.method.class' => 'Class Method',
16
- 'source.lang.swift.decl.var.class' => 'Class Variable',
17
- 'source.lang.swift.decl.class' => 'Class',
18
- 'source.lang.swift.decl.function.constructor' => 'Constructor',
19
- 'source.lang.swift.decl.function.destructor' => 'Destructor',
20
- 'source.lang.swift.decl.var.global' => 'Global Variable',
21
- 'source.lang.swift.decl.enumelement' => 'Enum Element',
22
- 'source.lang.swift.decl.enum' => 'Enum',
23
- 'source.lang.swift.decl.extension' => 'Extension',
24
- 'source.lang.swift.decl.function.free' => 'Function',
25
- 'source.lang.swift.decl.function.method.instance' => 'Instance Method',
26
- 'source.lang.swift.decl.var.instance' => 'Instance Variable',
27
- 'source.lang.swift.decl.var.local' => 'Local Variable',
28
- 'source.lang.swift.decl.var.parameter' => 'Parameter',
29
- 'source.lang.swift.decl.protocol' => 'Protocol',
30
- 'source.lang.swift.decl.function.method.static' => 'Static Method',
31
- 'source.lang.swift.decl.var.static' => 'Static Variable',
32
- 'source.lang.swift.decl.struct' => 'Struct',
33
- 'source.lang.swift.decl.function.subscript' => 'Subscript',
34
- 'source.lang.swift.decl.typealias' => 'Typealias',
35
- }
36
- end
14
+ @kinds = {
15
+ 'source.lang.swift.decl.function.method.class' => 'Class Method',
16
+ 'source.lang.swift.decl.var.class' => 'Class Variable',
17
+ 'source.lang.swift.decl.class' => 'Class',
18
+ 'source.lang.swift.decl.function.constructor' => 'Constructor',
19
+ 'source.lang.swift.decl.function.destructor' => 'Destructor',
20
+ 'source.lang.swift.decl.var.global' => 'Global Variable',
21
+ 'source.lang.swift.decl.enumelement' => 'Enum Element',
22
+ 'source.lang.swift.decl.enum' => 'Enum',
23
+ 'source.lang.swift.decl.extension' => 'Extension',
24
+ 'source.lang.swift.decl.function.free' => 'Function',
25
+ 'source.lang.swift.decl.function.method.instance' => 'Instance Method',
26
+ 'source.lang.swift.decl.var.instance' => 'Instance Variable',
27
+ 'source.lang.swift.decl.var.local' => 'Local Variable',
28
+ 'source.lang.swift.decl.var.parameter' => 'Parameter',
29
+ 'source.lang.swift.decl.protocol' => 'Protocol',
30
+ 'source.lang.swift.decl.function.method.static' => 'Static Method',
31
+ 'source.lang.swift.decl.var.static' => 'Static Variable',
32
+ 'source.lang.swift.decl.struct' => 'Struct',
33
+ 'source.lang.swift.decl.function.subscript' => 'Subscript',
34
+ 'source.lang.swift.decl.typealias' => 'Typealias',
35
+ }.freeze
37
36
 
38
37
  # Group root-level docs by kind and add as children to a group doc element
39
38
  def self.group_docs(docs, kind)
40
- kind_name_plural = kinds[kind].pluralize
39
+ kind_name_plural = @kinds[kind].pluralize
41
40
  group, docs = docs.partition { |doc| doc.kind == kind }
42
41
  docs << SourceDeclaration.new.tap do |sd|
43
42
  sd.name = kind_name_plural
44
43
  sd.kind = 'Overview'
45
- sd.abstract = "The following #{kind_name_plural.downcase} are available " \
46
- 'globally.'
44
+ sd.abstract = "The following #{kind_name_plural.downcase} are " \
45
+ 'available globally.'
47
46
  sd.children = group
48
47
  end if group.count > 0
49
48
  docs
@@ -69,10 +68,53 @@ module Jazzy
69
68
 
70
69
  # Run sourcekitten with given arguments and return STDOUT
71
70
  def self.run_sourcekitten(arguments)
72
- bin_path = File.expand_path(File.join(File.dirname(__FILE__), '../../bin'))
71
+ bin_path = Pathname(__FILE__).parent + '../../bin'
73
72
  `#{bin_path}/sourcekitten #{(arguments).join(' ')}`
74
73
  end
75
74
 
75
+ def self.make_default_doc_info(declaration)
76
+ # @todo: Fix these
77
+ declaration.line = 0
78
+ declaration.column = 0
79
+ declaration.abstract = 'Undocumented'
80
+ declaration.parameters = []
81
+ end
82
+
83
+ def self.make_doc_info(doc, declaration)
84
+ if doc['key.doc.full_as_xml']
85
+ xml = Nokogiri::XML(doc['key.doc.full_as_xml']).root
86
+ declaration.line = XMLHelper.attribute(xml, 'line').to_i
87
+ declaration.column = XMLHelper.attribute(xml, 'column').to_i
88
+ declaration.declaration = XMLHelper.xpath(xml, 'Declaration')
89
+ declaration.abstract = XMLHelper.xpath(xml, 'Abstract')
90
+ declaration.discussion = XMLHelper.xpath(xml, 'Discussion')
91
+ declaration.return = XMLHelper.xpath(xml, 'ResultDiscussion')
92
+
93
+ declaration.parameters = []
94
+ xml.xpath('Parameters/Parameter').each do |parameter_el|
95
+ declaration.parameters << {
96
+ name: XMLHelper.xpath(parameter_el, 'Name'),
97
+ discussion: Jazzy.markdown.render(
98
+ XMLHelper.xpath(parameter_el, 'Discussion'),
99
+ ),
100
+ }
101
+ end
102
+ else
103
+ make_default_doc_info(declaration)
104
+ end
105
+ end
106
+
107
+ def self.make_substructure(doc, declaration)
108
+ if doc['key.substructure']
109
+ declaration.children = make_source_declarations(
110
+ doc['key.substructure'],
111
+ )
112
+ else
113
+ declaration.children = []
114
+ end
115
+ end
116
+
117
+ # rubocop:disable Metrics/MethodLength
76
118
  def self.make_source_declarations(docs)
77
119
  declarations = []
78
120
  docs.each do |doc|
@@ -83,63 +125,46 @@ module Jazzy
83
125
  declaration = SourceDeclaration.new
84
126
  declaration.kind = doc['key.kind']
85
127
  next unless declaration.kind =~ /^source\.lang\.swift\.decl\..*/
86
- next if declaration.kind == 'source.lang.swift.decl.var.parameter'
87
128
 
88
- declaration.kindName = kinds[declaration.kind]
89
-
90
- raise 'Please file an issue on https://github.com/realm/jazzy/issues ' \
91
- "about adding support for `#{declaration.kind}`" unless declaration.kindName
129
+ unless declaration.kindName = @kinds[declaration.kind]
130
+ raise 'Please file an issue on ' \
131
+ 'https://github.com/realm/jazzy/issues about adding support for ' \
132
+ "`#{declaration.kind}`"
133
+ end
92
134
 
93
135
  declaration.kindNamePlural = declaration.kindName.pluralize
94
136
  declaration.file = doc['key.filepath']
95
137
  declaration.usr = doc['key.usr']
96
138
  declaration.name = doc['key.name']
97
139
 
98
- if doc['key.doc.full_as_xml']
99
- xml = Nokogiri::XML(doc['key.doc.full_as_xml']).root
100
- declaration.line = XMLHelper.attribute(xml, 'line').to_i
101
- declaration.column = XMLHelper.attribute(xml, 'column').to_i
102
- declaration.declaration = XMLHelper.xpath(xml, 'Declaration')
103
- declaration.abstract = XMLHelper.xpath(xml, 'Abstract')
104
- declaration.discussion = XMLHelper.xpath(xml, 'Discussion')
105
- declaration.return = XMLHelper.xpath(xml, 'ResultDiscussion')
106
-
107
- parameters = []
108
- xml.xpath('Parameters/Parameter').each do |parameter_el|
109
- parameters << {
110
- name: XMLHelper.xpath(parameter_el, 'Name'),
111
- discussion: Jazzy.markdown.render(
112
- XMLHelper.xpath(parameter_el, 'Discussion'),
113
- ),
114
- }
115
- end
116
- declaration.parameters = parameters
117
- else
118
- # @todo: Fix these
119
- declaration.line = 0
120
- declaration.column = 0
121
- declaration.abstract = 'Undocumented'
122
- declaration.parameters = []
123
- end
124
-
125
- if doc['key.substructure']
126
- declaration.children = make_source_declarations(doc['key.substructure'])
127
- else
128
- declaration.children = []
129
- end
140
+ make_doc_info(doc, declaration)
141
+ make_substructure(doc, declaration)
130
142
  declarations << declaration
131
143
  end
132
144
  declarations
133
145
  end
146
+ # rubocop:enable Metrics/MethodLength
147
+
148
+ def self.doc_coverage(sourcekitten_json)
149
+ documented = sourcekitten_json
150
+ .map { |el| el['key.doc.documented'] }
151
+ .inject(:+)
152
+ undocumented = sourcekitten_json
153
+ .map { |el| el['key.doc.undocumented'] }
154
+ .inject(:+)
155
+ return 0 if documented == 0 && undocumented == 0
156
+ (100 * documented) / (undocumented + documented)
157
+ end
134
158
 
135
- # Parse sourcekitten STDOUT+STDERR output as JSON
159
+ # Parse sourcekitten STDOUT output as JSON
136
160
  # @return [Hash] structured docs
137
161
  def self.parse(sourcekitten_output)
138
- docs = make_source_declarations(JSON.parse(sourcekitten_output))
139
- kinds.keys.each do |kind|
162
+ sourcekitten_json = JSON.parse(sourcekitten_output)
163
+ docs = make_source_declarations(sourcekitten_json)
164
+ @kinds.keys.each do |kind|
140
165
  docs = group_docs(docs, kind)
141
166
  end
142
- make_doc_urls(docs, [])
167
+ [make_doc_urls(docs, []), doc_coverage(sourcekitten_json)]
143
168
  end
144
169
  end
145
170
  end