yard-chefdoc 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +15 -0
  3. data/LICENSE +20 -0
  4. data/README.md +103 -0
  5. data/Rakefile +30 -0
  6. data/lib/yard/cli/stats.rb +142 -0
  7. data/lib/yard-chefdoc/code_objects/attribute.rb +43 -0
  8. data/lib/yard-chefdoc/code_objects/chef.rb +116 -0
  9. data/lib/yard-chefdoc/code_objects/cookbook.rb +55 -0
  10. data/lib/yard-chefdoc/code_objects/recipe.rb +29 -0
  11. data/lib/yard-chefdoc/code_objects/resource.rb +70 -0
  12. data/lib/yard-chefdoc/handlers/attribute.rb +32 -0
  13. data/lib/yard-chefdoc/handlers/base.rb +36 -0
  14. data/lib/yard-chefdoc/handlers/cookbook.rb +40 -0
  15. data/lib/yard-chefdoc/handlers/recipe.rb +15 -0
  16. data/lib/yard-chefdoc/handlers/resource_action.rb +31 -0
  17. data/lib/yard-chefdoc/handlers/resource_default_action.rb +16 -0
  18. data/lib/yard-chefdoc/handlers/resource_property.rb +54 -0
  19. data/lib/yard-chefdoc/handlers/resource_resource_name.rb +16 -0
  20. data/lib/yard-chefdoc/template_helpers/chef.rb +24 -0
  21. data/lib/yard-chefdoc/version.rb +9 -0
  22. data/lib/yard-chefdoc.rb +50 -0
  23. data/spec/attributes_spec.rb +19 -0
  24. data/spec/home_spec.rb +42 -0
  25. data/spec/recipes_spec.rb +15 -0
  26. data/spec/resources_spec.rb +11 -0
  27. data/spec/spec_helper.rb +32 -0
  28. data/templates/default/attribute/html/attribute.erb +30 -0
  29. data/templates/default/attribute/html/setup.rb +5 -0
  30. data/templates/default/cookbook/html/attributes.erb +14 -0
  31. data/templates/default/cookbook/html/cookbook_title.erb +2 -0
  32. data/templates/default/cookbook/html/docstring.erb +1 -0
  33. data/templates/default/cookbook/html/element_details.erb +3 -0
  34. data/templates/default/cookbook/html/generated_docs.erb +2 -0
  35. data/templates/default/cookbook/html/libraries.erb +13 -0
  36. data/templates/default/cookbook/html/metadata.erb +86 -0
  37. data/templates/default/cookbook/html/recipes.erb +14 -0
  38. data/templates/default/cookbook/html/resources.erb +14 -0
  39. data/templates/default/cookbook/html/setup.rb +9 -0
  40. data/templates/default/fulldoc/html/css/chefdoc.css +52 -0
  41. data/templates/default/fulldoc/html/full_list_attributes.erb +14 -0
  42. data/templates/default/fulldoc/html/full_list_libraries.erb +6 -0
  43. data/templates/default/fulldoc/html/full_list_recipes.erb +13 -0
  44. data/templates/default/fulldoc/html/full_list_resources.erb +13 -0
  45. data/templates/default/fulldoc/html/setup.rb +117 -0
  46. data/templates/default/layout/html/layout.erb +24 -0
  47. data/templates/default/layout/html/setup.rb +81 -0
  48. data/templates/default/layout/html/title.erb +1 -0
  49. data/templates/default/recipe/html/recipe.erb +8 -0
  50. data/templates/default/recipe/html/setup.rb +8 -0
  51. data/templates/default/recipe/html/source.erb +10 -0
  52. data/templates/default/resource/html/actions.erb +19 -0
  53. data/templates/default/resource/html/properties.erb +18 -0
  54. data/templates/default/resource/html/resource.erb +3 -0
  55. data/templates/default/resource/html/setup.rb +15 -0
  56. metadata +111 -0
@@ -0,0 +1,36 @@
1
+ require 'yard'
2
+
3
+ module YARD::Handlers
4
+ module Chef
5
+ # Base handler for chef elements.
6
+ class Base < YARD::Handlers::Ruby::Base
7
+ include YARD::CodeObjects::Chef
8
+
9
+ # Gets the name of the handled object.
10
+ #
11
+ def name
12
+ statement.parameters.first.jump(:string_content, :ident).source
13
+ end
14
+
15
+ # Gets the filename which is often used as the object name in chef
16
+ #
17
+ # @return [String] the file name without the rb extension
18
+ #
19
+ def filename
20
+ File.basename(statement.file, '.rb')
21
+ end
22
+
23
+ # Registers the cookbook in {YARD::Registry} and returns the same.
24
+ #
25
+ # @return [ChefObject] the ChefObject
26
+ #
27
+ def cookbook
28
+ cbs = YARD::Registry.all(:cookbook)
29
+ raise 'Something went wrong! Found more that one cookbook.' if cbs.length > 1
30
+ raise 'Something went wrong! Could not find any cookbook' if cbs.empty?
31
+
32
+ cbs.first
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,40 @@
1
+ require 'yard'
2
+
3
+ module YARD::Handlers
4
+ module Chef
5
+ # Handles specific cookbook information like README, description and version.
6
+ #
7
+ class CookbookHandler < Base
8
+ in_file(/^metadata\.json$/)
9
+ handles(/.*/) # Handle the file itself, so everything in it
10
+
11
+ def process
12
+ metadata = JSON.parse(File.read(File.expand_path(statement.file)))
13
+ base_dir = File.dirname(statement.file)
14
+
15
+ cookbook_obj = cookbook
16
+
17
+ %w[name version dependencies source_url
18
+ issues_url maintainer maintainer_email
19
+ license platforms gems].each do |m|
20
+ cookbook_obj.send("#{m}=", metadata[m]) if metadata.key?(m)
21
+ end
22
+
23
+ cookbook_obj.docstring = docstring(base_dir)
24
+ cookbook_obj.docstring_type = :markdown
25
+ end
26
+
27
+ # Generates docstring from the README file.
28
+ #
29
+ # @return [YARD::Docstring] the docstring
30
+ #
31
+ def docstring(base_dir)
32
+ string = ''
33
+ readme_path = base_dir + '/README.md'
34
+ string = IO.read(readme_path) if File.exist?(readme_path)
35
+
36
+ YARD::DocstringParser.new.parse(string).to_docstring
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,15 @@
1
+ require 'yard'
2
+
3
+ module YARD::Handlers
4
+ module Chef
5
+ # Handles "recipes" in a cookbook.
6
+ class RecipeHandler < Base
7
+ in_file(%r{^recipes\/.*\.rb$})
8
+ handles(/.*/) # Handle the file itself, so everything in it
9
+
10
+ def process
11
+ ChefObject.register(filename, :recipe, statement.file)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,31 @@
1
+ require 'yard'
2
+
3
+ module YARD::Handlers
4
+ module Chef
5
+ # Handles actions in custom resources and LWRPs
6
+ class ResourceActionHandler < Base
7
+ in_file(%r{^resources\/.*\.rb$})
8
+ handles method_call(:action)
9
+
10
+ def process
11
+ resource_obj = ChefObject.register(filename, :resource, statement.file)
12
+
13
+ docstring_is_header = (statement.docstring == resource_obj.header)
14
+ resource_obj.add_action action_hash(docstring_is_header)
15
+ end
16
+
17
+ # Creates the hash to initialize the single resource property object
18
+ #
19
+ # @return [Hash] the hash to initialize the property in the resource code object
20
+ #
21
+ def action_hash(nodoc)
22
+ {
23
+ identifier: statement[1][0].source.to_s[1..-1],
24
+ source: statement.source,
25
+ docstring: nodoc ? '' : statement.docstring,
26
+ line: statement.line
27
+ }
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,16 @@
1
+ require 'yard'
2
+
3
+ module YARD::Handlers
4
+ module Chef
5
+ # Handles the default_action in custom resources and LWRPs
6
+ class ResourceDefaultActionHandler < Base
7
+ in_file(%r{^resources\/.*\.rb$})
8
+ handles method_call(:default_action)
9
+
10
+ def process
11
+ resource_obj = ChefObject.register(filename, :resource, statement.file)
12
+ resource_obj.default_action = statement.parameters[0][0][0].source # Gets the first parameter as string
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,54 @@
1
+ require 'yard'
2
+
3
+ module YARD::Handlers
4
+ module Chef
5
+ # Handles properties in custom resources and LWRPs
6
+ class ResourcePropertyHandler < Base
7
+ in_file(%r{^resources\/.*\.rb$})
8
+ handles method_call(:property)
9
+
10
+ def process
11
+ resource_obj = ChefObject.register(filename, :resource, statement.file)
12
+
13
+ docstring_is_header = (statement.docstring == resource_obj.header)
14
+ resource_obj.add_property res_prop_hash(docstring_is_header)
15
+ end
16
+
17
+ # Creates the hash to initialize the single resource property object
18
+ #
19
+ # @return [Hash] the hash to initialize the property in the resource code object
20
+ #
21
+ def res_prop_hash(nodoc)
22
+ props = {}
23
+ statement[1].entries.each do |e|
24
+ next if e == false
25
+ if %i[var_ref array].include?(e.type)
26
+ props[:type] = e.source
27
+ elsif e.type == :symbol_literal
28
+ props[:identifier] = e.source.delete(':')
29
+ elsif e.type == :list
30
+ props[:options] = parse_option_list(e)
31
+ end
32
+ end
33
+ props[:docstring] = nodoc ? '' : statement.docstring
34
+
35
+ props
36
+ end
37
+
38
+ # Goes through the option list AST node and returns a simple hash
39
+ #
40
+ # @return [Hash] The options passed as a hash
41
+ #
42
+ def parse_option_list(list)
43
+ return nil if list.nil? || list.empty?
44
+ opts = {}
45
+ list.each do |opt|
46
+ next unless opt.type == :assoc
47
+ opts[opt[0].source.delete(':')] = opt[1].source
48
+ end
49
+
50
+ opts
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,16 @@
1
+ require 'yard'
2
+
3
+ module YARD::Handlers
4
+ module Chef
5
+ # Handles the resource name in custom resources and LWRPs
6
+ class ResourceResourceNameHandler < Base
7
+ in_file(%r{^resources\/.*\.rb$})
8
+ handles method_call(:resource_name)
9
+
10
+ def process
11
+ resource_obj = ChefObject.register(filename, :resource, statement.file)
12
+ resource_obj.resource_name = statement.parameters[0][0][0].source # Gets the first parameter as string
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YARD::Templates::Helpers
4
+ # The chef helper module
5
+ module ChefHelper
6
+ # Returns children of an object of a particular type sorted the chef
7
+ # way. This means that the object with the name 'default' will be first
8
+ # and any remaining objects will be sorted alphabetically.
9
+ #
10
+ # @param type [Symbol] type of CookbookObject to be selected
11
+ #
12
+ # @return [Array<CookbookObject>] list of CookbookObjects
13
+ #
14
+ def chefsorted_objects(type = nil)
15
+ children = ::YARD::Registry.all.select { |o| o.type == type }.sort { |x, y| x.name.to_s <=> y.name.to_s }
16
+ default_index = children.find_index { |r| r.name.to_s == 'default' }
17
+
18
+ return children if default_index.nil?
19
+
20
+ default_child = children.delete_at(default_index)
21
+ [default_child].concat(children)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YARD
4
+ module CodeObjects
5
+ module Chef
6
+ VERSION = '0.1.0'.freeze
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,50 @@
1
+ require 'yard'
2
+ require 'json'
3
+
4
+ require_relative 'yard/cli/stats'
5
+
6
+ require 'yard-chefdoc/code_objects/chef'
7
+ require 'yard-chefdoc/code_objects/cookbook'
8
+ require 'yard-chefdoc/code_objects/recipe'
9
+ require 'yard-chefdoc/code_objects/attribute'
10
+ require 'yard-chefdoc/code_objects/resource'
11
+
12
+ require 'yard-chefdoc/handlers/base'
13
+ require 'yard-chefdoc/handlers/cookbook'
14
+ require 'yard-chefdoc/handlers/recipe'
15
+ require 'yard-chefdoc/handlers/attribute'
16
+ require 'yard-chefdoc/handlers/resource_property'
17
+ require 'yard-chefdoc/handlers/resource_action'
18
+ require 'yard-chefdoc/handlers/resource_resource_name'
19
+ require 'yard-chefdoc/handlers/resource_default_action'
20
+
21
+ require 'yard-chefdoc/template_helpers/chef'
22
+
23
+ require 'yard-chefdoc/version'
24
+
25
+ module YARD::CodeObjects
26
+ module Chef
27
+ # Initialize the whole magic
28
+ namespace = ChefObject.new(nil, :root)
29
+ CookbookObject.new(namespace, :root)
30
+ end
31
+
32
+ # YARD::Tags::Library.define_tag('Recipe description', :recipe)
33
+
34
+ # Register template directory for the chef plugin
35
+ template_dir = File.expand_path('../templates', File.dirname(__FILE__))
36
+ YARD::Templates::Engine.register_template_path(template_dir.to_s)
37
+ end
38
+
39
+ module YARD
40
+ module CLI
41
+ class Yardoc
42
+ # This overrides the method from Yard adding Chefs own objects to be rendered
43
+ # as individual pages. This adds recipes, attributes...
44
+ # @return [Array<CodeObjects::Base>] a list of code objects to process
45
+ def all_objects
46
+ Registry.all(:root, :module, :class, :recipe, :attribute, :resource)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'home page' do
4
+ before(:each) do
5
+ visit('/docs/attribute/default')
6
+ end
7
+
8
+ it 'shows the description' do
9
+ expect(page).to have_content('Some default attributes')
10
+ end
11
+
12
+ it 'has the test-attribute1' do
13
+ expect(page).to have_content("['test-cookbook1']['test-attribute1']")
14
+ end
15
+
16
+ it 'has the test-attribute1 description' do
17
+ expect(page).to have_content('This is the documentation of an attribute')
18
+ end
19
+ end
data/spec/home_spec.rb ADDED
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'home page' do
4
+ before(:each) do
5
+ visit('/')
6
+ end
7
+
8
+ it 'presents the README' do
9
+ expect(page).to have_content('Lorem ipsum dolor sit amet')
10
+ end
11
+
12
+ it 'shows metadata version' do
13
+ expect(page).to have_tag('td', text: '0.1.0')
14
+ end
15
+
16
+ it 'does not show empty license' do
17
+ expect(page).to_not have_tag('td', text: 'License')
18
+ end
19
+
20
+ it 'shows the recipe summary' do
21
+ expect(page).to have_content('Recipes summary')
22
+ expect(page).to have_content('Installs the system package for some_service')
23
+ end
24
+
25
+ it 'shows the attribute summary' do
26
+ expect(page).to have_content('Attributes summary')
27
+ end
28
+
29
+ it 'gives an overview of the libraries' do
30
+ expect(page).to have_content('Finder')
31
+ expect(page).to have_content('Finder::Node')
32
+ expect(page).to have_content('MyTestLib')
33
+ end
34
+
35
+ it 'shows cookbook documentation table' do
36
+ expect(page).to have_content('Cookbook documentation statistics')
37
+ end
38
+
39
+ it 'shows overall percentage' do
40
+ expect(page).to have_content('Total percentage 86.96%')
41
+ end
42
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'home page' do
4
+ before(:each) do
5
+ visit('/docs/recipe/default')
6
+ end
7
+
8
+ it 'shows the description' do
9
+ expect(page).to have_content('This is the description for the default recipe')
10
+ end
11
+
12
+ it 'shows the recipe file name and location' do
13
+ expect(find(:xpath, "//span[@class='info file']").text).to eq('# File \'recipes/default.rb\'')
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'home page' do
4
+ before(:each) do
5
+ visit('/docs/resource/etc_dir')
6
+ end
7
+
8
+ it 'shows the default_action as create' do
9
+ expect(page).to have_content('Default action: create')
10
+ end
11
+ end
@@ -0,0 +1,32 @@
1
+ require 'rspec'
2
+ require 'rspec-html-matchers'
3
+ require 'action_view'
4
+
5
+ # Add this to load Capybara integration:
6
+ require 'capybara'
7
+ require 'capybara/rspec'
8
+ # require 'capybara/rails'
9
+ require 'capybara/dsl'
10
+
11
+ require 'yard'
12
+ require_relative '../lib/yard-chefdoc'
13
+
14
+ RSpec.configure do |config|
15
+ config.include Capybara::DSL
16
+ config.include RSpecHtmlMatchers
17
+ end
18
+
19
+ # disable :run
20
+ # From: https://github.com/lsegal/yard/blob/master/lib/yard/cli/server.rb#L50
21
+ doc_root = File.expand_path('../../test/fixtures/test-cookbook1', __FILE__)
22
+ server_options = {
23
+ Port: 8808
24
+ }
25
+ db = File.expand_path('.yardoc', doc_root)
26
+ libver = YARD::Server::LibraryVersion.new('test-cookbook1', nil, db)
27
+ libver.source_path = doc_root
28
+ libraries = {
29
+ 'test-cookbook1' => [libver]
30
+ }
31
+ options = SymbolHash.new(false).update(single_library: true, caching: false)
32
+ Capybara.app = YARD::Server::RackAdapter.new(libraries, options, server_options)
@@ -0,0 +1,30 @@
1
+ <h2>Attribute <%= object.name %></h2>
2
+ <%= htmlify(object.docstring, :markdown) %>
3
+ <table style="width:100%">
4
+ <thead>
5
+ <th>Attribute</th>
6
+ <th>Precedence</th>
7
+ <th>Description</th>
8
+ <th>Default value</th>
9
+ </thead>
10
+ <tbody>
11
+ <% n = 2 %>
12
+ <% object.attributes.each do |attribute| %>
13
+ <tr class="r<%= n %>">
14
+ <td>
15
+ <strong><%= attribute.path %></strong>
16
+ </td>
17
+ <td><%= attribute.precedence %></td>
18
+ <td><%= htmlify attribute.docstring %></td>
19
+ <td>
20
+ <% if attribute.default.size > 60 %>
21
+ <span>[<a href="#" onclick="return false;" class="toggleSource">View source</a>]</span><br /><span class="source_code"><%= htmlify attribute.default %></span>
22
+ <% else %>
23
+ <%= htmlify attribute.default %>
24
+ <%end%>
25
+ </td>
26
+ </tr>
27
+ <% n = n == 1 ? 2 : 1 %>
28
+ <% end %>
29
+ </tbody>
30
+ </table>
@@ -0,0 +1,5 @@
1
+ include Helpers::ChefHelper
2
+
3
+ def init
4
+ sections.push :attribute
5
+ end
@@ -0,0 +1,14 @@
1
+ <% attributes = chefsorted_objects(:attribute) %>
2
+ <% if attributes.size > 0 %>
3
+ <h2>Attributes summary</h2>
4
+ <ul class="summary">
5
+ <% attributes.each do |attribute| %>
6
+ <li>
7
+ <span class="summary_signature">
8
+ <strong><a href="<%= url_for(attribute,nil) %>"><%= attribute.name %></a></strong>
9
+ </span>
10
+ <span class="summary_desc"><%= htmlify(attribute.docstring, :markdown) %></span>
11
+ </li>
12
+ <% end %>
13
+ </ul>
14
+ <% end %>
@@ -0,0 +1,2 @@
1
+ <h1>Cookbook <%= object.name.to_s %></h1>
2
+ <%= yieldall %>
@@ -0,0 +1 @@
1
+ <%= htmlify(object.docstring, object.docstring_type) %>
@@ -0,0 +1,3 @@
1
+ <div class="method_details_list">
2
+ <%= yieldall %>
3
+ </div>
@@ -0,0 +1,2 @@
1
+ <h1>Cookbook elements overview</h1>
2
+ <%= yieldall %>
@@ -0,0 +1,13 @@
1
+ <% libraries = object.libraries %>
2
+ <% if libraries.size > 0 %>
3
+ <h2>Libraries</h2>
4
+ <ul class="summary compact">
5
+ <% libraries.each do |lib| %>
6
+ <li>
7
+ <span class="summary_signature">
8
+ <a href="<%= url_for(lib, nil) %>"><%= lib %></a>
9
+ </span>
10
+ </li>
11
+ <% end %>
12
+ </ul>
13
+ <% end %>
@@ -0,0 +1,86 @@
1
+ <table class="metadata-box">
2
+ <tr>
3
+ <th class="merged" colspan="2">Cookbook metadata</th>
4
+ </tr>
5
+ <% { 'name' => 'Name',
6
+ 'version' => 'Version',
7
+ 'maintainer' => 'Maintainer',
8
+ 'maintainer_email' => 'Contact',
9
+ 'license' => 'License',
10
+ 'source_url' => 'Source',
11
+ 'issues_url' => 'Issues'}.each do |m, n| %>
12
+ <% meta_info = object.send(m.to_sym) %>
13
+ <% next if meta_info.nil? || meta_info.empty? %>
14
+ <tr>
15
+ <td><%= n %></td>
16
+ <% if m.end_with?('_url') %>
17
+ <td><a href="<%= meta_info %>" target="_blank"><%= meta_info %></a></td>
18
+ <% else %>
19
+ <td><%= meta_info %></td>
20
+ <% end %>
21
+ </tr>
22
+ <% end %>
23
+
24
+ <% unless object.dependencies.nil? || object.dependencies.empty? %>
25
+ <tr class="section">
26
+ <td class="merged" colspan="2">Dependencies</td>
27
+ </tr>
28
+ <% object.dependencies.each do |cookbook, version| %>
29
+ <tr>
30
+ <td><%= cookbook %></td>
31
+ <td><%= version %> </td>
32
+ </tr>
33
+ <% end %>
34
+ <% end %>
35
+ <% unless object.platforms.nil? || object.platforms.empty? %>
36
+ <tr class="section">
37
+ <td class="merged" colspan="2">Supported platforms</td>
38
+ </tr>
39
+ <% object.platforms.each do |platform, version| %>
40
+ <tr>
41
+ <td><%= platform %></td>
42
+ <td><%= version %> </td>
43
+ </tr>
44
+ <% end %>
45
+ <% end %>
46
+ <% unless object.gems.nil? || object.gems.empty? %>
47
+ <tr class="section">
48
+ <td class="merged" colspan="2">Rubygem dependencies</td>
49
+ </tr>
50
+ <% object.gems.each do |g| %>
51
+ <tr>
52
+ <td colspan="2"><%= g %></td>
53
+ </tr>
54
+ <% end %>
55
+ <% end %>
56
+ </table>
57
+
58
+ <table class="metadata-box">
59
+ <tr>
60
+ <th class="merged" colspan="2">Cookbook documentation statistics</th>
61
+ </tr>
62
+ <tr>
63
+ <td>Total percentage</td>
64
+ <td><%= @cookbook_statistics['total_percentage'].round(2) %>%</td>
65
+ </tr>
66
+ <tr>
67
+ <td class="merged" colspan="2">Chef</th>
68
+ </tr>
69
+ <% @cookbook_statistics.each do |stat, values| %>
70
+ <% next unless (values.is_a?(Hash) && stat.start_with?('chef_') && !values['items'].zero?) %>
71
+ <tr>
72
+ <td><%= values['name'].sub(/^Chef\s/, '') %></td>
73
+ <td><%= values['percentage'].to_f.round(1) %>% (<%= values['items'] - values['undocumented'] %> of <%= values['items'] %>)</td>
74
+ </tr>
75
+ <% end %>
76
+ <tr>
77
+ <td class="merged" colspan="2">Ruby</th>
78
+ </tr>
79
+ <% @cookbook_statistics.each do |stat, values| %>
80
+ <% next unless (values.is_a?(Hash) && !stat.start_with?('chef_') && !values['items'].zero?) %>
81
+ <tr>
82
+ <td><%= values['name'] %></td>
83
+ <td><%= values['percentage'].to_f.round(1) %>% (<%= values['items'] - values['undocumented'] %> of <%= values['items'] %>)</td>
84
+ </tr>
85
+ <% end %>
86
+ </table>
@@ -0,0 +1,14 @@
1
+ <% recipes = chefsorted_objects(:recipe) %>
2
+ <% if recipes.size > 0 %>
3
+ <h2>Recipes summary</h2>
4
+ <ul class="summary">
5
+ <% recipes.each do |recipe| %>
6
+ <li>
7
+ <span class="summary_signature">
8
+ <strong><a href="<%= url_for(recipe, nil) %>"><%= recipe.name %></a></strong>
9
+ </span>
10
+ <span class="summary_desc"><%= htmlify(recipe.docstring, :markdown) %></span>
11
+ </li>
12
+ <% end %>
13
+ </ul>
14
+ <% end %>
@@ -0,0 +1,14 @@
1
+ <% resources = chefsorted_objects(:resource) %>
2
+ <% if resources.size > 0 %>
3
+ <h2>Resources summary</h2>
4
+ <ul class="summary">
5
+ <% resources.each do |resource| %>
6
+ <li>
7
+ <span class="summary_signature">
8
+ <strong><a href="<%= url_for(resource,nil) %>"><%= resource.name %></a></strong>
9
+ </span>
10
+ <span class="summary_desc"><%= htmlify(resource.docstring, :markdown) %></span>
11
+ </li>
12
+ <% end %>
13
+ </ul>
14
+ <% end %>
@@ -0,0 +1,9 @@
1
+ include Helpers::ChefHelper
2
+ include T('default/module')
3
+
4
+ def init
5
+ @cookbook_statistics = YARD::CLI::Stats.new(false).statistics_hash
6
+
7
+ recipe_parts = %I[recipes attributes resources libraries]
8
+ sections [:cookbook_title, :metadata, :docstring, :generated_docs, recipe_parts]
9
+ end